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 1181 2004-06-17 19:23:25Z twisti $
40 #include <sys/ucontext.h>
50 #include "jit/parse.h"
52 #include "jit/i386/codegen.h"
53 #include "jit/i386/emitfuncs.h"
54 #include "jit/i386/offsets.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,
94 This function determines a register, to which the result of an operation
95 should go, when it is ultimatively intended to store the result in
97 If v is assigned to an actual register, this register will be returned.
98 Otherwise (when v is spilled) this function returns tempregnum.
99 If not already done, regoff and flags are set in the stack location.
102 static int reg_of_var(stackptr v, int tempregnum)
106 switch (v->varkind) {
108 if (!(v->flags & INMEMORY))
112 var = &(interfaces[v->varnum][v->type]);
113 v->regoff = var->regoff;
114 if (!(var->flags & INMEMORY))
118 var = &(locals[v->varnum][v->type]);
119 v->regoff = var->regoff;
120 if (!(var->flags & INMEMORY))
124 v->regoff = v->varnum;
125 if (IS_FLT_DBL_TYPE(v->type)) {
126 if (v->varnum < fltreg_argnum) {
127 v->regoff = argfltregs[v->varnum];
128 return(argfltregs[v->varnum]);
132 if (v->varnum < intreg_argnum) {
133 v->regoff = argintregs[v->varnum];
134 return(argintregs[v->varnum]);
136 v->regoff -= intreg_argnum;
139 v->flags |= INMEMORY;
144 void codegen_stubcalled() {
145 log_text("Stub has been called");
148 void codegen_general_stubcalled() {
149 log_text("general exception stub has been called");
153 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
154 void thread_restartcriticalsection(ucontext_t *uc)
157 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
158 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
163 #define PREPARE_NATIVE_STACKINFO \
164 i386_push_reg(REG_ITMP1); /*save itmp1, needed by some stubs */ \
165 i386_alu_imm_reg(I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
166 i386_mov_imm_reg((s4) codegen_stubcalled,REG_ITMP1); \
167 i386_call_reg(REG_ITMP1); /*call codegen_stubcalled*/ \
168 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
169 i386_call_reg(REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
170 i386_mov_reg_membase(REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
171 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
172 i386_mov_reg_membase(REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
173 i386_mov_reg_membase(REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
174 i386_mov_membase_reg(REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
175 i386_mov_imm_membase(0,REG_SP, 2*4); /* builtin */
178 #define REMOVE_NATIVE_STACKINFO \
179 i386_mov_membase_reg(REG_SP,0,REG_ITMP2); \
180 i386_mov_membase_reg(REG_SP,4,REG_ITMP3); \
181 i386_mov_reg_membase(REG_ITMP2,REG_ITMP3,0); \
182 i386_alu_imm_reg(I386_ADD,3*4,REG_SP);
186 /* NullPointerException signal handler for hardware null pointer check */
188 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
191 /* long faultaddr; */
193 struct ucontext *_uc = (struct ucontext *) _p;
194 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
195 struct sigaction act;
197 /* Reset signal handler - necessary for SysV, does no harm for BSD */
199 /* instr = *((int*)(sigctx->eip)); */
200 /* faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
202 /* fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
204 /* if (faultaddr == 0) { */
205 /* signal(sig, (void *) catch_NullPointerException); */
206 act.sa_sigaction = (void *) catch_NullPointerException;
207 act.sa_flags = SA_SIGINFO;
208 sigaction(sig, &act, NULL); /* reinstall handler */
211 sigaddset(&nsig, sig);
212 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
214 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
215 sigctx->eax = (u4) string_java_lang_NullPointerException;
216 sigctx->eip = (u4) asm_throw_and_handle_exception;
221 /* faultaddr += (long) ((instr << 16) >> 16); */
222 /* fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
223 /* panic("Stack overflow"); */
228 /* ArithmeticException signal handler for hardware divide by zero check */
230 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
234 /* void **_p = (void **) &sig; */
235 /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
236 struct ucontext *_uc = (struct ucontext *) _p;
237 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
238 struct sigaction act;
240 /* Reset signal handler - necessary for SysV, does no harm for BSD */
242 /* signal(sig, (void *) catch_ArithmeticException); */
243 act.sa_sigaction = (void *) catch_ArithmeticException;
244 act.sa_flags = SA_SIGINFO;
245 sigaction(sig, &act, NULL); /* reinstall handler */
248 sigaddset(&nsig, sig);
249 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
251 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
252 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
258 void init_exceptions(void)
260 struct sigaction act;
262 /* install signal handlers we need to convert to exceptions */
266 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
267 act.sa_sigaction = (void *) catch_NullPointerException;
268 act.sa_flags = SA_SIGINFO;
269 sigaction(SIGSEGV, &act, NULL);
273 /* signal(SIGBUS, (void *) catch_NullPointerException); */
274 act.sa_sigaction = (void *) catch_NullPointerException;
275 act.sa_flags = SA_SIGINFO;
276 sigaction(SIGBUS, &act, NULL);
280 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
281 act.sa_sigaction = (void *) catch_ArithmeticException;
282 act.sa_flags = SA_SIGINFO;
283 sigaction(SIGFPE, &act, NULL);
287 /* function codegen ************************************************************
289 generates machine code
291 *******************************************************************************/
293 /* global code generation pointer */
298 int len, s1, s2, s3, d;
305 int fpu_st_offset = 0;
314 /* space to save used callee saved registers */
316 savedregs_num += (savintregcnt - maxsavintreguse);
317 savedregs_num += (savfltregcnt - maxsavfltreguse);
319 parentargs_base = maxmemuse + savedregs_num;
321 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
323 if (checksync && (method->flags & ACC_SYNCHRONIZED))
328 /* create method header */
330 (void) dseg_addaddress(method); /* MethodPointer */
331 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
333 #if defined(USE_THREADS)
335 /* IsSync contains the offset relative to the stack pointer for the
336 argument of monitor_exit used in the exception handler. Since the
337 offset could be zero and give a wrong meaning of the flag it is
341 if (checksync && (method->flags & ACC_SYNCHRONIZED))
342 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
347 (void) dseg_adds4(0); /* IsSync */
349 (void) dseg_adds4(isleafmethod); /* IsLeaf */
350 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
351 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
353 /* adds a reference for the length of the line number counter. We don't
354 know the size yet, since we evaluate the information during code
355 generation, to save one additional iteration over the whole
356 instructions. During code optimization the position could have changed
357 to the information gotten from the class file */
358 (void) dseg_addlinenumbertablesize();
360 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
362 /* create exception table */
364 for (ex = extable; ex != NULL; ex = ex->down) {
365 dseg_addtarget(ex->start);
366 dseg_addtarget(ex->end);
367 dseg_addtarget(ex->handler);
368 (void) dseg_addaddress(ex->catchtype);
372 /* initialize mcode variables */
374 mcodeptr = (u1*) mcodebase;
375 mcodeend = (s4*) (mcodebase + mcodesize);
376 MCODECHECK(128 + mparamcount);
378 /* create stack frame (if necessary) */
380 if (parentargs_base) {
381 i386_alu_imm_reg(I386_SUB, parentargs_base * 8, REG_SP);
384 /* save return address and used callee saved registers */
387 for (r = savintregcnt - 1; r >= maxsavintreguse; r--) {
388 p--; i386_mov_reg_membase(savintregs[r], REG_SP, p * 8);
390 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--) {
391 p--; i386_fld_reg(savfltregs[r]); i386_fstpl_membase(REG_SP, p * 8);
394 /* save monitorenter argument */
396 #if defined(USE_THREADS)
397 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
398 if (method->flags & ACC_STATIC) {
399 i386_mov_imm_reg((s4) class, REG_ITMP1);
400 i386_mov_reg_membase(REG_ITMP1, REG_SP, maxmemuse * 8);
403 i386_mov_membase_reg(REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
404 i386_mov_reg_membase(REG_ITMP1, REG_SP, maxmemuse * 8);
407 /* call monitorenter function */
409 i386_alu_imm_reg(I386_SUB, 4, REG_SP);
410 i386_mov_reg_membase(REG_ITMP1, REG_SP, 0);
411 i386_mov_imm_reg((s4) builtin_monitorenter, REG_ITMP1);
412 i386_call_reg(REG_ITMP1);
413 i386_alu_imm_reg(I386_ADD, 4, REG_SP);
417 /* copy argument registers to stack and call trace function with pointer
418 to arguments on stack.
422 i386_alu_imm_reg(I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
424 for (p = 0; p < mparamcount && p < TRACE_ARGS_NUM; p++) {
427 if (IS_INT_LNG_TYPE(t)) {
428 if (IS_2_WORD_TYPE(t)) {
429 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
430 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
431 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
432 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
434 /* } else if (t == TYPE_ADR) { */
436 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
437 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
438 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
439 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
442 /* i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
444 /* i386_mov_reg_membase(EAX, REG_SP, p * 8); */
445 /* i386_mov_reg_membase(EDX, REG_SP, p * 8 + 4); */
449 if (!IS_2_WORD_TYPE(t)) {
450 i386_flds_membase(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
451 i386_fstps_membase(REG_SP, p * 8);
452 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
453 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
456 i386_fldl_membase(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
457 i386_fstpl_membase(REG_SP, p * 8);
462 /* fill up the remaining arguments */
463 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
464 for (p = mparamcount; p < TRACE_ARGS_NUM; p++) {
465 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
466 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
469 i386_mov_imm_membase((s4) method, REG_SP, TRACE_ARGS_NUM * 8);
470 i386_mov_imm_reg((s4) builtin_trace_args, REG_ITMP1);
471 i386_call_reg(REG_ITMP1);
473 i386_alu_imm_reg(I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
476 /* take arguments out of register or stack frame */
478 for (p = 0, l = 0; p < mparamcount; p++) {
480 var = &(locals[l][t]);
482 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
487 if (IS_INT_LNG_TYPE(t)) { /* integer args */
488 if (p < intreg_argnum) { /* register arguments */
489 panic("integer register argument");
490 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
491 /* M_INTMOVE (argintregs[p], r); */
493 } else { /* reg arg -> spilled */
494 /* M_LST (argintregs[p], REG_SP, 8 * r); */
496 } else { /* stack arguments */
497 pa = p - intreg_argnum;
498 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
499 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, r); /* + 4 for return address */
500 } else { /* stack arg -> spilled */
501 if (!IS_2_WORD_TYPE(t)) {
502 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
503 i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8);
506 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
507 i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8);
508 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
509 i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8 + 4);
514 } else { /* floating args */
515 if (p < fltreg_argnum) { /* register arguments */
516 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
517 panic("There are no float argument registers!");
519 } else { /* reg arg -> spilled */
520 panic("There are no float argument registers!");
523 } else { /* stack arguments */
524 pa = p - fltreg_argnum;
525 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
527 i386_flds_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
529 i386_fstp_reg(r + fpu_st_offset);
533 i386_fldl_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
535 i386_fstp_reg(r + fpu_st_offset);
539 } else { /* stack-arg -> spilled */
540 /* i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
541 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8); */
543 i386_flds_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
544 i386_fstps_membase(REG_SP, r * 8);
547 i386_fldl_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
548 i386_fstpl_membase(REG_SP, r * 8);
557 /* end of header generation */
559 /* walk through all basic blocks */
560 for (bptr = block; bptr != NULL; bptr = bptr->next) {
562 bptr->mpc = (int)((u1*) mcodeptr - mcodebase);
564 if (bptr->flags >= BBREACHED) {
566 /* branch resolving */
569 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
570 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
571 brefs->branchpos, bptr->mpc);
574 /* copy interface registers to their destination */
579 while (src != NULL) {
581 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
582 if (!IS_2_WORD_TYPE(src->type)) {
583 if (bptr->type == BBTYPE_SBR) {
584 d = reg_of_var(src, REG_ITMP1);
586 store_reg_to_var_int(src, d);
588 } else if (bptr->type == BBTYPE_EXH) {
589 d = reg_of_var(src, REG_ITMP1);
590 M_INTMOVE(REG_ITMP1, d);
591 store_reg_to_var_int(src, d);
595 panic("copy interface registers: longs have to me in memory (begin 1)");
599 d = reg_of_var(src, REG_ITMP1);
600 if ((src->varkind != STACKVAR)) {
602 if (IS_FLT_DBL_TYPE(s2)) {
603 s1 = interfaces[len][s2].regoff;
604 if (!(interfaces[len][s2].flags & INMEMORY)) {
608 if (s2 == TYPE_FLT) {
609 i386_flds_membase(REG_SP, s1 * 8);
612 i386_fldl_membase(REG_SP, s1 * 8);
615 store_reg_to_var_flt(src, d);
618 s1 = interfaces[len][s2].regoff;
619 if (!IS_2_WORD_TYPE(interfaces[len][s2].type)) {
620 if (!(interfaces[len][s2].flags & INMEMORY)) {
624 i386_mov_membase_reg(REG_SP, s1 * 8, d);
626 store_reg_to_var_int(src, d);
629 if (interfaces[len][s2].flags & INMEMORY) {
630 M_LNGMEMMOVE(s1, src->regoff);
633 panic("copy interface registers: longs have to be in memory (begin 2)");
642 /* walk through all instructions */
646 for (iptr = bptr->iinstr;
648 src = iptr->dst, len--, iptr++) {
650 if (iptr->line!=currentline) {
651 dseg_addlinenumber(iptr->line,mcodeptr);
652 currentline=iptr->line;
654 MCODECHECK(64); /* an instruction usually needs < 64 words */
657 case ICMD_NOP: /* ... ==> ... */
660 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
661 if (src->flags & INMEMORY) {
662 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
665 i386_test_reg_reg(src->regoff, src->regoff);
667 i386_jcc(I386_CC_E, 0);
668 codegen_addxnullrefs(mcodeptr);
671 /* constant operations ************************************************/
673 case ICMD_ICONST: /* ... ==> ..., constant */
674 /* op1 = 0, val.i = constant */
676 d = reg_of_var(iptr->dst, REG_ITMP1);
677 if (iptr->dst->flags & INMEMORY) {
678 i386_mov_imm_membase(iptr->val.i, REG_SP, iptr->dst->regoff * 8);
681 if (iptr->val.i == 0) {
682 i386_alu_reg_reg(I386_XOR, d, d);
685 i386_mov_imm_reg(iptr->val.i, d);
690 case ICMD_LCONST: /* ... ==> ..., constant */
691 /* op1 = 0, val.l = constant */
693 d = reg_of_var(iptr->dst, REG_ITMP1);
694 if (iptr->dst->flags & INMEMORY) {
695 i386_mov_imm_membase(iptr->val.l, REG_SP, iptr->dst->regoff * 8);
696 i386_mov_imm_membase(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
699 panic("LCONST: longs have to be in memory");
703 case ICMD_FCONST: /* ... ==> ..., constant */
704 /* op1 = 0, val.f = constant */
706 d = reg_of_var(iptr->dst, REG_FTMP1);
707 if (iptr->val.f == 0.0) {
712 if (iptr->val.i == 0x80000000) {
716 } else if (iptr->val.f == 1.0) {
720 } else if (iptr->val.f == 2.0) {
727 a = dseg_addfloat(iptr->val.f);
728 i386_mov_imm_reg(0, REG_ITMP1);
729 dseg_adddata(mcodeptr);
730 i386_flds_membase(REG_ITMP1, a);
733 store_reg_to_var_flt(iptr->dst, d);
736 case ICMD_DCONST: /* ... ==> ..., constant */
737 /* op1 = 0, val.d = constant */
739 d = reg_of_var(iptr->dst, REG_FTMP1);
740 if (iptr->val.d == 0.0) {
745 if (iptr->val.l == 0x8000000000000000LL) {
749 } else if (iptr->val.d == 1.0) {
753 } else if (iptr->val.d == 2.0) {
760 a = dseg_adddouble(iptr->val.d);
761 i386_mov_imm_reg(0, REG_ITMP1);
762 dseg_adddata(mcodeptr);
763 i386_fldl_membase(REG_ITMP1, a);
766 store_reg_to_var_flt(iptr->dst, d);
769 case ICMD_ACONST: /* ... ==> ..., constant */
770 /* op1 = 0, val.a = constant */
772 d = reg_of_var(iptr->dst, REG_ITMP1);
773 if (iptr->dst->flags & INMEMORY) {
774 i386_mov_imm_membase((s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
777 if ((s4) iptr->val.a == 0) {
778 i386_alu_reg_reg(I386_XOR, d, d);
781 i386_mov_imm_reg((s4) iptr->val.a, d);
787 /* load/store operations **********************************************/
789 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
790 case ICMD_ALOAD: /* op1 = local variable */
792 d = reg_of_var(iptr->dst, REG_ITMP1);
793 if ((iptr->dst->varkind == LOCALVAR) &&
794 (iptr->dst->varnum == iptr->op1)) {
797 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
798 if (iptr->dst->flags & INMEMORY) {
799 if (var->flags & INMEMORY) {
800 i386_mov_membase_reg(REG_SP, var->regoff * 8, REG_ITMP1);
801 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
804 i386_mov_reg_membase(var->regoff, REG_SP, iptr->dst->regoff * 8);
808 if (var->flags & INMEMORY) {
809 i386_mov_membase_reg(REG_SP, var->regoff * 8, iptr->dst->regoff);
812 M_INTMOVE(var->regoff, iptr->dst->regoff);
817 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
818 /* op1 = local variable */
820 d = reg_of_var(iptr->dst, REG_ITMP1);
821 if ((iptr->dst->varkind == LOCALVAR) &&
822 (iptr->dst->varnum == iptr->op1)) {
825 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
826 if (iptr->dst->flags & INMEMORY) {
827 if (var->flags & INMEMORY) {
828 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
831 panic("LLOAD: longs have to be in memory");
835 panic("LLOAD: longs have to be in memory");
839 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
840 /* op1 = local variable */
842 d = reg_of_var(iptr->dst, REG_FTMP1);
843 if ((iptr->dst->varkind == LOCALVAR) &&
844 (iptr->dst->varnum == iptr->op1)) {
847 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
848 if (var->flags & INMEMORY) {
849 i386_flds_membase(REG_SP, var->regoff * 8);
852 i386_fld_reg(var->regoff + fpu_st_offset);
855 store_reg_to_var_flt(iptr->dst, d);
858 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
859 /* op1 = local variable */
861 d = reg_of_var(iptr->dst, REG_FTMP1);
862 if ((iptr->dst->varkind == LOCALVAR) &&
863 (iptr->dst->varnum == iptr->op1)) {
866 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
867 if (var->flags & INMEMORY) {
868 i386_fldl_membase(REG_SP, var->regoff * 8);
871 i386_fld_reg(var->regoff + fpu_st_offset);
874 store_reg_to_var_flt(iptr->dst, d);
877 case ICMD_ISTORE: /* ..., value ==> ... */
878 case ICMD_ASTORE: /* op1 = local variable */
880 if ((src->varkind == LOCALVAR) &&
881 (src->varnum == iptr->op1)) {
884 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
885 if (var->flags & INMEMORY) {
886 if (src->flags & INMEMORY) {
887 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
888 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8);
891 i386_mov_reg_membase(src->regoff, REG_SP, var->regoff * 8);
895 var_to_reg_int(s1, src, var->regoff);
896 M_INTMOVE(s1, var->regoff);
900 case ICMD_LSTORE: /* ..., value ==> ... */
901 /* op1 = local variable */
903 if ((src->varkind == LOCALVAR) &&
904 (src->varnum == iptr->op1)) {
907 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
908 if (var->flags & INMEMORY) {
909 if (src->flags & INMEMORY) {
910 M_LNGMEMMOVE(src->regoff, var->regoff);
913 panic("LSTORE: longs have to be in memory");
917 panic("LSTORE: longs have to be in memory");
921 case ICMD_FSTORE: /* ..., value ==> ... */
922 /* op1 = local variable */
924 if ((src->varkind == LOCALVAR) &&
925 (src->varnum == iptr->op1)) {
928 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
929 if (var->flags & INMEMORY) {
930 var_to_reg_flt(s1, src, REG_FTMP1);
931 i386_fstps_membase(REG_SP, var->regoff * 8);
934 var_to_reg_flt(s1, src, var->regoff);
935 /* M_FLTMOVE(s1, var->regoff); */
936 i386_fstp_reg(var->regoff + fpu_st_offset);
941 case ICMD_DSTORE: /* ..., value ==> ... */
942 /* op1 = local variable */
944 if ((src->varkind == LOCALVAR) &&
945 (src->varnum == iptr->op1)) {
948 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
949 if (var->flags & INMEMORY) {
950 var_to_reg_flt(s1, src, REG_FTMP1);
951 i386_fstpl_membase(REG_SP, var->regoff * 8);
954 var_to_reg_flt(s1, src, var->regoff);
955 /* M_FLTMOVE(s1, var->regoff); */
956 i386_fstp_reg(var->regoff + fpu_st_offset);
962 /* pop/dup/swap operations ********************************************/
964 /* attention: double and longs are only one entry in CACAO ICMDs */
966 case ICMD_POP: /* ..., value ==> ... */
967 case ICMD_POP2: /* ..., value, value ==> ... */
970 #define M_COPY(from,to) \
971 d = reg_of_var(to, REG_ITMP1); \
972 if ((from->regoff != to->regoff) || \
973 ((from->flags ^ to->flags) & INMEMORY)) { \
974 if (IS_FLT_DBL_TYPE(from->type)) { \
975 var_to_reg_flt(s1, from, d); \
976 /* M_FLTMOVE(s1, d);*/ \
977 store_reg_to_var_flt(to, d); \
979 if (!IS_2_WORD_TYPE(from->type)) { \
980 if (to->flags & INMEMORY) { \
981 if (from->flags & INMEMORY) { \
982 i386_mov_membase_reg(REG_SP, from->regoff * 8, REG_ITMP1); \
983 i386_mov_reg_membase(REG_ITMP1, REG_SP, to->regoff * 8); \
985 i386_mov_reg_membase(from->regoff, REG_SP, to->regoff * 8); \
988 if (from->flags & INMEMORY) { \
989 i386_mov_membase_reg(REG_SP, from->regoff * 8, to->regoff); \
991 i386_mov_reg_reg(from->regoff, to->regoff); \
995 M_LNGMEMMOVE(from->regoff, to->regoff); \
1000 case ICMD_DUP: /* ..., a ==> ..., a, a */
1001 M_COPY(src, iptr->dst);
1004 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
1006 M_COPY(src, iptr->dst->prev->prev);
1008 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
1010 M_COPY(src, iptr->dst);
1011 M_COPY(src->prev, iptr->dst->prev);
1014 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
1016 M_COPY(src->prev, iptr->dst->prev->prev->prev);
1018 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
1020 M_COPY(src, iptr->dst);
1021 M_COPY(src->prev, iptr->dst->prev);
1022 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1023 M_COPY(src, iptr->dst->prev->prev->prev);
1026 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
1028 M_COPY(src, iptr->dst);
1029 M_COPY(src->prev, iptr->dst->prev);
1030 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1031 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1032 M_COPY(src, iptr->dst->prev->prev->prev->prev);
1033 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
1036 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1038 M_COPY(src, iptr->dst->prev);
1039 M_COPY(src->prev, iptr->dst);
1043 /* integer operations *************************************************/
1045 case ICMD_INEG: /* ..., value ==> ..., - value */
1047 d = reg_of_var(iptr->dst, REG_NULL);
1048 if (iptr->dst->flags & INMEMORY) {
1049 if (src->flags & INMEMORY) {
1050 if (src->regoff == iptr->dst->regoff) {
1051 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1054 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1055 i386_neg_reg(REG_ITMP1);
1056 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1060 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1061 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1065 if (src->flags & INMEMORY) {
1066 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1067 i386_neg_reg(iptr->dst->regoff);
1070 M_INTMOVE(src->regoff, iptr->dst->regoff);
1071 i386_neg_reg(iptr->dst->regoff);
1076 case ICMD_LNEG: /* ..., value ==> ..., - value */
1078 d = reg_of_var(iptr->dst, REG_NULL);
1079 if (iptr->dst->flags & INMEMORY) {
1080 if (src->flags & INMEMORY) {
1081 if (src->regoff == iptr->dst->regoff) {
1082 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1083 i386_alu_imm_membase(I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1084 i386_neg_membase(REG_SP, iptr->dst->regoff * 8 + 4);
1087 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1088 i386_neg_reg(REG_ITMP1);
1089 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1090 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1091 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP1);
1092 i386_neg_reg(REG_ITMP1);
1093 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1099 case ICMD_I2L: /* ..., value ==> ..., value */
1101 d = reg_of_var(iptr->dst, REG_NULL);
1102 if (iptr->dst->flags & INMEMORY) {
1103 if (src->flags & INMEMORY) {
1104 i386_mov_membase_reg(REG_SP, src->regoff * 8, EAX);
1106 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1107 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1110 M_INTMOVE(src->regoff, EAX);
1112 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1113 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1118 case ICMD_L2I: /* ..., value ==> ..., value */
1120 d = reg_of_var(iptr->dst, REG_NULL);
1121 if (iptr->dst->flags & INMEMORY) {
1122 if (src->flags & INMEMORY) {
1123 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1124 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1128 if (src->flags & INMEMORY) {
1129 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1134 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1136 d = reg_of_var(iptr->dst, REG_NULL);
1137 if (iptr->dst->flags & INMEMORY) {
1138 if (src->flags & INMEMORY) {
1139 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1140 i386_shift_imm_reg(I386_SHL, 24, REG_ITMP1);
1141 i386_shift_imm_reg(I386_SAR, 24, REG_ITMP1);
1142 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1145 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1146 i386_shift_imm_membase(I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1147 i386_shift_imm_membase(I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1151 if (src->flags & INMEMORY) {
1152 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1153 i386_shift_imm_reg(I386_SHL, 24, iptr->dst->regoff);
1154 i386_shift_imm_reg(I386_SAR, 24, iptr->dst->regoff);
1157 M_INTMOVE(src->regoff, iptr->dst->regoff);
1158 i386_shift_imm_reg(I386_SHL, 24, iptr->dst->regoff);
1159 i386_shift_imm_reg(I386_SAR, 24, iptr->dst->regoff);
1164 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1166 d = reg_of_var(iptr->dst, REG_NULL);
1167 if (iptr->dst->flags & INMEMORY) {
1168 if (src->flags & INMEMORY) {
1169 if (src->regoff == iptr->dst->regoff) {
1170 i386_alu_imm_membase(I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1173 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1174 i386_alu_imm_reg(I386_AND, 0x0000ffff, REG_ITMP1);
1175 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1179 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1180 i386_alu_imm_membase(I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1184 if (src->flags & INMEMORY) {
1185 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1186 i386_alu_imm_reg(I386_AND, 0x0000ffff, iptr->dst->regoff);
1189 M_INTMOVE(src->regoff, iptr->dst->regoff);
1190 i386_alu_imm_reg(I386_AND, 0x0000ffff, iptr->dst->regoff);
1195 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1197 d = reg_of_var(iptr->dst, REG_NULL);
1198 if (iptr->dst->flags & INMEMORY) {
1199 if (src->flags & INMEMORY) {
1200 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1201 i386_shift_imm_reg(I386_SHL, 16, REG_ITMP1);
1202 i386_shift_imm_reg(I386_SAR, 16, REG_ITMP1);
1203 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1206 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1207 i386_shift_imm_membase(I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1208 i386_shift_imm_membase(I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1212 if (src->flags & INMEMORY) {
1213 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1214 i386_shift_imm_reg(I386_SHL, 16, iptr->dst->regoff);
1215 i386_shift_imm_reg(I386_SAR, 16, iptr->dst->regoff);
1218 M_INTMOVE(src->regoff, iptr->dst->regoff);
1219 i386_shift_imm_reg(I386_SHL, 16, iptr->dst->regoff);
1220 i386_shift_imm_reg(I386_SAR, 16, iptr->dst->regoff);
1226 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1228 d = reg_of_var(iptr->dst, REG_NULL);
1229 i386_emit_ialu(I386_ADD, src, iptr);
1232 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1233 /* val.i = constant */
1235 d = reg_of_var(iptr->dst, REG_NULL);
1236 /* should we use a inc optimization for smaller code size? */
1237 i386_emit_ialuconst(I386_ADD, src, iptr);
1240 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1242 d = reg_of_var(iptr->dst, REG_NULL);
1243 if (iptr->dst->flags & INMEMORY) {
1244 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1245 if (src->regoff == iptr->dst->regoff) {
1246 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1247 i386_alu_reg_membase(I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1248 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1249 i386_alu_reg_membase(I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1251 } else if (src->prev->regoff == iptr->dst->regoff) {
1252 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1253 i386_alu_reg_membase(I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1254 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1255 i386_alu_reg_membase(I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1258 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1259 i386_alu_membase_reg(I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1260 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1261 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1262 i386_alu_membase_reg(I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1263 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1270 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1271 /* val.l = constant */
1273 d = reg_of_var(iptr->dst, REG_NULL);
1274 if (iptr->dst->flags & INMEMORY) {
1275 if (src->flags & INMEMORY) {
1276 if (src->regoff == iptr->dst->regoff) {
1277 i386_alu_imm_membase(I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1278 i386_alu_imm_membase(I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1281 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1282 i386_alu_imm_reg(I386_ADD, iptr->val.l, REG_ITMP1);
1283 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1284 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1285 i386_alu_imm_reg(I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1286 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1292 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1294 d = reg_of_var(iptr->dst, REG_NULL);
1295 if (iptr->dst->flags & INMEMORY) {
1296 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1297 if (src->prev->regoff == iptr->dst->regoff) {
1298 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1299 i386_alu_reg_membase(I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1302 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1303 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1304 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1307 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1308 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1309 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1310 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1312 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1313 if (src->prev->regoff == iptr->dst->regoff) {
1314 i386_alu_reg_membase(I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1317 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1318 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1319 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1323 i386_mov_reg_membase(src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1324 i386_alu_reg_membase(I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1328 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1329 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, d);
1330 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, d);
1332 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1333 M_INTMOVE(src->prev->regoff, d);
1334 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, d);
1336 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1337 /* workaround for reg alloc */
1338 if (src->regoff == iptr->dst->regoff) {
1339 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1340 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1341 M_INTMOVE(REG_ITMP1, d);
1344 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, d);
1345 i386_alu_reg_reg(I386_SUB, src->regoff, d);
1349 /* workaround for reg alloc */
1350 if (src->regoff == iptr->dst->regoff) {
1351 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1352 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1353 M_INTMOVE(REG_ITMP1, d);
1356 M_INTMOVE(src->prev->regoff, d);
1357 i386_alu_reg_reg(I386_SUB, src->regoff, d);
1363 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1364 /* val.i = constant */
1366 d = reg_of_var(iptr->dst, REG_NULL);
1367 i386_emit_ialuconst(I386_SUB, src, iptr);
1370 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1372 d = reg_of_var(iptr->dst, REG_NULL);
1373 if (iptr->dst->flags & INMEMORY) {
1374 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1375 if (src->prev->regoff == iptr->dst->regoff) {
1376 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1377 i386_alu_reg_membase(I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1378 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1379 i386_alu_reg_membase(I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1382 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1383 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1384 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1385 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1386 i386_alu_membase_reg(I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1387 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1393 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1394 /* val.l = constant */
1396 d = reg_of_var(iptr->dst, REG_NULL);
1397 if (iptr->dst->flags & INMEMORY) {
1398 if (src->flags & INMEMORY) {
1399 if (src->regoff == iptr->dst->regoff) {
1400 i386_alu_imm_membase(I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1401 i386_alu_imm_membase(I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1404 /* TODO: could be size optimized with lea -- see gcc output */
1405 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1406 i386_alu_imm_reg(I386_SUB, iptr->val.l, REG_ITMP1);
1407 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1408 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1409 i386_alu_imm_reg(I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1410 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1416 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1418 d = reg_of_var(iptr->dst, REG_NULL);
1419 if (iptr->dst->flags & INMEMORY) {
1420 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1421 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1422 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1423 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1425 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1426 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1427 i386_imul_reg_reg(src->prev->regoff, REG_ITMP1);
1428 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1430 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1431 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1432 i386_imul_reg_reg(src->regoff, REG_ITMP1);
1433 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1436 i386_mov_reg_reg(src->prev->regoff, REG_ITMP1);
1437 i386_imul_reg_reg(src->regoff, REG_ITMP1);
1438 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1442 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1443 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1444 i386_imul_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1446 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1447 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1448 i386_imul_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1450 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1451 M_INTMOVE(src->regoff, iptr->dst->regoff);
1452 i386_imul_membase_reg(REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1455 if (src->regoff == iptr->dst->regoff) {
1456 i386_imul_reg_reg(src->prev->regoff, iptr->dst->regoff);
1459 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1460 i386_imul_reg_reg(src->regoff, iptr->dst->regoff);
1466 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1467 /* val.i = constant */
1469 d = reg_of_var(iptr->dst, REG_NULL);
1470 if (iptr->dst->flags & INMEMORY) {
1471 if (src->flags & INMEMORY) {
1472 i386_imul_imm_membase_reg(iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1473 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1476 i386_imul_imm_reg_reg(iptr->val.i, src->regoff, REG_ITMP1);
1477 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1481 if (src->flags & INMEMORY) {
1482 i386_imul_imm_membase_reg(iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1485 i386_imul_imm_reg_reg(iptr->val.i, src->regoff, iptr->dst->regoff);
1490 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1492 d = reg_of_var(iptr->dst, REG_NULL);
1493 if (iptr->dst->flags & INMEMORY) {
1494 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1495 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1496 /* optimize move EAX -> REG_ITMP3 is slower??? */
1497 /* i386_mov_reg_reg(EAX, REG_ITMP3); */
1498 i386_mul_membase(REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1500 /* TODO: optimize move EAX -> REG_ITMP3 */
1501 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1502 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1503 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1505 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1506 i386_imul_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1508 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1509 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1510 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1515 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1516 /* val.l = constant */
1518 d = reg_of_var(iptr->dst, REG_NULL);
1519 if (iptr->dst->flags & INMEMORY) {
1520 if (src->flags & INMEMORY) {
1521 i386_mov_imm_reg(iptr->val.l, EAX); /* imm -> EAX */
1522 i386_mul_membase(REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1523 /* TODO: optimize move EAX -> REG_ITMP3 */
1524 i386_mov_imm_reg(iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1525 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1527 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1528 i386_mov_imm_reg(iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1529 i386_imul_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1531 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1532 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1533 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1538 #define gen_div_check(v) \
1540 if ((v)->flags & INMEMORY) { \
1541 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8); \
1543 i386_test_reg_reg(src->regoff, src->regoff); \
1545 i386_jcc(I386_CC_E, 0); \
1546 codegen_addxdivrefs(mcodeptr); \
1549 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1551 d = reg_of_var(iptr->dst, REG_NULL);
1552 var_to_reg_int(s1, src, REG_ITMP2);
1554 if (src->prev->flags & INMEMORY) {
1555 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX);
1558 M_INTMOVE(src->prev->regoff, EAX);
1561 i386_alu_imm_reg(I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1562 i386_jcc(I386_CC_NE, 3 + 6);
1563 i386_alu_imm_reg(I386_CMP, -1, s1);
1564 i386_jcc(I386_CC_E, 1 + 2);
1569 if (iptr->dst->flags & INMEMORY) {
1570 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1573 M_INTMOVE(EAX, iptr->dst->regoff);
1577 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1579 d = reg_of_var(iptr->dst, REG_NULL);
1580 var_to_reg_int(s1, src, REG_ITMP2);
1582 if (src->prev->flags & INMEMORY) {
1583 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX);
1586 M_INTMOVE(src->prev->regoff, EAX);
1589 i386_alu_imm_reg(I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1590 i386_jcc(I386_CC_NE, 2 + 3 + 6);
1591 i386_alu_reg_reg(I386_XOR, EDX, EDX);
1592 i386_alu_imm_reg(I386_CMP, -1, s1);
1593 i386_jcc(I386_CC_E, 1 + 2);
1598 if (iptr->dst->flags & INMEMORY) {
1599 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8);
1602 M_INTMOVE(EDX, iptr->dst->regoff);
1606 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1607 /* val.i = constant */
1609 /* TODO: optimize for `/ 2' */
1610 var_to_reg_int(s1, src, REG_ITMP1);
1611 d = reg_of_var(iptr->dst, REG_ITMP1);
1614 i386_test_reg_reg(d, d);
1616 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1617 i386_jcc(I386_CC_NS, a);
1618 i386_alu_imm_reg(I386_ADD, (1 << iptr->val.i) - 1, d);
1620 i386_shift_imm_reg(I386_SAR, iptr->val.i, d);
1621 store_reg_to_var_int(iptr->dst, d);
1624 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1625 /* val.i = constant */
1627 d = reg_of_var(iptr->dst, REG_NULL);
1628 if (iptr->dst->flags & INMEMORY) {
1629 if (src->flags & INMEMORY) {
1631 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1633 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1634 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1636 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
1637 i386_jcc(I386_CC_NS, a);
1638 i386_alu_imm_reg(I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1639 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1640 i386_shrd_imm_reg_reg(iptr->val.i, REG_ITMP2, REG_ITMP1);
1641 i386_shift_imm_reg(I386_SAR, iptr->val.i, REG_ITMP2);
1643 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1644 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1649 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1650 /* val.i = constant */
1652 var_to_reg_int(s1, src, REG_ITMP1);
1653 d = reg_of_var(iptr->dst, REG_ITMP2);
1655 M_INTMOVE(s1, REG_ITMP1);
1662 CALCIMMEDIATEBYTES(a, iptr->val.i);
1665 /* TODO: optimize */
1667 i386_alu_imm_reg(I386_AND, iptr->val.i, d);
1668 i386_test_reg_reg(s1, s1);
1669 i386_jcc(I386_CC_GE, a);
1670 i386_mov_reg_reg(s1, d);
1672 i386_alu_imm_reg(I386_AND, iptr->val.i, d);
1675 /* M_INTMOVE(s1, EAX); */
1677 /* i386_alu_reg_reg(I386_XOR, EDX, EAX); */
1678 /* i386_alu_reg_reg(I386_SUB, EDX, EAX); */
1679 /* i386_alu_reg_reg(I386_AND, iptr->val.i, EAX); */
1680 /* i386_alu_reg_reg(I386_XOR, EDX, EAX); */
1681 /* i386_alu_reg_reg(I386_SUB, EDX, EAX); */
1682 /* M_INTMOVE(EAX, d); */
1684 /* i386_alu_reg_reg(I386_XOR, d, d); */
1685 /* i386_mov_imm_reg(iptr->val.i, ECX); */
1686 /* i386_shrd_reg_reg(s1, d); */
1687 /* i386_shift_imm_reg(I386_SHR, 32 - iptr->val.i, d); */
1689 store_reg_to_var_int(iptr->dst, d);
1692 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1693 /* val.l = constant */
1695 d = reg_of_var(iptr->dst, REG_NULL);
1696 if (iptr->dst->flags & INMEMORY) {
1697 if (src->flags & INMEMORY) {
1698 /* Intel algorithm -- does not work, because constant is wrong */
1699 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1); */
1700 /* i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1702 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1703 /* i386_test_reg_reg(REG_ITMP3, REG_ITMP3); */
1704 /* i386_jcc(I386_CC_NS, offset); */
1705 /* i386_alu_imm_reg(I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1706 /* i386_alu_imm_reg(I386_ADC, 0, REG_ITMP3); */
1708 /* i386_shrd_imm_reg_reg(iptr->val.l, REG_ITMP3, REG_ITMP2); */
1709 /* i386_shift_imm_reg(I386_SAR, iptr->val.l, REG_ITMP3); */
1710 /* i386_shld_imm_reg_reg(iptr->val.l, REG_ITMP2, REG_ITMP3); */
1712 /* i386_shift_imm_reg(I386_SHL, iptr->val.l, REG_ITMP2); */
1714 /* i386_alu_reg_reg(I386_SUB, REG_ITMP2, REG_ITMP1); */
1715 /* i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1716 /* i386_alu_reg_reg(I386_SBB, REG_ITMP3, REG_ITMP2); */
1718 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1719 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1721 /* Alpha algorithm */
1723 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1725 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1731 /* TODO: hmm, don't know if this is always correct */
1733 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1735 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1741 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1742 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1744 i386_alu_imm_reg(I386_AND, iptr->val.l, REG_ITMP1);
1745 i386_alu_imm_reg(I386_AND, iptr->val.l >> 32, REG_ITMP2);
1746 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1747 i386_jcc(I386_CC_GE, a);
1749 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1750 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1752 i386_neg_reg(REG_ITMP1);
1753 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1754 i386_neg_reg(REG_ITMP2);
1756 i386_alu_imm_reg(I386_AND, iptr->val.l, REG_ITMP1);
1757 i386_alu_imm_reg(I386_AND, iptr->val.l >> 32, REG_ITMP2);
1759 i386_neg_reg(REG_ITMP1);
1760 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1761 i386_neg_reg(REG_ITMP2);
1763 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1764 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1769 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1771 d = reg_of_var(iptr->dst, REG_NULL);
1772 i386_emit_ishift(I386_SHL, src, iptr);
1775 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1776 /* val.i = constant */
1778 d = reg_of_var(iptr->dst, REG_NULL);
1779 i386_emit_ishiftconst(I386_SHL, src, iptr);
1782 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1784 d = reg_of_var(iptr->dst, REG_NULL);
1785 i386_emit_ishift(I386_SAR, src, iptr);
1788 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1789 /* val.i = constant */
1791 d = reg_of_var(iptr->dst, REG_NULL);
1792 i386_emit_ishiftconst(I386_SAR, src, iptr);
1795 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1797 d = reg_of_var(iptr->dst, REG_NULL);
1798 i386_emit_ishift(I386_SHR, src, iptr);
1801 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1802 /* val.i = constant */
1804 d = reg_of_var(iptr->dst, REG_NULL);
1805 i386_emit_ishiftconst(I386_SHR, src, iptr);
1808 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1810 d = reg_of_var(iptr->dst, REG_NULL);
1811 if (iptr->dst->flags & INMEMORY ){
1812 if (src->prev->flags & INMEMORY) {
1813 /* if (src->prev->regoff == iptr->dst->regoff) { */
1814 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1816 /* if (src->flags & INMEMORY) { */
1817 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1819 /* M_INTMOVE(src->regoff, ECX); */
1822 /* i386_test_imm_reg(32, ECX); */
1823 /* i386_jcc(I386_CC_E, 2 + 2); */
1824 /* i386_mov_reg_reg(REG_ITMP1, REG_ITMP2); */
1825 /* i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1); */
1827 /* i386_shld_reg_membase(REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1828 /* i386_shift_membase(I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1831 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1832 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1834 if (src->flags & INMEMORY) {
1835 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1837 M_INTMOVE(src->regoff, ECX);
1840 i386_test_imm_reg(32, ECX);
1841 i386_jcc(I386_CC_E, 2 + 2);
1842 i386_mov_reg_reg(REG_ITMP1, REG_ITMP3);
1843 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
1845 i386_shld_reg_reg(REG_ITMP1, REG_ITMP3);
1846 i386_shift_reg(I386_SHL, REG_ITMP1);
1847 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1848 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1854 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1855 /* val.i = constant */
1857 d = reg_of_var(iptr->dst, REG_NULL);
1858 if (iptr->dst->flags & INMEMORY ) {
1859 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1860 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1862 if (iptr->val.i & 0x20) {
1863 i386_mov_reg_reg(REG_ITMP1, REG_ITMP2);
1864 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
1865 i386_shld_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1868 i386_shld_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1869 i386_shift_imm_reg(I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1872 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1873 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1877 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1879 d = reg_of_var(iptr->dst, REG_NULL);
1880 if (iptr->dst->flags & INMEMORY ){
1881 if (src->prev->flags & INMEMORY) {
1882 /* if (src->prev->regoff == iptr->dst->regoff) { */
1883 /* TODO: optimize */
1884 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1885 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1887 /* if (src->flags & INMEMORY) { */
1888 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1890 /* M_INTMOVE(src->regoff, ECX); */
1893 /* i386_test_imm_reg(32, ECX); */
1894 /* i386_jcc(I386_CC_E, 2 + 3); */
1895 /* i386_mov_reg_reg(REG_ITMP2, REG_ITMP1); */
1896 /* i386_shift_imm_reg(I386_SAR, 31, REG_ITMP2); */
1898 /* i386_shrd_reg_reg(REG_ITMP2, REG_ITMP1); */
1899 /* i386_shift_reg(I386_SAR, REG_ITMP2); */
1900 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1901 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1904 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1905 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1907 if (src->flags & INMEMORY) {
1908 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1910 M_INTMOVE(src->regoff, ECX);
1913 i386_test_imm_reg(32, ECX);
1914 i386_jcc(I386_CC_E, 2 + 3);
1915 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1);
1916 i386_shift_imm_reg(I386_SAR, 31, REG_ITMP3);
1918 i386_shrd_reg_reg(REG_ITMP3, REG_ITMP1);
1919 i386_shift_reg(I386_SAR, REG_ITMP3);
1920 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1921 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1927 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1928 /* val.i = constant */
1930 d = reg_of_var(iptr->dst, REG_NULL);
1931 if (iptr->dst->flags & INMEMORY ) {
1932 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1933 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1935 if (iptr->val.i & 0x20) {
1936 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1);
1937 i386_shift_imm_reg(I386_SAR, 31, REG_ITMP2);
1938 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1941 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1942 i386_shift_imm_reg(I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1945 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1946 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1950 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1952 d = reg_of_var(iptr->dst, REG_NULL);
1953 if (iptr->dst->flags & INMEMORY ){
1954 if (src->prev->flags & INMEMORY) {
1955 /* if (src->prev->regoff == iptr->dst->regoff) { */
1956 /* TODO: optimize */
1957 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1958 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1960 /* if (src->flags & INMEMORY) { */
1961 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1963 /* M_INTMOVE(src->regoff, ECX); */
1966 /* i386_test_imm_reg(32, ECX); */
1967 /* i386_jcc(I386_CC_E, 2 + 2); */
1968 /* i386_mov_reg_reg(REG_ITMP2, REG_ITMP1); */
1969 /* i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2); */
1971 /* i386_shrd_reg_reg(REG_ITMP2, REG_ITMP1); */
1972 /* i386_shift_reg(I386_SHR, REG_ITMP2); */
1973 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1974 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1977 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1978 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1980 if (src->flags & INMEMORY) {
1981 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1983 M_INTMOVE(src->regoff, ECX);
1986 i386_test_imm_reg(32, ECX);
1987 i386_jcc(I386_CC_E, 2 + 2);
1988 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1);
1989 i386_alu_reg_reg(I386_XOR, REG_ITMP3, REG_ITMP3);
1991 i386_shrd_reg_reg(REG_ITMP3, REG_ITMP1);
1992 i386_shift_reg(I386_SHR, REG_ITMP3);
1993 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1994 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2000 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2001 /* val.l = constant */
2003 d = reg_of_var(iptr->dst, REG_NULL);
2004 if (iptr->dst->flags & INMEMORY ) {
2005 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
2006 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2008 if (iptr->val.i & 0x20) {
2009 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1);
2010 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
2011 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2014 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2015 i386_shift_imm_reg(I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2018 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2019 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2023 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2025 d = reg_of_var(iptr->dst, REG_NULL);
2026 i386_emit_ialu(I386_AND, src, iptr);
2029 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2030 /* val.i = constant */
2032 d = reg_of_var(iptr->dst, REG_NULL);
2033 i386_emit_ialuconst(I386_AND, src, iptr);
2036 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2038 d = reg_of_var(iptr->dst, REG_NULL);
2039 i386_emit_lalu(I386_AND, src, iptr);
2042 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2043 /* val.l = constant */
2045 d = reg_of_var(iptr->dst, REG_NULL);
2046 i386_emit_laluconst(I386_AND, src, iptr);
2049 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2051 d = reg_of_var(iptr->dst, REG_NULL);
2052 i386_emit_ialu(I386_OR, src, iptr);
2055 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2056 /* val.i = constant */
2058 d = reg_of_var(iptr->dst, REG_NULL);
2059 i386_emit_ialuconst(I386_OR, src, iptr);
2062 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2064 d = reg_of_var(iptr->dst, REG_NULL);
2065 i386_emit_lalu(I386_OR, src, iptr);
2068 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2069 /* val.l = constant */
2071 d = reg_of_var(iptr->dst, REG_NULL);
2072 i386_emit_laluconst(I386_OR, src, iptr);
2075 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2077 d = reg_of_var(iptr->dst, REG_NULL);
2078 i386_emit_ialu(I386_XOR, src, iptr);
2081 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2082 /* val.i = constant */
2084 d = reg_of_var(iptr->dst, REG_NULL);
2085 i386_emit_ialuconst(I386_XOR, src, iptr);
2088 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2090 d = reg_of_var(iptr->dst, REG_NULL);
2091 i386_emit_lalu(I386_XOR, src, iptr);
2094 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2095 /* val.l = constant */
2097 d = reg_of_var(iptr->dst, REG_NULL);
2098 i386_emit_laluconst(I386_XOR, src, iptr);
2101 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2102 /* op1 = variable, val.i = constant */
2104 var = &(locals[iptr->op1][TYPE_INT]);
2105 if (var->flags & INMEMORY) {
2106 i386_alu_imm_membase(I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2109 i386_alu_imm_reg(I386_ADD, iptr->val.i, var->regoff);
2114 /* floating operations ************************************************/
2116 #define ROUND_TO_SINGLE \
2117 i386_fstps_membase(REG_SP, -8); \
2118 i386_flds_membase(REG_SP, -8);
2120 #define ROUND_TO_DOUBLE \
2121 i386_fstpl_membase(REG_SP, -8); \
2122 i386_fldl_membase(REG_SP, -8);
2124 #define FPU_SET_24BIT_MODE \
2125 if (!fpu_in_24bit_mode) { \
2126 i386_fldcw_mem(&fpu_ctrlwrd_24bit); \
2127 fpu_in_24bit_mode = 1; \
2130 #define FPU_SET_53BIT_MODE \
2131 if (fpu_in_24bit_mode) { \
2132 i386_fldcw_mem(&fpu_ctrlwrd_53bit); \
2133 fpu_in_24bit_mode = 0; \
2136 #define ROUND_TO_SINGLE
2137 #define ROUND_TO_DOUBLE
2138 #define FPU_SET_24BIT_MODE
2139 #define FPU_SET_53BIT_MODE
2141 case ICMD_FNEG: /* ..., value ==> ..., - value */
2144 var_to_reg_flt(s1, src, REG_FTMP1);
2145 d = reg_of_var(iptr->dst, REG_FTMP3);
2147 store_reg_to_var_flt(iptr->dst, d);
2150 case ICMD_DNEG: /* ..., value ==> ..., - value */
2153 var_to_reg_flt(s1, src, REG_FTMP1);
2154 d = reg_of_var(iptr->dst, REG_FTMP3);
2156 store_reg_to_var_flt(iptr->dst, d);
2159 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2162 d = reg_of_var(iptr->dst, REG_FTMP3);
2163 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2164 var_to_reg_flt(s2, src, REG_FTMP2);
2167 store_reg_to_var_flt(iptr->dst, d);
2170 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2173 d = reg_of_var(iptr->dst, REG_FTMP3);
2174 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2175 var_to_reg_flt(s2, src, REG_FTMP2);
2178 store_reg_to_var_flt(iptr->dst, d);
2181 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2184 d = reg_of_var(iptr->dst, REG_FTMP3);
2185 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2186 var_to_reg_flt(s2, src, REG_FTMP2);
2189 store_reg_to_var_flt(iptr->dst, d);
2192 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2195 d = reg_of_var(iptr->dst, REG_FTMP3);
2196 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2197 var_to_reg_flt(s2, src, REG_FTMP2);
2200 store_reg_to_var_flt(iptr->dst, d);
2203 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2206 d = reg_of_var(iptr->dst, REG_FTMP3);
2207 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2208 var_to_reg_flt(s2, src, REG_FTMP2);
2212 store_reg_to_var_flt(iptr->dst, d);
2215 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2218 d = reg_of_var(iptr->dst, REG_FTMP3);
2219 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2221 /* i386_fldt_mem(subnormal_bias1); */
2224 var_to_reg_flt(s2, src, REG_FTMP2);
2229 /* i386_fldt_mem(subnormal_bias2); */
2232 store_reg_to_var_flt(iptr->dst, d);
2235 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2238 d = reg_of_var(iptr->dst, REG_FTMP3);
2239 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2240 var_to_reg_flt(s2, src, REG_FTMP2);
2244 store_reg_to_var_flt(iptr->dst, d);
2247 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2250 d = reg_of_var(iptr->dst, REG_FTMP3);
2251 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2253 /* i386_fldt_mem(subnormal_bias1); */
2256 var_to_reg_flt(s2, src, REG_FTMP2);
2261 /* i386_fldt_mem(subnormal_bias2); */
2264 store_reg_to_var_flt(iptr->dst, d);
2267 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2270 /* exchanged to skip fxch */
2271 var_to_reg_flt(s2, src, REG_FTMP2);
2272 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2273 d = reg_of_var(iptr->dst, REG_FTMP3);
2279 i386_jcc(I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2280 store_reg_to_var_flt(iptr->dst, d);
2286 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2289 /* exchanged to skip fxch */
2290 var_to_reg_flt(s2, src, REG_FTMP2);
2291 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2292 d = reg_of_var(iptr->dst, REG_FTMP3);
2298 i386_jcc(I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2299 store_reg_to_var_flt(iptr->dst, d);
2305 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2306 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2308 d = reg_of_var(iptr->dst, REG_FTMP1);
2309 if (src->flags & INMEMORY) {
2310 i386_fildl_membase(REG_SP, src->regoff * 8);
2315 i386_mov_imm_reg(0, REG_ITMP1);
2316 dseg_adddata(mcodeptr);
2317 i386_mov_reg_membase(src->regoff, REG_ITMP1, a);
2318 i386_fildl_membase(REG_ITMP1, a);
2321 store_reg_to_var_flt(iptr->dst, d);
2324 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2325 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2327 d = reg_of_var(iptr->dst, REG_FTMP1);
2328 if (src->flags & INMEMORY) {
2329 i386_fildll_membase(REG_SP, src->regoff * 8);
2333 panic("L2F: longs have to be in memory");
2335 store_reg_to_var_flt(iptr->dst, d);
2338 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2340 var_to_reg_flt(s1, src, REG_FTMP1);
2341 d = reg_of_var(iptr->dst, REG_NULL);
2343 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2344 i386_mov_imm_reg(0, REG_ITMP1);
2345 dseg_adddata(mcodeptr);
2346 i386_fldcw_membase(REG_ITMP1, a);
2348 if (iptr->dst->flags & INMEMORY) {
2349 i386_fistpl_membase(REG_SP, iptr->dst->regoff * 8);
2352 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2353 i386_fldcw_membase(REG_ITMP1, a);
2355 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2358 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2360 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2364 i386_fistpl_membase(REG_ITMP1, a);
2366 i386_mov_membase_reg(REG_ITMP1, a, iptr->dst->regoff);
2368 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2369 i386_fldcw_membase(REG_ITMP1, a);
2371 i386_alu_imm_reg(I386_CMP, 0x80000000, iptr->dst->regoff);
2374 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2375 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2378 i386_jcc(I386_CC_NE, a);
2380 /* XXX: change this when we use registers */
2381 i386_flds_membase(REG_SP, src->regoff * 8);
2382 i386_mov_imm_reg((s4) asm_builtin_f2i, REG_ITMP1);
2383 i386_call_reg(REG_ITMP1);
2385 if (iptr->dst->flags & INMEMORY) {
2386 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2389 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2393 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2395 var_to_reg_flt(s1, src, REG_FTMP1);
2396 d = reg_of_var(iptr->dst, REG_NULL);
2398 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2399 i386_mov_imm_reg(0, REG_ITMP1);
2400 dseg_adddata(mcodeptr);
2401 i386_fldcw_membase(REG_ITMP1, a);
2403 if (iptr->dst->flags & INMEMORY) {
2404 i386_fistpl_membase(REG_SP, iptr->dst->regoff * 8);
2407 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2408 i386_fldcw_membase(REG_ITMP1, a);
2410 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2413 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2415 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2419 i386_fistpl_membase(REG_ITMP1, a);
2421 i386_mov_membase_reg(REG_ITMP1, a, iptr->dst->regoff);
2423 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2424 i386_fldcw_membase(REG_ITMP1, a);
2426 i386_alu_imm_reg(I386_CMP, 0x80000000, iptr->dst->regoff);
2429 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2430 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2433 i386_jcc(I386_CC_NE, a);
2435 /* XXX: change this when we use registers */
2436 i386_fldl_membase(REG_SP, src->regoff * 8);
2437 i386_mov_imm_reg((s4) asm_builtin_d2i, REG_ITMP1);
2438 i386_call_reg(REG_ITMP1);
2440 if (iptr->dst->flags & INMEMORY) {
2441 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2443 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2447 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2449 var_to_reg_flt(s1, src, REG_FTMP1);
2450 d = reg_of_var(iptr->dst, REG_NULL);
2452 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2453 i386_mov_imm_reg(0, REG_ITMP1);
2454 dseg_adddata(mcodeptr);
2455 i386_fldcw_membase(REG_ITMP1, a);
2457 if (iptr->dst->flags & INMEMORY) {
2458 i386_fistpll_membase(REG_SP, iptr->dst->regoff * 8);
2461 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2462 i386_fldcw_membase(REG_ITMP1, a);
2464 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2467 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2469 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2472 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2474 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2476 i386_jcc(I386_CC_NE, a);
2478 i386_alu_imm_membase(I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2481 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2483 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2485 i386_jcc(I386_CC_NE, a);
2487 /* XXX: change this when we use registers */
2488 i386_flds_membase(REG_SP, src->regoff * 8);
2489 i386_mov_imm_reg((s4) asm_builtin_f2l, REG_ITMP1);
2490 i386_call_reg(REG_ITMP1);
2491 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2492 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2495 panic("F2L: longs have to be in memory");
2499 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2501 var_to_reg_flt(s1, src, REG_FTMP1);
2502 d = reg_of_var(iptr->dst, REG_NULL);
2504 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2505 i386_mov_imm_reg(0, REG_ITMP1);
2506 dseg_adddata(mcodeptr);
2507 i386_fldcw_membase(REG_ITMP1, a);
2509 if (iptr->dst->flags & INMEMORY) {
2510 i386_fistpll_membase(REG_SP, iptr->dst->regoff * 8);
2513 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2514 i386_fldcw_membase(REG_ITMP1, a);
2516 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2519 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2521 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2524 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2526 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2528 i386_jcc(I386_CC_NE, a);
2530 i386_alu_imm_membase(I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2533 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2535 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2537 i386_jcc(I386_CC_NE, a);
2539 /* XXX: change this when we use registers */
2540 i386_fldl_membase(REG_SP, src->regoff * 8);
2541 i386_mov_imm_reg((s4) asm_builtin_d2l, REG_ITMP1);
2542 i386_call_reg(REG_ITMP1);
2543 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2544 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2547 panic("D2L: longs have to be in memory");
2551 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2553 var_to_reg_flt(s1, src, REG_FTMP1);
2554 d = reg_of_var(iptr->dst, REG_FTMP3);
2556 store_reg_to_var_flt(iptr->dst, d);
2559 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2561 var_to_reg_flt(s1, src, REG_FTMP1);
2562 d = reg_of_var(iptr->dst, REG_FTMP3);
2564 store_reg_to_var_flt(iptr->dst, d);
2567 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2570 /* exchanged to skip fxch */
2571 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2572 var_to_reg_flt(s1, src, REG_FTMP2);
2573 d = reg_of_var(iptr->dst, REG_ITMP1);
2578 i386_test_imm_reg(0x400, EAX); /* unordered treat as GT */
2579 i386_jcc(I386_CC_E, 6);
2580 i386_alu_imm_reg(I386_AND, 0x000000ff, EAX);
2582 i386_mov_imm_reg(0, d); /* does not affect flags */
2583 i386_jcc(I386_CC_E, 6 + 3 + 5 + 3);
2584 i386_jcc(I386_CC_B, 3 + 5);
2585 i386_alu_imm_reg(I386_SUB, 1, d);
2587 i386_alu_imm_reg(I386_ADD, 1, d);
2588 store_reg_to_var_int(iptr->dst, d);
2591 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2594 /* exchanged to skip fxch */
2595 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2596 var_to_reg_flt(s1, src, REG_FTMP2);
2597 d = reg_of_var(iptr->dst, REG_ITMP1);
2602 i386_test_imm_reg(0x400, EAX); /* unordered treat as LT */
2603 i386_jcc(I386_CC_E, 3);
2604 i386_movb_imm_reg(1, I386_AH);
2606 i386_mov_imm_reg(0, d); /* does not affect flags */
2607 i386_jcc(I386_CC_E, 6 + 3 + 5 + 3);
2608 i386_jcc(I386_CC_B, 3 + 5);
2609 i386_alu_imm_reg(I386_SUB, 1, d);
2611 i386_alu_imm_reg(I386_ADD, 1, d);
2612 store_reg_to_var_int(iptr->dst, d);
2616 /* memory operations **************************************************/
2618 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2620 var_to_reg_int(s1, src, REG_ITMP1);
2621 d = reg_of_var(iptr->dst, REG_ITMP1);
2622 gen_nullptr_check(s1);
2623 i386_mov_membase_reg(s1, OFFSET(java_arrayheader, size), d);
2624 store_reg_to_var_int(iptr->dst, d);
2627 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2629 var_to_reg_int(s1, src->prev, REG_ITMP1);
2630 var_to_reg_int(s2, src, REG_ITMP2);
2631 d = reg_of_var(iptr->dst, REG_ITMP1);
2632 if (iptr->op1 == 0) {
2633 gen_nullptr_check(s1);
2636 i386_mov_memindex_reg(OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2637 store_reg_to_var_int(iptr->dst, d);
2640 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2642 var_to_reg_int(s1, src->prev, REG_ITMP1);
2643 var_to_reg_int(s2, src, REG_ITMP2);
2644 d = reg_of_var(iptr->dst, REG_ITMP3);
2645 if (iptr->op1 == 0) {
2646 gen_nullptr_check(s1);
2650 if (iptr->dst->flags & INMEMORY) {
2651 i386_mov_memindex_reg(OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2652 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2653 i386_mov_memindex_reg(OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2654 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2658 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2660 var_to_reg_int(s1, src->prev, REG_ITMP1);
2661 var_to_reg_int(s2, src, REG_ITMP2);
2662 d = reg_of_var(iptr->dst, REG_ITMP1);
2663 if (iptr->op1 == 0) {
2664 gen_nullptr_check(s1);
2667 i386_mov_memindex_reg(OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2668 store_reg_to_var_int(iptr->dst, d);
2671 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2673 var_to_reg_int(s1, src->prev, REG_ITMP1);
2674 var_to_reg_int(s2, src, REG_ITMP2);
2675 d = reg_of_var(iptr->dst, REG_FTMP1);
2676 if (iptr->op1 == 0) {
2677 gen_nullptr_check(s1);
2680 i386_flds_memindex(OFFSET(java_floatarray, data[0]), s1, s2, 2);
2682 store_reg_to_var_flt(iptr->dst, d);
2685 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2687 var_to_reg_int(s1, src->prev, REG_ITMP1);
2688 var_to_reg_int(s2, src, REG_ITMP2);
2689 d = reg_of_var(iptr->dst, REG_FTMP3);
2690 if (iptr->op1 == 0) {
2691 gen_nullptr_check(s1);
2694 i386_fldl_memindex(OFFSET(java_doublearray, data[0]), s1, s2, 3);
2696 store_reg_to_var_flt(iptr->dst, d);
2699 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2701 var_to_reg_int(s1, src->prev, REG_ITMP1);
2702 var_to_reg_int(s2, src, REG_ITMP2);
2703 d = reg_of_var(iptr->dst, REG_ITMP1);
2704 if (iptr->op1 == 0) {
2705 gen_nullptr_check(s1);
2708 i386_movzwl_memindex_reg(OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2709 store_reg_to_var_int(iptr->dst, d);
2712 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2714 var_to_reg_int(s1, src->prev, REG_ITMP1);
2715 var_to_reg_int(s2, src, REG_ITMP2);
2716 d = reg_of_var(iptr->dst, REG_ITMP1);
2717 if (iptr->op1 == 0) {
2718 gen_nullptr_check(s1);
2721 i386_movswl_memindex_reg(OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2722 store_reg_to_var_int(iptr->dst, d);
2725 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2727 var_to_reg_int(s1, src->prev, REG_ITMP1);
2728 var_to_reg_int(s2, src, REG_ITMP2);
2729 d = reg_of_var(iptr->dst, REG_ITMP1);
2730 if (iptr->op1 == 0) {
2731 gen_nullptr_check(s1);
2734 i386_movsbl_memindex_reg(OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2735 store_reg_to_var_int(iptr->dst, d);
2739 case ICMD_AASTORE: /* ..., 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_mov_reg_memindex(s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2751 case ICMD_LASTORE: /* ..., 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);
2760 if (src->flags & INMEMORY) {
2761 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP3);
2762 i386_mov_reg_memindex(REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2763 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2764 i386_mov_reg_memindex(REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2768 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2770 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2771 var_to_reg_int(s2, src->prev, REG_ITMP2);
2772 if (iptr->op1 == 0) {
2773 gen_nullptr_check(s1);
2776 var_to_reg_int(s3, src, REG_ITMP3);
2777 i386_mov_reg_memindex(s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2780 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2782 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2783 var_to_reg_int(s2, src->prev, REG_ITMP2);
2784 if (iptr->op1 == 0) {
2785 gen_nullptr_check(s1);
2788 var_to_reg_flt(s3, src, REG_FTMP1);
2789 i386_fstps_memindex(OFFSET(java_floatarray, data[0]), s1, s2, 2);
2793 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2795 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2796 var_to_reg_int(s2, src->prev, REG_ITMP2);
2797 if (iptr->op1 == 0) {
2798 gen_nullptr_check(s1);
2801 var_to_reg_flt(s3, src, REG_FTMP1);
2802 i386_fstpl_memindex(OFFSET(java_doublearray, data[0]), s1, s2, 3);
2806 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2808 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2809 var_to_reg_int(s2, src->prev, REG_ITMP2);
2810 if (iptr->op1 == 0) {
2811 gen_nullptr_check(s1);
2814 var_to_reg_int(s3, src, REG_ITMP3);
2815 i386_movw_reg_memindex(s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2818 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2820 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2821 var_to_reg_int(s2, src->prev, REG_ITMP2);
2822 if (iptr->op1 == 0) {
2823 gen_nullptr_check(s1);
2826 var_to_reg_int(s3, src, REG_ITMP3);
2827 i386_movw_reg_memindex(s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2830 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2832 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2833 var_to_reg_int(s2, src->prev, REG_ITMP2);
2834 if (iptr->op1 == 0) {
2835 gen_nullptr_check(s1);
2838 var_to_reg_int(s3, src, REG_ITMP3);
2839 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2840 M_INTMOVE(s3, REG_ITMP3);
2843 i386_movb_reg_memindex(s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2847 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2848 /* op1 = type, val.a = field address */
2850 /* if class isn't yet initialized, do it */
2851 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2852 /* call helper function which patches this code */
2853 i386_mov_imm_reg((s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2854 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
2855 i386_call_reg(REG_ITMP2);
2858 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2859 /* here it's slightly slower */
2860 i386_mov_imm_reg(0, REG_ITMP2);
2861 dseg_adddata(mcodeptr);
2862 i386_mov_membase_reg(REG_ITMP2, a, REG_ITMP2);
2863 switch (iptr->op1) {
2866 var_to_reg_int(s2, src, REG_ITMP1);
2867 i386_mov_reg_membase(s2, REG_ITMP2, 0);
2870 if (src->flags & INMEMORY) {
2871 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
2872 i386_mov_reg_membase(REG_ITMP1, REG_ITMP2, 0);
2873 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
2874 i386_mov_reg_membase(REG_ITMP1, REG_ITMP2, 0 + 4);
2876 panic("PUTSTATIC: longs have to be in memory");
2880 var_to_reg_flt(s2, src, REG_FTMP1);
2881 i386_fstps_membase(REG_ITMP2, 0);
2885 var_to_reg_flt(s2, src, REG_FTMP1);
2886 i386_fstpl_membase(REG_ITMP2, 0);
2889 default: panic ("internal error");
2893 case ICMD_GETSTATIC: /* ... ==> ..., value */
2894 /* op1 = type, val.a = field address */
2896 /* if class isn't yet initialized, do it */
2897 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2898 /* call helper function which patches this code */
2899 i386_mov_imm_reg((s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2900 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
2901 i386_call_reg(REG_ITMP2);
2904 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2905 i386_mov_imm_reg(0, REG_ITMP2);
2906 dseg_adddata(mcodeptr);
2907 i386_mov_membase_reg(REG_ITMP2, a, REG_ITMP2);
2908 switch (iptr->op1) {
2911 d = reg_of_var(iptr->dst, REG_ITMP1);
2912 i386_mov_membase_reg(REG_ITMP2, 0, d);
2913 store_reg_to_var_int(iptr->dst, d);
2916 d = reg_of_var(iptr->dst, REG_NULL);
2917 if (iptr->dst->flags & INMEMORY) {
2918 i386_mov_membase_reg(REG_ITMP2, 0, REG_ITMP1);
2919 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2920 i386_mov_membase_reg(REG_ITMP2, 0 + 4, REG_ITMP1);
2921 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
2923 panic("GETSTATIC: longs have to be in memory");
2927 d = reg_of_var(iptr->dst, REG_FTMP1);
2928 i386_flds_membase(REG_ITMP2, 0);
2930 store_reg_to_var_flt(iptr->dst, d);
2933 d = reg_of_var(iptr->dst, REG_FTMP1);
2934 i386_fldl_membase(REG_ITMP2, 0);
2936 store_reg_to_var_flt(iptr->dst, d);
2938 default: panic ("internal error");
2942 case ICMD_PUTFIELD: /* ..., value ==> ... */
2943 /* op1 = type, val.i = field offset */
2945 a = ((fieldinfo *)(iptr->val.a))->offset;
2946 switch (iptr->op1) {
2949 var_to_reg_int(s1, src->prev, REG_ITMP1);
2950 var_to_reg_int(s2, src, REG_ITMP2);
2951 gen_nullptr_check(s1);
2952 i386_mov_reg_membase(s2, s1, a);
2955 var_to_reg_int(s1, src->prev, REG_ITMP1);
2956 gen_nullptr_check(s1);
2957 if (src->flags & INMEMORY) {
2958 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2);
2959 i386_mov_reg_membase(REG_ITMP2, s1, a);
2960 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2961 i386_mov_reg_membase(REG_ITMP2, s1, a + 4);
2963 panic("PUTFIELD: longs have to be in memory");
2967 var_to_reg_int(s1, src->prev, REG_ITMP1);
2968 var_to_reg_flt(s2, src, REG_FTMP1);
2969 gen_nullptr_check(s1);
2970 i386_fstps_membase(s1, a);
2974 var_to_reg_int(s1, src->prev, REG_ITMP1);
2975 var_to_reg_flt(s2, src, REG_FTMP1);
2976 gen_nullptr_check(s1);
2977 i386_fstpl_membase(s1, a);
2980 default: panic ("internal error");
2984 case ICMD_GETFIELD: /* ... ==> ..., value */
2985 /* op1 = type, val.i = field offset */
2987 a = ((fieldinfo *)(iptr->val.a))->offset;
2988 switch (iptr->op1) {
2991 var_to_reg_int(s1, src, REG_ITMP1);
2992 d = reg_of_var(iptr->dst, REG_ITMP2);
2993 gen_nullptr_check(s1);
2994 i386_mov_membase_reg(s1, a, d);
2995 store_reg_to_var_int(iptr->dst, d);
2998 var_to_reg_int(s1, src, REG_ITMP1);
2999 d = reg_of_var(iptr->dst, REG_NULL);
3000 gen_nullptr_check(s1);
3001 i386_mov_membase_reg(s1, a, REG_ITMP2);
3002 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
3003 i386_mov_membase_reg(s1, a + 4, REG_ITMP2);
3004 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3007 var_to_reg_int(s1, src, REG_ITMP1);
3008 d = reg_of_var(iptr->dst, REG_FTMP1);
3009 gen_nullptr_check(s1);
3010 i386_flds_membase(s1, a);
3012 store_reg_to_var_flt(iptr->dst, d);
3015 var_to_reg_int(s1, src, REG_ITMP1);
3016 d = reg_of_var(iptr->dst, REG_FTMP1);
3017 gen_nullptr_check(s1);
3018 i386_fldl_membase(s1, a);
3020 store_reg_to_var_flt(iptr->dst, d);
3022 default: panic ("internal error");
3027 /* branch operations **************************************************/
3030 /* #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}} */
3031 #define ALIGNCODENOP do {} while (0)
3033 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3035 var_to_reg_int(s1, src, REG_ITMP1);
3036 M_INTMOVE(s1, REG_ITMP1_XPTR);
3038 i386_call_imm(0); /* passing exception pointer */
3039 i386_pop_reg(REG_ITMP2_XPC);
3041 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
3042 i386_jmp_reg(REG_ITMP3);
3046 case ICMD_GOTO: /* ... ==> ... */
3047 /* op1 = target JavaVM pc */
3050 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3054 case ICMD_JSR: /* ... ==> ... */
3055 /* op1 = target JavaVM pc */
3058 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3061 case ICMD_RET: /* ... ==> ... */
3062 /* op1 = local variable */
3064 var = &(locals[iptr->op1][TYPE_ADR]);
3065 var_to_reg_int(s1, var, REG_ITMP1);
3069 case ICMD_IFNULL: /* ..., value ==> ... */
3070 /* op1 = target JavaVM pc */
3072 if (src->flags & INMEMORY) {
3073 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
3076 i386_test_reg_reg(src->regoff, src->regoff);
3078 i386_jcc(I386_CC_E, 0);
3079 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3082 case ICMD_IFNONNULL: /* ..., value ==> ... */
3083 /* op1 = target JavaVM pc */
3085 if (src->flags & INMEMORY) {
3086 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
3089 i386_test_reg_reg(src->regoff, src->regoff);
3091 i386_jcc(I386_CC_NE, 0);
3092 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3095 case ICMD_IFEQ: /* ..., value ==> ... */
3096 /* op1 = target JavaVM pc, val.i = constant */
3098 if (src->flags & INMEMORY) {
3099 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3102 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3104 i386_jcc(I386_CC_E, 0);
3105 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3108 case ICMD_IFLT: /* ..., value ==> ... */
3109 /* op1 = target JavaVM pc, val.i = constant */
3111 if (src->flags & INMEMORY) {
3112 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3115 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3117 i386_jcc(I386_CC_L, 0);
3118 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3121 case ICMD_IFLE: /* ..., value ==> ... */
3122 /* op1 = target JavaVM pc, val.i = constant */
3124 if (src->flags & INMEMORY) {
3125 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3128 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3130 i386_jcc(I386_CC_LE, 0);
3131 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3134 case ICMD_IFNE: /* ..., value ==> ... */
3135 /* op1 = target JavaVM pc, val.i = constant */
3137 if (src->flags & INMEMORY) {
3138 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3141 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3143 i386_jcc(I386_CC_NE, 0);
3144 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3147 case ICMD_IFGT: /* ..., value ==> ... */
3148 /* op1 = target JavaVM pc, val.i = constant */
3150 if (src->flags & INMEMORY) {
3151 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3154 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3156 i386_jcc(I386_CC_G, 0);
3157 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3160 case ICMD_IFGE: /* ..., value ==> ... */
3161 /* op1 = target JavaVM pc, val.i = constant */
3163 if (src->flags & INMEMORY) {
3164 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3167 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3169 i386_jcc(I386_CC_GE, 0);
3170 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3173 case ICMD_IF_LEQ: /* ..., value ==> ... */
3174 /* op1 = target JavaVM pc, val.l = constant */
3176 if (src->flags & INMEMORY) {
3177 if (iptr->val.l == 0) {
3178 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3179 i386_alu_membase_reg(I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3182 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3183 i386_alu_imm_reg(I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3184 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3185 i386_alu_imm_reg(I386_XOR, iptr->val.l, REG_ITMP1);
3186 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3189 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3190 i386_jcc(I386_CC_E, 0);
3191 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3194 case ICMD_IF_LLT: /* ..., value ==> ... */
3195 /* op1 = target JavaVM pc, val.l = constant */
3197 if (src->flags & INMEMORY) {
3198 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3199 i386_jcc(I386_CC_L, 0);
3200 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3203 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3204 CALCIMMEDIATEBYTES(a, iptr->val.l);
3206 i386_jcc(I386_CC_G, a);
3208 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3209 i386_jcc(I386_CC_B, 0);
3210 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3214 case ICMD_IF_LLE: /* ..., value ==> ... */
3215 /* op1 = target JavaVM pc, val.l = constant */
3217 if (src->flags & INMEMORY) {
3218 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3219 i386_jcc(I386_CC_L, 0);
3220 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3223 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3224 CALCIMMEDIATEBYTES(a, iptr->val.l);
3226 i386_jcc(I386_CC_G, a);
3228 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3229 i386_jcc(I386_CC_BE, 0);
3230 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3234 case ICMD_IF_LNE: /* ..., value ==> ... */
3235 /* op1 = target JavaVM pc, val.l = constant */
3237 if (src->flags & INMEMORY) {
3238 if (iptr->val.l == 0) {
3239 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3240 i386_alu_membase_reg(I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3243 i386_mov_imm_reg(iptr->val.l, REG_ITMP1);
3244 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3245 i386_mov_imm_reg(iptr->val.l >> 32, REG_ITMP2);
3246 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3247 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3250 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3251 i386_jcc(I386_CC_NE, 0);
3252 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3255 case ICMD_IF_LGT: /* ..., value ==> ... */
3256 /* op1 = target JavaVM pc, val.l = constant */
3258 if (src->flags & INMEMORY) {
3259 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3260 i386_jcc(I386_CC_G, 0);
3261 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3264 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3265 CALCIMMEDIATEBYTES(a, iptr->val.l);
3267 i386_jcc(I386_CC_L, a);
3269 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3270 i386_jcc(I386_CC_A, 0);
3271 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3275 case ICMD_IF_LGE: /* ..., value ==> ... */
3276 /* op1 = target JavaVM pc, val.l = constant */
3278 if (src->flags & INMEMORY) {
3279 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3280 i386_jcc(I386_CC_G, 0);
3281 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3284 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3285 CALCIMMEDIATEBYTES(a, iptr->val.l);
3287 i386_jcc(I386_CC_L, a);
3289 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3290 i386_jcc(I386_CC_AE, 0);
3291 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3295 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3296 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3298 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3299 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3300 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3302 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3303 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3305 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3306 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3309 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3311 i386_jcc(I386_CC_E, 0);
3312 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3315 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3316 /* op1 = target JavaVM pc */
3318 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3319 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3320 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3321 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3322 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3323 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3324 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3326 i386_jcc(I386_CC_E, 0);
3327 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3330 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3331 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3333 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3334 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3335 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3337 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3338 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3340 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3341 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3344 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3346 i386_jcc(I386_CC_NE, 0);
3347 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3350 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3351 /* op1 = target JavaVM pc */
3353 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3354 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3355 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3356 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3357 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3358 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3359 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3361 i386_jcc(I386_CC_NE, 0);
3362 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3365 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3366 /* op1 = target JavaVM pc */
3368 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3369 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3370 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3372 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3373 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3375 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3376 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3379 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3381 i386_jcc(I386_CC_L, 0);
3382 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3385 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3386 /* op1 = target JavaVM pc */
3388 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3389 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3390 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3391 i386_jcc(I386_CC_L, 0);
3392 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3395 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3396 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3398 i386_jcc(I386_CC_G, a);
3400 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3401 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3402 i386_jcc(I386_CC_B, 0);
3403 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3407 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3408 /* op1 = target JavaVM pc */
3410 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3411 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3412 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3414 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3415 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3417 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3418 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3421 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3423 i386_jcc(I386_CC_G, 0);
3424 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3427 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3428 /* op1 = target JavaVM pc */
3430 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3431 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3432 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3433 i386_jcc(I386_CC_G, 0);
3434 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3437 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3438 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3440 i386_jcc(I386_CC_L, a);
3442 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3443 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3444 i386_jcc(I386_CC_A, 0);
3445 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3449 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3450 /* op1 = target JavaVM pc */
3452 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3453 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3454 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3456 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3457 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3459 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3460 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3463 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3465 i386_jcc(I386_CC_LE, 0);
3466 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3469 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3470 /* op1 = target JavaVM pc */
3472 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3473 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3474 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3475 i386_jcc(I386_CC_L, 0);
3476 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3479 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3480 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3482 i386_jcc(I386_CC_G, a);
3484 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3485 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3486 i386_jcc(I386_CC_BE, 0);
3487 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3491 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3492 /* op1 = target JavaVM pc */
3494 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3495 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3496 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3498 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3499 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3501 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3502 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3505 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3507 i386_jcc(I386_CC_GE, 0);
3508 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3511 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3512 /* op1 = target JavaVM pc */
3514 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3515 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3516 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3517 i386_jcc(I386_CC_G, 0);
3518 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3521 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3522 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3524 i386_jcc(I386_CC_L, a);
3526 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3527 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3528 i386_jcc(I386_CC_AE, 0);
3529 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3533 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3535 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3538 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3539 /* val.i = constant */
3541 d = reg_of_var(iptr->dst, REG_NULL);
3542 i386_emit_ifcc_iconst(I386_CC_NE, src, iptr);
3545 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3546 /* val.i = constant */
3548 d = reg_of_var(iptr->dst, REG_NULL);
3549 i386_emit_ifcc_iconst(I386_CC_E, src, iptr);
3552 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3553 /* val.i = constant */
3555 d = reg_of_var(iptr->dst, REG_NULL);
3556 i386_emit_ifcc_iconst(I386_CC_GE, src, iptr);
3559 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3560 /* val.i = constant */
3562 d = reg_of_var(iptr->dst, REG_NULL);
3563 i386_emit_ifcc_iconst(I386_CC_L, src, iptr);
3566 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3567 /* val.i = constant */
3569 d = reg_of_var(iptr->dst, REG_NULL);
3570 i386_emit_ifcc_iconst(I386_CC_LE, src, iptr);
3573 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3574 /* val.i = constant */
3576 d = reg_of_var(iptr->dst, REG_NULL);
3577 i386_emit_ifcc_iconst(I386_CC_G, src, iptr);
3581 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3584 var_to_reg_int(s1, src, REG_RESULT);
3585 M_INTMOVE(s1, REG_RESULT);
3587 goto nowperformreturn;
3589 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3591 if (src->flags & INMEMORY) {
3592 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_RESULT);
3593 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3596 panic("LRETURN: longs have to be in memory");
3599 goto nowperformreturn;
3601 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3602 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3604 var_to_reg_flt(s1, src, REG_FRESULT);
3605 /* this may be an early return -- keep the offset correct for the
3609 goto nowperformreturn;
3611 case ICMD_RETURN: /* ... ==> ... */
3617 p = parentargs_base;
3619 /* call trace function */
3621 i386_alu_imm_reg(I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3623 i386_mov_imm_membase((s4) method, REG_SP, 0);
3625 i386_mov_reg_membase(REG_RESULT, REG_SP, 4);
3626 i386_mov_reg_membase(REG_RESULT2, REG_SP, 4 + 4);
3628 i386_fstl_membase(REG_SP, 4 + 8);
3629 i386_fsts_membase(REG_SP, 4 + 8 + 8);
3631 i386_mov_imm_reg((s4) builtin_displaymethodstop, REG_ITMP1);
3632 i386_call_reg(REG_ITMP1);
3634 i386_mov_membase_reg(REG_SP, 4, REG_RESULT);
3635 i386_mov_membase_reg(REG_SP, 4 + 4, REG_RESULT2);
3637 i386_alu_imm_reg(I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3640 #if defined(USE_THREADS)
3641 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3642 i386_mov_membase_reg(REG_SP, 8 * maxmemuse, REG_ITMP2);
3644 /* we need to save the proper return value */
3645 switch (iptr->opc) {
3648 i386_mov_reg_membase(REG_RESULT, REG_SP, maxmemuse * 8);
3652 i386_mov_reg_membase(REG_RESULT, REG_SP, maxmemuse * 8);
3653 i386_mov_reg_membase(REG_RESULT2, REG_SP, maxmemuse * 8 + 4);
3657 i386_fsts_membase(REG_SP, maxmemuse * 8);
3661 i386_fstl_membase(REG_SP, maxmemuse * 8);
3665 i386_alu_imm_reg(I386_SUB, 4, REG_SP);
3666 i386_mov_reg_membase(REG_ITMP2, REG_SP, 0);
3667 i386_mov_imm_reg((s4) builtin_monitorexit, REG_ITMP1);
3668 i386_call_reg(REG_ITMP1);
3669 i386_alu_imm_reg(I386_ADD, 4, REG_SP);
3671 /* and now restore the proper return value */
3672 switch (iptr->opc) {
3675 i386_mov_membase_reg(REG_SP, maxmemuse * 8, REG_RESULT);
3679 i386_mov_membase_reg(REG_SP, maxmemuse * 8, REG_RESULT);
3680 i386_mov_membase_reg(REG_SP, maxmemuse * 8 + 4, REG_RESULT2);
3684 i386_flds_membase(REG_SP, maxmemuse * 8);
3688 i386_fldl_membase(REG_SP, maxmemuse * 8);
3694 /* restore saved registers */
3695 for (r = savintregcnt - 1; r >= maxsavintreguse; r--) {
3697 i386_mov_membase_reg(REG_SP, p * 8, savintregs[r]);
3699 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--) {
3701 i386_fldl_membase(REG_SP, p * 8);
3703 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3704 i386_fstp_reg(savfltregs[r] + fpu_st_offset + 1);
3706 i386_fstp_reg(savfltregs[r] + fpu_st_offset);
3711 /* deallocate stack */
3712 if (parentargs_base) {
3713 i386_alu_imm_reg(I386_ADD, parentargs_base * 8, REG_SP);
3722 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3727 tptr = (void **) iptr->target;
3729 s4ptr = iptr->val.a;
3730 l = s4ptr[1]; /* low */
3731 i = s4ptr[2]; /* high */
3733 var_to_reg_int(s1, src, REG_ITMP1);
3734 M_INTMOVE(s1, REG_ITMP1);
3736 i386_alu_imm_reg(I386_SUB, l, REG_ITMP1);
3742 i386_alu_imm_reg(I386_CMP, i - 1, REG_ITMP1);
3743 i386_jcc(I386_CC_A, 0);
3745 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
3746 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3748 /* build jump table top down and use address of lowest entry */
3750 /* s4ptr += 3 + i; */
3754 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3755 dseg_addtarget((basicblock *) tptr[0]);
3759 /* length of dataseg after last dseg_addtarget is used by load */
3761 i386_mov_imm_reg(0, REG_ITMP2);
3762 dseg_adddata(mcodeptr);
3763 i386_mov_memindex_reg(-dseglen, REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3764 i386_jmp_reg(REG_ITMP1);
3770 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3772 s4 i, l, val, *s4ptr;
3775 tptr = (void **) iptr->target;
3777 s4ptr = iptr->val.a;
3778 l = s4ptr[0]; /* default */
3779 i = s4ptr[1]; /* count */
3781 MCODECHECK((i<<2)+8);
3782 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3788 i386_alu_imm_reg(I386_CMP, val, s1);
3789 i386_jcc(I386_CC_E, 0);
3790 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
3791 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3795 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
3797 tptr = (void **) iptr->target;
3798 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3805 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3806 /* op1 = return type, val.a = function pointer*/
3810 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3811 /* op1 = return type, val.a = function pointer*/
3815 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3816 /* op1 = return type, val.a = function pointer*/
3820 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3821 /* op1 = arg count, val.a = method pointer */
3823 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3824 /* op1 = arg count, val.a = method pointer */
3826 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3827 /* op1 = arg count, val.a = method pointer */
3829 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3830 /* op1 = arg count, val.a = method pointer */
3838 MCODECHECK((s3 << 1) + 64);
3840 /* copy arguments to registers or stack location */
3842 for (; --s3 >= 0; src = src->prev) {
3843 if (src->varkind == ARGVAR) {
3847 if (IS_INT_LNG_TYPE(src->type)) {
3848 if (s3 < intreg_argnum) {
3849 panic("No integer argument registers available!");
3852 if (!IS_2_WORD_TYPE(src->type)) {
3853 if (src->flags & INMEMORY) {
3854 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3855 i386_mov_reg_membase(REG_ITMP1, REG_SP, s3 * 8);
3858 i386_mov_reg_membase(src->regoff, REG_SP, s3 * 8);
3862 if (src->flags & INMEMORY) {
3863 M_LNGMEMMOVE(src->regoff, s3);
3866 panic("copy arguments: longs have to be in memory");
3872 if (s3 < fltreg_argnum) {
3873 panic("No float argument registers available!");
3876 var_to_reg_flt(d, src, REG_FTMP1);
3877 if (src->type == TYPE_FLT) {
3878 i386_fstps_membase(REG_SP, s3 * 8);
3881 i386_fstpl_membase(REG_SP, s3 * 8);
3888 switch (iptr->opc) {
3896 i386_mov_imm_reg(a, REG_ITMP1);
3897 i386_call_reg(REG_ITMP1);
3900 case ICMD_INVOKESTATIC:
3902 a = (u4) m->stubroutine;
3905 i386_mov_imm_reg(a, REG_ITMP2);
3906 i386_call_reg(REG_ITMP2);
3909 case ICMD_INVOKESPECIAL:
3911 a = (u4) m->stubroutine;
3914 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3915 gen_nullptr_check(REG_ITMP1);
3916 i386_mov_membase_reg(REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3918 i386_mov_imm_reg(a, REG_ITMP2);
3919 i386_call_reg(REG_ITMP2);
3922 case ICMD_INVOKEVIRTUAL:
3926 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3927 gen_nullptr_check(REG_ITMP1);
3928 i386_mov_membase_reg(REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3929 i386_mov_membase32_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + sizeof(methodptr) * m->vftblindex, REG_ITMP1);
3931 i386_call_reg(REG_ITMP1);
3934 case ICMD_INVOKEINTERFACE:
3939 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3940 gen_nullptr_check(REG_ITMP1);
3941 i386_mov_membase_reg(REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3942 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - sizeof(methodptr) * ci->index, REG_ITMP2);
3943 i386_mov_membase32_reg(REG_ITMP2, sizeof(methodptr) * (m - ci->methods), REG_ITMP1);
3945 i386_call_reg(REG_ITMP1);
3950 error("Unkown ICMD-Command: %d", iptr->opc);
3953 /* d contains return type */
3955 if (d != TYPE_VOID) {
3956 d = reg_of_var(iptr->dst, REG_NULL);
3958 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3959 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3960 if (iptr->dst->flags & INMEMORY) {
3961 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3962 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3965 panic("RETURN: longs have to be in memory");
3969 if (iptr->dst->flags & INMEMORY) {
3970 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3973 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3978 /* fld from called function -- has other fpu_st_offset counter */
3980 store_reg_to_var_flt(iptr->dst, d);
3987 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3989 /* op1: 0 == array, 1 == class */
3990 /* val.a: (classinfo*) superclass */
3992 /* superclass is an interface:
3994 * return (sub != NULL) &&
3995 * (sub->vftbl->interfacetablelength > super->index) &&
3996 * (sub->vftbl->interfacetable[-super->index] != NULL);
3998 * superclass is a class:
4000 * return ((sub != NULL) && (0
4001 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4002 * super->vftbl->diffvall));
4006 classinfo *super = (classinfo*) iptr->val.a;
4008 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4009 codegen_threadcritrestart(mcodeptr - mcodebase);
4011 var_to_reg_int(s1, src, REG_ITMP1);
4012 d = reg_of_var(iptr->dst, REG_ITMP3);
4014 M_INTMOVE(s1, REG_ITMP1);
4017 i386_alu_reg_reg(I386_XOR, d, d);
4018 if (iptr->op1) { /* class/interface */
4019 if (super->flags & ACC_INTERFACE) { /* interface */
4020 i386_test_reg_reg(s1, s1);
4022 /* TODO: clean up this calculation */
4024 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4027 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
4030 /* CALCOFFSETBYTES(a, super->index); */
4031 CALCIMMEDIATEBYTES(a, super->index);
4037 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*));
4044 i386_jcc(I386_CC_E, a);
4046 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4047 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetablelength), REG_ITMP2);
4048 i386_alu_imm_reg(I386_SUB, super->index, REG_ITMP2);
4050 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4052 /* TODO: clean up this calculation */
4055 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*));
4062 i386_jcc(I386_CC_LE, a);
4063 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4065 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP1);
4066 /* i386_setcc_reg(I386_CC_A, d); */
4067 /* i386_jcc(I386_CC_BE, 5); */
4068 i386_jcc(I386_CC_E, 5);
4069 i386_mov_imm_reg(1, d);
4072 } else { /* class */
4073 i386_test_reg_reg(s1, s1);
4075 /* TODO: clean up this calculation */
4077 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4080 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, baseval));
4082 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, baseval));
4085 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, diffval));
4095 i386_jcc(I386_CC_E, a);
4097 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4098 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4099 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4100 codegen_threadcritstart(mcodeptr - mcodebase);
4102 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, baseval), REG_ITMP1);
4103 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, baseval), REG_ITMP3);
4104 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, diffval), REG_ITMP2);
4105 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4106 codegen_threadcritstop(mcodeptr - mcodebase);
4108 i386_alu_reg_reg(I386_SUB, REG_ITMP3, REG_ITMP1);
4109 i386_alu_reg_reg(I386_XOR, d, d);
4111 i386_alu_reg_reg(I386_CMP, REG_ITMP2, REG_ITMP1);
4112 i386_jcc(I386_CC_A, 5);
4113 i386_mov_imm_reg(1, d);
4117 panic ("internal error: no inlined array instanceof");
4119 store_reg_to_var_int(iptr->dst, d);
4122 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4124 /* op1: 0 == array, 1 == class */
4125 /* val.a: (classinfo*) superclass */
4127 /* superclass is an interface:
4129 * OK if ((sub == NULL) ||
4130 * (sub->vftbl->interfacetablelength > super->index) &&
4131 * (sub->vftbl->interfacetable[-super->index] != NULL));
4133 * superclass is a class:
4135 * OK if ((sub == NULL) || (0
4136 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4137 * super->vftbl->diffvall));
4141 classinfo *super = (classinfo*) iptr->val.a;
4143 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4144 codegen_threadcritrestart(mcodeptr - mcodebase);
4146 d = reg_of_var(iptr->dst, REG_ITMP3);
4147 var_to_reg_int(s1, src, d);
4148 if (iptr->op1) { /* class/interface */
4149 if (super->flags & ACC_INTERFACE) { /* interface */
4150 i386_test_reg_reg(s1, s1);
4152 /* TODO: clean up this calculation */
4154 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4157 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
4160 /* CALCOFFSETBYTES(a, super->index); */
4161 CALCIMMEDIATEBYTES(a, super->index);
4167 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*));
4172 i386_jcc(I386_CC_E, a);
4174 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4175 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetablelength), REG_ITMP2);
4176 i386_alu_imm_reg(I386_SUB, super->index, REG_ITMP2);
4178 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4179 i386_jcc(I386_CC_LE, 0);
4180 codegen_addxcastrefs(mcodeptr);
4181 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4183 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4184 i386_jcc(I386_CC_E, 0);
4185 codegen_addxcastrefs(mcodeptr);
4187 } else { /* class */
4188 i386_test_reg_reg(s1, s1);
4190 /* TODO: clean up this calculation */
4192 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4197 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, baseval));
4199 if (d != REG_ITMP3) {
4201 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, baseval));
4204 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, diffval));
4210 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, baseval));
4217 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, diffval));
4224 i386_jcc(I386_CC_E, a);
4226 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4227 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4228 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4229 codegen_threadcritstart(mcodeptr - mcodebase);
4231 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, baseval), REG_ITMP1);
4232 if (d != REG_ITMP3) {
4233 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, baseval), REG_ITMP3);
4234 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, diffval), REG_ITMP2);
4235 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4236 codegen_threadcritstop(mcodeptr - mcodebase);
4238 i386_alu_reg_reg(I386_SUB, REG_ITMP3, REG_ITMP1);
4241 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, baseval), REG_ITMP2);
4242 i386_alu_reg_reg(I386_SUB, REG_ITMP2, REG_ITMP1);
4243 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4244 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, diffval), REG_ITMP2);
4245 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4246 codegen_threadcritstop(mcodeptr - mcodebase);
4250 i386_alu_reg_reg(I386_CMP, REG_ITMP2, REG_ITMP1);
4251 i386_jcc(I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4252 codegen_addxcastrefs(mcodeptr);
4256 panic ("internal error: no inlined array checkcast");
4259 store_reg_to_var_int(iptr->dst, d);
4262 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4264 if (src->flags & INMEMORY) {
4265 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
4268 i386_test_reg_reg(src->regoff, src->regoff);
4270 i386_jcc(I386_CC_L, 0);
4271 codegen_addxcheckarefs(mcodeptr);
4274 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4276 i386_test_reg_reg(REG_RESULT, REG_RESULT);
4277 i386_jcc(I386_CC_E, 0);
4278 codegen_addxexceptionrefs(mcodeptr);
4281 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4282 /* op1 = dimension, val.a = array descriptor */
4284 /* check for negative sizes and copy sizes to stack if necessary */
4286 MCODECHECK((iptr->op1 << 1) + 64);
4288 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4289 if (src->flags & INMEMORY) {
4290 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
4293 i386_test_reg_reg(src->regoff, src->regoff);
4295 i386_jcc(I386_CC_L, 0);
4296 codegen_addxcheckarefs(mcodeptr);
4299 * copy sizes to new stack location, be cause native function
4300 * builtin_nmultianewarray access them as (int *)
4302 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
4303 i386_mov_reg_membase(REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4305 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4307 if (src->varkind != ARGVAR) {
4308 if (src->flags & INMEMORY) {
4309 i386_mov_membase_reg(REG_SP, (src->regoff + intreg_argnum) * 8, REG_ITMP1);
4310 i386_mov_reg_membase(REG_ITMP1, REG_SP, (s1 + intreg_argnum) * 8);
4313 i386_mov_reg_membase(src->regoff, REG_SP, (s1 + intreg_argnum) * 8);
4317 i386_alu_imm_reg(I386_SUB, iptr->op1 * 4, REG_SP);
4319 /* a0 = dimension count */
4321 /* save stack pointer */
4322 M_INTMOVE(REG_SP, REG_ITMP1);
4324 i386_alu_imm_reg(I386_SUB, 12, REG_SP);
4325 i386_mov_imm_membase(iptr->op1, REG_SP, 0);
4327 /* a1 = arraydescriptor */
4329 i386_mov_imm_membase((s4) iptr->val.a, REG_SP, 4);
4331 /* a2 = pointer to dimensions = stack pointer */
4333 i386_mov_reg_membase(REG_ITMP1, REG_SP, 8);
4335 i386_mov_imm_reg((s4) (builtin_nmultianewarray), REG_ITMP1);
4336 i386_call_reg(REG_ITMP1);
4337 i386_alu_imm_reg(I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4339 s1 = reg_of_var(iptr->dst, REG_RESULT);
4340 M_INTMOVE(REG_RESULT, s1);
4341 store_reg_to_var_int(iptr->dst, s1);
4345 error ("Unknown pseudo command: %d", iptr->opc);
4348 } /* for instruction */
4350 /* copy values to interface registers */
4352 src = bptr->outstack;
4353 len = bptr->outdepth;
4357 if ((src->varkind != STACKVAR)) {
4359 if (IS_FLT_DBL_TYPE(s2)) {
4360 var_to_reg_flt(s1, src, REG_FTMP1);
4361 if (!(interfaces[len][s2].flags & INMEMORY)) {
4362 M_FLTMOVE(s1,interfaces[len][s2].regoff);
4365 panic("double store");
4366 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4370 var_to_reg_int(s1, src, REG_ITMP1);
4371 if (!IS_2_WORD_TYPE(interfaces[len][s2].type)) {
4372 if (!(interfaces[len][s2].flags & INMEMORY)) {
4373 M_INTMOVE(s1, interfaces[len][s2].regoff);
4376 i386_mov_reg_membase(s1, REG_SP, interfaces[len][s2].regoff * 8);
4380 if (interfaces[len][s2].flags & INMEMORY) {
4381 M_LNGMEMMOVE(s1, interfaces[len][s2].regoff);
4384 panic("copy interface registers: longs have to be in memory (end)");
4391 } /* if (bptr -> flags >= BBREACHED) */
4392 } /* for basic block */
4394 codegen_createlinenumbertable();
4396 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
4400 /* generate bound check stubs */
4402 u1 *xcodeptr = NULL;
4404 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
4405 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
4406 xboundrefs->branchpos,
4407 (u1*) mcodeptr - mcodebase);
4411 /* move index register into REG_ITMP1 */
4412 i386_mov_reg_reg(xboundrefs->reg, REG_ITMP1); /* 2 bytes */
4414 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4415 dseg_adddata(mcodeptr);
4416 i386_mov_imm_reg(xboundrefs->branchpos - 6, REG_ITMP3); /* 5 bytes */
4417 i386_alu_reg_reg(I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4419 if (xcodeptr != NULL) {
4420 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4423 xcodeptr = mcodeptr;
4425 i386_push_reg(REG_ITMP2_XPC);
4427 PREPARE_NATIVE_STACKINFO
4429 i386_alu_imm_reg(I386_SUB, 2 * 4, REG_SP);
4430 i386_mov_imm_membase((s4) string_java_lang_ArrayIndexOutOfBoundsException, REG_SP, 0 * 4);
4431 i386_mov_reg_membase(REG_ITMP1, REG_SP, 1 * 4);
4432 i386_mov_imm_reg((s4) new_exception_int, REG_ITMP1);
4433 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4434 i386_alu_imm_reg(I386_ADD, 2 * 4, REG_SP);
4436 REMOVE_NATIVE_STACKINFO
4438 i386_pop_reg(REG_ITMP2_XPC);
4440 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4441 i386_jmp_reg(REG_ITMP3);
4445 /* generate negative array size check stubs */
4449 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
4450 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4451 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
4452 xcheckarefs->branchpos,
4453 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4457 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
4458 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
4462 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4463 dseg_adddata(mcodeptr);
4464 i386_mov_imm_reg(xcheckarefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4465 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4467 if (xcodeptr != NULL) {
4468 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4471 xcodeptr = mcodeptr;
4473 i386_push_reg(REG_ITMP2_XPC);
4475 PREPARE_NATIVE_STACKINFO
4477 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4478 i386_mov_imm_membase((s4) string_java_lang_NegativeArraySizeException, REG_SP, 0 * 4);
4479 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4480 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4481 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4484 REMOVE_NATIVE_STACKINFO
4486 i386_pop_reg(REG_ITMP2_XPC);
4488 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4489 i386_jmp_reg(REG_ITMP3);
4493 /* generate cast check stubs */
4497 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
4498 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4499 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
4500 xcastrefs->branchpos,
4501 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4505 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
4506 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
4510 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4511 dseg_adddata(mcodeptr);
4512 i386_mov_imm_reg(xcastrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4513 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4515 if (xcodeptr != NULL) {
4516 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4519 xcodeptr = mcodeptr;
4521 i386_push_reg(REG_ITMP2_XPC);
4524 PREPARE_NATIVE_STACKINFO
4526 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4527 i386_mov_imm_membase((s4) string_java_lang_ClassCastException, REG_SP, 0 * 4);
4528 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4529 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4530 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4533 REMOVE_NATIVE_STACKINFO
4535 i386_pop_reg(REG_ITMP2_XPC);
4537 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4538 i386_jmp_reg(REG_ITMP3);
4542 /* generate divide by zero check stubs */
4546 for (; xdivrefs != NULL; xdivrefs = xdivrefs->next) {
4547 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4548 gen_resolvebranch((u1*) mcodebase + xdivrefs->branchpos,
4549 xdivrefs->branchpos,
4550 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4554 gen_resolvebranch((u1*) mcodebase + xdivrefs->branchpos,
4555 xdivrefs->branchpos, (u1*) mcodeptr - mcodebase);
4559 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4560 dseg_adddata(mcodeptr);
4561 i386_mov_imm_reg(xdivrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4562 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4564 if (xcodeptr != NULL) {
4565 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4568 xcodeptr = mcodeptr;
4570 i386_push_reg(REG_ITMP2_XPC);
4572 PREPARE_NATIVE_STACKINFO
4574 i386_alu_imm_reg(I386_SUB, 2 * 4, REG_SP);
4575 i386_mov_imm_membase((s4) string_java_lang_ArithmeticException, REG_SP, 0 * 4);
4576 i386_mov_imm_membase((s4) string_java_lang_ArithmeticException_message, REG_SP, 1 * 4);
4577 i386_mov_imm_reg((s4) new_exception_message, REG_ITMP1);
4578 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4579 i386_alu_imm_reg(I386_ADD, 2 * 4, REG_SP);
4581 REMOVE_NATIVE_STACKINFO
4583 i386_pop_reg(REG_ITMP2_XPC);
4585 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4586 i386_jmp_reg(REG_ITMP3);
4590 /* generate exception check stubs */
4594 for (; xexceptionrefs != NULL; xexceptionrefs = xexceptionrefs->next) {
4595 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4596 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
4597 xexceptionrefs->branchpos,
4598 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4602 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
4603 xexceptionrefs->branchpos, (u1*) mcodeptr - mcodebase);
4607 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4608 dseg_adddata(mcodeptr);
4609 i386_mov_imm_reg(xexceptionrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4610 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4612 if (xcodeptr != NULL) {
4613 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4616 xcodeptr = mcodeptr;
4618 i386_push_reg(REG_ITMP2_XPC);
4620 PREPARE_NATIVE_STACKINFO
4622 i386_mov_imm_reg((s4) codegen_general_stubcalled,REG_ITMP1);
4623 i386_call_reg(REG_ITMP1);
4626 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4627 i386_mov_imm_reg((s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4628 i386_call_reg(REG_ITMP1);
4629 i386_mov_membase_reg(REG_RESULT, 0, REG_ITMP3);
4630 i386_mov_imm_membase(0, REG_RESULT, 0);
4631 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1_XPTR);
4633 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP3);
4634 i386_mov_membase_reg(REG_ITMP3, 0, REG_ITMP1_XPTR);
4635 i386_mov_imm_membase(0, REG_ITMP3, 0);
4638 i386_push_reg(REG_ITMP1_XPTR);
4640 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4641 java stack at this point*/
4642 i386_mov_membase_reg(REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4643 i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl,class), REG_ITMP1);
4644 i386_push_imm(utf_fillInStackTrace_desc);
4645 i386_push_imm(utf_fillInStackTrace_name);
4646 i386_push_reg(REG_ITMP1);
4647 i386_mov_imm_reg((s4) class_resolvemethod, REG_ITMP3);
4648 i386_call_reg(REG_ITMP3);
4649 /*cleanup parameters of class_resolvemethod*/
4650 i386_alu_imm_reg(I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4651 /*prepare call to asm_calljavafunction2 */
4653 i386_push_imm(TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4654 i386_push_reg(REG_SP);
4655 i386_push_imm(sizeof(jni_callblock));
4657 i386_push_reg(REG_RESULT);
4659 i386_mov_imm_reg((s4) asm_calljavafunction2, REG_ITMP3);
4660 i386_call_reg(REG_ITMP3);
4662 /* check exceptionptr + fail (JOWENN)*/
4664 i386_alu_imm_reg(I386_ADD,6*4,REG_SP);
4666 i386_pop_reg(REG_ITMP1_XPTR);
4667 i386_pop_reg(REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4668 REMOVE_NATIVE_STACKINFO
4670 i386_pop_reg(REG_ITMP2_XPC);
4672 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4673 i386_jmp_reg(REG_ITMP3);
4677 /* generate null pointer check stubs */
4681 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
4682 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4683 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
4684 xnullrefs->branchpos,
4685 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4689 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
4690 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
4694 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4695 dseg_adddata(mcodeptr);
4696 i386_mov_imm_reg(xnullrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4697 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4699 if (xcodeptr != NULL) {
4700 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4703 xcodeptr = mcodeptr;
4705 i386_push_reg(REG_ITMP2_XPC);
4709 PREPARE_NATIVE_STACKINFO
4711 /* create native call block*/
4712 i386_alu_imm_reg(I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4715 i386_mov_imm_reg((s4) codegen_stubcalled,REG_ITMP1);
4716 i386_call_reg(REG_ITMP1); /*call codegen_stubcalled*/
4718 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4719 i386_call_reg(REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4720 i386_mov_imm_membase(0,REG_SP, 2*4); /* builtin */
4721 i386_mov_reg_membase(REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4722 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4723 i386_mov_reg_membase(REG_ITMP2,REG_SP,0*4); /* store value on stack */
4724 i386_mov_reg_membase(REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4730 /* create exception*/
4731 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4732 i386_mov_imm_membase((s4) string_java_lang_NullPointerException, REG_SP, 0 * 4);
4733 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4734 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4735 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4738 REMOVE_NATIVE_STACKINFO
4740 /* restore native call stack */
4741 i386_mov_membase_reg(REG_SP,0,REG_ITMP2);
4742 i386_mov_membase_reg(REG_SP,4,REG_ITMP3);
4743 i386_mov_reg_membase(REG_ITMP2,REG_ITMP3,0);
4744 i386_alu_imm_reg(I386_ADD,3*4,REG_SP);
4748 i386_pop_reg(REG_ITMP2_XPC);
4750 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4751 i386_jmp_reg(REG_ITMP3);
4756 codegen_finish((u4) ((u1 *) mcodeptr - mcodebase));
4760 /* function createcompilerstub *************************************************
4762 creates a stub routine which calls the compiler
4764 *******************************************************************************/
4766 #define COMPSTUBSIZE 12
4768 u1 *createcompilerstub(methodinfo *m)
4770 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4771 mcodeptr = s; /* code generation pointer */
4773 /* code for the stub */
4774 i386_mov_imm_reg((u4) m, REG_ITMP1);/* pass method pointer to compiler */
4776 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4777 i386_mov_imm_reg((u4) asm_call_jit_compiler, REG_ITMP3); /* load address */
4778 i386_jmp_reg(REG_ITMP3); /* jump to compiler */
4780 #if defined(STATISTICS)
4782 count_cstub_len += COMPSTUBSIZE;
4789 /* function removecompilerstub *************************************************
4791 deletes a compilerstub from memory (simply by freeing it)
4793 *******************************************************************************/
4795 void removecompilerstub(u1 *stub)
4797 CFREE(stub, COMPSTUBSIZE);
4801 /* function: createnativestub **************************************************
4803 creates a stub routine which calls a native method
4805 *******************************************************************************/
4807 #define NATIVESTUBSIZE 350
4809 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4810 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4813 void i386_native_stub_debug(void **p) {
4814 printf("Pos on stack: %p\n",p);
4815 printf("Return adress should be: %p\n",*p);
4818 void i386_native_stub_debug2(void **p) {
4819 printf("Pos on stack: %p\n",p);
4820 printf("Return for lookup is: %p\n",*p);
4823 void traverseStackInfo() {
4824 void **p=builtin_asm_get_stackframeinfo();
4828 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4829 m=*((methodinfo**)((*p)+8));
4830 utf_display(m->name);
4838 u1 *createnativestub(functionptr f, methodinfo *m)
4840 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4844 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4845 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4846 int stackframeoffset = 4;
4850 mcodeptr = s; /* make macros work */
4852 if (m->flags & ACC_STATIC) {
4853 stackframesize += 4;
4854 stackframeoffset += 4;
4858 descriptor2types(m); /* set paramcount and paramtypes */
4861 /* i386_push_reg(REG_SP);
4862 i386_mov_imm_reg((s4) i386_native_stub_debug, REG_ITMP1);
4863 i386_call_reg(REG_ITMP1);
4864 i386_pop_reg(REG_ITMP1);*/
4867 /* if function is static, check for initialized */
4869 if (m->flags & ACC_STATIC) {
4870 /* if class isn't yet initialized, do it */
4871 if (!m->class->initialized) {
4873 *header = 0;/*extablesize*/
4875 *header = 0;/*line number table start*/
4877 *header = 0;/*line number table size*/
4879 *header = 0;/*fltsave*/
4881 *header = 0;/*intsave*/
4883 *header = 0;/*isleaf*/
4885 *header = 0;/*issync*/
4887 *header = 0;/*framesize*/
4889 *header = m;/*methodpointer*/
4893 /* call helper function which patches this code */
4894 i386_mov_imm_reg((s4) m->class, REG_ITMP1);
4895 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
4896 i386_call_reg(REG_ITMP2);
4901 i386_alu_imm_reg(I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4903 for (p = 0; p < m->paramcount; p++) {
4904 t = m->paramtypes[p];
4905 if (IS_INT_LNG_TYPE(t)) {
4906 if (IS_2_WORD_TYPE(t)) {
4907 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4908 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4909 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4910 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4912 } else if (t == TYPE_ADR) {
4913 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4914 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
4915 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4916 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4919 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4921 i386_mov_reg_membase(EAX, REG_SP, p * 8);
4922 i386_mov_reg_membase(EDX, REG_SP, p * 8 + 4);
4926 if (!IS_2_WORD_TYPE(t)) {
4927 i386_flds_membase(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4928 i386_fstps_membase(REG_SP, p * 8);
4929 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
4930 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4933 i386_fldl_membase(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4934 i386_fstpl_membase(REG_SP, p * 8);
4939 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
4940 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
4941 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4942 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
4945 i386_mov_imm_membase((s4) m, REG_SP, TRACE_ARGS_NUM * 8);
4947 i386_mov_imm_reg((s4) builtin_trace_args, REG_ITMP1);
4948 i386_call_reg(REG_ITMP1);
4950 i386_alu_imm_reg(I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4954 * mark the whole fpu stack as free for native functions
4955 * (only for saved register count == 0)
4966 /* calculate stackframe size for native function */
4967 tptr = m->paramtypes;
4968 for (i = 0; i < m->paramcount; i++) {
4973 stackframesize += 4;
4978 stackframesize += 8;
4982 panic("unknown parameter type in native function");
4986 i386_alu_imm_reg(I386_SUB, stackframesize, REG_SP);
4988 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
4989 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-4);
4990 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
4991 i386_call_reg(REG_ITMP1);
4992 i386_mov_reg_membase(REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
4993 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2);
4994 i386_mov_reg_membase(REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
4995 i386_mov_reg_reg(REG_SP,REG_ITMP2);
4996 i386_alu_imm_reg(I386_ADD,stackframesize-12,REG_ITMP2);
4997 i386_mov_reg_membase(REG_ITMP2,REG_RESULT,0);
5000 /* i386_mov_imm_membase((s4) m, REG_SP,stackframesize-4);
5001 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-8);
5002 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-12);*/
5004 /* CREATE DYNAMIC STACK INFO -- END*/
5007 tptr = m->paramtypes;
5008 for (i = 0; i < m->paramcount; i++) {
5013 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5014 i386_mov_reg_membase(REG_ITMP1, REG_SP, stackframeoffset);
5015 stackframeoffset += 4;
5020 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5021 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5022 i386_mov_reg_membase(REG_ITMP1, REG_SP, stackframeoffset);
5023 i386_mov_reg_membase(REG_ITMP2, REG_SP, stackframeoffset + 4);
5024 stackframeoffset += 8;
5028 panic("unknown parameter type in native function");
5032 if (m->flags & ACC_STATIC) {
5033 /* put class into second argument */
5034 i386_mov_imm_membase((s4) m->class, REG_SP, 4);
5037 /* put env into first argument */
5038 i386_mov_imm_membase((s4) &env, REG_SP, 0);
5040 i386_mov_imm_reg((s4) f, REG_ITMP1);
5041 i386_call_reg(REG_ITMP1);
5042 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5043 i386_push_reg(REG_RESULT2);
5044 i386_mov_membase_reg(REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5045 i386_mov_membase_reg(REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5046 i386_mov_reg_membase(REG_ITMP2,REG_RESULT2,0);
5047 i386_pop_reg(REG_RESULT2);
5048 /*REMOVE DYNAMIC STACK INFO -END */
5050 i386_alu_imm_reg(I386_ADD, stackframesize, REG_SP);
5054 i386_alu_imm_reg(I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5056 i386_mov_imm_membase((s4) m, REG_SP, 0);
5058 i386_mov_reg_membase(REG_RESULT, REG_SP, 4);
5059 i386_mov_reg_membase(REG_RESULT2, REG_SP, 4 + 4);
5061 i386_fstl_membase(REG_SP, 4 + 8);
5062 i386_fsts_membase(REG_SP, 4 + 8 + 8);
5064 i386_mov_imm_reg((s4) builtin_displaymethodstop, REG_ITMP1);
5065 i386_call_reg(REG_ITMP1);
5067 i386_mov_membase_reg(REG_SP, 4, REG_RESULT);
5068 i386_mov_membase_reg(REG_SP, 4 + 4, REG_RESULT2);
5070 i386_alu_imm_reg(I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5074 /* we can't use REG_ITMP3 == REG_RESULT2 */
5075 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5076 i386_push_reg(REG_RESULT);
5077 i386_push_reg(REG_RESULT2);
5078 i386_call_mem((s4) &callgetexceptionptrptr);
5079 i386_mov_membase_reg(REG_RESULT, 0, REG_ITMP2);
5080 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
5081 i386_pop_reg(REG_RESULT2);
5082 i386_pop_reg(REG_RESULT);
5084 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP2);
5085 i386_mov_membase_reg(REG_ITMP2, 0, REG_ITMP2);
5086 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
5088 i386_jcc(I386_CC_NE, 1);
5092 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5093 i386_push_reg(REG_ITMP2);
5094 i386_call_mem((s4) &callgetexceptionptrptr);
5095 i386_mov_imm_membase(0, REG_RESULT, 0);
5096 i386_pop_reg(REG_ITMP1_XPTR);
5098 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1_XPTR);
5099 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP2);
5100 i386_mov_imm_membase(0, REG_ITMP2, 0);
5102 i386_mov_membase_reg(REG_SP, 0, REG_ITMP2_XPC);
5103 i386_alu_imm_reg(I386_SUB, 2, REG_ITMP2_XPC);
5105 i386_mov_imm_reg((s4) asm_handle_nat_exception, REG_ITMP3);
5106 i386_jmp_reg(REG_ITMP3);
5109 codegen_insertNative(s,mcodeptr);
5113 dolog_plain("native stubentry: %p, stubsize: %x (for %d params) --", (s4)s,(s4) (mcodeptr - s), m->paramcount);
5114 utf_display(m->name);
5118 #if defined(STATISTICS)
5120 count_nstub_len += NATIVESTUBSIZE;
5127 /* function: removenativestub **************************************************
5129 removes a previously created native-stub from memory
5131 *******************************************************************************/
5133 void removenativestub(u1 *stub)
5135 CFREE(stub, NATIVESTUBSIZE);
5140 * These are local overrides for various environment variables in Emacs.
5141 * Please do not remove this and leave it at the end of the file, where
5142 * Emacs will automagically detect them.
5143 * ---------------------------------------------------------------------
5146 * indent-tabs-mode: t