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 1506 2004-11-14 14:48:49Z jowenn $
41 #include <sys/ucontext.h>
46 #include "exceptions.h"
52 #include "jit/parse.h"
54 #include "jit/i386/codegen.h"
55 #include "jit/i386/emitfuncs.h"
58 /* register descripton - array ************************************************/
60 /* #define REG_RES 0 reserved register for OS or code generator */
61 /* #define REG_RET 1 return value register */
62 /* #define REG_EXC 2 exception value register (only old jit) */
63 /* #define REG_SAV 3 (callee) saved register */
64 /* #define REG_TMP 4 scratch temporary register (caller saved) */
65 /* #define REG_ARG 5 argument register (caller saved) */
67 /* #define REG_END -1 last entry in tables */
70 REG_RET, REG_RES, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
75 int nregdescfloat[] = {
76 /* rounding problems with callee saved registers */
77 /* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
78 /* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
79 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
84 /*******************************************************************************
86 include independent code generation stuff -- include after register
87 descriptions to avoid extern definitions
89 *******************************************************************************/
91 #include "jit/codegen.inc"
92 #include "jit/reg.inc"
95 void codegen_stubcalled() {
96 log_text("Stub has been called");
99 void codegen_general_stubcalled() {
100 log_text("general exception stub has been called");
104 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
105 void thread_restartcriticalsection(ucontext_t *uc)
108 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
109 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
114 #define PREPARE_NATIVE_STACKINFO \
115 i386_push_reg(cd, REG_ITMP1); /*save itmp1, needed by some stubs */ \
116 i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
117 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \
118 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/ \
119 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
120 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
121 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
122 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
123 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
124 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
125 i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
126 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
129 #define REMOVE_NATIVE_STACKINFO \
130 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \
131 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \
132 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \
133 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
136 /* NullPointerException signal handler for hardware null pointer check */
138 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
141 /* long faultaddr; */
143 struct ucontext *_uc = (struct ucontext *) _p;
144 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
145 struct sigaction act;
147 /* Reset signal handler - necessary for SysV, does no harm for BSD */
149 /* instr = *((int*)(sigctx->eip)); */
150 /* faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
152 /* fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
154 /* if (faultaddr == 0) { */
155 /* signal(sig, (void *) catch_NullPointerException); */
156 act.sa_sigaction = (void *) catch_NullPointerException;
157 act.sa_flags = SA_SIGINFO;
158 sigaction(sig, &act, NULL); /* reinstall handler */
161 sigaddset(&nsig, sig);
162 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
164 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
165 sigctx->eax = (u4) string_java_lang_NullPointerException;
166 sigctx->eip = (u4) asm_throw_and_handle_exception;
171 /* faultaddr += (long) ((instr << 16) >> 16); */
172 /* fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
173 /* panic("Stack overflow"); */
178 /* ArithmeticException signal handler for hardware divide by zero check */
180 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
184 /* void **_p = (void **) &sig; */
185 /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
186 struct ucontext *_uc = (struct ucontext *) _p;
187 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
188 struct sigaction act;
190 /* Reset signal handler - necessary for SysV, does no harm for BSD */
192 /* signal(sig, (void *) catch_ArithmeticException); */
193 act.sa_sigaction = (void *) catch_ArithmeticException;
194 act.sa_flags = SA_SIGINFO;
195 sigaction(sig, &act, NULL); /* reinstall handler */
198 sigaddset(&nsig, sig);
199 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
201 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
202 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
208 void init_exceptions(void)
210 struct sigaction act;
212 /* install signal handlers we need to convert to exceptions */
213 sigemptyset(&act.sa_mask);
217 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
218 act.sa_sigaction = (void *) catch_NullPointerException;
219 act.sa_flags = SA_SIGINFO;
220 sigaction(SIGSEGV, &act, NULL);
224 /* signal(SIGBUS, (void *) catch_NullPointerException); */
225 act.sa_sigaction = (void *) catch_NullPointerException;
226 act.sa_flags = SA_SIGINFO;
227 sigaction(SIGBUS, &act, NULL);
231 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
232 act.sa_sigaction = (void *) catch_ArithmeticException;
233 act.sa_flags = SA_SIGINFO;
234 sigaction(SIGFPE, &act, NULL);
238 /* function codegen ************************************************************
240 generates machine code
242 *******************************************************************************/
244 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
246 s4 len, s1, s2, s3, d;
254 s4 fpu_st_offset = 0;
260 s4 savedregs_num = 0;
262 /* space to save used callee saved registers */
264 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
265 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
267 parentargs_base = rd->maxmemuse + savedregs_num;
269 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
271 if (checksync && (m->flags & ACC_SYNCHRONIZED))
276 /* create method header */
278 (void) dseg_addaddress(cd, m); /* MethodPointer */
279 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
281 #if defined(USE_THREADS)
283 /* IsSync contains the offset relative to the stack pointer for the
284 argument of monitor_exit used in the exception handler. Since the
285 offset could be zero and give a wrong meaning of the flag it is
289 if (checksync && (m->flags & ACC_SYNCHRONIZED))
290 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
295 (void) dseg_adds4(cd, 0); /* IsSync */
297 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
298 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
299 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
301 /* adds a reference for the length of the line number counter. We don't
302 know the size yet, since we evaluate the information during code
303 generation, to save one additional iteration over the whole
304 instructions. During code optimization the position could have changed
305 to the information gotten from the class file */
306 (void) dseg_addlinenumbertablesize(cd);
308 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
310 /* create exception table */
312 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
313 dseg_addtarget(cd, ex->start);
314 dseg_addtarget(cd, ex->end);
315 dseg_addtarget(cd, ex->handler);
316 (void) dseg_addaddress(cd, ex->catchtype);
320 /* initialize mcode variables */
322 cd->mcodeptr = cd->mcodebase;
323 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
324 MCODECHECK(128 + m->paramcount);
326 /* create stack frame (if necessary) */
328 if (parentargs_base) {
329 i386_alu_imm_reg(cd, I386_SUB, parentargs_base * 8, REG_SP);
332 /* save return address and used callee saved registers */
335 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
336 p--; i386_mov_reg_membase(cd, rd->savintregs[i], REG_SP, p * 8);
338 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
339 p--; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 8);
342 /* save monitorenter argument */
344 #if defined(USE_THREADS)
345 s4 func_enter = (m->flags & ACC_STATIC) ?
346 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
348 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
349 if (m->flags & ACC_STATIC) {
350 i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
351 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
354 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
355 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
358 /* call monitorenter function */
360 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
361 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
362 i386_mov_imm_reg(cd, func_enter, REG_ITMP1);
363 i386_call_reg(cd, REG_ITMP1);
364 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
368 /* copy argument registers to stack and call trace function with pointer
369 to arguments on stack.
373 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
375 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
376 t = m->paramtypes[p];
378 if (IS_INT_LNG_TYPE(t)) {
379 if (IS_2_WORD_TYPE(t)) {
380 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
381 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
382 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
383 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
385 /* } else if (t == TYPE_ADR) { */
387 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
388 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
389 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
390 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
393 /* i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
395 /* i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */
396 /* i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */
400 if (!IS_2_WORD_TYPE(t)) {
401 i386_flds_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
402 i386_fstps_membase(cd, REG_SP, p * 8);
403 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
404 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
407 i386_fldl_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
408 i386_fstpl_membase(cd, REG_SP, p * 8);
413 /* fill up the remaining arguments */
414 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
415 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
416 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
417 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
420 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
421 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
422 i386_call_reg(cd, REG_ITMP1);
424 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
427 /* take arguments out of register or stack frame */
429 for (p = 0, l = 0; p < m->paramcount; p++) {
430 t = m->paramtypes[p];
431 var = &(rd->locals[l][t]);
433 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
437 if (IS_INT_LNG_TYPE(t)) { /* integer args */
438 if (p < rd->intreg_argnum) { /* register arguments */
439 panic("integer register argument");
440 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
441 /* M_INTMOVE (argintregs[p], r); */
443 } else { /* reg arg -> spilled */
444 /* M_LST (argintregs[p], REG_SP, 8 * r); */
446 } else { /* stack arguments */
447 pa = p - rd->intreg_argnum;
448 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
449 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
450 } else { /* stack arg -> spilled */
451 if (!IS_2_WORD_TYPE(t)) {
452 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
453 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
456 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
457 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
458 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
459 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8 + 4);
464 } else { /* floating args */
465 if (p < rd->fltreg_argnum) { /* register arguments */
466 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
467 panic("There are no float argument registers!");
469 } else { /* reg arg -> spilled */
470 panic("There are no float argument registers!");
473 } else { /* stack arguments */
474 pa = p - rd->fltreg_argnum;
475 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
477 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
479 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
483 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
485 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
489 } else { /* stack-arg -> spilled */
490 /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
491 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */
493 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
494 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
497 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
498 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
507 /* end of header generation */
509 /* walk through all basic blocks */
510 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
512 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
514 if (bptr->flags >= BBREACHED) {
516 /* branch resolving */
519 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
520 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
525 /* copy interface registers to their destination */
530 while (src != NULL) {
532 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
533 if (!IS_2_WORD_TYPE(src->type)) {
534 if (bptr->type == BBTYPE_SBR) {
535 d = reg_of_var(rd, src, REG_ITMP1);
537 store_reg_to_var_int(src, d);
539 } else if (bptr->type == BBTYPE_EXH) {
540 d = reg_of_var(rd, src, REG_ITMP1);
541 M_INTMOVE(REG_ITMP1, d);
542 store_reg_to_var_int(src, d);
546 panic("copy interface registers: longs have to me in memory (begin 1)");
550 d = reg_of_var(rd, src, REG_ITMP1);
551 if ((src->varkind != STACKVAR)) {
553 if (IS_FLT_DBL_TYPE(s2)) {
554 s1 = rd->interfaces[len][s2].regoff;
555 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
559 if (s2 == TYPE_FLT) {
560 i386_flds_membase(cd, REG_SP, s1 * 8);
563 i386_fldl_membase(cd, REG_SP, s1 * 8);
566 store_reg_to_var_flt(src, d);
569 s1 = rd->interfaces[len][s2].regoff;
570 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
571 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
575 i386_mov_membase_reg(cd, REG_SP, s1 * 8, d);
577 store_reg_to_var_int(src, d);
580 if (rd->interfaces[len][s2].flags & INMEMORY) {
581 M_LNGMEMMOVE(s1, src->regoff);
584 panic("copy interface registers: longs have to be in memory (begin 2)");
593 /* walk through all instructions */
598 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
599 if (iptr->line != currentline) {
600 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
601 currentline = iptr->line;
604 MCODECHECK(64); /* an instruction usually needs < 64 words */
607 case ICMD_NOP: /* ... ==> ... */
610 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
611 if (src->flags & INMEMORY) {
612 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
615 i386_test_reg_reg(cd, src->regoff, src->regoff);
617 i386_jcc(cd, I386_CC_E, 0);
618 codegen_addxnullrefs(cd, cd->mcodeptr);
621 /* constant operations ************************************************/
623 case ICMD_ICONST: /* ... ==> ..., constant */
624 /* op1 = 0, val.i = constant */
626 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
627 if (iptr->dst->flags & INMEMORY) {
628 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
631 if (iptr->val.i == 0) {
632 i386_alu_reg_reg(cd, I386_XOR, d, d);
635 i386_mov_imm_reg(cd, iptr->val.i, d);
640 case ICMD_LCONST: /* ... ==> ..., constant */
641 /* op1 = 0, val.l = constant */
643 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
644 if (iptr->dst->flags & INMEMORY) {
645 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
646 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
649 panic("LCONST: longs have to be in memory");
653 case ICMD_FCONST: /* ... ==> ..., constant */
654 /* op1 = 0, val.f = constant */
656 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
657 if (iptr->val.f == 0.0) {
662 if (iptr->val.i == 0x80000000) {
666 } else if (iptr->val.f == 1.0) {
670 } else if (iptr->val.f == 2.0) {
677 a = dseg_addfloat(cd, iptr->val.f);
678 i386_mov_imm_reg(cd, 0, REG_ITMP1);
679 dseg_adddata(cd, cd->mcodeptr);
680 i386_flds_membase(cd, REG_ITMP1, a);
683 store_reg_to_var_flt(iptr->dst, d);
686 case ICMD_DCONST: /* ... ==> ..., constant */
687 /* op1 = 0, val.d = constant */
689 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
690 if (iptr->val.d == 0.0) {
695 if (iptr->val.l == 0x8000000000000000LL) {
699 } else if (iptr->val.d == 1.0) {
703 } else if (iptr->val.d == 2.0) {
710 a = dseg_adddouble(cd, iptr->val.d);
711 i386_mov_imm_reg(cd, 0, REG_ITMP1);
712 dseg_adddata(cd, cd->mcodeptr);
713 i386_fldl_membase(cd, REG_ITMP1, a);
716 store_reg_to_var_flt(iptr->dst, d);
719 case ICMD_ACONST: /* ... ==> ..., constant */
720 /* op1 = 0, val.a = constant */
722 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
723 if (iptr->dst->flags & INMEMORY) {
724 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
727 if ((s4) iptr->val.a == 0) {
728 i386_alu_reg_reg(cd, I386_XOR, d, d);
731 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
737 /* load/store operations **********************************************/
739 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
740 case ICMD_ALOAD: /* op1 = local variable */
742 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
743 if ((iptr->dst->varkind == LOCALVAR) &&
744 (iptr->dst->varnum == iptr->op1)) {
747 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
748 if (iptr->dst->flags & INMEMORY) {
749 if (var->flags & INMEMORY) {
750 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
751 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
754 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
758 if (var->flags & INMEMORY) {
759 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
762 M_INTMOVE(var->regoff, iptr->dst->regoff);
767 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
768 /* op1 = local variable */
770 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
771 if ((iptr->dst->varkind == LOCALVAR) &&
772 (iptr->dst->varnum == iptr->op1)) {
775 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
776 if (iptr->dst->flags & INMEMORY) {
777 if (var->flags & INMEMORY) {
778 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
781 panic("LLOAD: longs have to be in memory");
785 panic("LLOAD: longs have to be in memory");
789 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
790 /* op1 = local variable */
792 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
793 if ((iptr->dst->varkind == LOCALVAR) &&
794 (iptr->dst->varnum == iptr->op1)) {
797 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
798 if (var->flags & INMEMORY) {
799 i386_flds_membase(cd, REG_SP, var->regoff * 8);
802 i386_fld_reg(cd, var->regoff + fpu_st_offset);
805 store_reg_to_var_flt(iptr->dst, d);
808 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
809 /* op1 = local variable */
811 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
812 if ((iptr->dst->varkind == LOCALVAR) &&
813 (iptr->dst->varnum == iptr->op1)) {
816 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
817 if (var->flags & INMEMORY) {
818 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
821 i386_fld_reg(cd, var->regoff + fpu_st_offset);
824 store_reg_to_var_flt(iptr->dst, d);
827 case ICMD_ISTORE: /* ..., value ==> ... */
828 case ICMD_ASTORE: /* op1 = local variable */
830 if ((src->varkind == LOCALVAR) &&
831 (src->varnum == iptr->op1)) {
834 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
835 if (var->flags & INMEMORY) {
836 if (src->flags & INMEMORY) {
837 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
838 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
841 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
845 var_to_reg_int(s1, src, var->regoff);
846 M_INTMOVE(s1, var->regoff);
850 case ICMD_LSTORE: /* ..., value ==> ... */
851 /* op1 = local variable */
853 if ((src->varkind == LOCALVAR) &&
854 (src->varnum == iptr->op1)) {
857 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
858 if (var->flags & INMEMORY) {
859 if (src->flags & INMEMORY) {
860 M_LNGMEMMOVE(src->regoff, var->regoff);
863 panic("LSTORE: longs have to be in memory");
867 panic("LSTORE: longs have to be in memory");
871 case ICMD_FSTORE: /* ..., value ==> ... */
872 /* op1 = local variable */
874 if ((src->varkind == LOCALVAR) &&
875 (src->varnum == iptr->op1)) {
878 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
879 if (var->flags & INMEMORY) {
880 var_to_reg_flt(s1, src, REG_FTMP1);
881 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
884 var_to_reg_flt(s1, src, var->regoff);
885 /* M_FLTMOVE(s1, var->regoff); */
886 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
891 case ICMD_DSTORE: /* ..., value ==> ... */
892 /* op1 = local variable */
894 if ((src->varkind == LOCALVAR) &&
895 (src->varnum == iptr->op1)) {
898 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
899 if (var->flags & INMEMORY) {
900 var_to_reg_flt(s1, src, REG_FTMP1);
901 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
904 var_to_reg_flt(s1, src, var->regoff);
905 /* M_FLTMOVE(s1, var->regoff); */
906 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
912 /* pop/dup/swap operations ********************************************/
914 /* attention: double and longs are only one entry in CACAO ICMDs */
916 case ICMD_POP: /* ..., value ==> ... */
917 case ICMD_POP2: /* ..., value, value ==> ... */
920 case ICMD_DUP: /* ..., a ==> ..., a, a */
921 M_COPY(src, iptr->dst);
924 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
926 M_COPY(src, iptr->dst);
927 M_COPY(src->prev, iptr->dst->prev);
930 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
932 M_COPY(src, iptr->dst);
933 M_COPY(src->prev, iptr->dst->prev);
934 M_COPY(iptr->dst, iptr->dst->prev->prev);
937 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
939 M_COPY(src, iptr->dst);
940 M_COPY(src->prev, iptr->dst->prev);
941 M_COPY(src->prev->prev, iptr->dst->prev->prev);
942 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
945 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
947 M_COPY(src, iptr->dst);
948 M_COPY(src->prev, iptr->dst->prev);
949 M_COPY(src->prev->prev, iptr->dst->prev->prev);
950 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
951 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
954 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
956 M_COPY(src, iptr->dst);
957 M_COPY(src->prev, iptr->dst->prev);
958 M_COPY(src->prev->prev, iptr->dst->prev->prev);
959 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
960 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
961 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
964 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
966 M_COPY(src, iptr->dst->prev);
967 M_COPY(src->prev, iptr->dst);
971 /* integer operations *************************************************/
973 case ICMD_INEG: /* ..., value ==> ..., - value */
975 d = reg_of_var(rd, iptr->dst, REG_NULL);
976 if (iptr->dst->flags & INMEMORY) {
977 if (src->flags & INMEMORY) {
978 if (src->regoff == iptr->dst->regoff) {
979 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
982 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
983 i386_neg_reg(cd, REG_ITMP1);
984 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
988 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
989 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
993 if (src->flags & INMEMORY) {
994 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
995 i386_neg_reg(cd, iptr->dst->regoff);
998 M_INTMOVE(src->regoff, iptr->dst->regoff);
999 i386_neg_reg(cd, iptr->dst->regoff);
1004 case ICMD_LNEG: /* ..., value ==> ..., - value */
1006 d = reg_of_var(rd, iptr->dst, REG_NULL);
1007 if (iptr->dst->flags & INMEMORY) {
1008 if (src->flags & INMEMORY) {
1009 if (src->regoff == iptr->dst->regoff) {
1010 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1011 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1012 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
1015 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1016 i386_neg_reg(cd, REG_ITMP1);
1017 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1018 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1019 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1020 i386_neg_reg(cd, REG_ITMP1);
1021 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1027 case ICMD_I2L: /* ..., value ==> ..., value */
1029 d = reg_of_var(rd, iptr->dst, REG_NULL);
1030 if (iptr->dst->flags & INMEMORY) {
1031 if (src->flags & INMEMORY) {
1032 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1034 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1035 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1038 M_INTMOVE(src->regoff, EAX);
1040 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1041 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1046 case ICMD_L2I: /* ..., value ==> ..., value */
1048 d = reg_of_var(rd, iptr->dst, REG_NULL);
1049 if (iptr->dst->flags & INMEMORY) {
1050 if (src->flags & INMEMORY) {
1051 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1052 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1056 if (src->flags & INMEMORY) {
1057 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1062 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1064 d = reg_of_var(rd, iptr->dst, REG_NULL);
1065 if (iptr->dst->flags & INMEMORY) {
1066 if (src->flags & INMEMORY) {
1067 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1068 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1069 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1070 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1073 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1074 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1075 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1079 if (src->flags & INMEMORY) {
1080 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1081 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1082 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1085 M_INTMOVE(src->regoff, iptr->dst->regoff);
1086 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1087 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1092 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1094 d = reg_of_var(rd, iptr->dst, REG_NULL);
1095 if (iptr->dst->flags & INMEMORY) {
1096 if (src->flags & INMEMORY) {
1097 if (src->regoff == iptr->dst->regoff) {
1098 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1101 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1102 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1103 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1107 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1108 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1112 if (src->flags & INMEMORY) {
1113 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1114 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1117 M_INTMOVE(src->regoff, iptr->dst->regoff);
1118 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1123 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1125 d = reg_of_var(rd, iptr->dst, REG_NULL);
1126 if (iptr->dst->flags & INMEMORY) {
1127 if (src->flags & INMEMORY) {
1128 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1129 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1130 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1131 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1134 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1135 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1136 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1140 if (src->flags & INMEMORY) {
1141 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1142 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1143 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1146 M_INTMOVE(src->regoff, iptr->dst->regoff);
1147 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1148 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1154 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1156 d = reg_of_var(rd, iptr->dst, REG_NULL);
1157 i386_emit_ialu(cd, I386_ADD, src, iptr);
1160 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1161 /* val.i = constant */
1163 d = reg_of_var(rd, iptr->dst, REG_NULL);
1164 /* should we use a inc optimization for smaller code size? */
1165 i386_emit_ialuconst(cd, I386_ADD, src, iptr);
1168 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1170 d = reg_of_var(rd, iptr->dst, REG_NULL);
1171 if (iptr->dst->flags & INMEMORY) {
1172 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1173 if (src->regoff == iptr->dst->regoff) {
1174 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1175 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1176 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1177 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1179 } else if (src->prev->regoff == iptr->dst->regoff) {
1180 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1181 i386_alu_reg_membase(cd, I386_ADD, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1182 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1183 i386_alu_reg_membase(cd, I386_ADC, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1186 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1187 i386_alu_membase_reg(cd, I386_ADD, REG_SP, src->regoff * 8, REG_ITMP1);
1188 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1189 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1190 i386_alu_membase_reg(cd, I386_ADC, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1191 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1198 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
1199 /* val.l = constant */
1201 d = reg_of_var(rd, iptr->dst, REG_NULL);
1202 if (iptr->dst->flags & INMEMORY) {
1203 if (src->flags & INMEMORY) {
1204 if (src->regoff == iptr->dst->regoff) {
1205 i386_alu_imm_membase(cd, I386_ADD, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1206 i386_alu_imm_membase(cd, I386_ADC, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1209 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1210 i386_alu_imm_reg(cd, I386_ADD, iptr->val.l, REG_ITMP1);
1211 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1212 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1213 i386_alu_imm_reg(cd, I386_ADC, iptr->val.l >> 32, REG_ITMP1);
1214 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1220 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1222 d = reg_of_var(rd, iptr->dst, REG_NULL);
1223 if (iptr->dst->flags & INMEMORY) {
1224 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1225 if (src->prev->regoff == iptr->dst->regoff) {
1226 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1227 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1230 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1231 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1232 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1235 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1236 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1237 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1238 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1240 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1241 if (src->prev->regoff == iptr->dst->regoff) {
1242 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1245 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1246 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1247 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1251 i386_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1252 i386_alu_reg_membase(cd, I386_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1256 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1257 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1258 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1260 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1261 M_INTMOVE(src->prev->regoff, d);
1262 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, d);
1264 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1265 /* workaround for reg alloc */
1266 if (src->regoff == iptr->dst->regoff) {
1267 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1268 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1269 M_INTMOVE(REG_ITMP1, d);
1272 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1273 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1277 /* workaround for reg alloc */
1278 if (src->regoff == iptr->dst->regoff) {
1279 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1280 i386_alu_reg_reg(cd, I386_SUB, src->regoff, REG_ITMP1);
1281 M_INTMOVE(REG_ITMP1, d);
1284 M_INTMOVE(src->prev->regoff, d);
1285 i386_alu_reg_reg(cd, I386_SUB, src->regoff, d);
1291 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1292 /* val.i = constant */
1294 d = reg_of_var(rd, iptr->dst, REG_NULL);
1295 i386_emit_ialuconst(cd, I386_SUB, src, iptr);
1298 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1300 d = reg_of_var(rd, iptr->dst, REG_NULL);
1301 if (iptr->dst->flags & INMEMORY) {
1302 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1303 if (src->prev->regoff == iptr->dst->regoff) {
1304 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1305 i386_alu_reg_membase(cd, I386_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1306 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1307 i386_alu_reg_membase(cd, I386_SBB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1310 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1311 i386_alu_membase_reg(cd, I386_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1312 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1313 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
1314 i386_alu_membase_reg(cd, I386_SBB, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1315 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1321 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1322 /* val.l = constant */
1324 d = reg_of_var(rd, iptr->dst, REG_NULL);
1325 if (iptr->dst->flags & INMEMORY) {
1326 if (src->flags & INMEMORY) {
1327 if (src->regoff == iptr->dst->regoff) {
1328 i386_alu_imm_membase(cd, I386_SUB, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
1329 i386_alu_imm_membase(cd, I386_SBB, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
1332 /* TODO: could be size optimized with lea -- see gcc output */
1333 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1334 i386_alu_imm_reg(cd, I386_SUB, iptr->val.l, REG_ITMP1);
1335 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1336 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1337 i386_alu_imm_reg(cd, I386_SBB, iptr->val.l >> 32, REG_ITMP1);
1338 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1344 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1346 d = reg_of_var(rd, iptr->dst, REG_NULL);
1347 if (iptr->dst->flags & INMEMORY) {
1348 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1349 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1350 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1351 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1353 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1354 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1355 i386_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1356 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1358 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1359 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1360 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1361 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1364 i386_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1365 i386_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1366 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1370 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1371 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1372 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1374 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1375 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1376 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1378 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1379 M_INTMOVE(src->regoff, iptr->dst->regoff);
1380 i386_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1383 if (src->regoff == iptr->dst->regoff) {
1384 i386_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1387 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1388 i386_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1394 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1395 /* val.i = constant */
1397 d = reg_of_var(rd, iptr->dst, REG_NULL);
1398 if (iptr->dst->flags & INMEMORY) {
1399 if (src->flags & INMEMORY) {
1400 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1401 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1404 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1405 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1409 if (src->flags & INMEMORY) {
1410 i386_imul_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1413 i386_imul_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);
1418 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1420 d = reg_of_var(rd, iptr->dst, REG_NULL);
1421 if (iptr->dst->flags & INMEMORY) {
1422 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1423 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX); /* mem -> EAX */
1424 /* optimize move EAX -> REG_ITMP3 is slower??? */
1425 /* i386_mov_reg_reg(cd, EAX, REG_ITMP3); */
1426 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1428 /* TODO: optimize move EAX -> REG_ITMP3 */
1429 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); /* mem -> ITMP3 */
1430 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1431 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1433 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP2); /* mem -> ITMP3 */
1434 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1436 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1437 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1438 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1443 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1444 /* val.l = constant */
1446 d = reg_of_var(rd, iptr->dst, REG_NULL);
1447 if (iptr->dst->flags & INMEMORY) {
1448 if (src->flags & INMEMORY) {
1449 i386_mov_imm_reg(cd, iptr->val.l, EAX); /* imm -> EAX */
1450 i386_mul_membase(cd, REG_SP, src->regoff * 8); /* mem * EAX -> EDX:EAX */
1451 /* TODO: optimize move EAX -> REG_ITMP3 */
1452 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2); /* imm -> ITMP3 */
1453 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1455 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1456 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP2); /* imm -> ITMP3 */
1457 i386_imul_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); /* mem * ITMP3 -> ITMP3 */
1459 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP2, EDX); /* ITMP3 + EDX -> EDX */
1460 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1461 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1466 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1468 d = reg_of_var(rd, iptr->dst, REG_NULL);
1469 var_to_reg_int(s1, src, REG_ITMP2);
1471 if (src->prev->flags & INMEMORY) {
1472 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1475 M_INTMOVE(src->prev->regoff, EAX);
1478 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1479 i386_jcc(cd, I386_CC_NE, 3 + 6);
1480 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1481 i386_jcc(cd, I386_CC_E, 1 + 2);
1484 i386_idiv_reg(cd, s1);
1486 if (iptr->dst->flags & INMEMORY) {
1487 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1490 M_INTMOVE(EAX, iptr->dst->regoff);
1494 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1496 d = reg_of_var(rd, iptr->dst, REG_NULL);
1497 var_to_reg_int(s1, src, REG_ITMP2);
1499 if (src->prev->flags & INMEMORY) {
1500 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, EAX);
1503 M_INTMOVE(src->prev->regoff, EAX);
1506 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, EAX); /* check as described in jvm spec */
1507 i386_jcc(cd, I386_CC_NE, 2 + 3 + 6);
1508 i386_alu_reg_reg(cd, I386_XOR, EDX, EDX);
1509 i386_alu_imm_reg(cd, I386_CMP, -1, s1);
1510 i386_jcc(cd, I386_CC_E, 1 + 2);
1513 i386_idiv_reg(cd, s1);
1515 if (iptr->dst->flags & INMEMORY) {
1516 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8);
1519 M_INTMOVE(EDX, iptr->dst->regoff);
1523 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1524 /* val.i = constant */
1526 /* TODO: optimize for `/ 2' */
1527 var_to_reg_int(s1, src, REG_ITMP1);
1528 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1531 i386_test_reg_reg(cd, d, d);
1533 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1534 i386_jcc(cd, I386_CC_NS, a);
1535 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, d);
1537 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, d);
1538 store_reg_to_var_int(iptr->dst, d);
1541 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1542 /* val.i = constant */
1544 d = reg_of_var(rd, iptr->dst, REG_NULL);
1545 if (iptr->dst->flags & INMEMORY) {
1546 if (src->flags & INMEMORY) {
1548 CALCIMMEDIATEBYTES(a, (1 << iptr->val.i) - 1);
1550 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1551 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1553 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
1554 i386_jcc(cd, I386_CC_NS, a);
1555 i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.i) - 1, REG_ITMP1);
1556 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1557 i386_shrd_imm_reg_reg(cd, iptr->val.i, REG_ITMP2, REG_ITMP1);
1558 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i, REG_ITMP2);
1560 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1561 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1566 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1567 /* val.i = constant */
1569 var_to_reg_int(s1, src, REG_ITMP1);
1570 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1572 M_INTMOVE(s1, REG_ITMP1);
1579 CALCIMMEDIATEBYTES(a, iptr->val.i);
1582 /* TODO: optimize */
1584 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1585 i386_test_reg_reg(cd, s1, s1);
1586 i386_jcc(cd, I386_CC_GE, a);
1587 i386_mov_reg_reg(cd, s1, d);
1588 i386_neg_reg(cd, d);
1589 i386_alu_imm_reg(cd, I386_AND, iptr->val.i, d);
1590 i386_neg_reg(cd, d);
1592 /* M_INTMOVE(s1, EAX); */
1593 /* i386_cltd(cd); */
1594 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1595 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1596 /* i386_alu_reg_reg(cd, I386_AND, iptr->val.i, EAX); */
1597 /* i386_alu_reg_reg(cd, I386_XOR, EDX, EAX); */
1598 /* i386_alu_reg_reg(cd, I386_SUB, EDX, EAX); */
1599 /* M_INTMOVE(EAX, d); */
1601 /* i386_alu_reg_reg(cd, I386_XOR, d, d); */
1602 /* i386_mov_imm_reg(cd, iptr->val.i, ECX); */
1603 /* i386_shrd_reg_reg(cd, s1, d); */
1604 /* i386_shift_imm_reg(cd, I386_SHR, 32 - iptr->val.i, d); */
1606 store_reg_to_var_int(iptr->dst, d);
1609 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1610 /* val.l = constant */
1612 d = reg_of_var(rd, iptr->dst, REG_NULL);
1613 if (iptr->dst->flags & INMEMORY) {
1614 if (src->flags & INMEMORY) {
1615 /* Intel algorithm -- does not work, because constant is wrong */
1616 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1); */
1617 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3); */
1619 /* M_INTMOVE(REG_ITMP1, REG_ITMP2); */
1620 /* i386_test_reg_reg(cd, REG_ITMP3, REG_ITMP3); */
1621 /* i386_jcc(cd, I386_CC_NS, offset); */
1622 /* i386_alu_imm_reg(cd, I386_ADD, (1 << iptr->val.l) - 1, REG_ITMP2); */
1623 /* i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP3); */
1625 /* i386_shrd_imm_reg_reg(cd, iptr->val.l, REG_ITMP3, REG_ITMP2); */
1626 /* i386_shift_imm_reg(cd, I386_SAR, iptr->val.l, REG_ITMP3); */
1627 /* i386_shld_imm_reg_reg(cd, iptr->val.l, REG_ITMP2, REG_ITMP3); */
1629 /* i386_shift_imm_reg(cd, I386_SHL, iptr->val.l, REG_ITMP2); */
1631 /* i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1); */
1632 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2); */
1633 /* i386_alu_reg_reg(cd, I386_SBB, REG_ITMP3, REG_ITMP2); */
1635 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1636 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1638 /* Alpha algorithm */
1640 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
1642 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8 + 4);
1648 /* TODO: hmm, don't know if this is always correct */
1650 CALCIMMEDIATEBYTES(a, iptr->val.l & 0x00000000ffffffff);
1652 CALCIMMEDIATEBYTES(a, iptr->val.l >> 32);
1658 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1659 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1661 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1662 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1663 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8 + 4);
1664 i386_jcc(cd, I386_CC_GE, a);
1666 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1667 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1669 i386_neg_reg(cd, REG_ITMP1);
1670 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1671 i386_neg_reg(cd, REG_ITMP2);
1673 i386_alu_imm_reg(cd, I386_AND, iptr->val.l, REG_ITMP1);
1674 i386_alu_imm_reg(cd, I386_AND, iptr->val.l >> 32, REG_ITMP2);
1676 i386_neg_reg(cd, REG_ITMP1);
1677 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP2);
1678 i386_neg_reg(cd, REG_ITMP2);
1680 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1681 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1686 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1688 d = reg_of_var(rd, iptr->dst, REG_NULL);
1689 i386_emit_ishift(cd, I386_SHL, src, iptr);
1692 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1693 /* val.i = constant */
1695 d = reg_of_var(rd, iptr->dst, REG_NULL);
1696 i386_emit_ishiftconst(cd, I386_SHL, src, iptr);
1699 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1701 d = reg_of_var(rd, iptr->dst, REG_NULL);
1702 i386_emit_ishift(cd, I386_SAR, src, iptr);
1705 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1706 /* val.i = constant */
1708 d = reg_of_var(rd, iptr->dst, REG_NULL);
1709 i386_emit_ishiftconst(cd, I386_SAR, src, iptr);
1712 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1714 d = reg_of_var(rd, iptr->dst, REG_NULL);
1715 i386_emit_ishift(cd, I386_SHR, src, iptr);
1718 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1719 /* val.i = constant */
1721 d = reg_of_var(rd, iptr->dst, REG_NULL);
1722 i386_emit_ishiftconst(cd, I386_SHR, src, iptr);
1725 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1727 d = reg_of_var(rd, iptr->dst, REG_NULL);
1728 if (iptr->dst->flags & INMEMORY ){
1729 if (src->prev->flags & INMEMORY) {
1730 /* if (src->prev->regoff == iptr->dst->regoff) { */
1731 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1733 /* if (src->flags & INMEMORY) { */
1734 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1736 /* M_INTMOVE(src->regoff, ECX); */
1739 /* i386_test_imm_reg(cd, 32, ECX); */
1740 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1741 /* i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2); */
1742 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1); */
1744 /* i386_shld_reg_membase(cd, REG_ITMP1, REG_SP, src->prev->regoff * 8 + 4); */
1745 /* i386_shift_membase(cd, I386_SHL, REG_SP, iptr->dst->regoff * 8); */
1748 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1749 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1751 if (src->flags & INMEMORY) {
1752 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1754 M_INTMOVE(src->regoff, ECX);
1757 i386_test_imm_reg(cd, 32, ECX);
1758 i386_jcc(cd, I386_CC_E, 2 + 2);
1759 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1760 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1762 i386_shld_reg_reg(cd, REG_ITMP1, REG_ITMP3);
1763 i386_shift_reg(cd, I386_SHL, REG_ITMP1);
1764 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1765 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1771 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1772 /* val.i = constant */
1774 d = reg_of_var(rd, iptr->dst, REG_NULL);
1775 if (iptr->dst->flags & INMEMORY ) {
1776 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1777 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1779 if (iptr->val.i & 0x20) {
1780 i386_mov_reg_reg(cd, REG_ITMP1, REG_ITMP2);
1781 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
1782 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1785 i386_shld_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP1, REG_ITMP2);
1786 i386_shift_imm_reg(cd, I386_SHL, iptr->val.i & 0x3f, REG_ITMP1);
1789 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1790 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1794 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1796 d = reg_of_var(rd, iptr->dst, REG_NULL);
1797 if (iptr->dst->flags & INMEMORY ){
1798 if (src->prev->flags & INMEMORY) {
1799 /* if (src->prev->regoff == iptr->dst->regoff) { */
1800 /* TODO: optimize */
1801 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1802 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1804 /* if (src->flags & INMEMORY) { */
1805 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1807 /* M_INTMOVE(src->regoff, ECX); */
1810 /* i386_test_imm_reg(cd, 32, ECX); */
1811 /* i386_jcc(cd, I386_CC_E, 2 + 3); */
1812 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1813 /* i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2); */
1815 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1816 /* i386_shift_reg(cd, I386_SAR, REG_ITMP2); */
1817 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1818 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1821 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1822 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1824 if (src->flags & INMEMORY) {
1825 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1827 M_INTMOVE(src->regoff, ECX);
1830 i386_test_imm_reg(cd, 32, ECX);
1831 i386_jcc(cd, I386_CC_E, 2 + 3);
1832 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1833 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP3);
1835 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1836 i386_shift_reg(cd, I386_SAR, REG_ITMP3);
1837 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1838 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1844 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1845 /* val.i = constant */
1847 d = reg_of_var(rd, iptr->dst, REG_NULL);
1848 if (iptr->dst->flags & INMEMORY ) {
1849 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1850 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1852 if (iptr->val.i & 0x20) {
1853 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1854 i386_shift_imm_reg(cd, I386_SAR, 31, REG_ITMP2);
1855 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1858 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1859 i386_shift_imm_reg(cd, I386_SAR, iptr->val.i & 0x3f, REG_ITMP2);
1862 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1863 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1867 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1869 d = reg_of_var(rd, iptr->dst, REG_NULL);
1870 if (iptr->dst->flags & INMEMORY ){
1871 if (src->prev->flags & INMEMORY) {
1872 /* if (src->prev->regoff == iptr->dst->regoff) { */
1873 /* TODO: optimize */
1874 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1); */
1875 /* i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2); */
1877 /* if (src->flags & INMEMORY) { */
1878 /* i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX); */
1880 /* M_INTMOVE(src->regoff, ECX); */
1883 /* i386_test_imm_reg(cd, 32, ECX); */
1884 /* i386_jcc(cd, I386_CC_E, 2 + 2); */
1885 /* i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1886 /* i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2); */
1888 /* i386_shrd_reg_reg(cd, REG_ITMP2, REG_ITMP1); */
1889 /* i386_shift_reg(cd, I386_SHR, REG_ITMP2); */
1890 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8); */
1891 /* i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4); */
1894 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1895 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP3);
1897 if (src->flags & INMEMORY) {
1898 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, ECX);
1900 M_INTMOVE(src->regoff, ECX);
1903 i386_test_imm_reg(cd, 32, ECX);
1904 i386_jcc(cd, I386_CC_E, 2 + 2);
1905 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1906 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP3, REG_ITMP3);
1908 i386_shrd_reg_reg(cd, REG_ITMP3, REG_ITMP1);
1909 i386_shift_reg(cd, I386_SHR, REG_ITMP3);
1910 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1911 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
1917 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1918 /* val.l = constant */
1920 d = reg_of_var(rd, iptr->dst, REG_NULL);
1921 if (iptr->dst->flags & INMEMORY ) {
1922 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1923 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
1925 if (iptr->val.i & 0x20) {
1926 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1);
1927 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
1928 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1931 i386_shrd_imm_reg_reg(cd, iptr->val.i & 0x3f, REG_ITMP2, REG_ITMP1);
1932 i386_shift_imm_reg(cd, I386_SHR, iptr->val.i & 0x3f, REG_ITMP2);
1935 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1936 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
1940 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1942 d = reg_of_var(rd, iptr->dst, REG_NULL);
1943 i386_emit_ialu(cd, I386_AND, src, iptr);
1946 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1947 /* val.i = constant */
1949 d = reg_of_var(rd, iptr->dst, REG_NULL);
1950 i386_emit_ialuconst(cd, I386_AND, src, iptr);
1953 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1955 d = reg_of_var(rd, iptr->dst, REG_NULL);
1956 i386_emit_lalu(cd, I386_AND, src, iptr);
1959 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1960 /* val.l = constant */
1962 d = reg_of_var(rd, iptr->dst, REG_NULL);
1963 i386_emit_laluconst(cd, I386_AND, src, iptr);
1966 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1968 d = reg_of_var(rd, iptr->dst, REG_NULL);
1969 i386_emit_ialu(cd, I386_OR, src, iptr);
1972 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1973 /* val.i = constant */
1975 d = reg_of_var(rd, iptr->dst, REG_NULL);
1976 i386_emit_ialuconst(cd, I386_OR, src, iptr);
1979 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1981 d = reg_of_var(rd, iptr->dst, REG_NULL);
1982 i386_emit_lalu(cd, I386_OR, src, iptr);
1985 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1986 /* val.l = constant */
1988 d = reg_of_var(rd, iptr->dst, REG_NULL);
1989 i386_emit_laluconst(cd, I386_OR, src, iptr);
1992 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1994 d = reg_of_var(rd, iptr->dst, REG_NULL);
1995 i386_emit_ialu(cd, I386_XOR, src, iptr);
1998 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1999 /* val.i = constant */
2001 d = reg_of_var(rd, iptr->dst, REG_NULL);
2002 i386_emit_ialuconst(cd, I386_XOR, src, iptr);
2005 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
2007 d = reg_of_var(rd, iptr->dst, REG_NULL);
2008 i386_emit_lalu(cd, I386_XOR, src, iptr);
2011 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
2012 /* val.l = constant */
2014 d = reg_of_var(rd, iptr->dst, REG_NULL);
2015 i386_emit_laluconst(cd, I386_XOR, src, iptr);
2018 case ICMD_IINC: /* ..., value ==> ..., value + constant */
2019 /* op1 = variable, val.i = constant */
2021 var = &(rd->locals[iptr->op1][TYPE_INT]);
2022 if (var->flags & INMEMORY) {
2023 i386_alu_imm_membase(cd, I386_ADD, iptr->val.i, REG_SP, var->regoff * 8);
2026 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2031 /* floating operations ************************************************/
2033 #define ROUND_TO_SINGLE \
2034 i386_fstps_membase(cd, REG_SP, -8); \
2035 i386_flds_membase(cd, REG_SP, -8);
2037 #define ROUND_TO_DOUBLE \
2038 i386_fstpl_membase(cd, REG_SP, -8); \
2039 i386_fldl_membase(cd, REG_SP, -8);
2041 #define FPU_SET_24BIT_MODE \
2042 if (!fpu_in_24bit_mode) { \
2043 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2044 fpu_in_24bit_mode = 1; \
2047 #define FPU_SET_53BIT_MODE \
2048 if (fpu_in_24bit_mode) { \
2049 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2050 fpu_in_24bit_mode = 0; \
2053 #define ROUND_TO_SINGLE
2054 #define ROUND_TO_DOUBLE
2055 #define FPU_SET_24BIT_MODE
2056 #define FPU_SET_53BIT_MODE
2058 case ICMD_FNEG: /* ..., value ==> ..., - value */
2061 var_to_reg_flt(s1, src, REG_FTMP1);
2062 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2064 store_reg_to_var_flt(iptr->dst, d);
2067 case ICMD_DNEG: /* ..., value ==> ..., - value */
2070 var_to_reg_flt(s1, src, REG_FTMP1);
2071 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2073 store_reg_to_var_flt(iptr->dst, d);
2076 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2079 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2080 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2081 var_to_reg_flt(s2, src, REG_FTMP2);
2084 store_reg_to_var_flt(iptr->dst, d);
2087 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2090 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2091 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2092 var_to_reg_flt(s2, src, REG_FTMP2);
2095 store_reg_to_var_flt(iptr->dst, d);
2098 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2101 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2102 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2103 var_to_reg_flt(s2, src, REG_FTMP2);
2106 store_reg_to_var_flt(iptr->dst, d);
2109 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2112 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2113 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2114 var_to_reg_flt(s2, src, REG_FTMP2);
2117 store_reg_to_var_flt(iptr->dst, d);
2120 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2123 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2124 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2125 var_to_reg_flt(s2, src, REG_FTMP2);
2129 store_reg_to_var_flt(iptr->dst, d);
2132 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2135 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2136 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2138 /* i386_fldt_mem(cd, subnormal_bias1); */
2139 /* i386_fmulp(cd); */
2141 var_to_reg_flt(s2, src, REG_FTMP2);
2146 /* i386_fldt_mem(cd, subnormal_bias2); */
2147 /* i386_fmulp(cd); */
2149 store_reg_to_var_flt(iptr->dst, d);
2152 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2155 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2156 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2157 var_to_reg_flt(s2, src, REG_FTMP2);
2161 store_reg_to_var_flt(iptr->dst, d);
2164 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2167 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2168 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2170 /* i386_fldt_mem(cd, subnormal_bias1); */
2171 /* i386_fmulp(cd); */
2173 var_to_reg_flt(s2, src, REG_FTMP2);
2178 /* i386_fldt_mem(cd, subnormal_bias2); */
2179 /* i386_fmulp(cd); */
2181 store_reg_to_var_flt(iptr->dst, d);
2184 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2187 /* exchanged to skip fxch */
2188 var_to_reg_flt(s2, src, REG_FTMP2);
2189 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2190 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2191 /* i386_fxch(cd); */
2196 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2197 store_reg_to_var_flt(iptr->dst, d);
2198 i386_ffree_reg(cd, 0);
2203 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2206 /* exchanged to skip fxch */
2207 var_to_reg_flt(s2, src, REG_FTMP2);
2208 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2209 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2210 /* i386_fxch(cd); */
2215 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2216 store_reg_to_var_flt(iptr->dst, d);
2217 i386_ffree_reg(cd, 0);
2222 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2223 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2225 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2226 if (src->flags & INMEMORY) {
2227 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2231 a = dseg_adds4(cd, 0);
2232 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2233 dseg_adddata(cd, cd->mcodeptr);
2234 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2235 i386_fildl_membase(cd, REG_ITMP1, a);
2238 store_reg_to_var_flt(iptr->dst, d);
2241 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2242 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2244 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2245 if (src->flags & INMEMORY) {
2246 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2250 panic("L2F: longs have to be in memory");
2252 store_reg_to_var_flt(iptr->dst, d);
2255 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2257 var_to_reg_flt(s1, src, REG_FTMP1);
2258 d = reg_of_var(rd, iptr->dst, REG_NULL);
2260 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2261 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2262 dseg_adddata(cd, cd->mcodeptr);
2263 i386_fldcw_membase(cd, REG_ITMP1, a);
2265 if (iptr->dst->flags & INMEMORY) {
2266 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2269 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2270 i386_fldcw_membase(cd, REG_ITMP1, a);
2272 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2275 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2277 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2280 a = dseg_adds4(cd, 0);
2281 i386_fistpl_membase(cd, REG_ITMP1, a);
2283 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2285 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2286 i386_fldcw_membase(cd, REG_ITMP1, a);
2288 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2291 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2292 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2295 i386_jcc(cd, I386_CC_NE, a);
2297 /* XXX: change this when we use registers */
2298 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2299 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2300 i386_call_reg(cd, REG_ITMP1);
2302 if (iptr->dst->flags & INMEMORY) {
2303 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2306 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2310 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2312 var_to_reg_flt(s1, src, REG_FTMP1);
2313 d = reg_of_var(rd, iptr->dst, REG_NULL);
2315 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2316 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2317 dseg_adddata(cd, cd->mcodeptr);
2318 i386_fldcw_membase(cd, REG_ITMP1, a);
2320 if (iptr->dst->flags & INMEMORY) {
2321 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2324 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2325 i386_fldcw_membase(cd, REG_ITMP1, a);
2327 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2330 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2332 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2335 a = dseg_adds4(cd, 0);
2336 i386_fistpl_membase(cd, REG_ITMP1, a);
2338 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2340 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2341 i386_fldcw_membase(cd, REG_ITMP1, a);
2343 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2346 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2347 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2350 i386_jcc(cd, I386_CC_NE, a);
2352 /* XXX: change this when we use registers */
2353 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2354 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2355 i386_call_reg(cd, REG_ITMP1);
2357 if (iptr->dst->flags & INMEMORY) {
2358 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2360 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2364 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2366 var_to_reg_flt(s1, src, REG_FTMP1);
2367 d = reg_of_var(rd, iptr->dst, REG_NULL);
2369 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2370 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2371 dseg_adddata(cd, cd->mcodeptr);
2372 i386_fldcw_membase(cd, REG_ITMP1, a);
2374 if (iptr->dst->flags & INMEMORY) {
2375 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2378 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2379 i386_fldcw_membase(cd, REG_ITMP1, a);
2381 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2384 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2386 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2389 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2391 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2393 i386_jcc(cd, I386_CC_NE, a);
2395 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2398 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2400 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2402 i386_jcc(cd, I386_CC_NE, a);
2404 /* XXX: change this when we use registers */
2405 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2406 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2407 i386_call_reg(cd, REG_ITMP1);
2408 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2409 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2412 panic("F2L: longs have to be in memory");
2416 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2418 var_to_reg_flt(s1, src, REG_FTMP1);
2419 d = reg_of_var(rd, iptr->dst, REG_NULL);
2421 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2422 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2423 dseg_adddata(cd, cd->mcodeptr);
2424 i386_fldcw_membase(cd, REG_ITMP1, a);
2426 if (iptr->dst->flags & INMEMORY) {
2427 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2430 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2431 i386_fldcw_membase(cd, REG_ITMP1, a);
2433 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2436 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2438 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2441 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2443 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2445 i386_jcc(cd, I386_CC_NE, a);
2447 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2450 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2452 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2454 i386_jcc(cd, I386_CC_NE, a);
2456 /* XXX: change this when we use registers */
2457 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2458 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2459 i386_call_reg(cd, REG_ITMP1);
2460 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2461 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2464 panic("D2L: longs have to be in memory");
2468 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2470 var_to_reg_flt(s1, src, REG_FTMP1);
2471 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2473 store_reg_to_var_flt(iptr->dst, d);
2476 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2478 var_to_reg_flt(s1, src, REG_FTMP1);
2479 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2481 store_reg_to_var_flt(iptr->dst, d);
2484 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2487 /* exchanged to skip fxch */
2488 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2489 var_to_reg_flt(s1, src, REG_FTMP2);
2490 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2491 /* i386_fxch(cd); */
2495 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2496 i386_jcc(cd, I386_CC_E, 6);
2497 i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2499 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2500 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2501 i386_jcc(cd, I386_CC_B, 3 + 5);
2502 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2503 i386_jmp_imm(cd, 3);
2504 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2505 store_reg_to_var_int(iptr->dst, d);
2508 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2511 /* exchanged to skip fxch */
2512 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2513 var_to_reg_flt(s1, src, REG_FTMP2);
2514 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2515 /* i386_fxch(cd); */
2519 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2520 i386_jcc(cd, I386_CC_E, 3);
2521 i386_movb_imm_reg(cd, 1, I386_AH);
2523 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2524 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2525 i386_jcc(cd, I386_CC_B, 3 + 5);
2526 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2527 i386_jmp_imm(cd, 3);
2528 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2529 store_reg_to_var_int(iptr->dst, d);
2533 /* memory operations **************************************************/
2535 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2537 var_to_reg_int(s1, src, REG_ITMP1);
2538 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2539 gen_nullptr_check(s1);
2540 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2541 store_reg_to_var_int(iptr->dst, d);
2544 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2546 var_to_reg_int(s1, src->prev, REG_ITMP1);
2547 var_to_reg_int(s2, src, REG_ITMP2);
2548 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2549 if (iptr->op1 == 0) {
2550 gen_nullptr_check(s1);
2553 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2554 store_reg_to_var_int(iptr->dst, d);
2557 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2559 var_to_reg_int(s1, src->prev, REG_ITMP1);
2560 var_to_reg_int(s2, src, REG_ITMP2);
2561 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2562 if (iptr->op1 == 0) {
2563 gen_nullptr_check(s1);
2567 if (iptr->dst->flags & INMEMORY) {
2568 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2569 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2570 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2571 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2575 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2577 var_to_reg_int(s1, src->prev, REG_ITMP1);
2578 var_to_reg_int(s2, src, REG_ITMP2);
2579 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2580 if (iptr->op1 == 0) {
2581 gen_nullptr_check(s1);
2584 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2585 store_reg_to_var_int(iptr->dst, d);
2588 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2590 var_to_reg_int(s1, src->prev, REG_ITMP1);
2591 var_to_reg_int(s2, src, REG_ITMP2);
2592 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2593 if (iptr->op1 == 0) {
2594 gen_nullptr_check(s1);
2597 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2599 store_reg_to_var_flt(iptr->dst, d);
2602 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2604 var_to_reg_int(s1, src->prev, REG_ITMP1);
2605 var_to_reg_int(s2, src, REG_ITMP2);
2606 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2607 if (iptr->op1 == 0) {
2608 gen_nullptr_check(s1);
2611 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2613 store_reg_to_var_flt(iptr->dst, d);
2616 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2618 var_to_reg_int(s1, src->prev, REG_ITMP1);
2619 var_to_reg_int(s2, src, REG_ITMP2);
2620 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2621 if (iptr->op1 == 0) {
2622 gen_nullptr_check(s1);
2625 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2626 store_reg_to_var_int(iptr->dst, d);
2629 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2631 var_to_reg_int(s1, src->prev, REG_ITMP1);
2632 var_to_reg_int(s2, src, REG_ITMP2);
2633 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2634 if (iptr->op1 == 0) {
2635 gen_nullptr_check(s1);
2638 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2639 store_reg_to_var_int(iptr->dst, d);
2642 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2644 var_to_reg_int(s1, src->prev, REG_ITMP1);
2645 var_to_reg_int(s2, src, REG_ITMP2);
2646 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2647 if (iptr->op1 == 0) {
2648 gen_nullptr_check(s1);
2651 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2652 store_reg_to_var_int(iptr->dst, d);
2656 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2658 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2659 var_to_reg_int(s2, src->prev, REG_ITMP2);
2660 if (iptr->op1 == 0) {
2661 gen_nullptr_check(s1);
2664 var_to_reg_int(s3, src, REG_ITMP3);
2665 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2668 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2670 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2671 var_to_reg_int(s2, src->prev, REG_ITMP2);
2672 if (iptr->op1 == 0) {
2673 gen_nullptr_check(s1);
2677 if (src->flags & INMEMORY) {
2678 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2679 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2680 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2681 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2685 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2687 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2688 var_to_reg_int(s2, src->prev, REG_ITMP2);
2689 if (iptr->op1 == 0) {
2690 gen_nullptr_check(s1);
2693 var_to_reg_int(s3, src, REG_ITMP3);
2694 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2697 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2699 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2700 var_to_reg_int(s2, src->prev, REG_ITMP2);
2701 if (iptr->op1 == 0) {
2702 gen_nullptr_check(s1);
2705 var_to_reg_flt(s3, src, REG_FTMP1);
2706 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2710 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2712 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2713 var_to_reg_int(s2, src->prev, REG_ITMP2);
2714 if (iptr->op1 == 0) {
2715 gen_nullptr_check(s1);
2718 var_to_reg_flt(s3, src, REG_FTMP1);
2719 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2723 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2725 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2726 var_to_reg_int(s2, src->prev, REG_ITMP2);
2727 if (iptr->op1 == 0) {
2728 gen_nullptr_check(s1);
2731 var_to_reg_int(s3, src, REG_ITMP3);
2732 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2735 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2737 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2738 var_to_reg_int(s2, src->prev, REG_ITMP2);
2739 if (iptr->op1 == 0) {
2740 gen_nullptr_check(s1);
2743 var_to_reg_int(s3, src, REG_ITMP3);
2744 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2747 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2749 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2750 var_to_reg_int(s2, src->prev, REG_ITMP2);
2751 if (iptr->op1 == 0) {
2752 gen_nullptr_check(s1);
2755 var_to_reg_int(s3, src, REG_ITMP3);
2756 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2757 M_INTMOVE(s3, REG_ITMP3);
2760 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2763 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2765 var_to_reg_int(s1, src->prev, REG_ITMP1);
2766 var_to_reg_int(s2, src, REG_ITMP2);
2767 if (iptr->op1 == 0) {
2768 gen_nullptr_check(s1);
2771 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2774 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2776 var_to_reg_int(s1, src->prev, REG_ITMP1);
2777 var_to_reg_int(s2, src, REG_ITMP2);
2778 if (iptr->op1 == 0) {
2779 gen_nullptr_check(s1);
2783 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2784 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2787 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2789 var_to_reg_int(s1, src->prev, REG_ITMP1);
2790 var_to_reg_int(s2, src, REG_ITMP2);
2791 if (iptr->op1 == 0) {
2792 gen_nullptr_check(s1);
2795 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2798 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2800 var_to_reg_int(s1, src->prev, REG_ITMP1);
2801 var_to_reg_int(s2, src, REG_ITMP2);
2802 if (iptr->op1 == 0) {
2803 gen_nullptr_check(s1);
2806 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2809 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2811 var_to_reg_int(s1, src->prev, REG_ITMP1);
2812 var_to_reg_int(s2, src, REG_ITMP2);
2813 if (iptr->op1 == 0) {
2814 gen_nullptr_check(s1);
2817 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2820 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2822 var_to_reg_int(s1, src->prev, REG_ITMP1);
2823 var_to_reg_int(s2, src, REG_ITMP2);
2824 if (iptr->op1 == 0) {
2825 gen_nullptr_check(s1);
2828 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2832 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2833 /* op1 = type, val.a = field address */
2835 /* if class isn't yet initialized, do it */
2836 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2837 /* call helper function which patches this code */
2838 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2839 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2840 i386_call_reg(cd, REG_ITMP2);
2843 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
2844 /* here it's slightly slower */
2845 i386_mov_imm_reg(cd, 0, REG_ITMP2);
2846 dseg_adddata(cd, cd->mcodeptr);
2847 i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2848 switch (iptr->op1) {
2851 var_to_reg_int(s2, src, REG_ITMP1);
2852 i386_mov_reg_membase(cd, s2, REG_ITMP2, 0);
2855 if (src->flags & INMEMORY) {
2856 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
2857 i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0);
2858 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
2859 i386_mov_reg_membase(cd, REG_ITMP1, REG_ITMP2, 0 + 4);
2861 panic("PUTSTATIC: longs have to be in memory");
2865 var_to_reg_flt(s2, src, REG_FTMP1);
2866 i386_fstps_membase(cd, REG_ITMP2, 0);
2870 var_to_reg_flt(s2, src, REG_FTMP1);
2871 i386_fstpl_membase(cd, REG_ITMP2, 0);
2874 default: panic ("internal error");
2878 case ICMD_GETSTATIC: /* ... ==> ..., value */
2879 /* op1 = type, val.a = field address */
2881 /* if class isn't yet initialized, do it */
2882 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2883 /* call helper function which patches this code */
2884 i386_mov_imm_reg(cd, (s4) ((fieldinfo *) iptr->val.a)->class, REG_ITMP1);
2885 i386_mov_imm_reg(cd, (s4) asm_check_clinit, REG_ITMP2);
2886 i386_call_reg(cd, REG_ITMP2);
2889 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
2890 i386_mov_imm_reg(cd, 0, REG_ITMP2);
2891 dseg_adddata(cd, cd->mcodeptr);
2892 i386_mov_membase_reg(cd, REG_ITMP2, a, REG_ITMP2);
2893 switch (iptr->op1) {
2896 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2897 i386_mov_membase_reg(cd, REG_ITMP2, 0, d);
2898 store_reg_to_var_int(iptr->dst, d);
2901 d = reg_of_var(rd, iptr->dst, REG_NULL);
2902 if (iptr->dst->flags & INMEMORY) {
2903 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP1);
2904 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2905 i386_mov_membase_reg(cd, REG_ITMP2, 0 + 4, REG_ITMP1);
2906 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
2908 panic("GETSTATIC: longs have to be in memory");
2912 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2913 i386_flds_membase(cd, REG_ITMP2, 0);
2915 store_reg_to_var_flt(iptr->dst, d);
2918 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2919 i386_fldl_membase(cd, REG_ITMP2, 0);
2921 store_reg_to_var_flt(iptr->dst, d);
2923 default: panic ("internal error");
2927 case ICMD_PUTFIELD: /* ..., value ==> ... */
2928 /* op1 = type, val.i = field offset */
2930 a = ((fieldinfo *)(iptr->val.a))->offset;
2931 switch (iptr->op1) {
2934 var_to_reg_int(s1, src->prev, REG_ITMP1);
2935 var_to_reg_int(s2, src, REG_ITMP2);
2936 gen_nullptr_check(s1);
2937 i386_mov_reg_membase(cd, s2, s1, a);
2940 var_to_reg_int(s1, src->prev, REG_ITMP1);
2941 gen_nullptr_check(s1);
2942 if (src->flags & INMEMORY) {
2943 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
2944 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
2945 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2946 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
2948 panic("PUTFIELD: longs have to be in memory");
2952 var_to_reg_int(s1, src->prev, REG_ITMP1);
2953 var_to_reg_flt(s2, src, REG_FTMP1);
2954 gen_nullptr_check(s1);
2955 i386_fstps_membase(cd, s1, a);
2959 var_to_reg_int(s1, src->prev, REG_ITMP1);
2960 var_to_reg_flt(s2, src, REG_FTMP1);
2961 gen_nullptr_check(s1);
2962 i386_fstpl_membase(cd, s1, a);
2965 default: panic ("internal error");
2969 case ICMD_GETFIELD: /* ... ==> ..., value */
2970 /* op1 = type, val.i = field offset */
2972 a = ((fieldinfo *)(iptr->val.a))->offset;
2973 switch (iptr->op1) {
2976 var_to_reg_int(s1, src, REG_ITMP1);
2977 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2978 gen_nullptr_check(s1);
2979 i386_mov_membase_reg(cd, s1, a, d);
2980 store_reg_to_var_int(iptr->dst, d);
2983 var_to_reg_int(s1, src, REG_ITMP1);
2984 d = reg_of_var(rd, iptr->dst, REG_NULL);
2985 gen_nullptr_check(s1);
2986 i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
2987 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
2988 i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
2989 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2992 var_to_reg_int(s1, src, REG_ITMP1);
2993 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2994 gen_nullptr_check(s1);
2995 i386_flds_membase(cd, s1, a);
2997 store_reg_to_var_flt(iptr->dst, d);
3000 var_to_reg_int(s1, src, REG_ITMP1);
3001 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3002 gen_nullptr_check(s1);
3003 i386_fldl_membase(cd, s1, a);
3005 store_reg_to_var_flt(iptr->dst, d);
3007 default: panic ("internal error");
3012 /* branch operations **************************************************/
3015 /* #define ALIGNCODENOP {if((int)((long)cd->mcodeptr&7)){M_NOP;}} */
3016 #define ALIGNCODENOP do {} while (0)
3018 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3020 var_to_reg_int(s1, src, REG_ITMP1);
3021 M_INTMOVE(s1, REG_ITMP1_XPTR);
3023 i386_call_imm(cd, 0); /* passing exception pointer */
3024 i386_pop_reg(cd, REG_ITMP2_XPC);
3026 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3027 i386_jmp_reg(cd, REG_ITMP3);
3031 case ICMD_GOTO: /* ... ==> ... */
3032 /* op1 = target JavaVM pc */
3034 i386_jmp_imm(cd, 0);
3035 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3039 case ICMD_JSR: /* ... ==> ... */
3040 /* op1 = target JavaVM pc */
3042 i386_call_imm(cd, 0);
3043 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3046 case ICMD_RET: /* ... ==> ... */
3047 /* op1 = local variable */
3049 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3050 var_to_reg_int(s1, var, REG_ITMP1);
3051 i386_jmp_reg(cd, s1);
3054 case ICMD_IFNULL: /* ..., value ==> ... */
3055 /* op1 = target JavaVM pc */
3057 if (src->flags & INMEMORY) {
3058 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3061 i386_test_reg_reg(cd, src->regoff, src->regoff);
3063 i386_jcc(cd, I386_CC_E, 0);
3064 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3067 case ICMD_IFNONNULL: /* ..., value ==> ... */
3068 /* op1 = target JavaVM pc */
3070 if (src->flags & INMEMORY) {
3071 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3074 i386_test_reg_reg(cd, src->regoff, src->regoff);
3076 i386_jcc(cd, I386_CC_NE, 0);
3077 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3080 case ICMD_IFEQ: /* ..., value ==> ... */
3081 /* op1 = target JavaVM pc, val.i = constant */
3083 if (src->flags & INMEMORY) {
3084 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3087 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3089 i386_jcc(cd, I386_CC_E, 0);
3090 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3093 case ICMD_IFLT: /* ..., value ==> ... */
3094 /* op1 = target JavaVM pc, val.i = constant */
3096 if (src->flags & INMEMORY) {
3097 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3100 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3102 i386_jcc(cd, I386_CC_L, 0);
3103 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3106 case ICMD_IFLE: /* ..., value ==> ... */
3107 /* op1 = target JavaVM pc, val.i = constant */
3109 if (src->flags & INMEMORY) {
3110 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3113 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3115 i386_jcc(cd, I386_CC_LE, 0);
3116 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3119 case ICMD_IFNE: /* ..., value ==> ... */
3120 /* op1 = target JavaVM pc, val.i = constant */
3122 if (src->flags & INMEMORY) {
3123 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3126 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3128 i386_jcc(cd, I386_CC_NE, 0);
3129 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3132 case ICMD_IFGT: /* ..., value ==> ... */
3133 /* op1 = target JavaVM pc, val.i = constant */
3135 if (src->flags & INMEMORY) {
3136 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3139 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3141 i386_jcc(cd, I386_CC_G, 0);
3142 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3145 case ICMD_IFGE: /* ..., value ==> ... */
3146 /* op1 = target JavaVM pc, val.i = constant */
3148 if (src->flags & INMEMORY) {
3149 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3152 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3154 i386_jcc(cd, I386_CC_GE, 0);
3155 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3158 case ICMD_IF_LEQ: /* ..., value ==> ... */
3159 /* op1 = target JavaVM pc, val.l = constant */
3161 if (src->flags & INMEMORY) {
3162 if (iptr->val.l == 0) {
3163 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3164 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3167 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3168 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3169 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3170 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3171 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3174 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3175 i386_jcc(cd, I386_CC_E, 0);
3176 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3179 case ICMD_IF_LLT: /* ..., value ==> ... */
3180 /* op1 = target JavaVM pc, val.l = constant */
3182 if (src->flags & INMEMORY) {
3183 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3184 i386_jcc(cd, I386_CC_L, 0);
3185 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3188 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3189 CALCIMMEDIATEBYTES(a, iptr->val.l);
3191 i386_jcc(cd, I386_CC_G, a);
3193 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3194 i386_jcc(cd, I386_CC_B, 0);
3195 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3199 case ICMD_IF_LLE: /* ..., value ==> ... */
3200 /* op1 = target JavaVM pc, val.l = constant */
3202 if (src->flags & INMEMORY) {
3203 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3204 i386_jcc(cd, I386_CC_L, 0);
3205 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3208 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3209 CALCIMMEDIATEBYTES(a, iptr->val.l);
3211 i386_jcc(cd, I386_CC_G, a);
3213 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3214 i386_jcc(cd, I386_CC_BE, 0);
3215 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3219 case ICMD_IF_LNE: /* ..., value ==> ... */
3220 /* op1 = target JavaVM pc, val.l = constant */
3222 if (src->flags & INMEMORY) {
3223 if (iptr->val.l == 0) {
3224 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3225 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3228 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3229 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3230 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3231 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3232 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3235 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3236 i386_jcc(cd, I386_CC_NE, 0);
3237 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3240 case ICMD_IF_LGT: /* ..., value ==> ... */
3241 /* op1 = target JavaVM pc, val.l = constant */
3243 if (src->flags & INMEMORY) {
3244 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3245 i386_jcc(cd, I386_CC_G, 0);
3246 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3249 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3250 CALCIMMEDIATEBYTES(a, iptr->val.l);
3252 i386_jcc(cd, I386_CC_L, a);
3254 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3255 i386_jcc(cd, I386_CC_A, 0);
3256 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3260 case ICMD_IF_LGE: /* ..., value ==> ... */
3261 /* op1 = target JavaVM pc, val.l = constant */
3263 if (src->flags & INMEMORY) {
3264 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3265 i386_jcc(cd, I386_CC_G, 0);
3266 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3269 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3270 CALCIMMEDIATEBYTES(a, iptr->val.l);
3272 i386_jcc(cd, I386_CC_L, a);
3274 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3275 i386_jcc(cd, I386_CC_AE, 0);
3276 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3280 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3281 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3283 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3284 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3285 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3287 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3288 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3290 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3291 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3294 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3296 i386_jcc(cd, I386_CC_E, 0);
3297 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3300 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3301 /* op1 = target JavaVM pc */
3303 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3304 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3305 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3306 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3307 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3308 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3309 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3311 i386_jcc(cd, I386_CC_E, 0);
3312 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3315 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3316 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3318 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3319 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3320 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3322 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3323 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3325 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3326 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3329 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3331 i386_jcc(cd, I386_CC_NE, 0);
3332 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3335 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3336 /* op1 = target JavaVM pc */
3338 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3339 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3340 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3341 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3342 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3343 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3344 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3346 i386_jcc(cd, I386_CC_NE, 0);
3347 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3350 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3351 /* op1 = target JavaVM pc */
3353 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3354 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3355 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3357 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3358 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3360 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3361 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3364 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3366 i386_jcc(cd, I386_CC_L, 0);
3367 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3370 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3371 /* op1 = target JavaVM pc */
3373 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3374 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3375 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3376 i386_jcc(cd, I386_CC_L, 0);
3377 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3380 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3381 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3383 i386_jcc(cd, I386_CC_G, a);
3385 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3386 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3387 i386_jcc(cd, I386_CC_B, 0);
3388 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3392 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3393 /* op1 = target JavaVM pc */
3395 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3396 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3397 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3399 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3400 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3402 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3403 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3406 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3408 i386_jcc(cd, I386_CC_G, 0);
3409 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3412 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3413 /* op1 = target JavaVM pc */
3415 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3416 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3417 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3418 i386_jcc(cd, I386_CC_G, 0);
3419 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3422 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3423 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3425 i386_jcc(cd, I386_CC_L, a);
3427 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3428 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3429 i386_jcc(cd, I386_CC_A, 0);
3430 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3434 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3435 /* op1 = target JavaVM pc */
3437 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3438 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3439 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3441 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3442 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3444 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3445 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3448 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3450 i386_jcc(cd, I386_CC_LE, 0);
3451 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3454 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3455 /* op1 = target JavaVM pc */
3457 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3458 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3459 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3460 i386_jcc(cd, I386_CC_L, 0);
3461 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3464 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3465 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3467 i386_jcc(cd, I386_CC_G, a);
3469 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3470 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3471 i386_jcc(cd, I386_CC_BE, 0);
3472 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3476 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3477 /* op1 = target JavaVM pc */
3479 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3480 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3481 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3483 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3484 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3486 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3487 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3490 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3492 i386_jcc(cd, I386_CC_GE, 0);
3493 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3496 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3497 /* op1 = target JavaVM pc */
3499 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3500 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3501 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3502 i386_jcc(cd, I386_CC_G, 0);
3503 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3506 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3507 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3509 i386_jcc(cd, I386_CC_L, a);
3511 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3512 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3513 i386_jcc(cd, I386_CC_AE, 0);
3514 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3518 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3520 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3523 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3524 /* val.i = constant */
3526 d = reg_of_var(rd, iptr->dst, REG_NULL);
3527 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3530 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3531 /* val.i = constant */
3533 d = reg_of_var(rd, iptr->dst, REG_NULL);
3534 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3537 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3538 /* val.i = constant */
3540 d = reg_of_var(rd, iptr->dst, REG_NULL);
3541 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3544 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3545 /* val.i = constant */
3547 d = reg_of_var(rd, iptr->dst, REG_NULL);
3548 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3551 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3552 /* val.i = constant */
3554 d = reg_of_var(rd, iptr->dst, REG_NULL);
3555 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3558 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3559 /* val.i = constant */
3561 d = reg_of_var(rd, iptr->dst, REG_NULL);
3562 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3566 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3569 var_to_reg_int(s1, src, REG_RESULT);
3570 M_INTMOVE(s1, REG_RESULT);
3572 goto nowperformreturn;
3574 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3576 if (src->flags & INMEMORY) {
3577 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3578 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3581 panic("LRETURN: longs have to be in memory");
3584 goto nowperformreturn;
3586 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3587 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3589 var_to_reg_flt(s1, src, REG_FRESULT);
3590 /* this may be an early return -- keep the offset correct for the
3594 goto nowperformreturn;
3596 case ICMD_RETURN: /* ... ==> ... */
3602 p = parentargs_base;
3604 /* call trace function */
3606 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3608 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3610 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3611 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3613 i386_fstl_membase(cd, REG_SP, 4 + 8);
3614 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3616 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3617 i386_call_reg(cd, REG_ITMP1);
3619 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3620 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3622 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3625 #if defined(USE_THREADS)
3626 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3627 i386_mov_membase_reg(cd, REG_SP, 8 * rd->maxmemuse, REG_ITMP2);
3629 /* we need to save the proper return value */
3630 switch (iptr->opc) {
3633 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3637 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3638 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, rd->maxmemuse * 8 + 4);
3642 i386_fsts_membase(cd, REG_SP, rd->maxmemuse * 8);
3646 i386_fstl_membase(cd, REG_SP, rd->maxmemuse * 8);
3650 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
3651 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
3652 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
3653 i386_call_reg(cd, REG_ITMP1);
3654 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
3656 /* and now restore the proper return value */
3657 switch (iptr->opc) {
3660 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3664 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3665 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8 + 4, REG_RESULT2);
3669 i386_flds_membase(cd, REG_SP, rd->maxmemuse * 8);
3673 i386_fldl_membase(cd, REG_SP, rd->maxmemuse * 8);
3679 /* restore saved registers */
3680 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
3682 i386_mov_membase_reg(cd, REG_SP, p * 8, rd->savintregs[i]);
3684 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
3686 i386_fldl_membase(cd, REG_SP, p * 8);
3688 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3689 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
3691 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
3696 /* deallocate stack */
3697 if (parentargs_base) {
3698 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
3707 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3712 tptr = (void **) iptr->target;
3714 s4ptr = iptr->val.a;
3715 l = s4ptr[1]; /* low */
3716 i = s4ptr[2]; /* high */
3718 var_to_reg_int(s1, src, REG_ITMP1);
3719 M_INTMOVE(s1, REG_ITMP1);
3721 i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
3727 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
3728 i386_jcc(cd, I386_CC_A, 0);
3730 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3731 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3733 /* build jump table top down and use address of lowest entry */
3735 /* s4ptr += 3 + i; */
3739 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
3740 dseg_addtarget(cd, (basicblock *) tptr[0]);
3744 /* length of dataseg after last dseg_addtarget is used by load */
3746 i386_mov_imm_reg(cd, 0, REG_ITMP2);
3747 dseg_adddata(cd, cd->mcodeptr);
3748 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3749 i386_jmp_reg(cd, REG_ITMP1);
3755 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3757 s4 i, l, val, *s4ptr;
3760 tptr = (void **) iptr->target;
3762 s4ptr = iptr->val.a;
3763 l = s4ptr[0]; /* default */
3764 i = s4ptr[1]; /* count */
3766 MCODECHECK((i<<2)+8);
3767 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3773 i386_alu_imm_reg(cd, I386_CMP, val, s1);
3774 i386_jcc(cd, I386_CC_E, 0);
3775 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
3776 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3779 i386_jmp_imm(cd, 0);
3780 /* codegen_addreference(cd, BlockPtrOfPC(l), cd->mcodeptr); */
3782 tptr = (void **) iptr->target;
3783 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3790 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3791 /* op1 = return type, val.a = function pointer*/
3795 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3796 /* op1 = return type, val.a = function pointer*/
3800 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3801 /* op1 = return type, val.a = function pointer*/
3805 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3806 /* op1 = arg count, val.a = method pointer */
3808 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3809 /* op1 = arg count, val.a = method pointer */
3811 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3812 /* op1 = arg count, val.a = method pointer */
3814 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3815 /* op1 = arg count, val.a = method pointer */
3822 MCODECHECK((s3 << 1) + 64);
3824 /* copy arguments to registers or stack location */
3826 for (; --s3 >= 0; src = src->prev) {
3827 if (src->varkind == ARGVAR) {
3831 if (IS_INT_LNG_TYPE(src->type)) {
3832 if (s3 < rd->intreg_argnum) {
3833 panic("No integer argument registers available!");
3836 if (!IS_2_WORD_TYPE(src->type)) {
3837 if (src->flags & INMEMORY) {
3838 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3839 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
3842 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
3846 if (src->flags & INMEMORY) {
3847 M_LNGMEMMOVE(src->regoff, s3);
3850 panic("copy arguments: longs have to be in memory");
3856 if (s3 < rd->fltreg_argnum) {
3857 panic("No float argument registers available!");
3860 var_to_reg_flt(d, src, REG_FTMP1);
3861 if (src->type == TYPE_FLT) {
3862 i386_fstps_membase(cd, REG_SP, s3 * 8);
3865 i386_fstpl_membase(cd, REG_SP, s3 * 8);
3872 switch (iptr->opc) {
3879 i386_mov_imm_reg(cd, a, REG_ITMP1);
3880 i386_call_reg(cd, REG_ITMP1);
3883 case ICMD_INVOKESTATIC:
3884 a = (u4) lm->stubroutine;
3887 i386_mov_imm_reg(cd, a, REG_ITMP2);
3888 i386_call_reg(cd, REG_ITMP2);
3891 case ICMD_INVOKESPECIAL:
3892 a = (u4) lm->stubroutine;
3895 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3896 gen_nullptr_check(REG_ITMP1);
3897 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3899 i386_mov_imm_reg(cd, a, REG_ITMP2);
3900 i386_call_reg(cd, REG_ITMP2);
3903 case ICMD_INVOKEVIRTUAL:
3906 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3907 gen_nullptr_check(REG_ITMP1);
3908 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3909 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3911 i386_call_reg(cd, REG_ITMP1);
3914 case ICMD_INVOKEINTERFACE:
3917 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3918 gen_nullptr_check(REG_ITMP1);
3919 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3920 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
3921 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
3923 i386_call_reg(cd, REG_ITMP1);
3927 /* d contains return type */
3929 if (d != TYPE_VOID) {
3930 d = reg_of_var(rd, iptr->dst, REG_NULL);
3932 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3933 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3934 if (iptr->dst->flags & INMEMORY) {
3935 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3936 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3939 panic("RETURN: longs have to be in memory");
3943 if (iptr->dst->flags & INMEMORY) {
3944 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3947 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3952 /* fld from called function -- has other fpu_st_offset counter */
3954 store_reg_to_var_flt(iptr->dst, d);
3961 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3963 /* op1: 0 == array, 1 == class */
3964 /* val.a: (classinfo*) superclass */
3966 /* superclass is an interface:
3968 * return (sub != NULL) &&
3969 * (sub->vftbl->interfacetablelength > super->index) &&
3970 * (sub->vftbl->interfacetable[-super->index] != NULL);
3972 * superclass is a class:
3974 * return ((sub != NULL) && (0
3975 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3976 * super->vftbl->diffvall));
3980 classinfo *super = (classinfo*) iptr->val.a;
3982 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3983 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3985 var_to_reg_int(s1, src, REG_ITMP1);
3986 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3988 M_INTMOVE(s1, REG_ITMP1);
3991 i386_alu_reg_reg(cd, I386_XOR, d, d);
3992 if (iptr->op1) { /* class/interface */
3993 if (super->flags & ACC_INTERFACE) { /* interface */
3994 i386_test_reg_reg(cd, s1, s1);
3996 /* TODO: clean up this calculation */
3998 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4001 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4004 /* CALCOFFSETBYTES(a, super->index); */
4005 CALCIMMEDIATEBYTES(a, super->index);
4011 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4018 i386_jcc(cd, I386_CC_E, a);
4020 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4021 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4022 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4024 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4026 /* TODO: clean up this calculation */
4029 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4036 i386_jcc(cd, I386_CC_LE, a);
4037 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4039 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4040 /* i386_setcc_reg(cd, I386_CC_A, d); */
4041 /* i386_jcc(cd, I386_CC_BE, 5); */
4042 i386_jcc(cd, I386_CC_E, 5);
4043 i386_mov_imm_reg(cd, 1, d);
4046 } else { /* class */
4047 i386_test_reg_reg(cd, s1, s1);
4049 /* TODO: clean up this calculation */
4051 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4054 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4056 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4059 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4069 i386_jcc(cd, I386_CC_E, a);
4071 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4072 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4073 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4074 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4076 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4077 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4078 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4079 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4080 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4082 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4083 i386_alu_reg_reg(cd, I386_XOR, d, d);
4085 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4086 i386_jcc(cd, I386_CC_A, 5);
4087 i386_mov_imm_reg(cd, 1, d);
4091 panic ("internal error: no inlined array instanceof");
4093 store_reg_to_var_int(iptr->dst, d);
4096 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4098 /* op1: 0 == array, 1 == class */
4099 /* val.a: (classinfo*) superclass */
4101 /* superclass is an interface:
4103 * OK if ((sub == NULL) ||
4104 * (sub->vftbl->interfacetablelength > super->index) &&
4105 * (sub->vftbl->interfacetable[-super->index] != NULL));
4107 * superclass is a class:
4109 * OK if ((sub == NULL) || (0
4110 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4111 * super->vftbl->diffvall));
4115 classinfo *super = (classinfo*) iptr->val.a;
4117 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4118 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4120 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4121 var_to_reg_int(s1, src, d);
4122 if (iptr->op1) { /* class/interface */
4123 if (super->flags & ACC_INTERFACE) { /* interface */
4124 i386_test_reg_reg(cd, s1, s1);
4126 /* TODO: clean up this calculation */
4128 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4131 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4134 /* CALCOFFSETBYTES(a, super->index); */
4135 CALCIMMEDIATEBYTES(a, super->index);
4141 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4146 i386_jcc(cd, I386_CC_E, a);
4148 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4149 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4150 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4152 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4153 i386_jcc(cd, I386_CC_LE, 0);
4154 codegen_addxcastrefs(cd, cd->mcodeptr);
4155 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4157 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4158 i386_jcc(cd, I386_CC_E, 0);
4159 codegen_addxcastrefs(cd, cd->mcodeptr);
4161 } else { /* class */
4162 i386_test_reg_reg(cd, s1, s1);
4164 /* TODO: clean up this calculation */
4166 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4171 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4173 if (d != REG_ITMP3) {
4175 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4178 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4184 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4191 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4198 i386_jcc(cd, I386_CC_E, a);
4200 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4201 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4202 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4203 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4205 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4206 if (d != REG_ITMP3) {
4207 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4208 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4209 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4210 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4212 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4215 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4216 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1);
4217 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4218 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4219 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4220 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4224 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4225 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4226 codegen_addxcastrefs(cd, cd->mcodeptr);
4230 panic ("internal error: no inlined array checkcast");
4233 store_reg_to_var_int(iptr->dst, d);
4236 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4238 if (src->flags & INMEMORY) {
4239 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4242 i386_test_reg_reg(cd, src->regoff, src->regoff);
4244 i386_jcc(cd, I386_CC_L, 0);
4245 codegen_addxcheckarefs(cd, cd->mcodeptr);
4248 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4250 i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4251 i386_jcc(cd, I386_CC_E, 0);
4252 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4255 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4256 /* op1 = dimension, val.a = array descriptor */
4258 /* check for negative sizes and copy sizes to stack if necessary */
4260 MCODECHECK((iptr->op1 << 1) + 64);
4262 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4263 if (src->flags & INMEMORY) {
4264 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4267 i386_test_reg_reg(cd, src->regoff, src->regoff);
4269 i386_jcc(cd, I386_CC_L, 0);
4270 codegen_addxcheckarefs(cd, cd->mcodeptr);
4273 * copy sizes to new stack location, be cause native function
4274 * builtin_nmultianewarray access them as (int *)
4276 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4277 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4279 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4281 if (src->varkind != ARGVAR) {
4282 if (src->flags & INMEMORY) {
4283 i386_mov_membase_reg(cd, REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4284 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4287 i386_mov_reg_membase(cd, src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4291 i386_alu_imm_reg(cd, I386_SUB, iptr->op1 * 4, REG_SP);
4293 /* a0 = dimension count */
4295 /* save stack pointer */
4296 M_INTMOVE(REG_SP, REG_ITMP1);
4298 i386_alu_imm_reg(cd, I386_SUB, 12, REG_SP);
4299 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4301 /* a1 = arraydescriptor */
4303 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, 4);
4305 /* a2 = pointer to dimensions = stack pointer */
4307 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4309 i386_mov_imm_reg(cd, (s4) (builtin_nmultianewarray), REG_ITMP1);
4310 i386_call_reg(cd, REG_ITMP1);
4311 i386_alu_imm_reg(cd, I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4313 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
4314 M_INTMOVE(REG_RESULT, s1);
4315 store_reg_to_var_int(iptr->dst, s1);
4318 case ICMD_INLINE_START:
4319 case ICMD_INLINE_END:
4322 error ("Unknown pseudo command: %d", iptr->opc);
4325 } /* for instruction */
4327 /* copy values to interface registers */
4329 src = bptr->outstack;
4330 len = bptr->outdepth;
4334 if ((src->varkind != STACKVAR)) {
4336 if (IS_FLT_DBL_TYPE(s2)) {
4337 var_to_reg_flt(s1, src, REG_FTMP1);
4338 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4339 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4342 panic("double store");
4343 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4347 var_to_reg_int(s1, src, REG_ITMP1);
4348 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
4349 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4350 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4353 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
4357 if (rd->interfaces[len][s2].flags & INMEMORY) {
4358 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
4361 panic("copy interface registers: longs have to be in memory (end)");
4368 } /* if (bptr -> flags >= BBREACHED) */
4369 } /* for basic block */
4371 codegen_createlinenumbertable(cd);
4375 /* generate bound check stubs */
4377 u1 *xcodeptr = NULL;
4380 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4381 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4383 cd->mcodeptr - cd->mcodebase);
4387 /* move index register into REG_ITMP1 */
4388 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1); /* 2 bytes */
4390 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4391 dseg_adddata(cd, cd->mcodeptr);
4392 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3); /* 5 bytes */
4393 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4395 if (xcodeptr != NULL) {
4396 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4399 xcodeptr = cd->mcodeptr;
4401 i386_push_reg(cd, REG_ITMP2_XPC);
4403 PREPARE_NATIVE_STACKINFO;
4405 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4406 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4);
4407 i386_mov_imm_reg(cd, (u4) new_arrayindexoutofboundsexception, REG_ITMP1);
4408 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4409 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4411 REMOVE_NATIVE_STACKINFO;
4413 i386_pop_reg(cd, REG_ITMP2_XPC);
4415 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4416 i386_jmp_reg(cd, REG_ITMP3);
4420 /* generate negative array size check stubs */
4424 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4425 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4426 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4428 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4432 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4434 cd->mcodeptr - cd->mcodebase);
4438 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4439 dseg_adddata(cd, cd->mcodeptr);
4440 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4441 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4443 if (xcodeptr != NULL) {
4444 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4447 xcodeptr = cd->mcodeptr;
4449 i386_push_reg(cd, REG_ITMP2_XPC);
4451 PREPARE_NATIVE_STACKINFO;
4453 i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1);
4454 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4455 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4458 REMOVE_NATIVE_STACKINFO;
4460 i386_pop_reg(cd, REG_ITMP2_XPC);
4462 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4463 i386_jmp_reg(cd, REG_ITMP3);
4467 /* generate cast check stubs */
4471 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4472 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4473 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4475 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4479 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4481 cd->mcodeptr - cd->mcodebase);
4485 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4486 dseg_adddata(cd, cd->mcodeptr);
4487 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4488 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4490 if (xcodeptr != NULL) {
4491 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4494 xcodeptr = cd->mcodeptr;
4496 i386_push_reg(cd, REG_ITMP2_XPC);
4498 PREPARE_NATIVE_STACKINFO;
4500 i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1);
4501 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4502 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4505 REMOVE_NATIVE_STACKINFO;
4507 i386_pop_reg(cd, REG_ITMP2_XPC);
4509 i386_mov_imm_reg(cd, (u4) asm_handle_exception, REG_ITMP3);
4510 i386_jmp_reg(cd, REG_ITMP3);
4514 /* generate divide by zero check stubs */
4518 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
4519 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4520 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4522 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4526 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4528 cd->mcodeptr - cd->mcodebase);
4532 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4533 dseg_adddata(cd, cd->mcodeptr);
4534 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4535 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4537 if (xcodeptr != NULL) {
4538 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4541 xcodeptr = cd->mcodeptr;
4543 i386_push_reg(cd, REG_ITMP2_XPC);
4545 PREPARE_NATIVE_STACKINFO;
4547 i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1);
4548 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4550 REMOVE_NATIVE_STACKINFO;
4552 i386_pop_reg(cd, REG_ITMP2_XPC);
4554 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4555 i386_jmp_reg(cd, REG_ITMP3);
4559 /* generate exception check stubs */
4563 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4564 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4565 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4567 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4571 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4573 cd->mcodeptr - cd->mcodebase);
4577 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4578 dseg_adddata(cd, cd->mcodeptr);
4579 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4580 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4582 if (xcodeptr != NULL) {
4583 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4586 xcodeptr = cd->mcodeptr;
4588 i386_push_reg(cd, REG_ITMP2_XPC);
4590 PREPARE_NATIVE_STACKINFO;
4592 i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1);
4593 i386_call_reg(cd, REG_ITMP1);
4595 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4596 i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4597 i386_call_reg(cd, REG_ITMP1);
4598 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4599 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
4600 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4602 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
4603 i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
4604 i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
4606 i386_push_imm(cd, 0);
4607 i386_push_reg(cd, REG_ITMP1_XPTR);
4609 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4610 java stack at this point*/
4611 i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4612 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
4613 i386_push_imm(cd, (u4) utf_fillInStackTrace_desc);
4614 i386_push_imm(cd, (u4) utf_fillInStackTrace_name);
4615 i386_push_reg(cd, REG_ITMP1);
4616 i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
4617 i386_call_reg(cd, REG_ITMP3);
4618 /*cleanup parameters of class_resolvemethod*/
4619 i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4620 /*prepare call to asm_calljavafunction2 */
4621 i386_push_imm(cd, 0);
4622 i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4623 i386_push_reg(cd, REG_SP);
4624 i386_push_imm(cd, sizeof(jni_callblock));
4625 i386_push_imm(cd, 1);
4626 i386_push_reg(cd, REG_RESULT);
4628 i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
4629 i386_call_reg(cd, REG_ITMP3);
4631 /* check exceptionptr + fail (JOWENN)*/
4633 i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
4635 i386_pop_reg(cd, REG_ITMP1_XPTR);
4636 i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4638 REMOVE_NATIVE_STACKINFO;
4640 i386_pop_reg(cd, REG_ITMP2_XPC);
4642 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4643 i386_jmp_reg(cd, REG_ITMP3);
4647 /* generate null pointer check stubs */
4651 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4652 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4653 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4655 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4659 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4661 cd->mcodeptr - cd->mcodebase);
4665 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4666 dseg_adddata(cd, cd->mcodeptr);
4667 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4668 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4670 if (xcodeptr != NULL) {
4671 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4674 xcodeptr = cd->mcodeptr;
4676 i386_push_reg(cd, REG_ITMP2_XPC);
4678 PREPARE_NATIVE_STACKINFO;
4681 /* create native call block*/
4682 i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4685 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
4686 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/
4688 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4689 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4690 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
4691 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4692 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4693 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
4694 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4697 i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1);
4698 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4700 REMOVE_NATIVE_STACKINFO;
4703 /* restore native call stack */
4704 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
4705 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
4706 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
4707 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
4710 i386_pop_reg(cd, REG_ITMP2_XPC);
4712 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4713 i386_jmp_reg(cd, REG_ITMP3);
4718 codegen_finish(m, cd, (u4) (cd->mcodeptr - cd->mcodebase));
4722 /* function createcompilerstub *************************************************
4724 creates a stub routine which calls the compiler
4726 *******************************************************************************/
4728 #define COMPSTUBSIZE 12
4730 u1 *createcompilerstub(methodinfo *m)
4732 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4733 codegendata *cd = NEW(codegendata);
4737 /* code for the stub */
4738 i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
4740 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4741 i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
4742 i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
4744 /* free codegendata memory */
4747 #if defined(STATISTICS)
4749 count_cstub_len += COMPSTUBSIZE;
4752 FREE(cd, codegendata);
4758 /* function removecompilerstub *************************************************
4760 deletes a compilerstub from memory (simply by freeing it)
4762 *******************************************************************************/
4764 void removecompilerstub(u1 *stub)
4766 CFREE(stub, COMPSTUBSIZE);
4770 /* function: createnativestub **************************************************
4772 creates a stub routine which calls a native method
4774 *******************************************************************************/
4776 #define NATIVESTUBSIZE 350
4778 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4779 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4782 void i386_native_stub_debug(void **p) {
4783 printf("Pos on stack: %p\n",p);
4784 printf("Return adress should be: %p\n",*p);
4787 void i386_native_stub_debug2(void **p) {
4788 printf("Pos on stack: %p\n",p);
4789 printf("Return for lookup is: %p\n",*p);
4792 void traverseStackInfo() {
4793 void **p=builtin_asm_get_stackframeinfo();
4797 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4798 m=*((methodinfo**)((*p)+8));
4799 utf_display(m->name);
4807 u1 *createnativestub(functionptr f, methodinfo *m)
4809 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4813 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4814 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4815 int stackframeoffset = 4;
4819 void** callAddrPatchPos=0;
4821 void** jmpInstrPatchPos=0;
4823 codegendata *cd = NEW(codegendata);
4824 registerdata *rd = NEW(registerdata);
4825 t_inlining_globals *id = NEW(t_inlining_globals);
4827 /* setup registers before using it */
4828 inlining_setup(m, id);
4829 reg_setup(m, rd, id);
4833 if (m->flags & ACC_STATIC) {
4834 stackframesize += 4;
4835 stackframeoffset += 4;
4839 descriptor2types(m); /* set paramcount and paramtypes */
4842 /* i386_push_reg(cd, REG_SP);
4843 i386_mov_imm_reg(cd, (s4) i386_native_stub_debug, REG_ITMP1);
4844 i386_call_reg(cd, REG_ITMP1);
4845 i386_pop_reg(cd, REG_ITMP1);*/
4848 /* if function is static, check for initialized */
4850 if (m->flags & ACC_STATIC) {
4851 /* if class isn't yet initialized, do it */
4852 if (!m->class->initialized) {
4853 s4 *header = (s4 *) s;
4854 *header = 0;/*extablesize*/
4856 *header = 0;/*line number table start*/
4858 *header = 0;/*line number table size*/
4860 *header = 0;/*fltsave*/
4862 *header = 0;/*intsave*/
4864 *header = 0;/*isleaf*/
4866 *header = 0;/*issync*/
4868 *header = 0;/*framesize*/
4870 *header = (u4) m;/*methodpointer*/
4872 cd->mcodeptr = s = (u1 *) header;
4875 /* call helper function which patches this code */
4876 i386_mov_imm_reg(cd, (u4) m->class, REG_ITMP1);
4877 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP2);
4878 i386_call_reg(cd, REG_ITMP2);
4883 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4885 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
4886 t = m->paramtypes[p];
4887 if (IS_INT_LNG_TYPE(t)) {
4888 if (IS_2_WORD_TYPE(t)) {
4889 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4890 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4891 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4892 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4894 } else if (t == TYPE_ADR) {
4895 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4896 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4897 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4898 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4901 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4903 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
4904 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
4908 if (!IS_2_WORD_TYPE(t)) {
4909 i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4910 i386_fstps_membase(cd, REG_SP, p * 8);
4911 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4912 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4915 i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4916 i386_fstpl_membase(cd, REG_SP, p * 8);
4921 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
4922 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
4923 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4924 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
4927 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
4929 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
4930 i386_call_reg(cd, REG_ITMP1);
4932 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4936 * mark the whole fpu stack as free for native functions
4937 * (only for saved register count == 0)
4939 i386_ffree_reg(cd, 0);
4940 i386_ffree_reg(cd, 1);
4941 i386_ffree_reg(cd, 2);
4942 i386_ffree_reg(cd, 3);
4943 i386_ffree_reg(cd, 4);
4944 i386_ffree_reg(cd, 5);
4945 i386_ffree_reg(cd, 6);
4946 i386_ffree_reg(cd, 7);
4948 /* calculate stackframe size for native function */
4949 tptr = m->paramtypes;
4950 for (i = 0; i < m->paramcount; i++) {
4955 stackframesize += 4;
4960 stackframesize += 8;
4964 panic("unknown parameter type in native function");
4968 i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
4970 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
4971 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4972 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
4973 i386_call_reg(cd, REG_ITMP1);
4974 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
4975 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
4976 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
4977 i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
4978 i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2);
4979 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
4982 /* i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
4983 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
4984 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
4986 /* CREATE DYNAMIC STACK INFO -- END*/
4988 /* RESOLVE NATIVE METHOD -- BEGIN*/
4989 #ifndef STATIC_CLASSPATH
4991 log_text("Dynamic classpath: preparing for delayed native function resolving");
4993 jmpInstrPos=cd->mcodeptr-4;
4995 i386_mov_imm_reg(cd,jmpInstrPos,REG_ITMP1);
4996 i386_push_reg(cd,REG_ITMP1);
4998 i386_mov_imm_reg(cd,0,REG_ITMP1);
4999 jmpInstrPatchPos=cd->mcodeptr-4;
5000 i386_push_reg(cd,REG_ITMP1);
5001 /*position of call address to patch*/
5002 i386_mov_imm_reg(cd,0,REG_ITMP1);
5003 callAddrPatchPos=(cd->mcodeptr-4);
5004 i386_push_reg(cd,REG_ITMP1);
5005 /*method info structure*/
5006 i386_mov_imm_reg(cd,(s4) m, REG_ITMP1);
5007 i386_push_reg(cd,REG_ITMP1);
5008 /*call resolve functions*/
5009 i386_mov_imm_reg(cd, (s4)codegen_resolve_native,REG_ITMP1);
5010 i386_call_reg(cd,REG_ITMP1);
5012 i386_pop_reg(cd,REG_ITMP1);
5013 i386_pop_reg(cd,REG_ITMP1);
5014 i386_pop_reg(cd,REG_ITMP1);
5015 i386_pop_reg(cd,REG_ITMP1);
5016 /*fix jmp offset replacement*/
5017 (*jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-4;
5018 } else log_text("Dynamic classpath: immediate native function resolution possible");
5020 /* RESOLVE NATIVE METHOD -- END*/
5024 tptr = m->paramtypes;
5025 for (i = 0; i < m->paramcount; i++) {
5030 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5031 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5032 stackframeoffset += 4;
5037 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5038 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5039 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5040 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5041 stackframeoffset += 8;
5045 panic("unknown parameter type in native function");
5049 if (m->flags & ACC_STATIC) {
5050 /* put class into second argument */
5051 i386_mov_imm_membase(cd, (s4) m->class, REG_SP, 4);
5054 /* put env into first argument */
5055 i386_mov_imm_membase(cd, (s4) &env, REG_SP, 0);
5057 i386_mov_imm_reg(cd, (s4) f, REG_ITMP1);
5058 #ifndef STATIC_CLASSPATH
5060 (*callAddrPatchPos)=(cd->mcodeptr-4);
5062 i386_call_reg(cd, REG_ITMP1);
5064 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5065 i386_push_reg(cd, REG_RESULT2);
5066 i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5067 i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5068 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5069 i386_pop_reg(cd, REG_RESULT2);
5070 /*REMOVE DYNAMIC STACK INFO -END */
5072 i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5076 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5078 i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5080 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5081 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5083 i386_fstl_membase(cd, REG_SP, 4 + 8);
5084 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5086 i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5087 i386_call_reg(cd, REG_ITMP1);
5089 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5090 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5092 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5096 /* we can't use REG_ITMP3 == REG_RESULT2 */
5097 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5098 i386_push_reg(cd, REG_RESULT);
5099 i386_push_reg(cd, REG_RESULT2);
5100 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5101 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5102 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5103 i386_pop_reg(cd, REG_RESULT2);
5104 i386_pop_reg(cd, REG_RESULT);
5106 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5107 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5108 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5110 i386_jcc(cd, I386_CC_NE, 1);
5114 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5115 i386_push_reg(cd, REG_ITMP2);
5116 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5117 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5118 i386_pop_reg(cd, REG_ITMP1_XPTR);
5120 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5121 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5122 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5124 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5125 i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5127 i386_mov_imm_reg(cd, (s4) asm_handle_nat_exception, REG_ITMP3);
5128 i386_jmp_reg(cd, REG_ITMP3);
5131 codegen_insertmethod(s, cd->mcodeptr);
5135 dolog_plain("native stubentry: %p, stubsize: %x (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
5136 utf_display(m->name);
5140 /* free codegendata memory */
5143 #if defined(STATISTICS)
5145 count_nstub_len += NATIVESTUBSIZE;
5148 FREE(cd, codegendata);
5149 FREE(rd, registerdata);
5150 FREE(id, t_inlining_globals);
5156 /* function: removenativestub **************************************************
5158 removes a previously created native-stub from memory
5160 *******************************************************************************/
5162 void removenativestub(u1 *stub)
5164 CFREE(stub, NATIVESTUBSIZE);
5169 * These are local overrides for various environment variables in Emacs.
5170 * Please do not remove this and leave it at the end of the file, where
5171 * Emacs will automagically detect them.
5172 * ---------------------------------------------------------------------
5175 * indent-tabs-mode: t