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 1132 2004-06-05 16:29:07Z twisti $
48 #include "jit/parse.h"
50 #include "jit/i386/codegen.h"
51 #include "jit/i386/emitfuncs.h"
52 #include "jit/i386/offsets.h"
54 /* include independent code generation stuff */
55 #include "jit/codegen.inc"
56 #include "jit/reg.inc"
59 /* register descripton - array ************************************************/
61 /* #define REG_RES 0 reserved register for OS or code generator */
62 /* #define REG_RET 1 return value register */
63 /* #define REG_EXC 2 exception value register (only old jit) */
64 /* #define REG_SAV 3 (callee) saved register */
65 /* #define REG_TMP 4 scratch temporary register (caller saved) */
66 /* #define REG_ARG 5 argument register (caller saved) */
68 /* #define REG_END -1 last entry in tables */
71 we initially try to use %edx as scratch register, it cannot be used if we
72 have one of these ICMDs:
73 LMUL, LMULCONST, IDIV, IREM, LALOAD, AASTORE, LASTORE, IASTORE, CASTORE,
74 SASTORE, BASTORE, INSTANCEOF, CHECKCAST, I2L, F2L, D2L
77 REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
82 int nregdescfloat[] = {
83 /* rounding problems with callee saved registers */
84 /* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
85 /* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
86 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
92 This function determines a register, to which the result of an operation
93 should go, when it is ultimatively intended to store the result in
95 If v is assigned to an actual register, this register will be returned.
96 Otherwise (when v is spilled) this function returns tempregnum.
97 If not already done, regoff and flags are set in the stack location.
100 static int reg_of_var(stackptr v, int tempregnum)
104 switch (v->varkind) {
106 if (!(v->flags & INMEMORY))
110 var = &(interfaces[v->varnum][v->type]);
111 v->regoff = var->regoff;
112 if (!(var->flags & INMEMORY))
116 var = &(locals[v->varnum][v->type]);
117 v->regoff = var->regoff;
118 if (!(var->flags & INMEMORY))
122 v->regoff = v->varnum;
123 if (IS_FLT_DBL_TYPE(v->type)) {
124 if (v->varnum < fltreg_argnum) {
125 v->regoff = argfltregs[v->varnum];
126 return(argfltregs[v->varnum]);
130 if (v->varnum < intreg_argnum) {
131 v->regoff = argintregs[v->varnum];
132 return(argintregs[v->varnum]);
134 v->regoff -= intreg_argnum;
137 v->flags |= INMEMORY;
142 void codegen_stubcalled() {
143 log_text("Stub has been called");
146 void codegen_general_stubcalled() {
147 log_text("general exception stub has been called");
151 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
152 void thread_restartcriticalsection(ucontext_t *uc)
155 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
156 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
161 #define PREPARE_NATIVE_STACKINFO \
162 i386_push_reg(REG_ITMP1); /*save itmp1, needed by some stubs */ \
163 i386_alu_imm_reg(I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
164 i386_mov_imm_reg((s4) codegen_stubcalled,REG_ITMP1); \
165 i386_call_reg(REG_ITMP1); /*call codegen_stubcalled*/ \
166 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
167 i386_call_reg(REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
168 i386_mov_reg_membase(REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
169 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
170 i386_mov_reg_membase(REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
171 i386_mov_reg_membase(REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
172 i386_mov_membase_reg(REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
173 i386_mov_imm_membase(0,REG_SP, 2*4); /* builtin */
176 #define REMOVE_NATIVE_STACKINFO \
177 i386_mov_membase_reg(REG_SP,0,REG_ITMP2); \
178 i386_mov_membase_reg(REG_SP,4,REG_ITMP3); \
179 i386_mov_reg_membase(REG_ITMP2,REG_ITMP3,0); \
180 i386_alu_imm_reg(I386_ADD,3*4,REG_SP);
184 /* NullPointerException signal handler for hardware null pointer check */
186 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
189 /* long faultaddr; */
191 struct ucontext *_uc = (struct ucontext *) _p;
192 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
193 struct sigaction act;
195 /* Reset signal handler - necessary for SysV, does no harm for BSD */
197 /* instr = *((int*)(sigctx->eip)); */
198 /* faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
200 /* fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
202 /* if (faultaddr == 0) { */
203 /* signal(sig, (void *) catch_NullPointerException); */
204 act.sa_sigaction = (void *) catch_NullPointerException;
205 act.sa_flags = SA_SIGINFO;
206 sigaction(sig, &act, NULL); /* reinstall handler */
209 sigaddset(&nsig, sig);
210 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
212 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
213 sigctx->eax = (u4) string_java_lang_NullPointerException;
214 sigctx->eip = (u4) asm_throw_and_handle_exception;
219 /* faultaddr += (long) ((instr << 16) >> 16); */
220 /* fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
221 /* panic("Stack overflow"); */
226 /* ArithmeticException signal handler for hardware divide by zero check */
228 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
232 /* void **_p = (void **) &sig; */
233 /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
234 struct ucontext *_uc = (struct ucontext *) _p;
235 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
236 struct sigaction act;
238 /* Reset signal handler - necessary for SysV, does no harm for BSD */
240 /* signal(sig, (void *) catch_ArithmeticException); */
241 act.sa_sigaction = (void *) catch_ArithmeticException;
242 act.sa_flags = SA_SIGINFO;
243 sigaction(sig, &act, NULL); /* reinstall handler */
246 sigaddset(&nsig, sig);
247 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
249 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
250 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
256 void init_exceptions(void)
258 struct sigaction act;
260 /* install signal handlers we need to convert to exceptions */
264 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
265 act.sa_sigaction = (void *) catch_NullPointerException;
266 act.sa_flags = SA_SIGINFO;
267 sigaction(SIGSEGV, &act, NULL);
271 /* signal(SIGBUS, (void *) catch_NullPointerException); */
272 act.sa_sigaction = (void *) catch_NullPointerException;
273 act.sa_flags = SA_SIGINFO;
274 sigaction(SIGBUS, &act, NULL);
278 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
279 act.sa_sigaction = (void *) catch_ArithmeticException;
280 act.sa_flags = SA_SIGINFO;
281 sigaction(SIGFPE, &act, NULL);
285 /* function codegen ************************************************************
287 generates machine code
289 *******************************************************************************/
291 /* global code generation pointer */
296 int len, s1, s2, s3, d;
303 int fpu_st_offset = 0;
312 /* space to save used callee saved registers */
314 savedregs_num += (savintregcnt - maxsavintreguse);
315 savedregs_num += (savfltregcnt - maxsavfltreguse);
317 parentargs_base = maxmemuse + savedregs_num;
319 #ifdef USE_THREADS /* space to save argument of monitor_enter */
321 if (checksync && (method->flags & ACC_SYNCHRONIZED))
326 /* create method header */
328 (void) dseg_addaddress(method); /* MethodPointer */
329 (void) dseg_adds4(parentargs_base * 8); /* FrameSize */
333 /* IsSync contains the offset relative to the stack pointer for the
334 argument of monitor_exit used in the exception handler. Since the
335 offset could be zero and give a wrong meaning of the flag it is
339 if (checksync && (method->flags & ACC_SYNCHRONIZED))
340 (void) dseg_adds4((maxmemuse + 1) * 8); /* IsSync */
345 (void) dseg_adds4(0); /* IsSync */
347 (void) dseg_adds4(isleafmethod); /* IsLeaf */
348 (void) dseg_adds4(savintregcnt - maxsavintreguse); /* IntSave */
349 (void) dseg_adds4(savfltregcnt - maxsavfltreguse); /* FltSave */
350 (void) dseg_addlinenumbertablesize(); /* adds a reference for the length of the line number counter
351 We don't know the size yet, since we evaluate the information
352 during code generation, to save one additional iteration over
353 the whole instructions. During code optimization the position
354 could have changed to the information gotten from the class file*/
355 (void) dseg_adds4(exceptiontablelength); /* ExTableSize */
357 /* create exception table */
359 for (ex = extable; ex != NULL; ex = ex->down) {
360 dseg_addtarget(ex->start);
361 dseg_addtarget(ex->end);
362 dseg_addtarget(ex->handler);
363 (void) dseg_addaddress(ex->catchtype);
367 /* initialize mcode variables */
369 mcodeptr = (u1*) mcodebase;
370 mcodeend = (s4*) (mcodebase + mcodesize);
371 MCODECHECK(128 + mparamcount);
373 /* create stack frame (if necessary) */
375 if (parentargs_base) {
376 i386_alu_imm_reg(I386_SUB, parentargs_base * 8, REG_SP);
379 /* save return address and used callee saved registers */
382 for (r = savintregcnt - 1; r >= maxsavintreguse; r--) {
383 p--; i386_mov_reg_membase(savintregs[r], REG_SP, p * 8);
385 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--) {
386 p--; i386_fld_reg(savfltregs[r]); i386_fstpl_membase(REG_SP, p * 8);
389 /* save monitorenter argument */
392 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
393 if (method->flags & ACC_STATIC) {
394 i386_mov_imm_reg((s4) class, REG_ITMP1);
395 i386_mov_reg_membase(REG_ITMP1, REG_SP, maxmemuse * 8);
398 i386_mov_membase_reg(REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
399 i386_mov_reg_membase(REG_ITMP1, REG_SP, maxmemuse * 8);
404 /* copy argument registers to stack and call trace function with pointer
405 to arguments on stack.
409 i386_alu_imm_reg(I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
411 for (p = 0; p < mparamcount && p < TRACE_ARGS_NUM; p++) {
414 if (IS_INT_LNG_TYPE(t)) {
415 if (IS_2_WORD_TYPE(t)) {
416 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
417 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
418 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
419 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
421 /* } else if (t == TYPE_ADR) { */
423 i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
424 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
425 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
426 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
429 /* i386_mov_membase_reg(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
431 /* i386_mov_reg_membase(EAX, REG_SP, p * 8); */
432 /* i386_mov_reg_membase(EDX, REG_SP, p * 8 + 4); */
436 if (!IS_2_WORD_TYPE(t)) {
437 i386_flds_membase(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
438 i386_fstps_membase(REG_SP, p * 8);
439 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
440 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
443 i386_fldl_membase(REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
444 i386_fstpl_membase(REG_SP, p * 8);
449 /* fill up the remaining arguments */
450 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
451 for (p = mparamcount; p < TRACE_ARGS_NUM; p++) {
452 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
453 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
456 i386_mov_imm_membase((s4) method, REG_SP, TRACE_ARGS_NUM * 8);
457 i386_mov_imm_reg((s4) builtin_trace_args, REG_ITMP1);
458 i386_call_reg(REG_ITMP1);
460 i386_alu_imm_reg(I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
463 /* take arguments out of register or stack frame */
465 for (p = 0, l = 0; p < mparamcount; p++) {
467 var = &(locals[l][t]);
469 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
474 if (IS_INT_LNG_TYPE(t)) { /* integer args */
475 if (p < intreg_argnum) { /* register arguments */
476 panic("integer register argument");
477 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
478 /* M_INTMOVE (argintregs[p], r); */
480 } else { /* reg arg -> spilled */
481 /* M_LST (argintregs[p], REG_SP, 8 * r); */
483 } else { /* stack arguments */
484 pa = p - intreg_argnum;
485 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
486 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, r); /* + 4 for return address */
487 } else { /* stack arg -> spilled */
488 if (!IS_2_WORD_TYPE(t)) {
489 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
490 i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8);
493 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
494 i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8);
495 i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
496 i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8 + 4);
501 } else { /* floating args */
502 if (p < fltreg_argnum) { /* register arguments */
503 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
504 panic("There are no float argument registers!");
506 } else { /* reg arg -> spilled */
507 panic("There are no float argument registers!");
510 } else { /* stack arguments */
511 pa = p - fltreg_argnum;
512 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
514 i386_flds_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
516 i386_fstp_reg(r + fpu_st_offset);
520 i386_fldl_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
522 i386_fstp_reg(r + fpu_st_offset);
526 } else { /* stack-arg -> spilled */
527 /* i386_mov_membase_reg(REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
528 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, r * 8); */
530 i386_flds_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
531 i386_fstps_membase(REG_SP, r * 8);
534 i386_fldl_membase(REG_SP, (parentargs_base + pa) * 8 + 4);
535 i386_fstpl_membase(REG_SP, r * 8);
542 /* call monitorenter function */
545 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
546 i386_mov_membase_reg(REG_SP, maxmemuse * 8, REG_ITMP1);
547 i386_alu_imm_reg(I386_SUB, 4, REG_SP);
548 i386_mov_reg_membase(REG_ITMP1, REG_SP, 0);
549 i386_mov_imm_reg((s4) builtin_monitorenter, REG_ITMP1);
550 i386_call_reg(REG_ITMP1);
551 i386_alu_imm_reg(I386_ADD, 4, REG_SP);
556 /* end of header generation */
558 /* walk through all basic blocks */
559 for (bptr = block; bptr != NULL; bptr = bptr->next) {
561 bptr->mpc = (int)((u1*) mcodeptr - mcodebase);
563 if (bptr->flags >= BBREACHED) {
565 /* branch resolving */
568 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
569 gen_resolvebranch((u1*) mcodebase + brefs->branchpos,
570 brefs->branchpos, bptr->mpc);
573 /* copy interface registers to their destination */
578 while (src != NULL) {
580 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
581 if (!IS_2_WORD_TYPE(src->type)) {
582 if (bptr->type == BBTYPE_SBR) {
583 d = reg_of_var(src, REG_ITMP1);
585 store_reg_to_var_int(src, d);
587 } else if (bptr->type == BBTYPE_EXH) {
588 d = reg_of_var(src, REG_ITMP1);
589 M_INTMOVE(REG_ITMP1, d);
590 store_reg_to_var_int(src, d);
594 panic("copy interface registers: longs have to me in memory (begin 1)");
598 d = reg_of_var(src, REG_ITMP1);
599 if ((src->varkind != STACKVAR)) {
601 if (IS_FLT_DBL_TYPE(s2)) {
602 s1 = interfaces[len][s2].regoff;
603 if (!(interfaces[len][s2].flags & INMEMORY)) {
607 if (s2 == TYPE_FLT) {
608 i386_flds_membase(REG_SP, s1 * 8);
611 i386_fldl_membase(REG_SP, s1 * 8);
614 store_reg_to_var_flt(src, d);
617 s1 = interfaces[len][s2].regoff;
618 if (!IS_2_WORD_TYPE(interfaces[len][s2].type)) {
619 if (!(interfaces[len][s2].flags & INMEMORY)) {
623 i386_mov_membase_reg(REG_SP, s1 * 8, d);
625 store_reg_to_var_int(src, d);
628 if (interfaces[len][s2].flags & INMEMORY) {
629 M_LNGMEMMOVE(s1, src->regoff);
632 panic("copy interface registers: longs have to be in memory (begin 2)");
641 /* walk through all instructions */
645 for (iptr = bptr->iinstr;
647 src = iptr->dst, len--, iptr++) {
649 if (iptr->line!=currentline) {
650 dseg_addlinenumber(iptr->line,mcodeptr);
651 currentline=iptr->line;
653 MCODECHECK(64); /* an instruction usually needs < 64 words */
656 case ICMD_NOP: /* ... ==> ... */
659 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
660 if (src->flags & INMEMORY) {
661 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
664 i386_test_reg_reg(src->regoff, src->regoff);
666 i386_jcc(I386_CC_E, 0);
667 codegen_addxnullrefs(mcodeptr);
670 /* constant operations ************************************************/
672 case ICMD_ICONST: /* ... ==> ..., constant */
673 /* op1 = 0, val.i = constant */
675 d = reg_of_var(iptr->dst, REG_ITMP1);
676 if (iptr->dst->flags & INMEMORY) {
677 i386_mov_imm_membase(iptr->val.i, REG_SP, iptr->dst->regoff * 8);
680 if (iptr->val.i == 0) {
681 i386_alu_reg_reg(I386_XOR, d, d);
684 i386_mov_imm_reg(iptr->val.i, d);
689 case ICMD_LCONST: /* ... ==> ..., constant */
690 /* op1 = 0, val.l = constant */
692 d = reg_of_var(iptr->dst, REG_ITMP1);
693 if (iptr->dst->flags & INMEMORY) {
694 i386_mov_imm_membase(iptr->val.l, REG_SP, iptr->dst->regoff * 8);
695 i386_mov_imm_membase(iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
698 panic("LCONST: longs have to be in memory");
702 case ICMD_FCONST: /* ... ==> ..., constant */
703 /* op1 = 0, val.f = constant */
705 d = reg_of_var(iptr->dst, REG_FTMP1);
706 if (iptr->val.f == 0.0) {
711 if (iptr->val.i == 0x80000000) {
715 } else if (iptr->val.f == 1.0) {
719 } else if (iptr->val.f == 2.0) {
726 a = dseg_addfloat(iptr->val.f);
727 i386_mov_imm_reg(0, REG_ITMP1);
728 dseg_adddata(mcodeptr);
729 i386_flds_membase(REG_ITMP1, a);
732 store_reg_to_var_flt(iptr->dst, d);
735 case ICMD_DCONST: /* ... ==> ..., constant */
736 /* op1 = 0, val.d = constant */
738 d = reg_of_var(iptr->dst, REG_FTMP1);
739 if (iptr->val.d == 0.0) {
744 if (iptr->val.l == 0x8000000000000000LL) {
748 } else if (iptr->val.d == 1.0) {
752 } else if (iptr->val.d == 2.0) {
759 a = dseg_adddouble(iptr->val.d);
760 i386_mov_imm_reg(0, REG_ITMP1);
761 dseg_adddata(mcodeptr);
762 i386_fldl_membase(REG_ITMP1, a);
765 store_reg_to_var_flt(iptr->dst, d);
768 case ICMD_ACONST: /* ... ==> ..., constant */
769 /* op1 = 0, val.a = constant */
771 d = reg_of_var(iptr->dst, REG_ITMP1);
772 if (iptr->dst->flags & INMEMORY) {
773 i386_mov_imm_membase((s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
776 if ((s4) iptr->val.a == 0) {
777 i386_alu_reg_reg(I386_XOR, d, d);
780 i386_mov_imm_reg((s4) iptr->val.a, d);
786 /* load/store operations **********************************************/
788 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
789 case ICMD_ALOAD: /* op1 = local variable */
791 d = reg_of_var(iptr->dst, REG_ITMP1);
792 if ((iptr->dst->varkind == LOCALVAR) &&
793 (iptr->dst->varnum == iptr->op1)) {
796 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
797 if (iptr->dst->flags & INMEMORY) {
798 if (var->flags & INMEMORY) {
799 i386_mov_membase_reg(REG_SP, var->regoff * 8, REG_ITMP1);
800 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
803 i386_mov_reg_membase(var->regoff, REG_SP, iptr->dst->regoff * 8);
807 if (var->flags & INMEMORY) {
808 i386_mov_membase_reg(REG_SP, var->regoff * 8, iptr->dst->regoff);
811 M_INTMOVE(var->regoff, iptr->dst->regoff);
816 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
817 /* op1 = local variable */
819 d = reg_of_var(iptr->dst, REG_ITMP1);
820 if ((iptr->dst->varkind == LOCALVAR) &&
821 (iptr->dst->varnum == iptr->op1)) {
824 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
825 if (iptr->dst->flags & INMEMORY) {
826 if (var->flags & INMEMORY) {
827 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
830 panic("LLOAD: longs have to be in memory");
834 panic("LLOAD: longs have to be in memory");
838 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
839 /* op1 = local variable */
841 d = reg_of_var(iptr->dst, REG_FTMP1);
842 if ((iptr->dst->varkind == LOCALVAR) &&
843 (iptr->dst->varnum == iptr->op1)) {
846 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
847 if (var->flags & INMEMORY) {
848 i386_flds_membase(REG_SP, var->regoff * 8);
851 i386_fld_reg(var->regoff + fpu_st_offset);
854 store_reg_to_var_flt(iptr->dst, d);
857 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
858 /* op1 = local variable */
860 d = reg_of_var(iptr->dst, REG_FTMP1);
861 if ((iptr->dst->varkind == LOCALVAR) &&
862 (iptr->dst->varnum == iptr->op1)) {
865 var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
866 if (var->flags & INMEMORY) {
867 i386_fldl_membase(REG_SP, var->regoff * 8);
870 i386_fld_reg(var->regoff + fpu_st_offset);
873 store_reg_to_var_flt(iptr->dst, d);
876 case ICMD_ISTORE: /* ..., value ==> ... */
877 case ICMD_ASTORE: /* op1 = local variable */
879 if ((src->varkind == LOCALVAR) &&
880 (src->varnum == iptr->op1)) {
883 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
884 if (var->flags & INMEMORY) {
885 if (src->flags & INMEMORY) {
886 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
887 i386_mov_reg_membase(REG_ITMP1, REG_SP, var->regoff * 8);
890 i386_mov_reg_membase(src->regoff, REG_SP, var->regoff * 8);
894 var_to_reg_int(s1, src, var->regoff);
895 M_INTMOVE(s1, var->regoff);
899 case ICMD_LSTORE: /* ..., value ==> ... */
900 /* op1 = local variable */
902 if ((src->varkind == LOCALVAR) &&
903 (src->varnum == iptr->op1)) {
906 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
907 if (var->flags & INMEMORY) {
908 if (src->flags & INMEMORY) {
909 M_LNGMEMMOVE(src->regoff, var->regoff);
912 panic("LSTORE: longs have to be in memory");
916 panic("LSTORE: longs have to be in memory");
920 case ICMD_FSTORE: /* ..., value ==> ... */
921 /* op1 = local variable */
923 if ((src->varkind == LOCALVAR) &&
924 (src->varnum == iptr->op1)) {
927 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
928 if (var->flags & INMEMORY) {
929 var_to_reg_flt(s1, src, REG_FTMP1);
930 i386_fstps_membase(REG_SP, var->regoff * 8);
933 var_to_reg_flt(s1, src, var->regoff);
934 /* M_FLTMOVE(s1, var->regoff); */
935 i386_fstp_reg(var->regoff + fpu_st_offset);
940 case ICMD_DSTORE: /* ..., value ==> ... */
941 /* op1 = local variable */
943 if ((src->varkind == LOCALVAR) &&
944 (src->varnum == iptr->op1)) {
947 var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
948 if (var->flags & INMEMORY) {
949 var_to_reg_flt(s1, src, REG_FTMP1);
950 i386_fstpl_membase(REG_SP, var->regoff * 8);
953 var_to_reg_flt(s1, src, var->regoff);
954 /* M_FLTMOVE(s1, var->regoff); */
955 i386_fstp_reg(var->regoff + fpu_st_offset);
961 /* pop/dup/swap operations ********************************************/
963 /* attention: double and longs are only one entry in CACAO ICMDs */
965 case ICMD_POP: /* ..., value ==> ... */
966 case ICMD_POP2: /* ..., value, value ==> ... */
969 #define M_COPY(from,to) \
970 d = reg_of_var(to, REG_ITMP1); \
971 if ((from->regoff != to->regoff) || \
972 ((from->flags ^ to->flags) & INMEMORY)) { \
973 if (IS_FLT_DBL_TYPE(from->type)) { \
974 var_to_reg_flt(s1, from, d); \
975 /* M_FLTMOVE(s1, d);*/ \
976 store_reg_to_var_flt(to, d); \
978 if (!IS_2_WORD_TYPE(from->type)) { \
979 if (to->flags & INMEMORY) { \
980 if (from->flags & INMEMORY) { \
981 i386_mov_membase_reg(REG_SP, from->regoff * 8, REG_ITMP1); \
982 i386_mov_reg_membase(REG_ITMP1, REG_SP, to->regoff * 8); \
984 i386_mov_reg_membase(from->regoff, REG_SP, to->regoff * 8); \
987 if (from->flags & INMEMORY) { \
988 i386_mov_membase_reg(REG_SP, from->regoff * 8, to->regoff); \
990 i386_mov_reg_reg(from->regoff, to->regoff); \
994 M_LNGMEMMOVE(from->regoff, to->regoff); \
999 case ICMD_DUP: /* ..., a ==> ..., a, a */
1000 M_COPY(src, iptr->dst);
1003 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
1005 M_COPY(src, iptr->dst->prev->prev);
1007 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
1009 M_COPY(src, iptr->dst);
1010 M_COPY(src->prev, iptr->dst->prev);
1013 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
1015 M_COPY(src->prev, iptr->dst->prev->prev->prev);
1017 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
1019 M_COPY(src, iptr->dst);
1020 M_COPY(src->prev, iptr->dst->prev);
1021 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1022 M_COPY(src, iptr->dst->prev->prev->prev);
1025 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
1027 M_COPY(src, iptr->dst);
1028 M_COPY(src->prev, iptr->dst->prev);
1029 M_COPY(src->prev->prev, iptr->dst->prev->prev);
1030 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
1031 M_COPY(src, iptr->dst->prev->prev->prev->prev);
1032 M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
1035 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
1037 M_COPY(src, iptr->dst->prev);
1038 M_COPY(src->prev, iptr->dst);
1042 /* integer operations *************************************************/
1044 case ICMD_INEG: /* ..., value ==> ..., - value */
1046 d = reg_of_var(iptr->dst, REG_NULL);
1047 if (iptr->dst->flags & INMEMORY) {
1048 if (src->flags & INMEMORY) {
1049 if (src->regoff == iptr->dst->regoff) {
1050 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1053 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1054 i386_neg_reg(REG_ITMP1);
1055 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1059 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1060 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1064 if (src->flags & INMEMORY) {
1065 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1066 i386_neg_reg(iptr->dst->regoff);
1069 M_INTMOVE(src->regoff, iptr->dst->regoff);
1070 i386_neg_reg(iptr->dst->regoff);
1075 case ICMD_LNEG: /* ..., value ==> ..., - value */
1077 d = reg_of_var(iptr->dst, REG_NULL);
1078 if (iptr->dst->flags & INMEMORY) {
1079 if (src->flags & INMEMORY) {
1080 if (src->regoff == iptr->dst->regoff) {
1081 i386_neg_membase(REG_SP, iptr->dst->regoff * 8);
1082 i386_alu_imm_membase(I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1083 i386_neg_membase(REG_SP, iptr->dst->regoff * 8 + 4);
1086 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1087 i386_neg_reg(REG_ITMP1);
1088 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1089 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1090 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP1);
1091 i386_neg_reg(REG_ITMP1);
1092 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1098 case ICMD_I2L: /* ..., value ==> ..., value */
1100 d = reg_of_var(iptr->dst, REG_NULL);
1101 if (iptr->dst->flags & INMEMORY) {
1102 if (src->flags & INMEMORY) {
1103 i386_mov_membase_reg(REG_SP, src->regoff * 8, EAX);
1105 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1106 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1109 M_INTMOVE(src->regoff, EAX);
1111 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1112 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1117 case ICMD_L2I: /* ..., value ==> ..., value */
1119 d = reg_of_var(iptr->dst, REG_NULL);
1120 if (iptr->dst->flags & INMEMORY) {
1121 if (src->flags & INMEMORY) {
1122 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1123 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1127 if (src->flags & INMEMORY) {
1128 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1133 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1135 d = reg_of_var(iptr->dst, REG_NULL);
1136 if (iptr->dst->flags & INMEMORY) {
1137 if (src->flags & INMEMORY) {
1138 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1139 i386_shift_imm_reg(I386_SHL, 24, REG_ITMP1);
1140 i386_shift_imm_reg(I386_SAR, 24, REG_ITMP1);
1141 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1144 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1145 i386_shift_imm_membase(I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1146 i386_shift_imm_membase(I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1150 if (src->flags & INMEMORY) {
1151 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1152 i386_shift_imm_reg(I386_SHL, 24, iptr->dst->regoff);
1153 i386_shift_imm_reg(I386_SAR, 24, iptr->dst->regoff);
1156 M_INTMOVE(src->regoff, iptr->dst->regoff);
1157 i386_shift_imm_reg(I386_SHL, 24, iptr->dst->regoff);
1158 i386_shift_imm_reg(I386_SAR, 24, iptr->dst->regoff);
1163 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1165 d = reg_of_var(iptr->dst, REG_NULL);
1166 if (iptr->dst->flags & INMEMORY) {
1167 if (src->flags & INMEMORY) {
1168 if (src->regoff == iptr->dst->regoff) {
1169 i386_alu_imm_membase(I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1172 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1173 i386_alu_imm_reg(I386_AND, 0x0000ffff, REG_ITMP1);
1174 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1178 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1179 i386_alu_imm_membase(I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1183 if (src->flags & INMEMORY) {
1184 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1185 i386_alu_imm_reg(I386_AND, 0x0000ffff, iptr->dst->regoff);
1188 M_INTMOVE(src->regoff, iptr->dst->regoff);
1189 i386_alu_imm_reg(I386_AND, 0x0000ffff, iptr->dst->regoff);
1194 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1196 d = reg_of_var(iptr->dst, REG_NULL);
1197 if (iptr->dst->flags & INMEMORY) {
1198 if (src->flags & INMEMORY) {
1199 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1200 i386_shift_imm_reg(I386_SHL, 16, REG_ITMP1);
1201 i386_shift_imm_reg(I386_SAR, 16, REG_ITMP1);
1202 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1205 i386_mov_reg_membase(src->regoff, REG_SP, iptr->dst->regoff * 8);
1206 i386_shift_imm_membase(I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1207 i386_shift_imm_membase(I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1211 if (src->flags & INMEMORY) {
1212 i386_mov_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1213 i386_shift_imm_reg(I386_SHL, 16, iptr->dst->regoff);
1214 i386_shift_imm_reg(I386_SAR, 16, iptr->dst->regoff);
1217 M_INTMOVE(src->regoff, iptr->dst->regoff);
1218 i386_shift_imm_reg(I386_SHL, 16, iptr->dst->regoff);
1219 i386_shift_imm_reg(I386_SAR, 16, iptr->dst->regoff);
1225 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1227 d = reg_of_var(iptr->dst, REG_NULL);
1228 i386_emit_ialu(I386_ADD, src, iptr);
1231 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1232 /* val.i = constant */
1234 d = reg_of_var(iptr->dst, REG_NULL);
1235 /* should we use a inc optimization for smaller code size? */
1236 i386_emit_ialuconst(I386_ADD, src, iptr);
1239 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1241 d = reg_of_var(iptr->dst, REG_NULL);
1242 if (iptr->dst->flags & INMEMORY) {
1243 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1244 if (src->regoff == iptr->dst->regoff) {
1245 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1246 i386_alu_reg_membase(I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1247 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1248 i386_alu_reg_membase(I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1250 } else if (src->prev->regoff == iptr->dst->regoff) {
1251 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1252 i386_alu_reg_membase(I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1253 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1254 i386_alu_reg_membase(I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1257 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1258 i386_alu_membase_reg(I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1259 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1260 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1261 i386_alu_membase_reg(I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1262 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1269 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1270 /* val.l = constant */
1272 d = reg_of_var(iptr->dst, REG_NULL);
1273 if (iptr->dst->flags & INMEMORY) {
1274 if (src->flags & INMEMORY) {
1275 if (src->regoff == iptr->dst->regoff) {
1276 i386_alu_imm_membase(I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1277 i386_alu_imm_membase(I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1280 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1281 i386_alu_imm_reg(I386_ADD, iptr->val.l, REG_ITMP1);
1282 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1283 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1284 i386_alu_imm_reg(I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1285 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1291 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1293 d = reg_of_var(iptr->dst, REG_NULL);
1294 if (iptr->dst->flags & INMEMORY) {
1295 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1296 if (src->prev->regoff == iptr->dst->regoff) {
1297 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1298 i386_alu_reg_membase(I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1301 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1302 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1303 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1306 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1307 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1308 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1309 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1311 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1312 if (src->prev->regoff == iptr->dst->regoff) {
1313 i386_alu_reg_membase(I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1316 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1317 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1318 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1322 i386_mov_reg_membase(src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1323 i386_alu_reg_membase(I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1327 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1328 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, d);
1329 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, d);
1331 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1332 M_INTMOVE(src->prev->regoff, d);
1333 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, d);
1335 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1336 /* workaround for reg alloc */
1337 if (src->regoff == iptr->dst->regoff) {
1338 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1339 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1340 M_INTMOVE(REG_ITMP1, d);
1343 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, d);
1344 i386_alu_reg_reg(I386_SUB, src->regoff, d);
1348 /* workaround for reg alloc */
1349 if (src->regoff == iptr->dst->regoff) {
1350 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1351 i386_alu_reg_reg(I386_SUB, src->regoff, REG_ITMP1);
1352 M_INTMOVE(REG_ITMP1, d);
1355 M_INTMOVE(src->prev->regoff, d);
1356 i386_alu_reg_reg(I386_SUB, src->regoff, d);
1362 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1363 /* val.i = constant */
1365 d = reg_of_var(iptr->dst, REG_NULL);
1366 i386_emit_ialuconst(I386_SUB, src, iptr);
1369 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1371 d = reg_of_var(iptr->dst, REG_NULL);
1372 if (iptr->dst->flags & INMEMORY) {
1373 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1374 if (src->prev->regoff == iptr->dst->regoff) {
1375 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1376 i386_alu_reg_membase(I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1377 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1378 i386_alu_reg_membase(I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1381 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1382 i386_alu_membase_reg(I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1383 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1384 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1385 i386_alu_membase_reg(I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1386 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1392 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1393 /* val.l = constant */
1395 d = reg_of_var(iptr->dst, REG_NULL);
1396 if (iptr->dst->flags & INMEMORY) {
1397 if (src->flags & INMEMORY) {
1398 if (src->regoff == iptr->dst->regoff) {
1399 i386_alu_imm_membase(I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1400 i386_alu_imm_membase(I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1403 /* TODO: could be size optimized with lea -- see gcc output */
1404 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1405 i386_alu_imm_reg(I386_SUB, iptr->val.l, REG_ITMP1);
1406 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1407 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1408 i386_alu_imm_reg(I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1409 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1415 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1417 d = reg_of_var(iptr->dst, REG_NULL);
1418 if (iptr->dst->flags & INMEMORY) {
1419 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1420 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1421 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1422 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1424 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1425 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1426 i386_imul_reg_reg(src->prev->regoff, REG_ITMP1);
1427 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1429 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1430 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1431 i386_imul_reg_reg(src->regoff, REG_ITMP1);
1432 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1435 i386_mov_reg_reg(src->prev->regoff, REG_ITMP1);
1436 i386_imul_reg_reg(src->regoff, REG_ITMP1);
1437 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1441 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1442 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1443 i386_imul_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1445 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1446 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1447 i386_imul_membase_reg(REG_SP, src->regoff * 8, iptr->dst->regoff);
1449 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1450 M_INTMOVE(src->regoff, iptr->dst->regoff);
1451 i386_imul_membase_reg(REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1454 if (src->regoff == iptr->dst->regoff) {
1455 i386_imul_reg_reg(src->prev->regoff, iptr->dst->regoff);
1458 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1459 i386_imul_reg_reg(src->regoff, iptr->dst->regoff);
1465 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1466 /* val.i = constant */
1468 d = reg_of_var(iptr->dst, REG_NULL);
1469 if (iptr->dst->flags & INMEMORY) {
1470 if (src->flags & INMEMORY) {
1471 i386_imul_imm_membase_reg(iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1472 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1475 i386_imul_imm_reg_reg(iptr->val.i, src->regoff, REG_ITMP1);
1476 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1480 if (src->flags & INMEMORY) {
1481 i386_imul_imm_membase_reg(iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1484 i386_imul_imm_reg_reg(iptr->val.i, src->regoff, iptr->dst->regoff);
1489 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1491 d = reg_of_var(iptr->dst, REG_NULL);
1492 if (iptr->dst->flags & INMEMORY) {
1493 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1494 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1495 /* optimize move EAX -> REG_ITMP3 is slower??? */
1496 /* i386_mov_reg_reg(EAX, REG_ITMP3); */
1497 i386_mul_membase(REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1499 /* TODO: optimize move EAX -> REG_ITMP3 */
1500 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1501 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1502 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1504 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1505 i386_imul_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1507 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1508 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1509 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1514 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1515 /* val.l = constant */
1517 d = reg_of_var(iptr->dst, REG_NULL);
1518 if (iptr->dst->flags & INMEMORY) {
1519 if (src->flags & INMEMORY) {
1520 i386_mov_imm_reg(iptr->val.l, EAX); /* imm -> EAX */
1521 i386_mul_membase(REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1522 /* TODO: optimize move EAX -> REG_ITMP3 */
1523 i386_mov_imm_reg(iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1524 i386_imul_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1526 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1527 i386_mov_imm_reg(iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1528 i386_imul_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1530 i386_alu_reg_reg(I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1531 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1532 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1537 #define gen_div_check(v) \
1539 if ((v)->flags & INMEMORY) { \
1540 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8); \
1542 i386_test_reg_reg(src->regoff, src->regoff); \
1544 i386_jcc(I386_CC_E, 0); \
1545 codegen_addxdivrefs(mcodeptr); \
1548 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1550 d = reg_of_var(iptr->dst, REG_NULL);
1551 var_to_reg_int(s1, src, REG_ITMP2);
1553 if (src->prev->flags & INMEMORY) {
1554 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX);
1557 M_INTMOVE(src->prev->regoff, EAX);
1560 i386_alu_imm_reg(I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1561 i386_jcc(I386_CC_NE, 3 + 6);
1562 i386_alu_imm_reg(I386_CMP, -1, s1);
1563 i386_jcc(I386_CC_E, 1 + 2);
1568 if (iptr->dst->flags & INMEMORY) {
1569 i386_mov_reg_membase(EAX, REG_SP, iptr->dst->regoff * 8);
1572 M_INTMOVE(EAX, iptr->dst->regoff);
1576 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1578 d = reg_of_var(iptr->dst, REG_NULL);
1579 var_to_reg_int(s1, src, REG_ITMP2);
1581 if (src->prev->flags & INMEMORY) {
1582 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, EAX);
1585 M_INTMOVE(src->prev->regoff, EAX);
1588 i386_alu_imm_reg(I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1589 i386_jcc(I386_CC_NE, 2 + 3 + 6);
1590 i386_alu_reg_reg(I386_XOR, EDX, EDX);
1591 i386_alu_imm_reg(I386_CMP, -1, s1);
1592 i386_jcc(I386_CC_E, 1 + 2);
1597 if (iptr->dst->flags & INMEMORY) {
1598 i386_mov_reg_membase(EDX, REG_SP, iptr->dst->regoff * 8);
1601 M_INTMOVE(EDX, iptr->dst->regoff);
1605 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1606 /* val.i = constant */
1608 /* TODO: optimize for `/ 2' */
1609 var_to_reg_int(s1, src, REG_ITMP1);
1610 d = reg_of_var(iptr->dst, REG_ITMP1);
1613 i386_test_reg_reg(d, d);
1615 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1616 i386_jcc(I386_CC_NS, a);
1617 i386_alu_imm_reg(I386_ADD, (1 << iptr->val.i) - 1, d);
1619 i386_shift_imm_reg(I386_SAR, iptr->val.i, d);
1620 store_reg_to_var_int(iptr->dst, d);
1623 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1624 /* val.i = constant */
1626 d = reg_of_var(iptr->dst, REG_NULL);
1627 if (iptr->dst->flags & INMEMORY) {
1628 if (src->flags & INMEMORY) {
1630 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1632 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1633 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1635 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
1636 i386_jcc(I386_CC_NS, a);
1637 i386_alu_imm_reg(I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1638 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1639 i386_shrd_imm_reg_reg(iptr->val.i, REG_ITMP2, REG_ITMP1);
1640 i386_shift_imm_reg(I386_SAR, iptr->val.i, REG_ITMP2);
1642 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1643 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1648 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1649 /* val.i = constant */
1651 var_to_reg_int(s1, src, REG_ITMP1);
1652 d = reg_of_var(iptr->dst, REG_ITMP2);
1654 M_INTMOVE(s1, REG_ITMP1);
1661 CALCIMMEDIATEBYTES(a, iptr->val.i);
1664 /* TODO: optimize */
1666 i386_alu_imm_reg(I386_AND, iptr->val.i, d);
1667 i386_test_reg_reg(s1, s1);
1668 i386_jcc(I386_CC_GE, a);
1669 i386_mov_reg_reg(s1, d);
1671 i386_alu_imm_reg(I386_AND, iptr->val.i, d);
1674 /* M_INTMOVE(s1, EAX); */
1676 /* i386_alu_reg_reg(I386_XOR, EDX, EAX); */
1677 /* i386_alu_reg_reg(I386_SUB, EDX, EAX); */
1678 /* i386_alu_reg_reg(I386_AND, iptr->val.i, EAX); */
1679 /* i386_alu_reg_reg(I386_XOR, EDX, EAX); */
1680 /* i386_alu_reg_reg(I386_SUB, EDX, EAX); */
1681 /* M_INTMOVE(EAX, d); */
1683 /* i386_alu_reg_reg(I386_XOR, d, d); */
1684 /* i386_mov_imm_reg(iptr->val.i, ECX); */
1685 /* i386_shrd_reg_reg(s1, d); */
1686 /* i386_shift_imm_reg(I386_SHR, 32 - iptr->val.i, d); */
1688 store_reg_to_var_int(iptr->dst, d);
1691 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1692 /* val.l = constant */
1694 d = reg_of_var(iptr->dst, REG_NULL);
1695 if (iptr->dst->flags & INMEMORY) {
1696 if (src->flags & INMEMORY) {
1697 /* Intel algorithm -- does not work, because constant is wrong */
1698 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1); */
1699 /* i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1701 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1702 /* i386_test_reg_reg(REG_ITMP3, REG_ITMP3); */
1703 /* i386_jcc(I386_CC_NS, offset); */
1704 /* i386_alu_imm_reg(I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1705 /* i386_alu_imm_reg(I386_ADC, 0, REG_ITMP3); */
1707 /* i386_shrd_imm_reg_reg(iptr->val.l, REG_ITMP3, REG_ITMP2); */
1708 /* i386_shift_imm_reg(I386_SAR, iptr->val.l, REG_ITMP3); */
1709 /* i386_shld_imm_reg_reg(iptr->val.l, REG_ITMP2, REG_ITMP3); */
1711 /* i386_shift_imm_reg(I386_SHL, iptr->val.l, REG_ITMP2); */
1713 /* i386_alu_reg_reg(I386_SUB, REG_ITMP2, REG_ITMP1); */
1714 /* i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1715 /* i386_alu_reg_reg(I386_SBB, REG_ITMP3, REG_ITMP2); */
1717 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1718 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1720 /* Alpha algorithm */
1722 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1724 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1730 /* TODO: hmm, don't know if this is always correct */
1732 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1734 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1740 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1741 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1743 i386_alu_imm_reg(I386_AND, iptr->val.l, REG_ITMP1);
1744 i386_alu_imm_reg(I386_AND, iptr->val.l >> 32, REG_ITMP2);
1745 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1746 i386_jcc(I386_CC_GE, a);
1748 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1749 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1751 i386_neg_reg(REG_ITMP1);
1752 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1753 i386_neg_reg(REG_ITMP2);
1755 i386_alu_imm_reg(I386_AND, iptr->val.l, REG_ITMP1);
1756 i386_alu_imm_reg(I386_AND, iptr->val.l >> 32, REG_ITMP2);
1758 i386_neg_reg(REG_ITMP1);
1759 i386_alu_imm_reg(I386_ADC, 0, REG_ITMP2);
1760 i386_neg_reg(REG_ITMP2);
1762 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1763 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1768 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1770 d = reg_of_var(iptr->dst, REG_NULL);
1771 i386_emit_ishift(I386_SHL, src, iptr);
1774 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1775 /* val.i = constant */
1777 d = reg_of_var(iptr->dst, REG_NULL);
1778 i386_emit_ishiftconst(I386_SHL, src, iptr);
1781 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1783 d = reg_of_var(iptr->dst, REG_NULL);
1784 i386_emit_ishift(I386_SAR, src, iptr);
1787 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1788 /* val.i = constant */
1790 d = reg_of_var(iptr->dst, REG_NULL);
1791 i386_emit_ishiftconst(I386_SAR, src, iptr);
1794 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1796 d = reg_of_var(iptr->dst, REG_NULL);
1797 i386_emit_ishift(I386_SHR, src, iptr);
1800 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1801 /* val.i = constant */
1803 d = reg_of_var(iptr->dst, REG_NULL);
1804 i386_emit_ishiftconst(I386_SHR, src, iptr);
1807 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1809 d = reg_of_var(iptr->dst, REG_NULL);
1810 if (iptr->dst->flags & INMEMORY ){
1811 if (src->prev->flags & INMEMORY) {
1812 /* if (src->prev->regoff == iptr->dst->regoff) { */
1813 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1815 /* if (src->flags & INMEMORY) { */
1816 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1818 /* M_INTMOVE(src->regoff, ECX); */
1821 /* i386_test_imm_reg(32, ECX); */
1822 /* i386_jcc(I386_CC_E, 2 + 2); */
1823 /* i386_mov_reg_reg(REG_ITMP1, REG_ITMP2); */
1824 /* i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1); */
1826 /* i386_shld_reg_membase(REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1827 /* i386_shift_membase(I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1830 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1831 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1833 if (src->flags & INMEMORY) {
1834 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1836 M_INTMOVE(src->regoff, ECX);
1839 i386_test_imm_reg(32, ECX);
1840 i386_jcc(I386_CC_E, 2 + 2);
1841 i386_mov_reg_reg(REG_ITMP1, REG_ITMP3);
1842 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
1844 i386_shld_reg_reg(REG_ITMP1, REG_ITMP3);
1845 i386_shift_reg(I386_SHL, REG_ITMP1);
1846 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1847 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1853 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1854 /* val.i = constant */
1856 d = reg_of_var(iptr->dst, REG_NULL);
1857 if (iptr->dst->flags & INMEMORY ) {
1858 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1859 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1861 if (iptr->val.i & 0x20) {
1862 i386_mov_reg_reg(REG_ITMP1, REG_ITMP2);
1863 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
1864 i386_shld_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1867 i386_shld_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1868 i386_shift_imm_reg(I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1871 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1872 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1876 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1878 d = reg_of_var(iptr->dst, REG_NULL);
1879 if (iptr->dst->flags & INMEMORY ){
1880 if (src->prev->flags & INMEMORY) {
1881 /* if (src->prev->regoff == iptr->dst->regoff) { */
1882 /* TODO: optimize */
1883 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1884 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1886 /* if (src->flags & INMEMORY) { */
1887 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1889 /* M_INTMOVE(src->regoff, ECX); */
1892 /* i386_test_imm_reg(32, ECX); */
1893 /* i386_jcc(I386_CC_E, 2 + 3); */
1894 /* i386_mov_reg_reg(REG_ITMP2, REG_ITMP1); */
1895 /* i386_shift_imm_reg(I386_SAR, 31, REG_ITMP2); */
1897 /* i386_shrd_reg_reg(REG_ITMP2, REG_ITMP1); */
1898 /* i386_shift_reg(I386_SAR, REG_ITMP2); */
1899 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1900 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1903 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1904 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1906 if (src->flags & INMEMORY) {
1907 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1909 M_INTMOVE(src->regoff, ECX);
1912 i386_test_imm_reg(32, ECX);
1913 i386_jcc(I386_CC_E, 2 + 3);
1914 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1);
1915 i386_shift_imm_reg(I386_SAR, 31, REG_ITMP3);
1917 i386_shrd_reg_reg(REG_ITMP3, REG_ITMP1);
1918 i386_shift_reg(I386_SAR, REG_ITMP3);
1919 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1920 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1926 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1927 /* val.i = constant */
1929 d = reg_of_var(iptr->dst, REG_NULL);
1930 if (iptr->dst->flags & INMEMORY ) {
1931 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
1932 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1934 if (iptr->val.i & 0x20) {
1935 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1);
1936 i386_shift_imm_reg(I386_SAR, 31, REG_ITMP2);
1937 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1940 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1941 i386_shift_imm_reg(I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1944 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1945 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1949 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1951 d = reg_of_var(iptr->dst, REG_NULL);
1952 if (iptr->dst->flags & INMEMORY ){
1953 if (src->prev->flags & INMEMORY) {
1954 /* if (src->prev->regoff == iptr->dst->regoff) { */
1955 /* TODO: optimize */
1956 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1957 /* i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1959 /* if (src->flags & INMEMORY) { */
1960 /* i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX); */
1962 /* M_INTMOVE(src->regoff, ECX); */
1965 /* i386_test_imm_reg(32, ECX); */
1966 /* i386_jcc(I386_CC_E, 2 + 2); */
1967 /* i386_mov_reg_reg(REG_ITMP2, REG_ITMP1); */
1968 /* i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2); */
1970 /* i386_shrd_reg_reg(REG_ITMP2, REG_ITMP1); */
1971 /* i386_shift_reg(I386_SHR, REG_ITMP2); */
1972 /* i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1973 /* i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1976 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
1977 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1979 if (src->flags & INMEMORY) {
1980 i386_mov_membase_reg(REG_SP, src->regoff * 8, ECX);
1982 M_INTMOVE(src->regoff, ECX);
1985 i386_test_imm_reg(32, ECX);
1986 i386_jcc(I386_CC_E, 2 + 2);
1987 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1);
1988 i386_alu_reg_reg(I386_XOR, REG_ITMP3, REG_ITMP3);
1990 i386_shrd_reg_reg(REG_ITMP3, REG_ITMP1);
1991 i386_shift_reg(I386_SHR, REG_ITMP3);
1992 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1993 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1999 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
2000 /* val.l = constant */
2002 d = reg_of_var(iptr->dst, REG_NULL);
2003 if (iptr->dst->flags & INMEMORY ) {
2004 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
2005 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2007 if (iptr->val.i & 0x20) {
2008 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1);
2009 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
2010 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2013 i386_shrd_imm_reg_reg(iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
2014 i386_shift_imm_reg(I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
2017 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2018 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2022 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2024 d = reg_of_var(iptr->dst, REG_NULL);
2025 i386_emit_ialu(I386_AND, src, iptr);
2028 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
2029 /* val.i = constant */
2031 d = reg_of_var(iptr->dst, REG_NULL);
2032 i386_emit_ialuconst(I386_AND, src, iptr);
2035 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
2037 d = reg_of_var(iptr->dst, REG_NULL);
2038 i386_emit_lalu(I386_AND, src, iptr);
2041 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
2042 /* val.l = constant */
2044 d = reg_of_var(iptr->dst, REG_NULL);
2045 i386_emit_laluconst(I386_AND, src, iptr);
2048 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2050 d = reg_of_var(iptr->dst, REG_NULL);
2051 i386_emit_ialu(I386_OR, src, iptr);
2054 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
2055 /* val.i = constant */
2057 d = reg_of_var(iptr->dst, REG_NULL);
2058 i386_emit_ialuconst(I386_OR, src, iptr);
2061 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
2063 d = reg_of_var(iptr->dst, REG_NULL);
2064 i386_emit_lalu(I386_OR, src, iptr);
2067 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
2068 /* val.l = constant */
2070 d = reg_of_var(iptr->dst, REG_NULL);
2071 i386_emit_laluconst(I386_OR, src, iptr);
2074 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2076 d = reg_of_var(iptr->dst, REG_NULL);
2077 i386_emit_ialu(I386_XOR, src, iptr);
2080 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
2081 /* val.i = constant */
2083 d = reg_of_var(iptr->dst, REG_NULL);
2084 i386_emit_ialuconst(I386_XOR, src, iptr);
2087 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2089 d = reg_of_var(iptr->dst, REG_NULL);
2090 i386_emit_lalu(I386_XOR, src, iptr);
2093 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2094 /* val.l = constant */
2096 d = reg_of_var(iptr->dst, REG_NULL);
2097 i386_emit_laluconst(I386_XOR, src, iptr);
2100 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2101 /* op1 = variable, val.i = constant */
2103 var = &(locals[iptr->op1][TYPE_INT]);
2104 if (var->flags & INMEMORY) {
2105 i386_alu_imm_membase(I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2108 i386_alu_imm_reg(I386_ADD, iptr->val.i, var->regoff);
2113 /* floating operations ************************************************/
2115 #define ROUND_TO_SINGLE \
2116 i386_fstps_membase(REG_SP, -8); \
2117 i386_flds_membase(REG_SP, -8);
2119 #define ROUND_TO_DOUBLE \
2120 i386_fstpl_membase(REG_SP, -8); \
2121 i386_fldl_membase(REG_SP, -8);
2123 #define FPU_SET_24BIT_MODE \
2124 if (!fpu_in_24bit_mode) { \
2125 i386_fldcw_mem(&fpu_ctrlwrd_24bit); \
2126 fpu_in_24bit_mode = 1; \
2129 #define FPU_SET_53BIT_MODE \
2130 if (fpu_in_24bit_mode) { \
2131 i386_fldcw_mem(&fpu_ctrlwrd_53bit); \
2132 fpu_in_24bit_mode = 0; \
2135 #define ROUND_TO_SINGLE
2136 #define ROUND_TO_DOUBLE
2137 #define FPU_SET_24BIT_MODE
2138 #define FPU_SET_53BIT_MODE
2140 case ICMD_FNEG: /* ..., value ==> ..., - value */
2143 var_to_reg_flt(s1, src, REG_FTMP1);
2144 d = reg_of_var(iptr->dst, REG_FTMP3);
2146 store_reg_to_var_flt(iptr->dst, d);
2149 case ICMD_DNEG: /* ..., value ==> ..., - value */
2152 var_to_reg_flt(s1, src, REG_FTMP1);
2153 d = reg_of_var(iptr->dst, REG_FTMP3);
2155 store_reg_to_var_flt(iptr->dst, d);
2158 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2161 d = reg_of_var(iptr->dst, REG_FTMP3);
2162 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2163 var_to_reg_flt(s2, src, REG_FTMP2);
2166 store_reg_to_var_flt(iptr->dst, d);
2169 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2172 d = reg_of_var(iptr->dst, REG_FTMP3);
2173 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2174 var_to_reg_flt(s2, src, REG_FTMP2);
2177 store_reg_to_var_flt(iptr->dst, d);
2180 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2183 d = reg_of_var(iptr->dst, REG_FTMP3);
2184 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2185 var_to_reg_flt(s2, src, REG_FTMP2);
2188 store_reg_to_var_flt(iptr->dst, d);
2191 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2194 d = reg_of_var(iptr->dst, REG_FTMP3);
2195 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2196 var_to_reg_flt(s2, src, REG_FTMP2);
2199 store_reg_to_var_flt(iptr->dst, d);
2202 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2205 d = reg_of_var(iptr->dst, REG_FTMP3);
2206 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2207 var_to_reg_flt(s2, src, REG_FTMP2);
2211 store_reg_to_var_flt(iptr->dst, d);
2214 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2217 d = reg_of_var(iptr->dst, REG_FTMP3);
2218 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2220 /* i386_fldt_mem(subnormal_bias1); */
2223 var_to_reg_flt(s2, src, REG_FTMP2);
2228 /* i386_fldt_mem(subnormal_bias2); */
2231 store_reg_to_var_flt(iptr->dst, d);
2234 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2237 d = reg_of_var(iptr->dst, REG_FTMP3);
2238 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2239 var_to_reg_flt(s2, src, REG_FTMP2);
2243 store_reg_to_var_flt(iptr->dst, d);
2246 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2249 d = reg_of_var(iptr->dst, REG_FTMP3);
2250 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2252 /* i386_fldt_mem(subnormal_bias1); */
2255 var_to_reg_flt(s2, src, REG_FTMP2);
2260 /* i386_fldt_mem(subnormal_bias2); */
2263 store_reg_to_var_flt(iptr->dst, d);
2266 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2269 /* exchanged to skip fxch */
2270 var_to_reg_flt(s2, src, REG_FTMP2);
2271 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2272 d = reg_of_var(iptr->dst, REG_FTMP3);
2278 i386_jcc(I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2279 store_reg_to_var_flt(iptr->dst, d);
2285 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2288 /* exchanged to skip fxch */
2289 var_to_reg_flt(s2, src, REG_FTMP2);
2290 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2291 d = reg_of_var(iptr->dst, REG_FTMP3);
2297 i386_jcc(I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2298 store_reg_to_var_flt(iptr->dst, d);
2304 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2305 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2307 d = reg_of_var(iptr->dst, REG_FTMP1);
2308 if (src->flags & INMEMORY) {
2309 i386_fildl_membase(REG_SP, src->regoff * 8);
2314 i386_mov_imm_reg(0, REG_ITMP1);
2315 dseg_adddata(mcodeptr);
2316 i386_mov_reg_membase(src->regoff, REG_ITMP1, a);
2317 i386_fildl_membase(REG_ITMP1, a);
2320 store_reg_to_var_flt(iptr->dst, d);
2323 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2324 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2326 d = reg_of_var(iptr->dst, REG_FTMP1);
2327 if (src->flags & INMEMORY) {
2328 i386_fildll_membase(REG_SP, src->regoff * 8);
2332 panic("L2F: longs have to be in memory");
2334 store_reg_to_var_flt(iptr->dst, d);
2337 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2339 var_to_reg_flt(s1, src, REG_FTMP1);
2340 d = reg_of_var(iptr->dst, REG_NULL);
2342 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2343 i386_mov_imm_reg(0, REG_ITMP1);
2344 dseg_adddata(mcodeptr);
2345 i386_fldcw_membase(REG_ITMP1, a);
2347 if (iptr->dst->flags & INMEMORY) {
2348 i386_fistpl_membase(REG_SP, iptr->dst->regoff * 8);
2351 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2352 i386_fldcw_membase(REG_ITMP1, a);
2354 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2357 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2359 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2363 i386_fistpl_membase(REG_ITMP1, a);
2365 i386_mov_membase_reg(REG_ITMP1, a, iptr->dst->regoff);
2367 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2368 i386_fldcw_membase(REG_ITMP1, a);
2370 i386_alu_imm_reg(I386_CMP, 0x80000000, iptr->dst->regoff);
2373 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2374 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2377 i386_jcc(I386_CC_NE, a);
2379 /* XXX: change this when we use registers */
2380 i386_flds_membase(REG_SP, src->regoff * 8);
2381 i386_mov_imm_reg((s4) asm_builtin_f2i, REG_ITMP1);
2382 i386_call_reg(REG_ITMP1);
2384 if (iptr->dst->flags & INMEMORY) {
2385 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2388 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2392 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2394 var_to_reg_flt(s1, src, REG_FTMP1);
2395 d = reg_of_var(iptr->dst, REG_NULL);
2397 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2398 i386_mov_imm_reg(0, REG_ITMP1);
2399 dseg_adddata(mcodeptr);
2400 i386_fldcw_membase(REG_ITMP1, a);
2402 if (iptr->dst->flags & INMEMORY) {
2403 i386_fistpl_membase(REG_SP, iptr->dst->regoff * 8);
2406 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2407 i386_fldcw_membase(REG_ITMP1, a);
2409 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2412 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2414 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2418 i386_fistpl_membase(REG_ITMP1, a);
2420 i386_mov_membase_reg(REG_ITMP1, a, iptr->dst->regoff);
2422 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2423 i386_fldcw_membase(REG_ITMP1, a);
2425 i386_alu_imm_reg(I386_CMP, 0x80000000, iptr->dst->regoff);
2428 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2429 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2432 i386_jcc(I386_CC_NE, a);
2434 /* XXX: change this when we use registers */
2435 i386_fldl_membase(REG_SP, src->regoff * 8);
2436 i386_mov_imm_reg((s4) asm_builtin_d2i, REG_ITMP1);
2437 i386_call_reg(REG_ITMP1);
2439 if (iptr->dst->flags & INMEMORY) {
2440 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2442 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2446 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2448 var_to_reg_flt(s1, src, REG_FTMP1);
2449 d = reg_of_var(iptr->dst, REG_NULL);
2451 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2452 i386_mov_imm_reg(0, REG_ITMP1);
2453 dseg_adddata(mcodeptr);
2454 i386_fldcw_membase(REG_ITMP1, a);
2456 if (iptr->dst->flags & INMEMORY) {
2457 i386_fistpll_membase(REG_SP, iptr->dst->regoff * 8);
2460 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2461 i386_fldcw_membase(REG_ITMP1, a);
2463 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2466 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2468 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2471 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2473 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2475 i386_jcc(I386_CC_NE, a);
2477 i386_alu_imm_membase(I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2480 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2482 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2484 i386_jcc(I386_CC_NE, a);
2486 /* XXX: change this when we use registers */
2487 i386_flds_membase(REG_SP, src->regoff * 8);
2488 i386_mov_imm_reg((s4) asm_builtin_f2l, REG_ITMP1);
2489 i386_call_reg(REG_ITMP1);
2490 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2491 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2494 panic("F2L: longs have to be in memory");
2498 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2500 var_to_reg_flt(s1, src, REG_FTMP1);
2501 d = reg_of_var(iptr->dst, REG_NULL);
2503 a = dseg_adds4(0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2504 i386_mov_imm_reg(0, REG_ITMP1);
2505 dseg_adddata(mcodeptr);
2506 i386_fldcw_membase(REG_ITMP1, a);
2508 if (iptr->dst->flags & INMEMORY) {
2509 i386_fistpll_membase(REG_SP, iptr->dst->regoff * 8);
2512 a = dseg_adds4(0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2513 i386_fldcw_membase(REG_ITMP1, a);
2515 i386_alu_imm_membase(I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2518 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2520 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2523 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2525 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2527 i386_jcc(I386_CC_NE, a);
2529 i386_alu_imm_membase(I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2532 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2534 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2536 i386_jcc(I386_CC_NE, a);
2538 /* XXX: change this when we use registers */
2539 i386_fldl_membase(REG_SP, src->regoff * 8);
2540 i386_mov_imm_reg((s4) asm_builtin_d2l, REG_ITMP1);
2541 i386_call_reg(REG_ITMP1);
2542 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2543 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2546 panic("D2L: longs have to be in memory");
2550 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2552 var_to_reg_flt(s1, src, REG_FTMP1);
2553 d = reg_of_var(iptr->dst, REG_FTMP3);
2555 store_reg_to_var_flt(iptr->dst, d);
2558 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2560 var_to_reg_flt(s1, src, REG_FTMP1);
2561 d = reg_of_var(iptr->dst, REG_FTMP3);
2563 store_reg_to_var_flt(iptr->dst, d);
2566 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2569 /* exchanged to skip fxch */
2570 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2571 var_to_reg_flt(s1, src, REG_FTMP2);
2572 d = reg_of_var(iptr->dst, REG_ITMP1);
2577 i386_test_imm_reg(0x400, EAX); /* unordered treat as GT */
2578 i386_jcc(I386_CC_E, 6);
2579 i386_alu_imm_reg(I386_AND, 0x000000ff, EAX);
2581 i386_mov_imm_reg(0, d); /* does not affect flags */
2582 i386_jcc(I386_CC_E, 6 + 3 + 5 + 3);
2583 i386_jcc(I386_CC_B, 3 + 5);
2584 i386_alu_imm_reg(I386_SUB, 1, d);
2586 i386_alu_imm_reg(I386_ADD, 1, d);
2587 store_reg_to_var_int(iptr->dst, d);
2590 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2593 /* exchanged to skip fxch */
2594 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2595 var_to_reg_flt(s1, src, REG_FTMP2);
2596 d = reg_of_var(iptr->dst, REG_ITMP1);
2601 i386_test_imm_reg(0x400, EAX); /* unordered treat as LT */
2602 i386_jcc(I386_CC_E, 3);
2603 i386_movb_imm_reg(1, I386_AH);
2605 i386_mov_imm_reg(0, d); /* does not affect flags */
2606 i386_jcc(I386_CC_E, 6 + 3 + 5 + 3);
2607 i386_jcc(I386_CC_B, 3 + 5);
2608 i386_alu_imm_reg(I386_SUB, 1, d);
2610 i386_alu_imm_reg(I386_ADD, 1, d);
2611 store_reg_to_var_int(iptr->dst, d);
2615 /* memory operations **************************************************/
2617 #define gen_bound_check \
2618 if (checkbounds) { \
2619 i386_alu_membase_reg(I386_CMP, s1, OFFSET(java_arrayheader, size), s2); \
2620 i386_jcc(I386_CC_AE, 0); \
2621 codegen_addxboundrefs(mcodeptr, s2); \
2624 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2626 var_to_reg_int(s1, src, REG_ITMP1);
2627 d = reg_of_var(iptr->dst, REG_ITMP1);
2628 gen_nullptr_check(s1);
2629 i386_mov_membase_reg(s1, OFFSET(java_arrayheader, size), d);
2630 store_reg_to_var_int(iptr->dst, d);
2633 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2635 var_to_reg_int(s1, src->prev, REG_ITMP1);
2636 var_to_reg_int(s2, src, REG_ITMP2);
2637 d = reg_of_var(iptr->dst, REG_ITMP1);
2638 if (iptr->op1 == 0) {
2639 gen_nullptr_check(s1);
2642 i386_mov_memindex_reg(OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2643 store_reg_to_var_int(iptr->dst, d);
2646 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2648 var_to_reg_int(s1, src->prev, REG_ITMP1);
2649 var_to_reg_int(s2, src, REG_ITMP2);
2650 d = reg_of_var(iptr->dst, REG_ITMP3);
2651 if (iptr->op1 == 0) {
2652 gen_nullptr_check(s1);
2656 if (iptr->dst->flags & INMEMORY) {
2657 i386_mov_memindex_reg(OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2658 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2659 i386_mov_memindex_reg(OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2660 i386_mov_reg_membase(REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2664 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2666 var_to_reg_int(s1, src->prev, REG_ITMP1);
2667 var_to_reg_int(s2, src, REG_ITMP2);
2668 d = reg_of_var(iptr->dst, REG_ITMP1);
2669 if (iptr->op1 == 0) {
2670 gen_nullptr_check(s1);
2673 i386_mov_memindex_reg(OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2674 store_reg_to_var_int(iptr->dst, d);
2677 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2679 var_to_reg_int(s1, src->prev, REG_ITMP1);
2680 var_to_reg_int(s2, src, REG_ITMP2);
2681 d = reg_of_var(iptr->dst, REG_FTMP1);
2682 if (iptr->op1 == 0) {
2683 gen_nullptr_check(s1);
2686 i386_flds_memindex(OFFSET(java_floatarray, data[0]), s1, s2, 2);
2688 store_reg_to_var_flt(iptr->dst, d);
2691 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2693 var_to_reg_int(s1, src->prev, REG_ITMP1);
2694 var_to_reg_int(s2, src, REG_ITMP2);
2695 d = reg_of_var(iptr->dst, REG_FTMP3);
2696 if (iptr->op1 == 0) {
2697 gen_nullptr_check(s1);
2700 i386_fldl_memindex(OFFSET(java_doublearray, data[0]), s1, s2, 3);
2702 store_reg_to_var_flt(iptr->dst, d);
2705 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2707 var_to_reg_int(s1, src->prev, REG_ITMP1);
2708 var_to_reg_int(s2, src, REG_ITMP2);
2709 d = reg_of_var(iptr->dst, REG_ITMP1);
2710 if (iptr->op1 == 0) {
2711 gen_nullptr_check(s1);
2714 i386_movzwl_memindex_reg(OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2715 store_reg_to_var_int(iptr->dst, d);
2718 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2720 var_to_reg_int(s1, src->prev, REG_ITMP1);
2721 var_to_reg_int(s2, src, REG_ITMP2);
2722 d = reg_of_var(iptr->dst, REG_ITMP1);
2723 if (iptr->op1 == 0) {
2724 gen_nullptr_check(s1);
2727 i386_movswl_memindex_reg(OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2728 store_reg_to_var_int(iptr->dst, d);
2731 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2733 var_to_reg_int(s1, src->prev, REG_ITMP1);
2734 var_to_reg_int(s2, src, REG_ITMP2);
2735 d = reg_of_var(iptr->dst, REG_ITMP1);
2736 if (iptr->op1 == 0) {
2737 gen_nullptr_check(s1);
2740 i386_movsbl_memindex_reg(OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2741 store_reg_to_var_int(iptr->dst, d);
2745 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2747 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2748 var_to_reg_int(s2, src->prev, REG_ITMP2);
2749 if (iptr->op1 == 0) {
2750 gen_nullptr_check(s1);
2753 var_to_reg_int(s3, src, REG_ITMP3);
2754 i386_mov_reg_memindex(s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2757 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2759 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2760 var_to_reg_int(s2, src->prev, REG_ITMP2);
2761 if (iptr->op1 == 0) {
2762 gen_nullptr_check(s1);
2766 if (src->flags & INMEMORY) {
2767 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP3);
2768 i386_mov_reg_memindex(REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2769 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2770 i386_mov_reg_memindex(REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2774 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2776 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2777 var_to_reg_int(s2, src->prev, REG_ITMP2);
2778 if (iptr->op1 == 0) {
2779 gen_nullptr_check(s1);
2782 var_to_reg_int(s3, src, REG_ITMP3);
2783 i386_mov_reg_memindex(s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2786 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2788 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2789 var_to_reg_int(s2, src->prev, REG_ITMP2);
2790 if (iptr->op1 == 0) {
2791 gen_nullptr_check(s1);
2794 var_to_reg_flt(s3, src, REG_FTMP1);
2795 i386_fstps_memindex(OFFSET(java_floatarray, data[0]), s1, s2, 2);
2799 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2801 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2802 var_to_reg_int(s2, src->prev, REG_ITMP2);
2803 if (iptr->op1 == 0) {
2804 gen_nullptr_check(s1);
2807 var_to_reg_flt(s3, src, REG_FTMP1);
2808 i386_fstpl_memindex(OFFSET(java_doublearray, data[0]), s1, s2, 3);
2812 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2814 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2815 var_to_reg_int(s2, src->prev, REG_ITMP2);
2816 if (iptr->op1 == 0) {
2817 gen_nullptr_check(s1);
2820 var_to_reg_int(s3, src, REG_ITMP3);
2821 i386_movw_reg_memindex(s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2824 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2826 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2827 var_to_reg_int(s2, src->prev, REG_ITMP2);
2828 if (iptr->op1 == 0) {
2829 gen_nullptr_check(s1);
2832 var_to_reg_int(s3, src, REG_ITMP3);
2833 i386_movw_reg_memindex(s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2836 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2838 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2839 var_to_reg_int(s2, src->prev, REG_ITMP2);
2840 if (iptr->op1 == 0) {
2841 gen_nullptr_check(s1);
2844 var_to_reg_int(s3, src, REG_ITMP3);
2845 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2846 M_INTMOVE(s3, REG_ITMP3);
2849 i386_movb_reg_memindex(s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2853 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2854 /* op1 = type, val.a = field address */
2856 /* if class isn't yet initialized, do it */
2857 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2858 /* call helper function which patches this code */
2859 i386_mov_imm_reg((s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2860 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
2861 i386_call_reg(REG_ITMP2);
2864 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2865 /* here it's slightly slower */
2866 i386_mov_imm_reg(0, REG_ITMP2);
2867 dseg_adddata(mcodeptr);
2868 i386_mov_membase_reg(REG_ITMP2, a, REG_ITMP2);
2869 switch (iptr->op1) {
2872 var_to_reg_int(s2, src, REG_ITMP1);
2873 i386_mov_reg_membase(s2, REG_ITMP2, 0);
2876 if (src->flags & INMEMORY) {
2877 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
2878 i386_mov_reg_membase(REG_ITMP1, REG_ITMP2, 0);
2879 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP1);
2880 i386_mov_reg_membase(REG_ITMP1, REG_ITMP2, 0 + 4);
2882 panic("PUTSTATIC: longs have to be in memory");
2886 var_to_reg_flt(s2, src, REG_FTMP1);
2887 i386_fstps_membase(REG_ITMP2, 0);
2891 var_to_reg_flt(s2, src, REG_FTMP1);
2892 i386_fstpl_membase(REG_ITMP2, 0);
2895 default: panic ("internal error");
2899 case ICMD_GETSTATIC: /* ... ==> ..., value */
2900 /* op1 = type, val.a = field address */
2902 /* if class isn't yet initialized, do it */
2903 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2904 /* call helper function which patches this code */
2905 i386_mov_imm_reg((s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2906 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
2907 i386_call_reg(REG_ITMP2);
2910 a = dseg_addaddress(&(((fieldinfo *) iptr->val.a)->value));
2911 i386_mov_imm_reg(0, REG_ITMP2);
2912 dseg_adddata(mcodeptr);
2913 i386_mov_membase_reg(REG_ITMP2, a, REG_ITMP2);
2914 switch (iptr->op1) {
2917 d = reg_of_var(iptr->dst, REG_ITMP1);
2918 i386_mov_membase_reg(REG_ITMP2, 0, d);
2919 store_reg_to_var_int(iptr->dst, d);
2922 d = reg_of_var(iptr->dst, REG_NULL);
2923 if (iptr->dst->flags & INMEMORY) {
2924 i386_mov_membase_reg(REG_ITMP2, 0, REG_ITMP1);
2925 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2926 i386_mov_membase_reg(REG_ITMP2, 0 + 4, REG_ITMP1);
2927 i386_mov_reg_membase(REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
2929 panic("GETSTATIC: longs have to be in memory");
2933 d = reg_of_var(iptr->dst, REG_FTMP1);
2934 i386_flds_membase(REG_ITMP2, 0);
2936 store_reg_to_var_flt(iptr->dst, d);
2939 d = reg_of_var(iptr->dst, REG_FTMP1);
2940 i386_fldl_membase(REG_ITMP2, 0);
2942 store_reg_to_var_flt(iptr->dst, d);
2944 default: panic ("internal error");
2948 case ICMD_PUTFIELD: /* ..., value ==> ... */
2949 /* op1 = type, val.i = field offset */
2951 a = ((fieldinfo *)(iptr->val.a))->offset;
2952 switch (iptr->op1) {
2955 var_to_reg_int(s1, src->prev, REG_ITMP1);
2956 var_to_reg_int(s2, src, REG_ITMP2);
2957 gen_nullptr_check(s1);
2958 i386_mov_reg_membase(s2, s1, a);
2961 var_to_reg_int(s1, src->prev, REG_ITMP1);
2962 gen_nullptr_check(s1);
2963 if (src->flags & INMEMORY) {
2964 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP2);
2965 i386_mov_reg_membase(REG_ITMP2, s1, a);
2966 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2967 i386_mov_reg_membase(REG_ITMP2, s1, a + 4);
2969 panic("PUTFIELD: longs have to be in memory");
2973 var_to_reg_int(s1, src->prev, REG_ITMP1);
2974 var_to_reg_flt(s2, src, REG_FTMP1);
2975 gen_nullptr_check(s1);
2976 i386_fstps_membase(s1, a);
2980 var_to_reg_int(s1, src->prev, REG_ITMP1);
2981 var_to_reg_flt(s2, src, REG_FTMP1);
2982 gen_nullptr_check(s1);
2983 i386_fstpl_membase(s1, a);
2986 default: panic ("internal error");
2990 case ICMD_GETFIELD: /* ... ==> ..., value */
2991 /* op1 = type, val.i = field offset */
2993 a = ((fieldinfo *)(iptr->val.a))->offset;
2994 switch (iptr->op1) {
2997 var_to_reg_int(s1, src, REG_ITMP1);
2998 d = reg_of_var(iptr->dst, REG_ITMP2);
2999 gen_nullptr_check(s1);
3000 i386_mov_membase_reg(s1, a, d);
3001 store_reg_to_var_int(iptr->dst, d);
3004 var_to_reg_int(s1, src, REG_ITMP1);
3005 d = reg_of_var(iptr->dst, REG_NULL);
3006 gen_nullptr_check(s1);
3007 i386_mov_membase_reg(s1, a, REG_ITMP2);
3008 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
3009 i386_mov_membase_reg(s1, a + 4, REG_ITMP2);
3010 i386_mov_reg_membase(REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3013 var_to_reg_int(s1, src, REG_ITMP1);
3014 d = reg_of_var(iptr->dst, REG_FTMP1);
3015 gen_nullptr_check(s1);
3016 i386_flds_membase(s1, a);
3018 store_reg_to_var_flt(iptr->dst, d);
3021 var_to_reg_int(s1, src, REG_ITMP1);
3022 d = reg_of_var(iptr->dst, REG_FTMP1);
3023 gen_nullptr_check(s1);
3024 i386_fldl_membase(s1, a);
3026 store_reg_to_var_flt(iptr->dst, d);
3028 default: panic ("internal error");
3033 /* branch operations **************************************************/
3036 /* #define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}} */
3037 #define ALIGNCODENOP do {} while (0)
3039 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3041 var_to_reg_int(s1, src, REG_ITMP1);
3042 M_INTMOVE(s1, REG_ITMP1_XPTR);
3044 i386_call_imm(0); /* passing exception pointer */
3045 i386_pop_reg(REG_ITMP2_XPC);
3047 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
3048 i386_jmp_reg(REG_ITMP3);
3052 case ICMD_GOTO: /* ... ==> ... */
3053 /* op1 = target JavaVM pc */
3056 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3060 case ICMD_JSR: /* ... ==> ... */
3061 /* op1 = target JavaVM pc */
3064 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3067 case ICMD_RET: /* ... ==> ... */
3068 /* op1 = local variable */
3070 var = &(locals[iptr->op1][TYPE_ADR]);
3071 var_to_reg_int(s1, var, REG_ITMP1);
3075 case ICMD_IFNULL: /* ..., value ==> ... */
3076 /* op1 = target JavaVM pc */
3078 if (src->flags & INMEMORY) {
3079 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
3082 i386_test_reg_reg(src->regoff, src->regoff);
3084 i386_jcc(I386_CC_E, 0);
3085 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3088 case ICMD_IFNONNULL: /* ..., value ==> ... */
3089 /* op1 = target JavaVM pc */
3091 if (src->flags & INMEMORY) {
3092 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
3095 i386_test_reg_reg(src->regoff, src->regoff);
3097 i386_jcc(I386_CC_NE, 0);
3098 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3101 case ICMD_IFEQ: /* ..., value ==> ... */
3102 /* op1 = target JavaVM pc, val.i = constant */
3104 if (src->flags & INMEMORY) {
3105 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3108 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3110 i386_jcc(I386_CC_E, 0);
3111 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3114 case ICMD_IFLT: /* ..., value ==> ... */
3115 /* op1 = target JavaVM pc, val.i = constant */
3117 if (src->flags & INMEMORY) {
3118 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3121 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3123 i386_jcc(I386_CC_L, 0);
3124 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3127 case ICMD_IFLE: /* ..., value ==> ... */
3128 /* op1 = target JavaVM pc, val.i = constant */
3130 if (src->flags & INMEMORY) {
3131 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3134 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3136 i386_jcc(I386_CC_LE, 0);
3137 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3140 case ICMD_IFNE: /* ..., value ==> ... */
3141 /* op1 = target JavaVM pc, val.i = constant */
3143 if (src->flags & INMEMORY) {
3144 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3147 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3149 i386_jcc(I386_CC_NE, 0);
3150 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3153 case ICMD_IFGT: /* ..., value ==> ... */
3154 /* op1 = target JavaVM pc, val.i = constant */
3156 if (src->flags & INMEMORY) {
3157 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3160 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3162 i386_jcc(I386_CC_G, 0);
3163 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3166 case ICMD_IFGE: /* ..., value ==> ... */
3167 /* op1 = target JavaVM pc, val.i = constant */
3169 if (src->flags & INMEMORY) {
3170 i386_alu_imm_membase(I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3173 i386_alu_imm_reg(I386_CMP, iptr->val.i, src->regoff);
3175 i386_jcc(I386_CC_GE, 0);
3176 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3179 case ICMD_IF_LEQ: /* ..., value ==> ... */
3180 /* op1 = target JavaVM pc, val.l = constant */
3182 if (src->flags & INMEMORY) {
3183 if (iptr->val.l == 0) {
3184 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3185 i386_alu_membase_reg(I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3188 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3189 i386_alu_imm_reg(I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3190 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3191 i386_alu_imm_reg(I386_XOR, iptr->val.l, REG_ITMP1);
3192 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3195 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3196 i386_jcc(I386_CC_E, 0);
3197 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3200 case ICMD_IF_LLT: /* ..., value ==> ... */
3201 /* op1 = target JavaVM pc, val.l = constant */
3203 if (src->flags & INMEMORY) {
3204 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3205 i386_jcc(I386_CC_L, 0);
3206 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3209 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3210 CALCIMMEDIATEBYTES(a, iptr->val.l);
3212 i386_jcc(I386_CC_G, a);
3214 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3215 i386_jcc(I386_CC_B, 0);
3216 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3220 case ICMD_IF_LLE: /* ..., value ==> ... */
3221 /* op1 = target JavaVM pc, val.l = constant */
3223 if (src->flags & INMEMORY) {
3224 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3225 i386_jcc(I386_CC_L, 0);
3226 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3229 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3230 CALCIMMEDIATEBYTES(a, iptr->val.l);
3232 i386_jcc(I386_CC_G, a);
3234 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3235 i386_jcc(I386_CC_BE, 0);
3236 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3240 case ICMD_IF_LNE: /* ..., value ==> ... */
3241 /* op1 = target JavaVM pc, val.l = constant */
3243 if (src->flags & INMEMORY) {
3244 if (iptr->val.l == 0) {
3245 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3246 i386_alu_membase_reg(I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3249 i386_mov_imm_reg(iptr->val.l, REG_ITMP1);
3250 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3251 i386_mov_imm_reg(iptr->val.l >> 32, REG_ITMP2);
3252 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3253 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3256 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3257 i386_jcc(I386_CC_NE, 0);
3258 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3261 case ICMD_IF_LGT: /* ..., value ==> ... */
3262 /* op1 = target JavaVM pc, val.l = constant */
3264 if (src->flags & INMEMORY) {
3265 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3266 i386_jcc(I386_CC_G, 0);
3267 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3270 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3271 CALCIMMEDIATEBYTES(a, iptr->val.l);
3273 i386_jcc(I386_CC_L, a);
3275 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3276 i386_jcc(I386_CC_A, 0);
3277 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3281 case ICMD_IF_LGE: /* ..., value ==> ... */
3282 /* op1 = target JavaVM pc, val.l = constant */
3284 if (src->flags & INMEMORY) {
3285 i386_alu_imm_membase(I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3286 i386_jcc(I386_CC_G, 0);
3287 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3290 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3291 CALCIMMEDIATEBYTES(a, iptr->val.l);
3293 i386_jcc(I386_CC_L, a);
3295 i386_alu_imm_membase(I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3296 i386_jcc(I386_CC_AE, 0);
3297 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3301 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3302 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3304 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3305 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3306 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3308 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3309 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3311 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3312 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3315 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3317 i386_jcc(I386_CC_E, 0);
3318 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3321 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3322 /* op1 = target JavaVM pc */
3324 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3325 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3326 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3327 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3328 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3329 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3330 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3332 i386_jcc(I386_CC_E, 0);
3333 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3336 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3337 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3339 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3340 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3341 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3343 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3344 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3346 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3347 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3350 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3352 i386_jcc(I386_CC_NE, 0);
3353 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3356 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3357 /* op1 = target JavaVM pc */
3359 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3360 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3361 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3362 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3363 i386_alu_membase_reg(I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3364 i386_alu_reg_reg(I386_OR, REG_ITMP2, REG_ITMP1);
3365 i386_test_reg_reg(REG_ITMP1, REG_ITMP1);
3367 i386_jcc(I386_CC_NE, 0);
3368 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3371 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3372 /* op1 = target JavaVM pc */
3374 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3375 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3376 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3378 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3379 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3381 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3382 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3385 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3387 i386_jcc(I386_CC_L, 0);
3388 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3391 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3392 /* op1 = target JavaVM pc */
3394 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3395 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3396 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3397 i386_jcc(I386_CC_L, 0);
3398 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3401 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3402 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3404 i386_jcc(I386_CC_G, a);
3406 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3407 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3408 i386_jcc(I386_CC_B, 0);
3409 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3413 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3414 /* op1 = target JavaVM pc */
3416 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3417 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3418 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3420 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3421 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3423 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3424 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3427 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3429 i386_jcc(I386_CC_G, 0);
3430 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3433 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3434 /* op1 = target JavaVM pc */
3436 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3437 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3438 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3439 i386_jcc(I386_CC_G, 0);
3440 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3443 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3444 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3446 i386_jcc(I386_CC_L, a);
3448 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3449 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3450 i386_jcc(I386_CC_A, 0);
3451 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3455 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3456 /* op1 = target JavaVM pc */
3458 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3459 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3460 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3462 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3463 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3465 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3466 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3469 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3471 i386_jcc(I386_CC_LE, 0);
3472 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3475 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3476 /* op1 = target JavaVM pc */
3478 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3479 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3480 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3481 i386_jcc(I386_CC_L, 0);
3482 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3485 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3486 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3488 i386_jcc(I386_CC_G, a);
3490 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3491 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3492 i386_jcc(I386_CC_BE, 0);
3493 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3497 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3498 /* op1 = target JavaVM pc */
3500 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3501 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3502 i386_alu_reg_membase(I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3504 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3505 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3507 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3508 i386_alu_reg_membase(I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3511 i386_alu_reg_reg(I386_CMP, src->regoff, src->prev->regoff);
3513 i386_jcc(I386_CC_GE, 0);
3514 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3517 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3518 /* op1 = target JavaVM pc */
3520 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3521 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3522 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3523 i386_jcc(I386_CC_G, 0);
3524 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3527 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3528 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3530 i386_jcc(I386_CC_L, a);
3532 i386_mov_membase_reg(REG_SP, src->prev->regoff * 8, REG_ITMP1);
3533 i386_alu_membase_reg(I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3534 i386_jcc(I386_CC_AE, 0);
3535 codegen_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
3539 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3541 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3544 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3545 /* val.i = constant */
3547 d = reg_of_var(iptr->dst, REG_NULL);
3548 i386_emit_ifcc_iconst(I386_CC_NE, src, iptr);
3551 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3552 /* val.i = constant */
3554 d = reg_of_var(iptr->dst, REG_NULL);
3555 i386_emit_ifcc_iconst(I386_CC_E, src, iptr);
3558 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3559 /* val.i = constant */
3561 d = reg_of_var(iptr->dst, REG_NULL);
3562 i386_emit_ifcc_iconst(I386_CC_GE, src, iptr);
3565 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3566 /* val.i = constant */
3568 d = reg_of_var(iptr->dst, REG_NULL);
3569 i386_emit_ifcc_iconst(I386_CC_L, src, iptr);
3572 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3573 /* val.i = constant */
3575 d = reg_of_var(iptr->dst, REG_NULL);
3576 i386_emit_ifcc_iconst(I386_CC_LE, src, iptr);
3579 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3580 /* val.i = constant */
3582 d = reg_of_var(iptr->dst, REG_NULL);
3583 i386_emit_ifcc_iconst(I386_CC_G, src, iptr);
3587 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3590 var_to_reg_int(s1, src, REG_RESULT);
3591 M_INTMOVE(s1, REG_RESULT);
3593 #if defined(USE_THREADS)
3594 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3595 i386_mov_membase_reg(REG_SP, maxmemuse * 8, REG_ITMP2);
3596 i386_mov_reg_membase(REG_RESULT, REG_SP, maxmemuse * 8);
3598 i386_alu_imm_reg(I386_SUB, 1 * 8, REG_SP);
3599 i386_mov_reg_membase(REG_ITMP2, REG_SP, 0 * 8);
3600 i386_mov_imm_reg((s4) asm_builtin_monitorexit, REG_ITMP1);
3601 i386_call_reg(REG_ITMP1);
3602 i386_alu_imm_reg(I386_ADD, 1 * 8, REG_SP);
3604 i386_mov_membase_reg(REG_SP, maxmemuse * 8, REG_RESULT);
3608 goto nowperformreturn;
3610 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3612 if (src->flags & INMEMORY) {
3613 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_RESULT);
3614 i386_mov_membase_reg(REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3617 panic("LRETURN: longs have to be in memory");
3620 #if defined(USE_THREADS)
3621 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3622 i386_mov_membase_reg(REG_SP, maxmemuse * 8, REG_ITMP2);
3623 i386_mov_reg_membase(REG_RESULT, REG_SP, maxmemuse * 8);
3624 i386_mov_reg_membase(REG_RESULT2, REG_SP, maxmemuse * 8 + 4);
3626 i386_alu_imm_reg(I386_SUB, 1 * 8, REG_SP);
3627 i386_mov_reg_membase(REG_ITMP2, REG_SP, 0 * 8);
3628 i386_mov_imm_reg((s4) builtin_monitorexit, REG_ITMP1);
3629 i386_call_reg(REG_ITMP1);
3630 i386_alu_imm_reg(I386_ADD, 1 * 8, REG_SP);
3632 i386_mov_membase_reg(REG_SP, maxmemuse * 8, REG_RESULT);
3633 i386_mov_membase_reg(REG_SP, maxmemuse * 8 + 4, REG_RESULT2);
3637 goto nowperformreturn;
3639 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3640 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3642 var_to_reg_flt(s1, src, REG_FRESULT);
3643 /* this may be an early return -- keep the offset correct for the remaining code */
3647 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3648 i386_mov_membase_reg(REG_SP, maxmemuse * 8, REG_ITMP2);
3649 i386_fstl_membase(REG_SP, maxmemuse * 8);
3651 i386_alu_imm_reg(I386_SUB, 1 * 8, REG_SP);
3652 i386_mov_reg_membase(REG_ITMP2, REG_SP, 0 * 8);
3653 i386_mov_imm_reg((s4) builtin_monitorexit, REG_ITMP1);
3654 i386_call_reg(REG_ITMP1);
3655 i386_alu_imm_reg(I386_ADD, 1 * 8, REG_SP);
3657 i386_fldl_membase(REG_SP, maxmemuse * 8);
3661 goto nowperformreturn;
3663 case ICMD_RETURN: /* ... ==> ... */
3666 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
3667 i386_mov_membase_reg(REG_SP, 8 * maxmemuse, REG_ITMP1);
3668 i386_alu_imm_reg(I386_SUB, 4, REG_SP);
3669 i386_mov_reg_membase(REG_ITMP1, REG_SP, 0);
3670 i386_mov_imm_reg((s4) builtin_monitorexit, REG_ITMP1);
3671 i386_call_reg(REG_ITMP1);
3672 i386_alu_imm_reg(I386_ADD, 4, REG_SP);
3680 p = parentargs_base;
3682 /* restore saved registers */
3683 for (r = savintregcnt - 1; r >= maxsavintreguse; r--) {
3685 i386_mov_membase_reg(REG_SP, p * 8, savintregs[r]);
3687 for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--) {
3689 i386_fldl_membase(REG_SP, p * 8);
3691 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3692 i386_fstp_reg(savfltregs[r] + fpu_st_offset + 1);
3694 i386_fstp_reg(savfltregs[r] + fpu_st_offset);
3699 /* deallocate stack */
3700 if (parentargs_base) {
3701 i386_alu_imm_reg(I386_ADD, parentargs_base * 8, REG_SP);
3704 /* call trace function */
3706 i386_alu_imm_reg(I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3708 i386_mov_imm_membase((s4) method, REG_SP, 0);
3710 i386_mov_reg_membase(REG_RESULT, REG_SP, 4);
3711 i386_mov_reg_membase(REG_RESULT2, REG_SP, 4 + 4);
3713 i386_fstl_membase(REG_SP, 4 + 8);
3714 i386_fsts_membase(REG_SP, 4 + 8 + 8);
3716 i386_mov_imm_reg((s4) builtin_displaymethodstop, REG_ITMP1);
3717 /* i386_mov_imm_reg(asm_builtin_exittrace, REG_ITMP1); */
3718 i386_call_reg(REG_ITMP1);
3720 i386_mov_membase_reg(REG_SP, 4, REG_RESULT);
3721 i386_mov_membase_reg(REG_SP, 4 + 4, REG_RESULT2);
3723 i386_alu_imm_reg(I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3732 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3737 tptr = (void **) iptr->target;
3739 s4ptr = iptr->val.a;
3740 l = s4ptr[1]; /* low */
3741 i = s4ptr[2]; /* high */
3743 var_to_reg_int(s1, src, REG_ITMP1);
3744 M_INTMOVE(s1, REG_ITMP1);
3746 i386_alu_imm_reg(I386_SUB, l, REG_ITMP1);
3752 i386_alu_imm_reg(I386_CMP, i - 1, REG_ITMP1);
3753 i386_jcc(I386_CC_A, 0);
3755 /* codegen_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr); */
3756 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3758 /* build jump table top down and use address of lowest entry */
3760 /* s4ptr += 3 + i; */
3764 /* dseg_addtarget(BlockPtrOfPC(*--s4ptr)); */
3765 dseg_addtarget((basicblock *) tptr[0]);
3769 /* length of dataseg after last dseg_addtarget is used by load */
3771 i386_mov_imm_reg(0, REG_ITMP2);
3772 dseg_adddata(mcodeptr);
3773 i386_mov_memindex_reg(-dseglen, REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3774 i386_jmp_reg(REG_ITMP1);
3780 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3782 s4 i, l, val, *s4ptr;
3785 tptr = (void **) iptr->target;
3787 s4ptr = iptr->val.a;
3788 l = s4ptr[0]; /* default */
3789 i = s4ptr[1]; /* count */
3791 MCODECHECK((i<<2)+8);
3792 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3798 i386_alu_imm_reg(I386_CMP, val, s1);
3799 i386_jcc(I386_CC_E, 0);
3800 /* codegen_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr); */
3801 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3805 /* codegen_addreference(BlockPtrOfPC(l), mcodeptr); */
3807 tptr = (void **) iptr->target;
3808 codegen_addreference((basicblock *) tptr[0], mcodeptr);
3815 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3816 /* op1 = return type, val.a = function pointer*/
3820 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3821 /* op1 = return type, val.a = function pointer*/
3825 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3826 /* op1 = return type, val.a = function pointer*/
3830 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3831 /* op1 = arg count, val.a = method pointer */
3833 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3834 /* op1 = arg count, val.a = method pointer */
3836 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3837 /* op1 = arg count, val.a = method pointer */
3839 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3840 /* op1 = arg count, val.a = method pointer */
3848 MCODECHECK((s3 << 1) + 64);
3850 /* copy arguments to registers or stack location */
3852 for (; --s3 >= 0; src = src->prev) {
3853 if (src->varkind == ARGVAR) {
3857 if (IS_INT_LNG_TYPE(src->type)) {
3858 if (s3 < intreg_argnum) {
3859 panic("No integer argument registers available!");
3862 if (!IS_2_WORD_TYPE(src->type)) {
3863 if (src->flags & INMEMORY) {
3864 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
3865 i386_mov_reg_membase(REG_ITMP1, REG_SP, s3 * 8);
3868 i386_mov_reg_membase(src->regoff, REG_SP, s3 * 8);
3872 if (src->flags & INMEMORY) {
3873 M_LNGMEMMOVE(src->regoff, s3);
3876 panic("copy arguments: longs have to be in memory");
3882 if (s3 < fltreg_argnum) {
3883 panic("No float argument registers available!");
3886 var_to_reg_flt(d, src, REG_FTMP1);
3887 if (src->type == TYPE_FLT) {
3888 i386_fstps_membase(REG_SP, s3 * 8);
3891 i386_fstpl_membase(REG_SP, s3 * 8);
3898 switch (iptr->opc) {
3906 i386_mov_imm_reg(a, REG_ITMP1);
3907 i386_call_reg(REG_ITMP1);
3910 case ICMD_INVOKESTATIC:
3912 a = (u4) m->stubroutine;
3915 i386_mov_imm_reg(a, REG_ITMP2);
3916 i386_call_reg(REG_ITMP2);
3919 case ICMD_INVOKESPECIAL:
3921 a = (u4) m->stubroutine;
3924 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3925 gen_nullptr_check(REG_ITMP1);
3926 i386_mov_membase_reg(REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3928 i386_mov_imm_reg(a, REG_ITMP2);
3929 i386_call_reg(REG_ITMP2);
3932 case ICMD_INVOKEVIRTUAL:
3936 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3937 gen_nullptr_check(REG_ITMP1);
3938 i386_mov_membase_reg(REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3939 i386_mov_membase32_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + sizeof(methodptr) * m->vftblindex, REG_ITMP1);
3941 i386_call_reg(REG_ITMP1);
3944 case ICMD_INVOKEINTERFACE:
3949 i386_mov_membase_reg(REG_SP, 0, REG_ITMP1);
3950 gen_nullptr_check(REG_ITMP1);
3951 i386_mov_membase_reg(REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3952 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - sizeof(methodptr) * ci->index, REG_ITMP2);
3953 i386_mov_membase32_reg(REG_ITMP2, sizeof(methodptr) * (m - ci->methods), REG_ITMP1);
3955 i386_call_reg(REG_ITMP1);
3960 error("Unkown ICMD-Command: %d", iptr->opc);
3963 /* d contains return type */
3965 if (d != TYPE_VOID) {
3966 d = reg_of_var(iptr->dst, REG_NULL);
3968 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3969 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3970 if (iptr->dst->flags & INMEMORY) {
3971 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3972 i386_mov_reg_membase(REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3975 panic("RETURN: longs have to be in memory");
3979 if (iptr->dst->flags & INMEMORY) {
3980 i386_mov_reg_membase(REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3983 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3988 /* fld from called function -- has other fpu_st_offset counter */
3990 store_reg_to_var_flt(iptr->dst, d);
3997 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3999 /* op1: 0 == array, 1 == class */
4000 /* val.a: (classinfo*) superclass */
4002 /* superclass is an interface:
4004 * return (sub != NULL) &&
4005 * (sub->vftbl->interfacetablelength > super->index) &&
4006 * (sub->vftbl->interfacetable[-super->index] != NULL);
4008 * superclass is a class:
4010 * return ((sub != NULL) && (0
4011 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4012 * super->vftbl->diffvall));
4016 classinfo *super = (classinfo*) iptr->val.a;
4018 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4019 codegen_threadcritrestart(mcodeptr - mcodebase);
4021 var_to_reg_int(s1, src, REG_ITMP1);
4022 d = reg_of_var(iptr->dst, REG_ITMP3);
4024 M_INTMOVE(s1, REG_ITMP1);
4027 i386_alu_reg_reg(I386_XOR, d, d);
4028 if (iptr->op1) { /* class/interface */
4029 if (super->flags & ACC_INTERFACE) { /* interface */
4030 i386_test_reg_reg(s1, s1);
4032 /* TODO: clean up this calculation */
4034 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4037 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
4040 /* CALCOFFSETBYTES(a, super->index); */
4041 CALCIMMEDIATEBYTES(a, super->index);
4047 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*));
4054 i386_jcc(I386_CC_E, a);
4056 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4057 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetablelength), REG_ITMP2);
4058 i386_alu_imm_reg(I386_SUB, super->index, REG_ITMP2);
4060 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4062 /* TODO: clean up this calculation */
4065 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*));
4072 i386_jcc(I386_CC_LE, a);
4073 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4075 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP1);
4076 /* i386_setcc_reg(I386_CC_A, d); */
4077 /* i386_jcc(I386_CC_BE, 5); */
4078 i386_jcc(I386_CC_E, 5);
4079 i386_mov_imm_reg(1, d);
4082 } else { /* class */
4083 i386_test_reg_reg(s1, s1);
4085 /* TODO: clean up this calculation */
4087 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4090 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, baseval));
4092 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, baseval));
4095 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, diffval));
4105 i386_jcc(I386_CC_E, a);
4107 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4108 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4109 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4110 codegen_threadcritstart(mcodeptr - mcodebase);
4112 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, baseval), REG_ITMP1);
4113 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, baseval), REG_ITMP3);
4114 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, diffval), REG_ITMP2);
4115 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4116 codegen_threadcritstop(mcodeptr - mcodebase);
4118 i386_alu_reg_reg(I386_SUB, REG_ITMP3, REG_ITMP1);
4119 i386_alu_reg_reg(I386_XOR, d, d);
4121 i386_alu_reg_reg(I386_CMP, REG_ITMP2, REG_ITMP1);
4122 i386_jcc(I386_CC_A, 5);
4123 i386_mov_imm_reg(1, d);
4127 panic ("internal error: no inlined array instanceof");
4129 store_reg_to_var_int(iptr->dst, d);
4132 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4134 /* op1: 0 == array, 1 == class */
4135 /* val.a: (classinfo*) superclass */
4137 /* superclass is an interface:
4139 * OK if ((sub == NULL) ||
4140 * (sub->vftbl->interfacetablelength > super->index) &&
4141 * (sub->vftbl->interfacetable[-super->index] != NULL));
4143 * superclass is a class:
4145 * OK if ((sub == NULL) || (0
4146 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4147 * super->vftbl->diffvall));
4151 classinfo *super = (classinfo*) iptr->val.a;
4153 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4154 codegen_threadcritrestart(mcodeptr - mcodebase);
4156 d = reg_of_var(iptr->dst, REG_ITMP3);
4157 var_to_reg_int(s1, src, d);
4158 if (iptr->op1) { /* class/interface */
4159 if (super->flags & ACC_INTERFACE) { /* interface */
4160 i386_test_reg_reg(s1, s1);
4162 /* TODO: clean up this calculation */
4164 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4167 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetablelength));
4170 /* CALCOFFSETBYTES(a, super->index); */
4171 CALCIMMEDIATEBYTES(a, super->index);
4177 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*));
4182 i386_jcc(I386_CC_E, a);
4184 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4185 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetablelength), REG_ITMP2);
4186 i386_alu_imm_reg(I386_SUB, super->index, REG_ITMP2);
4188 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4189 i386_jcc(I386_CC_LE, 0);
4190 codegen_addxcastrefs(mcodeptr);
4191 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4193 i386_alu_imm_reg(I386_CMP, 0, REG_ITMP2);
4194 i386_jcc(I386_CC_E, 0);
4195 codegen_addxcastrefs(mcodeptr);
4197 } else { /* class */
4198 i386_test_reg_reg(s1, s1);
4200 /* TODO: clean up this calculation */
4202 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4207 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl, baseval));
4209 if (d != REG_ITMP3) {
4211 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, baseval));
4214 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, diffval));
4220 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, baseval));
4227 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl, diffval));
4234 i386_jcc(I386_CC_E, a);
4236 i386_mov_membase_reg(s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4237 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4238 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4239 codegen_threadcritstart(mcodeptr - mcodebase);
4241 i386_mov_membase_reg(REG_ITMP1, OFFSET(vftbl, baseval), REG_ITMP1);
4242 if (d != REG_ITMP3) {
4243 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, baseval), REG_ITMP3);
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);
4248 i386_alu_reg_reg(I386_SUB, REG_ITMP3, REG_ITMP1);
4251 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, baseval), REG_ITMP2);
4252 i386_alu_reg_reg(I386_SUB, REG_ITMP2, REG_ITMP1);
4253 i386_mov_imm_reg((s4) super->vftbl, REG_ITMP2);
4254 i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, diffval), REG_ITMP2);
4255 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4256 codegen_threadcritstop(mcodeptr - mcodebase);
4260 i386_alu_reg_reg(I386_CMP, REG_ITMP2, REG_ITMP1);
4261 i386_jcc(I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4262 codegen_addxcastrefs(mcodeptr);
4266 panic ("internal error: no inlined array checkcast");
4269 store_reg_to_var_int(iptr->dst, d);
4272 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4274 if (src->flags & INMEMORY) {
4275 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
4278 i386_test_reg_reg(src->regoff, src->regoff);
4280 i386_jcc(I386_CC_L, 0);
4281 codegen_addxcheckarefs(mcodeptr);
4284 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4286 i386_test_reg_reg(REG_RESULT, REG_RESULT);
4287 i386_jcc(I386_CC_E, 0);
4288 codegen_addxexceptionrefs(mcodeptr);
4291 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4292 /* op1 = dimension, val.a = array descriptor */
4294 /* check for negative sizes and copy sizes to stack if necessary */
4296 MCODECHECK((iptr->op1 << 1) + 64);
4298 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4299 if (src->flags & INMEMORY) {
4300 i386_alu_imm_membase(I386_CMP, 0, REG_SP, src->regoff * 8);
4303 i386_test_reg_reg(src->regoff, src->regoff);
4305 i386_jcc(I386_CC_L, 0);
4306 codegen_addxcheckarefs(mcodeptr);
4309 * copy sizes to new stack location, be cause native function
4310 * builtin_nmultianewarray access them as (int *)
4312 i386_mov_membase_reg(REG_SP, src->regoff * 8, REG_ITMP1);
4313 i386_mov_reg_membase(REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4315 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4317 if (src->varkind != ARGVAR) {
4318 if (src->flags & INMEMORY) {
4319 i386_mov_membase_reg(REG_SP, (src->regoff + intreg_argnum) * 8, REG_ITMP1);
4320 i386_mov_reg_membase(REG_ITMP1, REG_SP, (s1 + intreg_argnum) * 8);
4323 i386_mov_reg_membase(src->regoff, REG_SP, (s1 + intreg_argnum) * 8);
4327 i386_alu_imm_reg(I386_SUB, iptr->op1 * 4, REG_SP);
4329 /* a0 = dimension count */
4331 /* save stack pointer */
4332 M_INTMOVE(REG_SP, REG_ITMP1);
4334 i386_alu_imm_reg(I386_SUB, 12, REG_SP);
4335 i386_mov_imm_membase(iptr->op1, REG_SP, 0);
4337 /* a1 = arraydescriptor */
4339 i386_mov_imm_membase((s4) iptr->val.a, REG_SP, 4);
4341 /* a2 = pointer to dimensions = stack pointer */
4343 i386_mov_reg_membase(REG_ITMP1, REG_SP, 8);
4345 i386_mov_imm_reg((s4) (builtin_nmultianewarray), REG_ITMP1);
4346 i386_call_reg(REG_ITMP1);
4347 i386_alu_imm_reg(I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4349 s1 = reg_of_var(iptr->dst, REG_RESULT);
4350 M_INTMOVE(REG_RESULT, s1);
4351 store_reg_to_var_int(iptr->dst, s1);
4355 error ("Unknown pseudo command: %d", iptr->opc);
4358 } /* for instruction */
4360 /* copy values to interface registers */
4362 src = bptr->outstack;
4363 len = bptr->outdepth;
4367 if ((src->varkind != STACKVAR)) {
4369 if (IS_FLT_DBL_TYPE(s2)) {
4370 var_to_reg_flt(s1, src, REG_FTMP1);
4371 if (!(interfaces[len][s2].flags & INMEMORY)) {
4372 M_FLTMOVE(s1,interfaces[len][s2].regoff);
4375 panic("double store");
4376 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4380 var_to_reg_int(s1, src, REG_ITMP1);
4381 if (!IS_2_WORD_TYPE(interfaces[len][s2].type)) {
4382 if (!(interfaces[len][s2].flags & INMEMORY)) {
4383 M_INTMOVE(s1, interfaces[len][s2].regoff);
4386 i386_mov_reg_membase(s1, REG_SP, interfaces[len][s2].regoff * 8);
4390 if (interfaces[len][s2].flags & INMEMORY) {
4391 M_LNGMEMMOVE(s1, interfaces[len][s2].regoff);
4394 panic("copy interface registers: longs have to be in memory (end)");
4401 } /* if (bptr -> flags >= BBREACHED) */
4402 } /* for basic block */
4404 codegen_createlinenumbertable();
4406 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
4410 /* generate bound check stubs */
4412 u1 *xcodeptr = NULL;
4414 for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
4415 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4416 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
4417 xboundrefs->branchpos,
4418 (u1*) xcodeptr - (u1*) mcodebase - (2 + 5 + 5 + 2));
4423 gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos,
4424 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
4428 /* move index register into REG_ITMP1 */
4429 i386_mov_reg_reg(xboundrefs->reg, REG_ITMP1); /* 2 bytes */
4431 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4432 dseg_adddata(mcodeptr);
4433 i386_mov_imm_reg(xboundrefs->branchpos - 6, REG_ITMP3); /* 5 bytes */
4434 i386_alu_reg_reg(I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4436 if (xcodeptr != NULL) {
4437 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4440 xcodeptr = mcodeptr;
4442 i386_push_reg(REG_ITMP2_XPC);
4444 PREPARE_NATIVE_STACKINFO
4446 i386_alu_imm_reg(I386_SUB, 2 * 4, REG_SP);
4447 i386_mov_imm_membase((s4) string_java_lang_ArrayIndexOutOfBoundsException, REG_SP, 0 * 4);
4448 i386_mov_reg_membase(REG_ITMP1, REG_SP, 1 * 4);
4449 i386_mov_imm_reg((s4) new_exception_int, REG_ITMP1);
4450 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4451 i386_alu_imm_reg(I386_ADD, 2 * 4, REG_SP);
4453 REMOVE_NATIVE_STACKINFO
4455 i386_pop_reg(REG_ITMP2_XPC);
4457 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4458 i386_jmp_reg(REG_ITMP3);
4462 /* generate negative array size check stubs */
4466 for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
4467 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4468 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
4469 xcheckarefs->branchpos,
4470 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4474 gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos,
4475 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
4479 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4480 dseg_adddata(mcodeptr);
4481 i386_mov_imm_reg(xcheckarefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4482 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4484 if (xcodeptr != NULL) {
4485 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4488 xcodeptr = mcodeptr;
4490 i386_push_reg(REG_ITMP2_XPC);
4492 PREPARE_NATIVE_STACKINFO
4494 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4495 i386_mov_imm_membase((s4) string_java_lang_NegativeArraySizeException, REG_SP, 0 * 4);
4496 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4497 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4498 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4501 REMOVE_NATIVE_STACKINFO
4503 i386_pop_reg(REG_ITMP2_XPC);
4505 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4506 i386_jmp_reg(REG_ITMP3);
4510 /* generate cast check stubs */
4514 for (; xcastrefs != NULL; xcastrefs = xcastrefs->next) {
4515 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4516 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
4517 xcastrefs->branchpos,
4518 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4522 gen_resolvebranch((u1*) mcodebase + xcastrefs->branchpos,
4523 xcastrefs->branchpos, (u1*) mcodeptr - mcodebase);
4527 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4528 dseg_adddata(mcodeptr);
4529 i386_mov_imm_reg(xcastrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4530 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4532 if (xcodeptr != NULL) {
4533 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4536 xcodeptr = mcodeptr;
4538 i386_push_reg(REG_ITMP2_XPC);
4541 PREPARE_NATIVE_STACKINFO
4543 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4544 i386_mov_imm_membase((s4) string_java_lang_ClassCastException, REG_SP, 0 * 4);
4545 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4546 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4547 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4550 REMOVE_NATIVE_STACKINFO
4552 i386_pop_reg(REG_ITMP2_XPC);
4554 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4555 i386_jmp_reg(REG_ITMP3);
4559 /* generate divide by zero check stubs */
4563 for (; xdivrefs != NULL; xdivrefs = xdivrefs->next) {
4564 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4565 gen_resolvebranch((u1*) mcodebase + xdivrefs->branchpos,
4566 xdivrefs->branchpos,
4567 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4571 gen_resolvebranch((u1*) mcodebase + xdivrefs->branchpos,
4572 xdivrefs->branchpos, (u1*) mcodeptr - mcodebase);
4576 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4577 dseg_adddata(mcodeptr);
4578 i386_mov_imm_reg(xdivrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4579 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4581 if (xcodeptr != NULL) {
4582 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4585 xcodeptr = mcodeptr;
4587 i386_push_reg(REG_ITMP2_XPC);
4589 PREPARE_NATIVE_STACKINFO
4591 i386_alu_imm_reg(I386_SUB, 2 * 4, REG_SP);
4592 i386_mov_imm_membase((s4) string_java_lang_ArithmeticException, REG_SP, 0 * 4);
4593 i386_mov_imm_membase((s4) string_java_lang_ArithmeticException_message, REG_SP, 1 * 4);
4594 i386_mov_imm_reg((s4) new_exception_message, REG_ITMP1);
4595 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4596 i386_alu_imm_reg(I386_ADD, 2 * 4, REG_SP);
4598 REMOVE_NATIVE_STACKINFO
4600 i386_pop_reg(REG_ITMP2_XPC);
4602 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4603 i386_jmp_reg(REG_ITMP3);
4607 /* generate exception check stubs */
4611 for (; xexceptionrefs != NULL; xexceptionrefs = xexceptionrefs->next) {
4612 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4613 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
4614 xexceptionrefs->branchpos,
4615 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4619 gen_resolvebranch((u1*) mcodebase + xexceptionrefs->branchpos,
4620 xexceptionrefs->branchpos, (u1*) mcodeptr - mcodebase);
4624 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4625 dseg_adddata(mcodeptr);
4626 i386_mov_imm_reg(xexceptionrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4627 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4629 if (xcodeptr != NULL) {
4630 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4633 xcodeptr = mcodeptr;
4635 i386_push_reg(REG_ITMP2_XPC);
4637 PREPARE_NATIVE_STACKINFO
4639 i386_mov_imm_reg((s4) codegen_general_stubcalled,REG_ITMP1);
4640 i386_call_reg(REG_ITMP1);
4643 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4644 i386_mov_imm_reg((s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4645 i386_call_reg(REG_ITMP1);
4646 i386_mov_membase_reg(REG_RESULT, 0, REG_ITMP3);
4647 i386_mov_imm_membase(0, REG_RESULT, 0);
4648 i386_mov_reg_reg(REG_ITMP3, REG_ITMP1_XPTR);
4650 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP3);
4651 i386_mov_membase_reg(REG_ITMP3, 0, REG_ITMP1_XPTR);
4652 i386_mov_imm_membase(0, REG_ITMP3, 0);
4655 i386_push_reg(REG_ITMP1_XPTR);
4657 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4658 java stack at this point*/
4659 i386_mov_membase_reg(REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4660 i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl,class), REG_ITMP1);
4661 i386_push_imm(utf_fillInStackTrace_desc);
4662 i386_push_imm(utf_fillInStackTrace_name);
4663 i386_push_reg(REG_ITMP1);
4664 i386_mov_imm_reg((s4) class_resolvemethod, REG_ITMP3);
4665 i386_call_reg(REG_ITMP3);
4666 /*cleanup parameters of class_resolvemethod*/
4667 i386_alu_imm_reg(I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4668 /*prepare call to asm_calljavafunction2 */
4670 i386_push_imm(TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4671 i386_push_reg(REG_SP);
4672 i386_push_imm(sizeof(jni_callblock));
4674 i386_push_reg(REG_RESULT);
4676 i386_mov_imm_reg((s4) asm_calljavafunction2, REG_ITMP3);
4677 i386_call_reg(REG_ITMP3);
4679 /* check exceptionptr + fail (JOWENN)*/
4681 i386_alu_imm_reg(I386_ADD,6*4,REG_SP);
4683 i386_pop_reg(REG_ITMP1_XPTR);
4684 i386_pop_reg(REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4685 REMOVE_NATIVE_STACKINFO
4687 i386_pop_reg(REG_ITMP2_XPC);
4689 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4690 i386_jmp_reg(REG_ITMP3);
4694 /* generate null pointer check stubs */
4698 for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
4699 if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
4700 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
4701 xnullrefs->branchpos,
4702 (u1*) xcodeptr - (u1*) mcodebase - (5 + 5 + 2));
4706 gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos,
4707 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
4711 i386_mov_imm_reg(0, REG_ITMP2_XPC); /* 5 bytes */
4712 dseg_adddata(mcodeptr);
4713 i386_mov_imm_reg(xnullrefs->branchpos - 6, REG_ITMP1); /* 5 bytes */
4714 i386_alu_reg_reg(I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4716 if (xcodeptr != NULL) {
4717 i386_jmp_imm(((u1 *) xcodeptr - (u1 *) mcodeptr) - 5);
4720 xcodeptr = mcodeptr;
4722 i386_push_reg(REG_ITMP2_XPC);
4726 PREPARE_NATIVE_STACKINFO
4728 /* create native call block*/
4729 i386_alu_imm_reg(I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4732 i386_mov_imm_reg((s4) codegen_stubcalled,REG_ITMP1);
4733 i386_call_reg(REG_ITMP1); /*call codegen_stubcalled*/
4735 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4736 i386_call_reg(REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4737 i386_mov_imm_membase(0,REG_SP, 2*4); /* builtin */
4738 i386_mov_reg_membase(REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4739 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4740 i386_mov_reg_membase(REG_ITMP2,REG_SP,0*4); /* store value on stack */
4741 i386_mov_reg_membase(REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4747 /* create exception*/
4748 i386_alu_imm_reg(I386_SUB, 1 * 4, REG_SP);
4749 i386_mov_imm_membase((s4) string_java_lang_NullPointerException, REG_SP, 0 * 4);
4750 i386_mov_imm_reg((s4) new_exception, REG_ITMP1);
4751 i386_call_reg(REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4752 i386_alu_imm_reg(I386_ADD, 1 * 4, REG_SP);
4755 REMOVE_NATIVE_STACKINFO
4757 /* restore native call stack */
4758 i386_mov_membase_reg(REG_SP,0,REG_ITMP2);
4759 i386_mov_membase_reg(REG_SP,4,REG_ITMP3);
4760 i386_mov_reg_membase(REG_ITMP2,REG_ITMP3,0);
4761 i386_alu_imm_reg(I386_ADD,3*4,REG_SP);
4765 i386_pop_reg(REG_ITMP2_XPC);
4767 i386_mov_imm_reg((s4) asm_handle_exception, REG_ITMP3);
4768 i386_jmp_reg(REG_ITMP3);
4773 codegen_finish((u4) ((u1 *) mcodeptr - mcodebase));
4777 /* function createcompilerstub *************************************************
4779 creates a stub routine which calls the compiler
4781 *******************************************************************************/
4783 #define COMPSTUBSIZE 12
4785 u1 *createcompilerstub(methodinfo *m)
4787 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4788 mcodeptr = s; /* code generation pointer */
4790 /* code for the stub */
4791 i386_mov_imm_reg((u4) m, REG_ITMP1);/* pass method pointer to compiler */
4793 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4794 i386_mov_imm_reg((u4) asm_call_jit_compiler, REG_ITMP3); /* load address */
4795 i386_jmp_reg(REG_ITMP3); /* jump to compiler */
4797 #if defined(STATISTICS)
4799 count_cstub_len += COMPSTUBSIZE;
4806 /* function removecompilerstub *************************************************
4808 deletes a compilerstub from memory (simply by freeing it)
4810 *******************************************************************************/
4812 void removecompilerstub(u1 *stub)
4814 CFREE(stub, COMPSTUBSIZE);
4818 /* function: createnativestub **************************************************
4820 creates a stub routine which calls a native method
4822 *******************************************************************************/
4824 #define NATIVESTUBSIZE 350
4826 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4827 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4830 void i386_native_stub_debug(void **p) {
4831 printf("Pos on stack: %p\n",p);
4832 printf("Return adress should be: %p\n",*p);
4835 void i386_native_stub_debug2(void **p) {
4836 printf("Pos on stack: %p\n",p);
4837 printf("Return for lookup is: %p\n",*p);
4840 void traverseStackInfo() {
4841 void **p=builtin_asm_get_stackframeinfo();
4844 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4845 methodinfo *m=*((methodinfo**)((*p)+8));
4846 utf_display(m->name);
4854 u1 *createnativestub(functionptr f, methodinfo *m)
4856 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4860 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4861 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4862 int stackframeoffset = 4;
4866 mcodeptr = s; /* make macros work */
4868 if (m->flags & ACC_STATIC) {
4869 stackframesize += 4;
4870 stackframeoffset += 4;
4874 descriptor2types(m); /* set paramcount and paramtypes */
4877 /* i386_push_reg(REG_SP);
4878 i386_mov_imm_reg((s4) i386_native_stub_debug, REG_ITMP1);
4879 i386_call_reg(REG_ITMP1);
4880 i386_pop_reg(REG_ITMP1);*/
4883 /* if function is static, check for initialized */
4885 if (m->flags & ACC_STATIC) {
4886 /* if class isn't yet initialized, do it */
4887 if (!m->class->initialized) {
4888 /* call helper function which patches this code */
4889 i386_mov_imm_reg((s4) m->class, REG_ITMP1);
4890 i386_mov_imm_reg((s4) asm_check_clinit, REG_ITMP2);
4891 i386_call_reg(REG_ITMP2);
4896 i386_alu_imm_reg(I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4898 for (p = 0; p < m->paramcount; p++) {
4899 t = m->paramtypes[p];
4900 if (IS_INT_LNG_TYPE(t)) {
4901 if (IS_2_WORD_TYPE(t)) {
4902 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4903 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4904 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4905 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4907 } else if (t == TYPE_ADR) {
4908 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4909 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
4910 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4911 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4914 i386_mov_membase_reg(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4916 i386_mov_reg_membase(EAX, REG_SP, p * 8);
4917 i386_mov_reg_membase(EDX, REG_SP, p * 8 + 4);
4921 if (!IS_2_WORD_TYPE(t)) {
4922 i386_flds_membase(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4923 i386_fstps_membase(REG_SP, p * 8);
4924 i386_alu_reg_reg(I386_XOR, REG_ITMP2, REG_ITMP2);
4925 i386_mov_reg_membase(REG_ITMP2, REG_SP, p * 8 + 4);
4928 i386_fldl_membase(REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4929 i386_fstpl_membase(REG_SP, p * 8);
4934 i386_alu_reg_reg(I386_XOR, REG_ITMP1, REG_ITMP1);
4935 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
4936 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8);
4937 i386_mov_reg_membase(REG_ITMP1, REG_SP, p * 8 + 4);
4940 i386_mov_imm_membase((s4) m, REG_SP, TRACE_ARGS_NUM * 8);
4942 i386_mov_imm_reg((s4) builtin_trace_args, REG_ITMP1);
4943 i386_call_reg(REG_ITMP1);
4945 i386_alu_imm_reg(I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4949 * mark the whole fpu stack as free for native functions
4950 * (only for saved register count == 0)
4961 /* calculate stackframe size for native function */
4962 tptr = m->paramtypes;
4963 for (i = 0; i < m->paramcount; i++) {
4968 stackframesize += 4;
4973 stackframesize += 8;
4977 panic("unknown parameter type in native function");
4981 i386_alu_imm_reg(I386_SUB, stackframesize, REG_SP);
4983 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
4984 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-4);
4985 i386_mov_imm_reg((s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
4986 i386_call_reg(REG_ITMP1);
4987 i386_mov_reg_membase(REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
4988 i386_mov_membase_reg(REG_RESULT,0,REG_ITMP2);
4989 i386_mov_reg_membase(REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
4990 i386_mov_reg_reg(REG_SP,REG_ITMP2);
4991 i386_alu_imm_reg(I386_ADD,stackframesize-12,REG_ITMP2);
4992 i386_mov_reg_membase(REG_ITMP2,REG_RESULT,0);
4995 /* i386_mov_imm_membase((s4) m, REG_SP,stackframesize-4);
4996 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-8);
4997 i386_mov_imm_membase((s4) m, REG_SP,stackframesize-12);*/
4999 /* CREATE DYNAMIC STACK INFO -- END*/
5002 tptr = m->paramtypes;
5003 for (i = 0; i < m->paramcount; i++) {
5008 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5009 i386_mov_reg_membase(REG_ITMP1, REG_SP, stackframeoffset);
5010 stackframeoffset += 4;
5015 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5016 i386_mov_membase_reg(REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5017 i386_mov_reg_membase(REG_ITMP1, REG_SP, stackframeoffset);
5018 i386_mov_reg_membase(REG_ITMP2, REG_SP, stackframeoffset + 4);
5019 stackframeoffset += 8;
5023 panic("unknown parameter type in native function");
5027 if (m->flags & ACC_STATIC) {
5028 /* put class into second argument */
5029 i386_mov_imm_membase((s4) m->class, REG_SP, 4);
5032 /* put env into first argument */
5033 i386_mov_imm_membase((s4) &env, REG_SP, 0);
5035 i386_mov_imm_reg((s4) f, REG_ITMP1);
5036 i386_call_reg(REG_ITMP1);
5037 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5038 i386_push_reg(REG_RESULT2);
5039 i386_mov_membase_reg(REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5040 i386_mov_membase_reg(REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5041 i386_mov_reg_membase(REG_ITMP2,REG_RESULT2,0);
5042 i386_pop_reg(REG_RESULT2);
5043 /*REMOVE DYNAMIC STACK INFO -END */
5045 i386_alu_imm_reg(I386_ADD, stackframesize, REG_SP);
5049 i386_alu_imm_reg(I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5051 i386_mov_imm_membase((s4) m, REG_SP, 0);
5053 i386_mov_reg_membase(REG_RESULT, REG_SP, 4);
5054 i386_mov_reg_membase(REG_RESULT2, REG_SP, 4 + 4);
5056 i386_fstl_membase(REG_SP, 4 + 8);
5057 i386_fsts_membase(REG_SP, 4 + 8 + 8);
5059 i386_mov_imm_reg((s4) builtin_displaymethodstop, REG_ITMP1);
5060 i386_call_reg(REG_ITMP1);
5062 i386_mov_membase_reg(REG_SP, 4, REG_RESULT);
5063 i386_mov_membase_reg(REG_SP, 4 + 4, REG_RESULT2);
5065 i386_alu_imm_reg(I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5069 /* we can't use REG_ITMP3 == REG_RESULT2 */
5070 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5071 i386_push_reg(REG_RESULT);
5072 i386_push_reg(REG_RESULT2);
5073 i386_call_mem((s4) &callgetexceptionptrptr);
5074 i386_mov_membase_reg(REG_RESULT, 0, REG_ITMP2);
5075 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
5076 i386_pop_reg(REG_RESULT2);
5077 i386_pop_reg(REG_RESULT);
5079 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP2);
5080 i386_mov_membase_reg(REG_ITMP2, 0, REG_ITMP2);
5081 i386_test_reg_reg(REG_ITMP2, REG_ITMP2);
5083 i386_jcc(I386_CC_NE, 1);
5087 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5088 i386_push_reg(REG_ITMP2);
5089 i386_call_mem((s4) &callgetexceptionptrptr);
5090 i386_mov_imm_membase(0, REG_RESULT, 0);
5091 i386_pop_reg(REG_ITMP1_XPTR);
5093 i386_mov_reg_reg(REG_ITMP2, REG_ITMP1_XPTR);
5094 i386_mov_imm_reg((s4) &_exceptionptr, REG_ITMP2);
5095 i386_mov_imm_membase(0, REG_ITMP2, 0);
5097 i386_mov_membase_reg(REG_SP, 0, REG_ITMP2_XPC);
5098 i386_alu_imm_reg(I386_SUB, 2, REG_ITMP2_XPC);
5100 i386_mov_imm_reg((s4) asm_handle_nat_exception, REG_ITMP3);
5101 i386_jmp_reg(REG_ITMP3);
5104 dolog_plain("stubsize: %d (for %d params)\n", (s4) (mcodeptr - s), m->paramcount);
5107 #if defined(STATISTICS)
5109 count_nstub_len += NATIVESTUBSIZE;
5116 /* function: removenativestub **************************************************
5118 removes a previously created native-stub from memory
5120 *******************************************************************************/
5122 void removenativestub(u1 *stub)
5124 CFREE(stub, NATIVESTUBSIZE);
5129 * These are local overrides for various environment variables in Emacs.
5130 * Please do not remove this and leave it at the end of the file, where
5131 * Emacs will automagically detect them.
5132 * ---------------------------------------------------------------------
5135 * indent-tabs-mode: t