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 1577 2004-11-24 13:06:56Z twisti $
39 #include <sys/ucontext.h>
47 #include "exceptions.h"
53 #include "jit/parse.h"
55 #include "jit/i386/codegen.h"
56 #include "jit/i386/emitfuncs.h"
59 /* register descripton - array ************************************************/
61 /* #define REG_RES 0 reserved register for OS or code generator */
62 /* #define REG_RET 1 return value register */
63 /* #define REG_EXC 2 exception value register (only old jit) */
64 /* #define REG_SAV 3 (callee) saved register */
65 /* #define REG_TMP 4 scratch temporary register (caller saved) */
66 /* #define REG_ARG 5 argument register (caller saved) */
68 /* #define REG_END -1 last entry in tables */
70 static int nregdescint[] = {
71 REG_RET, REG_RES, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_SAV, REG_SAV,
76 static int nregdescfloat[] = {
77 /* rounding problems with callee saved registers */
78 /* REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_RES, REG_RES, */
79 /* REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, */
80 REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
85 /*******************************************************************************
87 include independent code generation stuff -- include after register
88 descriptions to avoid extern definitions
90 *******************************************************************************/
92 #include "jit/codegen.inc"
93 #include "jit/reg.inc"
96 void codegen_stubcalled() {
97 log_text("Stub has been called");
100 void codegen_general_stubcalled() {
101 log_text("general exception stub has been called");
105 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
106 void thread_restartcriticalsection(ucontext_t *uc)
109 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[REG_EIP])) != NULL)
110 uc->uc_mcontext.gregs[REG_EIP] = (u4) critical;
115 #define PREPARE_NATIVE_STACKINFO \
116 i386_push_reg(cd, REG_ITMP1); /*save itmp1, needed by some stubs */ \
117 i386_alu_imm_reg(cd, I386_SUB, 2*4, REG_SP); /* build stack frame (2 * 4 bytes), together with previous =3*4 */ \
118 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1); \
119 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/ \
120 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1); \
121 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/ \
122 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/ \
123 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */ \
124 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */ \
125 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */ \
126 i386_mov_membase_reg(cd, REG_SP,2*4,REG_ITMP1); /* restore ITMP1, need for some stubs*/ \
127 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
130 #define REMOVE_NATIVE_STACKINFO \
131 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2); \
132 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3); \
133 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0); \
134 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
137 /* NullPointerException signal handler for hardware null pointer check */
139 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
142 /* long faultaddr; */
144 struct ucontext *_uc = (struct ucontext *) _p;
145 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
146 struct sigaction act;
148 /* Reset signal handler - necessary for SysV, does no harm for BSD */
150 /* instr = *((int*)(sigctx->eip)); */
151 /* faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
153 /* fprintf(stderr, "null=%d %p addr=%p\n", sig, sigctx, sigctx->eip);*/
155 /* if (faultaddr == 0) { */
156 /* signal(sig, (void *) catch_NullPointerException); */
157 act.sa_sigaction = (functionptr) catch_NullPointerException;
158 act.sa_flags = SA_SIGINFO;
159 sigaction(sig, &act, NULL); /* reinstall handler */
162 sigaddset(&nsig, sig);
163 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
165 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
166 sigctx->eax = (u4) string_java_lang_NullPointerException;
167 sigctx->eip = (u4) asm_throw_and_handle_exception;
172 /* faultaddr += (long) ((instr << 16) >> 16); */
173 /* fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
174 /* panic("Stack overflow"); */
179 /* ArithmeticException signal handler for hardware divide by zero check */
181 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
185 /* void **_p = (void **) &sig; */
186 /* struct sigcontext *sigctx = (struct sigcontext *) ++_p; */
187 struct ucontext *_uc = (struct ucontext *) _p;
188 struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
189 struct sigaction act;
191 /* Reset signal handler - necessary for SysV, does no harm for BSD */
193 /* signal(sig, (void *) catch_ArithmeticException); */
194 act.sa_sigaction = (functionptr) catch_ArithmeticException;
195 act.sa_flags = SA_SIGINFO;
196 sigaction(sig, &act, NULL); /* reinstall handler */
199 sigaddset(&nsig, sig);
200 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
202 sigctx->ecx = sigctx->eip; /* REG_ITMP2_XPC */
203 sigctx->eip = (u4) asm_throw_and_handle_hardware_arithmetic_exception;
209 void init_exceptions(void)
211 struct sigaction act;
213 /* install signal handlers we need to convert to exceptions */
214 sigemptyset(&act.sa_mask);
218 /* signal(SIGSEGV, (void *) catch_NullPointerException); */
219 act.sa_sigaction = (functionptr) catch_NullPointerException;
220 act.sa_flags = SA_SIGINFO;
221 sigaction(SIGSEGV, &act, NULL);
225 /* signal(SIGBUS, (void *) catch_NullPointerException); */
226 act.sa_sigaction = (functionptr) catch_NullPointerException;
227 act.sa_flags = SA_SIGINFO;
228 sigaction(SIGBUS, &act, NULL);
232 /* signal(SIGFPE, (void *) catch_ArithmeticException); */
233 act.sa_sigaction = (functionptr) catch_ArithmeticException;
234 act.sa_flags = SA_SIGINFO;
235 sigaction(SIGFPE, &act, NULL);
239 /* function codegen ************************************************************
241 generates machine code
243 *******************************************************************************/
245 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
247 s4 len, s1, s2, s3, d;
255 s4 fpu_st_offset = 0;
261 s4 savedregs_num = 0;
263 /* space to save used callee saved registers */
265 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
266 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
268 parentargs_base = rd->maxmemuse + savedregs_num;
270 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
272 if (checksync && (m->flags & ACC_SYNCHRONIZED))
277 /* create method header */
279 (void) dseg_addaddress(cd, m); /* MethodPointer */
280 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
282 #if defined(USE_THREADS)
284 /* IsSync contains the offset relative to the stack pointer for the
285 argument of monitor_exit used in the exception handler. Since the
286 offset could be zero and give a wrong meaning of the flag it is
290 if (checksync && (m->flags & ACC_SYNCHRONIZED))
291 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
296 (void) dseg_adds4(cd, 0); /* IsSync */
298 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
299 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
300 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
302 /* adds a reference for the length of the line number counter. We don't
303 know the size yet, since we evaluate the information during code
304 generation, to save one additional iteration over the whole
305 instructions. During code optimization the position could have changed
306 to the information gotten from the class file */
307 (void) dseg_addlinenumbertablesize(cd);
309 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
311 /* create exception table */
313 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
314 dseg_addtarget(cd, ex->start);
315 dseg_addtarget(cd, ex->end);
316 dseg_addtarget(cd, ex->handler);
317 (void) dseg_addaddress(cd, ex->catchtype);
321 /* initialize mcode variables */
323 cd->mcodeptr = cd->mcodebase;
324 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
325 MCODECHECK(128 + m->paramcount);
327 /* create stack frame (if necessary) */
329 if (parentargs_base) {
330 i386_alu_imm_reg(cd, I386_SUB, parentargs_base * 8, REG_SP);
333 /* save return address and used callee saved registers */
336 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
337 p--; i386_mov_reg_membase(cd, rd->savintregs[i], REG_SP, p * 8);
339 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
340 p--; i386_fld_reg(cd, rd->savfltregs[i]); i386_fstpl_membase(cd, REG_SP, p * 8);
343 /* save monitorenter argument */
345 #if defined(USE_THREADS)
346 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
347 s4 func_enter = (m->flags & ACC_STATIC) ?
348 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
350 if (m->flags & ACC_STATIC) {
351 i386_mov_imm_reg(cd, (s4) m->class, REG_ITMP1);
352 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
355 i386_mov_membase_reg(cd, REG_SP, parentargs_base * 8 + 4, REG_ITMP1);
356 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
359 /* call monitorenter function */
361 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
362 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0);
363 i386_mov_imm_reg(cd, func_enter, REG_ITMP1);
364 i386_call_reg(cd, REG_ITMP1);
365 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
369 /* copy argument registers to stack and call trace function with pointer
370 to arguments on stack.
374 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
376 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
377 t = m->paramtypes[p];
379 if (IS_INT_LNG_TYPE(t)) {
380 if (IS_2_WORD_TYPE(t)) {
381 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
382 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
383 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP1);
384 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
386 /* } else if (t == TYPE_ADR) { */
388 i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
389 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
390 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
391 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
394 /* i386_mov_membase_reg(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4, EAX); */
396 /* i386_mov_reg_membase(cd, EAX, REG_SP, p * 8); */
397 /* i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4); */
401 if (!IS_2_WORD_TYPE(t)) {
402 i386_flds_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
403 i386_fstps_membase(cd, REG_SP, p * 8);
404 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
405 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
408 i386_fldl_membase(cd, REG_SP, 4 + (parentargs_base + TRACE_ARGS_NUM + p) * 8 + 4);
409 i386_fstpl_membase(cd, REG_SP, p * 8);
414 /* fill up the remaining arguments */
415 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
416 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
417 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
418 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
421 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
422 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
423 i386_call_reg(cd, REG_ITMP1);
425 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
428 /* take arguments out of register or stack frame */
430 for (p = 0, l = 0; p < m->paramcount; p++) {
431 t = m->paramtypes[p];
432 var = &(rd->locals[l][t]);
434 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
438 if (IS_INT_LNG_TYPE(t)) { /* integer args */
439 if (p < rd->intreg_argnum) { /* register arguments */
440 panic("integer register argument");
441 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
442 /* M_INTMOVE (argintregs[p], r); */
444 } else { /* reg arg -> spilled */
445 /* M_LST (argintregs[p], REG_SP, 8 * r); */
447 } else { /* stack arguments */
448 pa = p - rd->intreg_argnum;
449 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
450 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, var->regoff); /* + 4 for return address */
451 } else { /* stack arg -> spilled */
452 if (!IS_2_WORD_TYPE(t)) {
453 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
454 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
457 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); /* + 4 for return address */
458 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
459 i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4 + 4, REG_ITMP1); /* + 4 for return address */
460 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8 + 4);
465 } else { /* floating args */
466 if (p < rd->fltreg_argnum) { /* register arguments */
467 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
468 panic("There are no float argument registers!");
470 } else { /* reg arg -> spilled */
471 panic("There are no float argument registers!");
474 } else { /* stack arguments */
475 pa = p - rd->fltreg_argnum;
476 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
478 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
480 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
484 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
486 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
490 } else { /* stack-arg -> spilled */
491 /* i386_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 4, REG_ITMP1); */
492 /* i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, r * 8); */
494 i386_flds_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
495 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
498 i386_fldl_membase(cd, REG_SP, (parentargs_base + pa) * 8 + 4);
499 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
508 /* end of header generation */
510 /* walk through all basic blocks */
511 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
513 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
515 if (bptr->flags >= BBREACHED) {
517 /* branch resolving */
520 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
521 gen_resolvebranch(cd->mcodebase + brefs->branchpos,
526 /* copy interface registers to their destination */
531 while (src != NULL) {
533 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
534 if (!IS_2_WORD_TYPE(src->type)) {
535 if (bptr->type == BBTYPE_SBR) {
536 d = reg_of_var(rd, src, REG_ITMP1);
538 store_reg_to_var_int(src, d);
540 } else if (bptr->type == BBTYPE_EXH) {
541 d = reg_of_var(rd, src, REG_ITMP1);
542 M_INTMOVE(REG_ITMP1, d);
543 store_reg_to_var_int(src, d);
547 panic("copy interface registers: longs have to me in memory (begin 1)");
551 d = reg_of_var(rd, src, REG_ITMP1);
552 if ((src->varkind != STACKVAR)) {
554 if (IS_FLT_DBL_TYPE(s2)) {
555 s1 = rd->interfaces[len][s2].regoff;
556 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
560 if (s2 == TYPE_FLT) {
561 i386_flds_membase(cd, REG_SP, s1 * 8);
564 i386_fldl_membase(cd, REG_SP, s1 * 8);
567 store_reg_to_var_flt(src, d);
570 s1 = rd->interfaces[len][s2].regoff;
571 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
572 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
576 i386_mov_membase_reg(cd, REG_SP, s1 * 8, d);
578 store_reg_to_var_int(src, d);
581 if (rd->interfaces[len][s2].flags & INMEMORY) {
582 M_LNGMEMMOVE(s1, src->regoff);
585 panic("copy interface registers: longs have to be in memory (begin 2)");
594 /* walk through all instructions */
599 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
600 if (iptr->line != currentline) {
601 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
602 currentline = iptr->line;
605 MCODECHECK(64); /* an instruction usually needs < 64 words */
608 case ICMD_NOP: /* ... ==> ... */
611 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
612 if (src->flags & INMEMORY) {
613 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
616 i386_test_reg_reg(cd, src->regoff, src->regoff);
618 i386_jcc(cd, I386_CC_E, 0);
619 codegen_addxnullrefs(cd, cd->mcodeptr);
622 /* constant operations ************************************************/
624 case ICMD_ICONST: /* ... ==> ..., constant */
625 /* op1 = 0, val.i = constant */
627 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
628 if (iptr->dst->flags & INMEMORY) {
629 i386_mov_imm_membase(cd, iptr->val.i, REG_SP, iptr->dst->regoff * 8);
632 if (iptr->val.i == 0) {
633 i386_alu_reg_reg(cd, I386_XOR, d, d);
636 i386_mov_imm_reg(cd, iptr->val.i, d);
641 case ICMD_LCONST: /* ... ==> ..., constant */
642 /* op1 = 0, val.l = constant */
644 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
645 if (iptr->dst->flags & INMEMORY) {
646 i386_mov_imm_membase(cd, iptr->val.l, REG_SP, iptr->dst->regoff * 8);
647 i386_mov_imm_membase(cd, iptr->val.l >> 32, REG_SP, iptr->dst->regoff * 8 + 4);
650 panic("LCONST: longs have to be in memory");
654 case ICMD_FCONST: /* ... ==> ..., constant */
655 /* op1 = 0, val.f = constant */
657 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
658 if (iptr->val.f == 0.0) {
663 if (iptr->val.i == 0x80000000) {
667 } else if (iptr->val.f == 1.0) {
671 } else if (iptr->val.f == 2.0) {
678 a = dseg_addfloat(cd, iptr->val.f);
679 i386_mov_imm_reg(cd, 0, REG_ITMP1);
680 dseg_adddata(cd, cd->mcodeptr);
681 i386_flds_membase(cd, REG_ITMP1, a);
684 store_reg_to_var_flt(iptr->dst, d);
687 case ICMD_DCONST: /* ... ==> ..., constant */
688 /* op1 = 0, val.d = constant */
690 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
691 if (iptr->val.d == 0.0) {
696 if (iptr->val.l == 0x8000000000000000LL) {
700 } else if (iptr->val.d == 1.0) {
704 } else if (iptr->val.d == 2.0) {
711 a = dseg_adddouble(cd, iptr->val.d);
712 i386_mov_imm_reg(cd, 0, REG_ITMP1);
713 dseg_adddata(cd, cd->mcodeptr);
714 i386_fldl_membase(cd, REG_ITMP1, a);
717 store_reg_to_var_flt(iptr->dst, d);
720 case ICMD_ACONST: /* ... ==> ..., constant */
721 /* op1 = 0, val.a = constant */
723 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
724 if (iptr->dst->flags & INMEMORY) {
725 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, iptr->dst->regoff * 8);
728 if ((s4) iptr->val.a == 0) {
729 i386_alu_reg_reg(cd, I386_XOR, d, d);
732 i386_mov_imm_reg(cd, (s4) iptr->val.a, d);
738 /* load/store operations **********************************************/
740 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
741 case ICMD_ALOAD: /* op1 = local variable */
743 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
744 if ((iptr->dst->varkind == LOCALVAR) &&
745 (iptr->dst->varnum == iptr->op1)) {
748 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
749 if (iptr->dst->flags & INMEMORY) {
750 if (var->flags & INMEMORY) {
751 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, REG_ITMP1);
752 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
755 i386_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
759 if (var->flags & INMEMORY) {
760 i386_mov_membase_reg(cd, REG_SP, var->regoff * 8, iptr->dst->regoff);
763 M_INTMOVE(var->regoff, iptr->dst->regoff);
768 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
769 /* op1 = local variable */
771 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
772 if ((iptr->dst->varkind == LOCALVAR) &&
773 (iptr->dst->varnum == iptr->op1)) {
776 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
777 if (iptr->dst->flags & INMEMORY) {
778 if (var->flags & INMEMORY) {
779 M_LNGMEMMOVE(var->regoff, iptr->dst->regoff);
782 panic("LLOAD: longs have to be in memory");
786 panic("LLOAD: longs have to be in memory");
790 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
791 /* op1 = local variable */
793 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
794 if ((iptr->dst->varkind == LOCALVAR) &&
795 (iptr->dst->varnum == iptr->op1)) {
798 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
799 if (var->flags & INMEMORY) {
800 i386_flds_membase(cd, REG_SP, var->regoff * 8);
803 i386_fld_reg(cd, var->regoff + fpu_st_offset);
806 store_reg_to_var_flt(iptr->dst, d);
809 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
810 /* op1 = local variable */
812 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
813 if ((iptr->dst->varkind == LOCALVAR) &&
814 (iptr->dst->varnum == iptr->op1)) {
817 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
818 if (var->flags & INMEMORY) {
819 i386_fldl_membase(cd, REG_SP, var->regoff * 8);
822 i386_fld_reg(cd, var->regoff + fpu_st_offset);
825 store_reg_to_var_flt(iptr->dst, d);
828 case ICMD_ISTORE: /* ..., value ==> ... */
829 case ICMD_ASTORE: /* op1 = local variable */
831 if ((src->varkind == LOCALVAR) &&
832 (src->varnum == iptr->op1)) {
835 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
836 if (var->flags & INMEMORY) {
837 if (src->flags & INMEMORY) {
838 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
839 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
842 i386_mov_reg_membase(cd, src->regoff, REG_SP, var->regoff * 8);
846 var_to_reg_int(s1, src, var->regoff);
847 M_INTMOVE(s1, var->regoff);
851 case ICMD_LSTORE: /* ..., value ==> ... */
852 /* op1 = local variable */
854 if ((src->varkind == LOCALVAR) &&
855 (src->varnum == iptr->op1)) {
858 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
859 if (var->flags & INMEMORY) {
860 if (src->flags & INMEMORY) {
861 M_LNGMEMMOVE(src->regoff, var->regoff);
864 panic("LSTORE: longs have to be in memory");
868 panic("LSTORE: longs have to be in memory");
872 case ICMD_FSTORE: /* ..., value ==> ... */
873 /* op1 = local variable */
875 if ((src->varkind == LOCALVAR) &&
876 (src->varnum == iptr->op1)) {
879 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
880 if (var->flags & INMEMORY) {
881 var_to_reg_flt(s1, src, REG_FTMP1);
882 i386_fstps_membase(cd, REG_SP, var->regoff * 8);
885 var_to_reg_flt(s1, src, var->regoff);
886 /* M_FLTMOVE(s1, var->regoff); */
887 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
892 case ICMD_DSTORE: /* ..., value ==> ... */
893 /* op1 = local variable */
895 if ((src->varkind == LOCALVAR) &&
896 (src->varnum == iptr->op1)) {
899 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
900 if (var->flags & INMEMORY) {
901 var_to_reg_flt(s1, src, REG_FTMP1);
902 i386_fstpl_membase(cd, REG_SP, var->regoff * 8);
905 var_to_reg_flt(s1, src, var->regoff);
906 /* M_FLTMOVE(s1, var->regoff); */
907 i386_fstp_reg(cd, var->regoff + fpu_st_offset);
913 /* pop/dup/swap operations ********************************************/
915 /* attention: double and longs are only one entry in CACAO ICMDs */
917 case ICMD_POP: /* ..., value ==> ... */
918 case ICMD_POP2: /* ..., value, value ==> ... */
921 case ICMD_DUP: /* ..., a ==> ..., a, a */
922 M_COPY(src, iptr->dst);
925 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
927 M_COPY(src, iptr->dst);
928 M_COPY(src->prev, iptr->dst->prev);
931 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
933 M_COPY(src, iptr->dst);
934 M_COPY(src->prev, iptr->dst->prev);
935 M_COPY(iptr->dst, iptr->dst->prev->prev);
938 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
940 M_COPY(src, iptr->dst);
941 M_COPY(src->prev, iptr->dst->prev);
942 M_COPY(src->prev->prev, iptr->dst->prev->prev);
943 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
946 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
948 M_COPY(src, iptr->dst);
949 M_COPY(src->prev, iptr->dst->prev);
950 M_COPY(src->prev->prev, iptr->dst->prev->prev);
951 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
952 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev);
955 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
957 M_COPY(src, iptr->dst);
958 M_COPY(src->prev, iptr->dst->prev);
959 M_COPY(src->prev->prev, iptr->dst->prev->prev);
960 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
961 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
962 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
965 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
967 M_COPY(src, iptr->dst->prev);
968 M_COPY(src->prev, iptr->dst);
972 /* integer operations *************************************************/
974 case ICMD_INEG: /* ..., value ==> ..., - value */
976 d = reg_of_var(rd, iptr->dst, REG_NULL);
977 if (iptr->dst->flags & INMEMORY) {
978 if (src->flags & INMEMORY) {
979 if (src->regoff == iptr->dst->regoff) {
980 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
983 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
984 i386_neg_reg(cd, REG_ITMP1);
985 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
989 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
990 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
994 if (src->flags & INMEMORY) {
995 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
996 i386_neg_reg(cd, iptr->dst->regoff);
999 M_INTMOVE(src->regoff, iptr->dst->regoff);
1000 i386_neg_reg(cd, iptr->dst->regoff);
1005 case ICMD_LNEG: /* ..., value ==> ..., - value */
1007 d = reg_of_var(rd, iptr->dst, REG_NULL);
1008 if (iptr->dst->flags & INMEMORY) {
1009 if (src->flags & INMEMORY) {
1010 if (src->regoff == iptr->dst->regoff) {
1011 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
1012 i386_alu_imm_membase(cd, I386_ADC, 0, REG_SP, iptr->dst->regoff * 8 + 4);
1013 i386_neg_membase(cd, REG_SP, iptr->dst->regoff * 8 + 4);
1016 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1017 i386_neg_reg(cd, REG_ITMP1);
1018 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1019 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
1020 i386_alu_imm_reg(cd, I386_ADC, 0, REG_ITMP1);
1021 i386_neg_reg(cd, REG_ITMP1);
1022 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8 + 4);
1028 case ICMD_I2L: /* ..., value ==> ..., value */
1030 d = reg_of_var(rd, iptr->dst, REG_NULL);
1031 if (iptr->dst->flags & INMEMORY) {
1032 if (src->flags & INMEMORY) {
1033 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, EAX);
1035 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1036 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1039 M_INTMOVE(src->regoff, EAX);
1041 i386_mov_reg_membase(cd, EAX, REG_SP, iptr->dst->regoff * 8);
1042 i386_mov_reg_membase(cd, EDX, REG_SP, iptr->dst->regoff * 8 + 4);
1047 case ICMD_L2I: /* ..., value ==> ..., value */
1049 d = reg_of_var(rd, iptr->dst, REG_NULL);
1050 if (iptr->dst->flags & INMEMORY) {
1051 if (src->flags & INMEMORY) {
1052 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1053 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1057 if (src->flags & INMEMORY) {
1058 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1063 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
1065 d = reg_of_var(rd, iptr->dst, REG_NULL);
1066 if (iptr->dst->flags & INMEMORY) {
1067 if (src->flags & INMEMORY) {
1068 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1069 i386_shift_imm_reg(cd, I386_SHL, 24, REG_ITMP1);
1070 i386_shift_imm_reg(cd, I386_SAR, 24, REG_ITMP1);
1071 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1074 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1075 i386_shift_imm_membase(cd, I386_SHL, 24, REG_SP, iptr->dst->regoff * 8);
1076 i386_shift_imm_membase(cd, I386_SAR, 24, REG_SP, iptr->dst->regoff * 8);
1080 if (src->flags & INMEMORY) {
1081 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1082 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1083 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1086 M_INTMOVE(src->regoff, iptr->dst->regoff);
1087 i386_shift_imm_reg(cd, I386_SHL, 24, iptr->dst->regoff);
1088 i386_shift_imm_reg(cd, I386_SAR, 24, iptr->dst->regoff);
1093 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
1095 d = reg_of_var(rd, iptr->dst, REG_NULL);
1096 if (iptr->dst->flags & INMEMORY) {
1097 if (src->flags & INMEMORY) {
1098 if (src->regoff == iptr->dst->regoff) {
1099 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1102 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1103 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, REG_ITMP1);
1104 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1108 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1109 i386_alu_imm_membase(cd, I386_AND, 0x0000ffff, REG_SP, iptr->dst->regoff * 8);
1113 if (src->flags & INMEMORY) {
1114 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1115 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1118 M_INTMOVE(src->regoff, iptr->dst->regoff);
1119 i386_alu_imm_reg(cd, I386_AND, 0x0000ffff, iptr->dst->regoff);
1124 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
1126 d = reg_of_var(rd, iptr->dst, REG_NULL);
1127 if (iptr->dst->flags & INMEMORY) {
1128 if (src->flags & INMEMORY) {
1129 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1130 i386_shift_imm_reg(cd, I386_SHL, 16, REG_ITMP1);
1131 i386_shift_imm_reg(cd, I386_SAR, 16, REG_ITMP1);
1132 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1135 i386_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
1136 i386_shift_imm_membase(cd, I386_SHL, 16, REG_SP, iptr->dst->regoff * 8);
1137 i386_shift_imm_membase(cd, I386_SAR, 16, REG_SP, iptr->dst->regoff * 8);
1141 if (src->flags & INMEMORY) {
1142 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1143 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1144 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1147 M_INTMOVE(src->regoff, iptr->dst->regoff);
1148 i386_shift_imm_reg(cd, I386_SHL, 16, iptr->dst->regoff);
1149 i386_shift_imm_reg(cd, I386_SAR, 16, iptr->dst->regoff);
1155 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1157 d = reg_of_var(rd, iptr->dst, REG_NULL);
1158 i386_emit_ialu(cd, I386_ADD, src, iptr);
1161 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
1162 /* val.i = constant */
1164 d = reg_of_var(rd, iptr->dst, REG_NULL);
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 /* `inc reg' is slower on p4's (regarding to ia32 */
2027 /* optimization reference manual and benchmarks) and as fast */
2029 i386_alu_imm_reg(cd, I386_ADD, iptr->val.i, var->regoff);
2034 /* floating operations ************************************************/
2036 #define ROUND_TO_SINGLE \
2037 i386_fstps_membase(cd, REG_SP, -8); \
2038 i386_flds_membase(cd, REG_SP, -8);
2040 #define ROUND_TO_DOUBLE \
2041 i386_fstpl_membase(cd, REG_SP, -8); \
2042 i386_fldl_membase(cd, REG_SP, -8);
2044 #define FPU_SET_24BIT_MODE \
2045 if (!fpu_in_24bit_mode) { \
2046 i386_fldcw_mem(cd, &fpu_ctrlwrd_24bit); \
2047 fpu_in_24bit_mode = 1; \
2050 #define FPU_SET_53BIT_MODE \
2051 if (fpu_in_24bit_mode) { \
2052 i386_fldcw_mem(cd, &fpu_ctrlwrd_53bit); \
2053 fpu_in_24bit_mode = 0; \
2056 #define ROUND_TO_SINGLE
2057 #define ROUND_TO_DOUBLE
2058 #define FPU_SET_24BIT_MODE
2059 #define FPU_SET_53BIT_MODE
2061 case ICMD_FNEG: /* ..., value ==> ..., - value */
2064 var_to_reg_flt(s1, src, REG_FTMP1);
2065 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2067 store_reg_to_var_flt(iptr->dst, d);
2070 case ICMD_DNEG: /* ..., value ==> ..., - value */
2073 var_to_reg_flt(s1, src, REG_FTMP1);
2074 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2076 store_reg_to_var_flt(iptr->dst, d);
2079 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2082 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2083 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2084 var_to_reg_flt(s2, src, REG_FTMP2);
2087 store_reg_to_var_flt(iptr->dst, d);
2090 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
2093 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2094 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2095 var_to_reg_flt(s2, src, REG_FTMP2);
2098 store_reg_to_var_flt(iptr->dst, d);
2101 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2104 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2105 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2106 var_to_reg_flt(s2, src, REG_FTMP2);
2109 store_reg_to_var_flt(iptr->dst, d);
2112 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
2115 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2116 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2117 var_to_reg_flt(s2, src, REG_FTMP2);
2120 store_reg_to_var_flt(iptr->dst, d);
2123 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2126 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2127 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2128 var_to_reg_flt(s2, src, REG_FTMP2);
2132 store_reg_to_var_flt(iptr->dst, d);
2135 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
2138 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2139 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2141 /* i386_fldt_mem(cd, subnormal_bias1); */
2142 /* i386_fmulp(cd); */
2144 var_to_reg_flt(s2, src, REG_FTMP2);
2149 /* i386_fldt_mem(cd, subnormal_bias2); */
2150 /* i386_fmulp(cd); */
2152 store_reg_to_var_flt(iptr->dst, d);
2155 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2158 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2159 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2160 var_to_reg_flt(s2, src, REG_FTMP2);
2164 store_reg_to_var_flt(iptr->dst, d);
2167 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
2170 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2171 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2173 /* i386_fldt_mem(cd, subnormal_bias1); */
2174 /* i386_fmulp(cd); */
2176 var_to_reg_flt(s2, src, REG_FTMP2);
2181 /* i386_fldt_mem(cd, subnormal_bias2); */
2182 /* i386_fmulp(cd); */
2184 store_reg_to_var_flt(iptr->dst, d);
2187 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2190 /* exchanged to skip fxch */
2191 var_to_reg_flt(s2, src, REG_FTMP2);
2192 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2193 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2194 /* i386_fxch(cd); */
2199 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2200 store_reg_to_var_flt(iptr->dst, d);
2201 i386_ffree_reg(cd, 0);
2206 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
2209 /* exchanged to skip fxch */
2210 var_to_reg_flt(s2, src, REG_FTMP2);
2211 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2212 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2213 /* i386_fxch(cd); */
2218 i386_jcc(cd, I386_CC_P, -(2 + 1 + 2 + 1 + 6));
2219 store_reg_to_var_flt(iptr->dst, d);
2220 i386_ffree_reg(cd, 0);
2225 case ICMD_I2F: /* ..., value ==> ..., (float) value */
2226 case ICMD_I2D: /* ..., value ==> ..., (double) value */
2228 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2229 if (src->flags & INMEMORY) {
2230 i386_fildl_membase(cd, REG_SP, src->regoff * 8);
2234 a = dseg_adds4(cd, 0);
2235 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2236 dseg_adddata(cd, cd->mcodeptr);
2237 i386_mov_reg_membase(cd, src->regoff, REG_ITMP1, a);
2238 i386_fildl_membase(cd, REG_ITMP1, a);
2241 store_reg_to_var_flt(iptr->dst, d);
2244 case ICMD_L2F: /* ..., value ==> ..., (float) value */
2245 case ICMD_L2D: /* ..., value ==> ..., (double) value */
2247 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2248 if (src->flags & INMEMORY) {
2249 i386_fildll_membase(cd, REG_SP, src->regoff * 8);
2253 panic("L2F: longs have to be in memory");
2255 store_reg_to_var_flt(iptr->dst, d);
2258 case ICMD_F2I: /* ..., value ==> ..., (int) value */
2260 var_to_reg_flt(s1, src, REG_FTMP1);
2261 d = reg_of_var(rd, iptr->dst, REG_NULL);
2263 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2264 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2265 dseg_adddata(cd, cd->mcodeptr);
2266 i386_fldcw_membase(cd, REG_ITMP1, a);
2268 if (iptr->dst->flags & INMEMORY) {
2269 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2272 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2273 i386_fldcw_membase(cd, REG_ITMP1, a);
2275 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2278 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2280 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2283 a = dseg_adds4(cd, 0);
2284 i386_fistpl_membase(cd, REG_ITMP1, a);
2286 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2288 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2289 i386_fldcw_membase(cd, REG_ITMP1, a);
2291 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2294 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2295 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2298 i386_jcc(cd, I386_CC_NE, a);
2300 /* XXX: change this when we use registers */
2301 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2302 i386_mov_imm_reg(cd, (s4) asm_builtin_f2i, REG_ITMP1);
2303 i386_call_reg(cd, REG_ITMP1);
2305 if (iptr->dst->flags & INMEMORY) {
2306 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2309 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2313 case ICMD_D2I: /* ..., value ==> ..., (int) value */
2315 var_to_reg_flt(s1, src, REG_FTMP1);
2316 d = reg_of_var(rd, iptr->dst, REG_NULL);
2318 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2319 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2320 dseg_adddata(cd, cd->mcodeptr);
2321 i386_fldcw_membase(cd, REG_ITMP1, a);
2323 if (iptr->dst->flags & INMEMORY) {
2324 i386_fistpl_membase(cd, REG_SP, iptr->dst->regoff * 8);
2327 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2328 i386_fldcw_membase(cd, REG_ITMP1, a);
2330 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8);
2333 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2335 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2338 a = dseg_adds4(cd, 0);
2339 i386_fistpl_membase(cd, REG_ITMP1, a);
2341 i386_mov_membase_reg(cd, REG_ITMP1, a, iptr->dst->regoff);
2343 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2344 i386_fldcw_membase(cd, REG_ITMP1, a);
2346 i386_alu_imm_reg(cd, I386_CMP, 0x80000000, iptr->dst->regoff);
2349 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2350 a += 5 + 2 + ((REG_RESULT == iptr->dst->regoff) ? 0 : 2);
2353 i386_jcc(cd, I386_CC_NE, a);
2355 /* XXX: change this when we use registers */
2356 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2357 i386_mov_imm_reg(cd, (s4) asm_builtin_d2i, REG_ITMP1);
2358 i386_call_reg(cd, REG_ITMP1);
2360 if (iptr->dst->flags & INMEMORY) {
2361 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2363 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
2367 case ICMD_F2L: /* ..., value ==> ..., (long) value */
2369 var_to_reg_flt(s1, src, REG_FTMP1);
2370 d = reg_of_var(rd, iptr->dst, REG_NULL);
2372 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2373 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2374 dseg_adddata(cd, cd->mcodeptr);
2375 i386_fldcw_membase(cd, REG_ITMP1, a);
2377 if (iptr->dst->flags & INMEMORY) {
2378 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2381 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2382 i386_fldcw_membase(cd, REG_ITMP1, a);
2384 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2387 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2389 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2392 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2394 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2396 i386_jcc(cd, I386_CC_NE, a);
2398 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2401 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2403 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2405 i386_jcc(cd, I386_CC_NE, a);
2407 /* XXX: change this when we use registers */
2408 i386_flds_membase(cd, REG_SP, src->regoff * 8);
2409 i386_mov_imm_reg(cd, (s4) asm_builtin_f2l, REG_ITMP1);
2410 i386_call_reg(cd, REG_ITMP1);
2411 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2412 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2415 panic("F2L: longs have to be in memory");
2419 case ICMD_D2L: /* ..., value ==> ..., (long) value */
2421 var_to_reg_flt(s1, src, REG_FTMP1);
2422 d = reg_of_var(rd, iptr->dst, REG_NULL);
2424 a = dseg_adds4(cd, 0x0e7f); /* Round to zero, 53-bit mode, exception masked */
2425 i386_mov_imm_reg(cd, 0, REG_ITMP1);
2426 dseg_adddata(cd, cd->mcodeptr);
2427 i386_fldcw_membase(cd, REG_ITMP1, a);
2429 if (iptr->dst->flags & INMEMORY) {
2430 i386_fistpll_membase(cd, REG_SP, iptr->dst->regoff * 8);
2433 a = dseg_adds4(cd, 0x027f); /* Round to nearest, 53-bit mode, exceptions masked */
2434 i386_fldcw_membase(cd, REG_ITMP1, a);
2436 i386_alu_imm_membase(cd, I386_CMP, 0x80000000, REG_SP, iptr->dst->regoff * 8 + 4);
2439 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2441 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2444 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2446 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8 + 4);
2448 i386_jcc(cd, I386_CC_NE, a);
2450 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, iptr->dst->regoff * 8);
2453 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
2455 CALCOFFSETBYTES(a, REG_SP, iptr->dst->regoff * 8);
2457 i386_jcc(cd, I386_CC_NE, a);
2459 /* XXX: change this when we use registers */
2460 i386_fldl_membase(cd, REG_SP, src->regoff * 8);
2461 i386_mov_imm_reg(cd, (s4) asm_builtin_d2l, REG_ITMP1);
2462 i386_call_reg(cd, REG_ITMP1);
2463 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
2464 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
2467 panic("D2L: longs have to be in memory");
2471 case ICMD_F2D: /* ..., value ==> ..., (double) value */
2473 var_to_reg_flt(s1, src, REG_FTMP1);
2474 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2476 store_reg_to_var_flt(iptr->dst, d);
2479 case ICMD_D2F: /* ..., value ==> ..., (float) value */
2481 var_to_reg_flt(s1, src, REG_FTMP1);
2482 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2484 store_reg_to_var_flt(iptr->dst, d);
2487 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
2490 /* exchanged to skip fxch */
2491 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2492 var_to_reg_flt(s1, src, REG_FTMP2);
2493 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2494 /* i386_fxch(cd); */
2498 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as GT */
2499 i386_jcc(cd, I386_CC_E, 6);
2500 i386_alu_imm_reg(cd, I386_AND, 0x000000ff, EAX);
2502 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2503 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2504 i386_jcc(cd, I386_CC_B, 3 + 5);
2505 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2506 i386_jmp_imm(cd, 3);
2507 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2508 store_reg_to_var_int(iptr->dst, d);
2511 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2514 /* exchanged to skip fxch */
2515 var_to_reg_flt(s2, src->prev, REG_FTMP1);
2516 var_to_reg_flt(s1, src, REG_FTMP2);
2517 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2518 /* i386_fxch(cd); */
2522 i386_test_imm_reg(cd, 0x400, EAX); /* unordered treat as LT */
2523 i386_jcc(cd, I386_CC_E, 3);
2524 i386_movb_imm_reg(cd, 1, I386_AH);
2526 i386_mov_imm_reg(cd, 0, d); /* does not affect flags */
2527 i386_jcc(cd, I386_CC_E, 6 + 3 + 5 + 3);
2528 i386_jcc(cd, I386_CC_B, 3 + 5);
2529 i386_alu_imm_reg(cd, I386_SUB, 1, d);
2530 i386_jmp_imm(cd, 3);
2531 i386_alu_imm_reg(cd, I386_ADD, 1, d);
2532 store_reg_to_var_int(iptr->dst, d);
2536 /* memory operations **************************************************/
2538 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
2540 var_to_reg_int(s1, src, REG_ITMP1);
2541 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2542 gen_nullptr_check(s1);
2543 i386_mov_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2544 store_reg_to_var_int(iptr->dst, d);
2547 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2549 var_to_reg_int(s1, src->prev, REG_ITMP1);
2550 var_to_reg_int(s2, src, REG_ITMP2);
2551 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2552 if (iptr->op1 == 0) {
2553 gen_nullptr_check(s1);
2556 i386_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 2, d);
2557 store_reg_to_var_int(iptr->dst, d);
2560 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2562 var_to_reg_int(s1, src->prev, REG_ITMP1);
2563 var_to_reg_int(s2, src, REG_ITMP2);
2564 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2565 if (iptr->op1 == 0) {
2566 gen_nullptr_check(s1);
2570 if (iptr->dst->flags & INMEMORY) {
2571 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, REG_ITMP3);
2572 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8);
2573 i386_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3, REG_ITMP3);
2574 i386_mov_reg_membase(cd, REG_ITMP3, REG_SP, iptr->dst->regoff * 8 + 4);
2578 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2580 var_to_reg_int(s1, src->prev, REG_ITMP1);
2581 var_to_reg_int(s2, src, REG_ITMP2);
2582 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2583 if (iptr->op1 == 0) {
2584 gen_nullptr_check(s1);
2587 i386_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2588 store_reg_to_var_int(iptr->dst, d);
2591 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2593 var_to_reg_int(s1, src->prev, REG_ITMP1);
2594 var_to_reg_int(s2, src, REG_ITMP2);
2595 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2596 if (iptr->op1 == 0) {
2597 gen_nullptr_check(s1);
2600 i386_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2602 store_reg_to_var_flt(iptr->dst, d);
2605 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2607 var_to_reg_int(s1, src->prev, REG_ITMP1);
2608 var_to_reg_int(s2, src, REG_ITMP2);
2609 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2610 if (iptr->op1 == 0) {
2611 gen_nullptr_check(s1);
2614 i386_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2616 store_reg_to_var_flt(iptr->dst, d);
2619 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2621 var_to_reg_int(s1, src->prev, REG_ITMP1);
2622 var_to_reg_int(s2, src, REG_ITMP2);
2623 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2624 if (iptr->op1 == 0) {
2625 gen_nullptr_check(s1);
2628 i386_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2629 store_reg_to_var_int(iptr->dst, d);
2632 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2634 var_to_reg_int(s1, src->prev, REG_ITMP1);
2635 var_to_reg_int(s2, src, REG_ITMP2);
2636 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2637 if (iptr->op1 == 0) {
2638 gen_nullptr_check(s1);
2641 i386_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2642 store_reg_to_var_int(iptr->dst, d);
2645 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2647 var_to_reg_int(s1, src->prev, REG_ITMP1);
2648 var_to_reg_int(s2, src, REG_ITMP2);
2649 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2650 if (iptr->op1 == 0) {
2651 gen_nullptr_check(s1);
2654 i386_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2655 store_reg_to_var_int(iptr->dst, d);
2659 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2661 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2662 var_to_reg_int(s2, src->prev, REG_ITMP2);
2663 if (iptr->op1 == 0) {
2664 gen_nullptr_check(s1);
2667 var_to_reg_int(s3, src, REG_ITMP3);
2668 i386_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2671 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2673 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2674 var_to_reg_int(s2, src->prev, REG_ITMP2);
2675 if (iptr->op1 == 0) {
2676 gen_nullptr_check(s1);
2680 if (src->flags & INMEMORY) {
2681 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
2682 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2683 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP3);
2684 i386_mov_reg_memindex(cd, REG_ITMP3, OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2688 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2690 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2691 var_to_reg_int(s2, src->prev, REG_ITMP2);
2692 if (iptr->op1 == 0) {
2693 gen_nullptr_check(s1);
2696 var_to_reg_int(s3, src, REG_ITMP3);
2697 i386_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2700 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2702 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2703 var_to_reg_int(s2, src->prev, REG_ITMP2);
2704 if (iptr->op1 == 0) {
2705 gen_nullptr_check(s1);
2708 var_to_reg_flt(s3, src, REG_FTMP1);
2709 i386_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2713 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2715 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2716 var_to_reg_int(s2, src->prev, REG_ITMP2);
2717 if (iptr->op1 == 0) {
2718 gen_nullptr_check(s1);
2721 var_to_reg_flt(s3, src, REG_FTMP1);
2722 i386_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2726 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2728 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2729 var_to_reg_int(s2, src->prev, REG_ITMP2);
2730 if (iptr->op1 == 0) {
2731 gen_nullptr_check(s1);
2734 var_to_reg_int(s3, src, REG_ITMP3);
2735 i386_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2738 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2740 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2741 var_to_reg_int(s2, src->prev, REG_ITMP2);
2742 if (iptr->op1 == 0) {
2743 gen_nullptr_check(s1);
2746 var_to_reg_int(s3, src, REG_ITMP3);
2747 i386_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2750 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2752 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2753 var_to_reg_int(s2, src->prev, REG_ITMP2);
2754 if (iptr->op1 == 0) {
2755 gen_nullptr_check(s1);
2758 var_to_reg_int(s3, src, REG_ITMP3);
2759 if (s3 >= EBP) { /* because EBP, ESI, EDI have no xH and xL nibbles */
2760 M_INTMOVE(s3, REG_ITMP3);
2763 i386_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2766 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2768 var_to_reg_int(s1, src->prev, REG_ITMP1);
2769 var_to_reg_int(s2, src, REG_ITMP2);
2770 if (iptr->op1 == 0) {
2771 gen_nullptr_check(s1);
2774 i386_mov_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2777 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2779 var_to_reg_int(s1, src->prev, REG_ITMP1);
2780 var_to_reg_int(s2, src, REG_ITMP2);
2781 if (iptr->op1 == 0) {
2782 gen_nullptr_check(s1);
2786 i386_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2787 i386_mov_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2790 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2792 var_to_reg_int(s1, src->prev, REG_ITMP1);
2793 var_to_reg_int(s2, src, REG_ITMP2);
2794 if (iptr->op1 == 0) {
2795 gen_nullptr_check(s1);
2798 i386_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 2);
2801 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2803 var_to_reg_int(s1, src->prev, REG_ITMP1);
2804 var_to_reg_int(s2, src, REG_ITMP2);
2805 if (iptr->op1 == 0) {
2806 gen_nullptr_check(s1);
2809 i386_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2812 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2814 var_to_reg_int(s1, src->prev, REG_ITMP1);
2815 var_to_reg_int(s2, src, REG_ITMP2);
2816 if (iptr->op1 == 0) {
2817 gen_nullptr_check(s1);
2820 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2823 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2825 var_to_reg_int(s1, src->prev, REG_ITMP1);
2826 var_to_reg_int(s2, src, REG_ITMP2);
2827 if (iptr->op1 == 0) {
2828 gen_nullptr_check(s1);
2831 i386_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2835 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2836 /* op1 = type, val.a = field address */
2838 /* If the static fields' class is not yet initialized, we do it */
2839 /* now. The call code is generated later. */
2840 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2841 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2843 /* This is just for debugging purposes. Is very difficult to */
2844 /* read patched code. Here we patch the following 5 nop's */
2845 /* so that the real code keeps untouched. */
2846 if (showdisassemble) {
2855 a = &(((fieldinfo *) iptr->val.a)->value);
2856 switch (iptr->op1) {
2859 var_to_reg_int(s2, src, REG_ITMP1);
2860 i386_mov_reg_mem(cd, s2, a);
2863 if (src->flags & INMEMORY) {
2864 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
2865 /* using REG_ITMP1 alternating. */
2867 i386_mov_membase_reg(cd, REG_SP, s2 * 8, REG_ITMP1);
2868 i386_mov_membase_reg(cd, REG_SP, s2 * 8 + 4, REG_ITMP2);
2869 i386_mov_reg_mem(cd, REG_ITMP1, a);
2870 i386_mov_reg_mem(cd, REG_ITMP2, a + 4);
2872 panic("PUTSTATIC: longs have to be in memory");
2876 var_to_reg_flt(s2, src, REG_FTMP1);
2877 i386_fstps_mem(cd, a);
2881 var_to_reg_flt(s2, src, REG_FTMP1);
2882 i386_fstpl_mem(cd, a);
2886 throw_cacao_exception_exit(string_java_lang_InternalError,
2887 "Unknown PUTSTATIC operand type %d",
2892 case ICMD_GETSTATIC: /* ... ==> ..., value */
2893 /* op1 = type, val.a = field address */
2895 /* If the static fields' class is not yet initialized, we do it */
2896 /* now. The call code is generated later. */
2897 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2898 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2900 /* This is just for debugging purposes. Is very difficult to */
2901 /* read patched code. Here we patch the following 5 nop's */
2902 /* so that the real code keeps untouched. */
2903 if (showdisassemble) {
2912 a = &(((fieldinfo *) iptr->val.a)->value);
2913 switch (iptr->op1) {
2916 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2917 i386_mov_mem_reg(cd, a, d);
2918 store_reg_to_var_int(iptr->dst, d);
2921 d = reg_of_var(rd, iptr->dst, REG_NULL);
2922 if (iptr->dst->flags & INMEMORY) {
2923 /* Using both REG_ITMP1 and REG_ITMP2 is faster than only */
2924 /* using REG_ITMP1 alternating. */
2925 i386_mov_mem_reg(cd, a, REG_ITMP1);
2926 i386_mov_mem_reg(cd, a + 4, REG_ITMP2);
2927 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
2928 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
2930 panic("GETSTATIC: longs have to be in memory");
2934 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2935 i386_flds_mem(cd, a);
2937 store_reg_to_var_flt(iptr->dst, d);
2940 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2941 i386_fldl_mem(cd, a);
2943 store_reg_to_var_flt(iptr->dst, d);
2946 throw_cacao_exception_exit(string_java_lang_InternalError,
2947 "Unknown GETSTATIC operand type %d",
2952 case ICMD_PUTFIELD: /* ..., value ==> ... */
2953 /* op1 = type, val.i = field offset */
2955 a = ((fieldinfo *) (iptr->val.a))->offset;
2956 switch (iptr->op1) {
2959 var_to_reg_int(s1, src->prev, REG_ITMP1);
2960 var_to_reg_int(s2, src, REG_ITMP2);
2961 gen_nullptr_check(s1);
2962 i386_mov_reg_membase(cd, s2, s1, a);
2965 var_to_reg_int(s1, src->prev, REG_ITMP1);
2966 gen_nullptr_check(s1);
2967 if (src->flags & INMEMORY) {
2968 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP2);
2969 i386_mov_reg_membase(cd, REG_ITMP2, s1, a);
2970 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
2971 i386_mov_reg_membase(cd, REG_ITMP2, s1, a + 4);
2973 panic("PUTFIELD: longs have to be in memory");
2977 var_to_reg_int(s1, src->prev, REG_ITMP1);
2978 var_to_reg_flt(s2, src, REG_FTMP1);
2979 gen_nullptr_check(s1);
2980 i386_fstps_membase(cd, s1, a);
2984 var_to_reg_int(s1, src->prev, REG_ITMP1);
2985 var_to_reg_flt(s2, src, REG_FTMP1);
2986 gen_nullptr_check(s1);
2987 i386_fstpl_membase(cd, s1, a);
2991 throw_cacao_exception_exit(string_java_lang_InternalError,
2992 "Unknown PUTFIELD operand type %d",
2997 case ICMD_GETFIELD: /* ... ==> ..., value */
2998 /* op1 = type, val.i = field offset */
3000 a = ((fieldinfo *) (iptr->val.a))->offset;
3001 switch (iptr->op1) {
3004 var_to_reg_int(s1, src, REG_ITMP1);
3005 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3006 gen_nullptr_check(s1);
3007 i386_mov_membase_reg(cd, s1, a, d);
3008 store_reg_to_var_int(iptr->dst, d);
3011 var_to_reg_int(s1, src, REG_ITMP1);
3012 d = reg_of_var(rd, iptr->dst, REG_NULL);
3013 gen_nullptr_check(s1);
3014 i386_mov_membase_reg(cd, s1, a, REG_ITMP2);
3015 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8);
3016 i386_mov_membase_reg(cd, s1, a + 4, REG_ITMP2);
3017 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, iptr->dst->regoff * 8 + 4);
3020 var_to_reg_int(s1, src, REG_ITMP1);
3021 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3022 gen_nullptr_check(s1);
3023 i386_flds_membase(cd, s1, a);
3025 store_reg_to_var_flt(iptr->dst, d);
3028 var_to_reg_int(s1, src, REG_ITMP1);
3029 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
3030 gen_nullptr_check(s1);
3031 i386_fldl_membase(cd, s1, a);
3033 store_reg_to_var_flt(iptr->dst, d);
3036 throw_cacao_exception_exit(string_java_lang_InternalError,
3037 "Unknown GETFIELD operand type %d",
3043 /* branch operations **************************************************/
3045 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
3047 var_to_reg_int(s1, src, REG_ITMP1);
3048 M_INTMOVE(s1, REG_ITMP1_XPTR);
3050 i386_call_imm(cd, 0); /* passing exception pointer */
3051 i386_pop_reg(cd, REG_ITMP2_XPC);
3053 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
3054 i386_jmp_reg(cd, REG_ITMP3);
3058 case ICMD_GOTO: /* ... ==> ... */
3059 /* op1 = target JavaVM pc */
3061 i386_jmp_imm(cd, 0);
3062 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3066 case ICMD_JSR: /* ... ==> ... */
3067 /* op1 = target JavaVM pc */
3069 i386_call_imm(cd, 0);
3070 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3073 case ICMD_RET: /* ... ==> ... */
3074 /* op1 = local variable */
3076 var = &(rd->locals[iptr->op1][TYPE_ADR]);
3077 var_to_reg_int(s1, var, REG_ITMP1);
3078 i386_jmp_reg(cd, s1);
3081 case ICMD_IFNULL: /* ..., value ==> ... */
3082 /* op1 = target JavaVM pc */
3084 if (src->flags & INMEMORY) {
3085 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3088 i386_test_reg_reg(cd, src->regoff, src->regoff);
3090 i386_jcc(cd, I386_CC_E, 0);
3091 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3094 case ICMD_IFNONNULL: /* ..., value ==> ... */
3095 /* op1 = target JavaVM pc */
3097 if (src->flags & INMEMORY) {
3098 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
3101 i386_test_reg_reg(cd, src->regoff, src->regoff);
3103 i386_jcc(cd, I386_CC_NE, 0);
3104 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3107 case ICMD_IFEQ: /* ..., value ==> ... */
3108 /* op1 = target JavaVM pc, val.i = constant */
3110 if (src->flags & INMEMORY) {
3111 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3114 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3116 i386_jcc(cd, I386_CC_E, 0);
3117 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3120 case ICMD_IFLT: /* ..., value ==> ... */
3121 /* op1 = target JavaVM pc, val.i = constant */
3123 if (src->flags & INMEMORY) {
3124 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3127 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3129 i386_jcc(cd, I386_CC_L, 0);
3130 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3133 case ICMD_IFLE: /* ..., value ==> ... */
3134 /* op1 = target JavaVM pc, val.i = constant */
3136 if (src->flags & INMEMORY) {
3137 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3140 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3142 i386_jcc(cd, I386_CC_LE, 0);
3143 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3146 case ICMD_IFNE: /* ..., value ==> ... */
3147 /* op1 = target JavaVM pc, val.i = constant */
3149 if (src->flags & INMEMORY) {
3150 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3153 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3155 i386_jcc(cd, I386_CC_NE, 0);
3156 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3159 case ICMD_IFGT: /* ..., value ==> ... */
3160 /* op1 = target JavaVM pc, val.i = constant */
3162 if (src->flags & INMEMORY) {
3163 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3166 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3168 i386_jcc(cd, I386_CC_G, 0);
3169 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3172 case ICMD_IFGE: /* ..., value ==> ... */
3173 /* op1 = target JavaVM pc, val.i = constant */
3175 if (src->flags & INMEMORY) {
3176 i386_alu_imm_membase(cd, I386_CMP, iptr->val.i, REG_SP, src->regoff * 8);
3179 i386_alu_imm_reg(cd, I386_CMP, iptr->val.i, src->regoff);
3181 i386_jcc(cd, I386_CC_GE, 0);
3182 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3185 case ICMD_IF_LEQ: /* ..., value ==> ... */
3186 /* op1 = target JavaVM pc, val.l = constant */
3188 if (src->flags & INMEMORY) {
3189 if (iptr->val.l == 0) {
3190 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3191 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3194 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3195 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l >> 32, REG_ITMP2);
3196 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3197 i386_alu_imm_reg(cd, I386_XOR, iptr->val.l, REG_ITMP1);
3198 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3201 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3202 i386_jcc(cd, I386_CC_E, 0);
3203 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3206 case ICMD_IF_LLT: /* ..., value ==> ... */
3207 /* op1 = target JavaVM pc, val.l = constant */
3209 if (src->flags & INMEMORY) {
3210 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3211 i386_jcc(cd, I386_CC_L, 0);
3212 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3215 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3216 CALCIMMEDIATEBYTES(a, iptr->val.l);
3218 i386_jcc(cd, I386_CC_G, a);
3220 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3221 i386_jcc(cd, I386_CC_B, 0);
3222 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3226 case ICMD_IF_LLE: /* ..., value ==> ... */
3227 /* op1 = target JavaVM pc, val.l = constant */
3229 if (src->flags & INMEMORY) {
3230 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3231 i386_jcc(cd, I386_CC_L, 0);
3232 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3235 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3236 CALCIMMEDIATEBYTES(a, iptr->val.l);
3238 i386_jcc(cd, I386_CC_G, a);
3240 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3241 i386_jcc(cd, I386_CC_BE, 0);
3242 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3246 case ICMD_IF_LNE: /* ..., value ==> ... */
3247 /* op1 = target JavaVM pc, val.l = constant */
3249 if (src->flags & INMEMORY) {
3250 if (iptr->val.l == 0) {
3251 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3252 i386_alu_membase_reg(cd, I386_OR, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3255 i386_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
3256 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3257 i386_mov_imm_reg(cd, iptr->val.l >> 32, REG_ITMP2);
3258 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3259 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3262 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3263 i386_jcc(cd, I386_CC_NE, 0);
3264 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3267 case ICMD_IF_LGT: /* ..., value ==> ... */
3268 /* op1 = target JavaVM pc, val.l = constant */
3270 if (src->flags & INMEMORY) {
3271 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3272 i386_jcc(cd, I386_CC_G, 0);
3273 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3276 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3277 CALCIMMEDIATEBYTES(a, iptr->val.l);
3279 i386_jcc(cd, I386_CC_L, a);
3281 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3282 i386_jcc(cd, I386_CC_A, 0);
3283 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3287 case ICMD_IF_LGE: /* ..., value ==> ... */
3288 /* op1 = target JavaVM pc, val.l = constant */
3290 if (src->flags & INMEMORY) {
3291 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l >> 32, REG_SP, src->regoff * 8 + 4);
3292 i386_jcc(cd, I386_CC_G, 0);
3293 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3296 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3297 CALCIMMEDIATEBYTES(a, iptr->val.l);
3299 i386_jcc(cd, I386_CC_L, a);
3301 i386_alu_imm_membase(cd, I386_CMP, iptr->val.l, REG_SP, src->regoff * 8);
3302 i386_jcc(cd, I386_CC_AE, 0);
3303 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3307 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
3308 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
3310 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3311 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3312 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3314 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3315 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3317 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3318 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3321 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3323 i386_jcc(cd, I386_CC_E, 0);
3324 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3327 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
3328 /* op1 = target JavaVM pc */
3330 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3331 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3332 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3333 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3334 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3335 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3336 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3338 i386_jcc(cd, I386_CC_E, 0);
3339 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3342 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
3343 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
3345 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3346 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3347 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3349 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3350 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3352 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3353 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3356 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3358 i386_jcc(cd, I386_CC_NE, 0);
3359 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3362 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
3363 /* op1 = target JavaVM pc */
3365 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3366 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3367 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP2);
3368 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8, REG_ITMP1);
3369 i386_alu_membase_reg(cd, I386_XOR, REG_SP, src->regoff * 8 + 4, REG_ITMP2);
3370 i386_alu_reg_reg(cd, I386_OR, REG_ITMP2, REG_ITMP1);
3371 i386_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3373 i386_jcc(cd, I386_CC_NE, 0);
3374 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3377 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
3378 /* op1 = target JavaVM pc */
3380 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3381 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3382 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3384 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3385 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3387 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3388 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3391 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3393 i386_jcc(cd, I386_CC_L, 0);
3394 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3397 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
3398 /* op1 = target JavaVM pc */
3400 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3401 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3402 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3403 i386_jcc(cd, I386_CC_L, 0);
3404 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3407 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3408 CALCOFFSETBYTES(a, REG_SP, src->regoff);
3410 i386_jcc(cd, I386_CC_G, a);
3412 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3413 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3414 i386_jcc(cd, I386_CC_B, 0);
3415 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3419 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
3420 /* op1 = target JavaVM pc */
3422 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3423 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3424 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3426 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3427 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3429 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3430 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3433 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3435 i386_jcc(cd, I386_CC_G, 0);
3436 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3439 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
3440 /* op1 = target JavaVM pc */
3442 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3443 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3444 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3445 i386_jcc(cd, I386_CC_G, 0);
3446 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3449 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3450 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3452 i386_jcc(cd, I386_CC_L, a);
3454 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3455 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3456 i386_jcc(cd, I386_CC_A, 0);
3457 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3461 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
3462 /* op1 = target JavaVM pc */
3464 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3465 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3466 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3468 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3469 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3471 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3472 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3475 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3477 i386_jcc(cd, I386_CC_LE, 0);
3478 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3481 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
3482 /* op1 = target JavaVM pc */
3484 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3485 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3486 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3487 i386_jcc(cd, I386_CC_L, 0);
3488 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3491 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3492 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3494 i386_jcc(cd, I386_CC_G, a);
3496 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3497 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3498 i386_jcc(cd, I386_CC_BE, 0);
3499 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3503 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
3504 /* op1 = target JavaVM pc */
3506 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3507 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3508 i386_alu_reg_membase(cd, I386_CMP, REG_ITMP1, REG_SP, src->prev->regoff * 8);
3510 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
3511 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, src->prev->regoff);
3513 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3514 i386_alu_reg_membase(cd, I386_CMP, src->regoff, REG_SP, src->prev->regoff * 8);
3517 i386_alu_reg_reg(cd, I386_CMP, src->regoff, src->prev->regoff);
3519 i386_jcc(cd, I386_CC_GE, 0);
3520 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3523 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
3524 /* op1 = target JavaVM pc */
3526 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
3527 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8 + 4, REG_ITMP1);
3528 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8 + 4, REG_ITMP1);
3529 i386_jcc(cd, I386_CC_G, 0);
3530 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3533 CALCOFFSETBYTES(a, REG_SP, src->prev->regoff * 8);
3534 CALCOFFSETBYTES(a, REG_SP, src->regoff * 8);
3536 i386_jcc(cd, I386_CC_L, a);
3538 i386_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
3539 i386_alu_membase_reg(cd, I386_CMP, REG_SP, src->regoff * 8, REG_ITMP1);
3540 i386_jcc(cd, I386_CC_AE, 0);
3541 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
3545 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
3547 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
3550 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
3551 /* val.i = constant */
3553 d = reg_of_var(rd, iptr->dst, REG_NULL);
3554 i386_emit_ifcc_iconst(cd, I386_CC_NE, src, iptr);
3557 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
3558 /* val.i = constant */
3560 d = reg_of_var(rd, iptr->dst, REG_NULL);
3561 i386_emit_ifcc_iconst(cd, I386_CC_E, src, iptr);
3564 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
3565 /* val.i = constant */
3567 d = reg_of_var(rd, iptr->dst, REG_NULL);
3568 i386_emit_ifcc_iconst(cd, I386_CC_GE, src, iptr);
3571 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
3572 /* val.i = constant */
3574 d = reg_of_var(rd, iptr->dst, REG_NULL);
3575 i386_emit_ifcc_iconst(cd, I386_CC_L, src, iptr);
3578 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
3579 /* val.i = constant */
3581 d = reg_of_var(rd, iptr->dst, REG_NULL);
3582 i386_emit_ifcc_iconst(cd, I386_CC_LE, src, iptr);
3585 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
3586 /* val.i = constant */
3588 d = reg_of_var(rd, iptr->dst, REG_NULL);
3589 i386_emit_ifcc_iconst(cd, I386_CC_G, src, iptr);
3593 case ICMD_IRETURN: /* ..., retvalue ==> ... */
3596 var_to_reg_int(s1, src, REG_RESULT);
3597 M_INTMOVE(s1, REG_RESULT);
3599 goto nowperformreturn;
3601 case ICMD_LRETURN: /* ..., retvalue ==> ... */
3603 if (src->flags & INMEMORY) {
3604 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_RESULT);
3605 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8 + 4, REG_RESULT2);
3608 panic("LRETURN: longs have to be in memory");
3611 goto nowperformreturn;
3613 case ICMD_FRETURN: /* ..., retvalue ==> ... */
3614 case ICMD_DRETURN: /* ..., retvalue ==> ... */
3616 var_to_reg_flt(s1, src, REG_FRESULT);
3617 /* this may be an early return -- keep the offset correct for the
3621 goto nowperformreturn;
3623 case ICMD_RETURN: /* ... ==> ... */
3629 p = parentargs_base;
3631 /* call trace function */
3633 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
3635 i386_mov_imm_membase(cd, (s4) m, REG_SP, 0);
3637 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
3638 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
3640 i386_fstl_membase(cd, REG_SP, 4 + 8);
3641 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
3643 i386_mov_imm_reg(cd, (s4) builtin_displaymethodstop, REG_ITMP1);
3644 i386_call_reg(cd, REG_ITMP1);
3646 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
3647 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
3649 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
3652 #if defined(USE_THREADS)
3653 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3654 i386_mov_membase_reg(cd, REG_SP, 8 * rd->maxmemuse, REG_ITMP2);
3656 /* we need to save the proper return value */
3657 switch (iptr->opc) {
3660 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3664 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
3665 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, rd->maxmemuse * 8 + 4);
3669 i386_fsts_membase(cd, REG_SP, rd->maxmemuse * 8);
3673 i386_fstl_membase(cd, REG_SP, rd->maxmemuse * 8);
3677 i386_alu_imm_reg(cd, I386_SUB, 4, REG_SP);
3678 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0);
3679 i386_mov_imm_reg(cd, (s4) builtin_monitorexit, REG_ITMP1);
3680 i386_call_reg(cd, REG_ITMP1);
3681 i386_alu_imm_reg(cd, I386_ADD, 4, REG_SP);
3683 /* and now restore the proper return value */
3684 switch (iptr->opc) {
3687 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3691 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
3692 i386_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8 + 4, REG_RESULT2);
3696 i386_flds_membase(cd, REG_SP, rd->maxmemuse * 8);
3700 i386_fldl_membase(cd, REG_SP, rd->maxmemuse * 8);
3706 /* restore saved registers */
3707 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
3709 i386_mov_membase_reg(cd, REG_SP, p * 8, rd->savintregs[i]);
3711 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
3713 i386_fldl_membase(cd, REG_SP, p * 8);
3715 if (iptr->opc == ICMD_FRETURN || iptr->opc == ICMD_DRETURN) {
3716 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset + 1);
3718 i386_fstp_reg(cd, rd->savfltregs[i] + fpu_st_offset);
3723 /* deallocate stack */
3724 if (parentargs_base) {
3725 i386_alu_imm_reg(cd, I386_ADD, parentargs_base * 8, REG_SP);
3734 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3739 tptr = (void **) iptr->target;
3741 s4ptr = iptr->val.a;
3742 l = s4ptr[1]; /* low */
3743 i = s4ptr[2]; /* high */
3745 var_to_reg_int(s1, src, REG_ITMP1);
3746 M_INTMOVE(s1, REG_ITMP1);
3748 i386_alu_imm_reg(cd, I386_SUB, l, REG_ITMP1);
3754 i386_alu_imm_reg(cd, I386_CMP, i - 1, REG_ITMP1);
3755 i386_jcc(cd, I386_CC_A, 0);
3757 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3758 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3760 /* build jump table top down and use address of lowest entry */
3762 /* s4ptr += 3 + i; */
3766 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
3767 dseg_addtarget(cd, (basicblock *) tptr[0]);
3771 /* length of dataseg after last dseg_addtarget is used by load */
3773 i386_mov_imm_reg(cd, 0, REG_ITMP2);
3774 dseg_adddata(cd, cd->mcodeptr);
3775 i386_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
3776 i386_jmp_reg(cd, REG_ITMP1);
3782 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3784 s4 i, l, val, *s4ptr;
3787 tptr = (void **) iptr->target;
3789 s4ptr = iptr->val.a;
3790 l = s4ptr[0]; /* default */
3791 i = s4ptr[1]; /* count */
3793 MCODECHECK((i<<2)+8);
3794 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3800 i386_alu_imm_reg(cd, I386_CMP, val, s1);
3801 i386_jcc(cd, I386_CC_E, 0);
3802 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
3803 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3806 i386_jmp_imm(cd, 0);
3807 /* codegen_addreference(cd, BlockPtrOfPC(l), cd->mcodeptr); */
3809 tptr = (void **) iptr->target;
3810 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3817 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
3818 /* op1 = return type, val.a = function pointer*/
3822 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
3823 /* op1 = return type, val.a = function pointer*/
3827 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
3828 /* op1 = return type, val.a = function pointer*/
3832 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3833 /* op1 = arg count, val.a = method pointer */
3835 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3836 /* op1 = arg count, val.a = method pointer */
3838 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3839 /* op1 = arg count, val.a = method pointer */
3841 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
3842 /* op1 = arg count, val.a = method pointer */
3849 MCODECHECK((s3 << 1) + 64);
3851 /* copy arguments to registers or stack location */
3853 for (; --s3 >= 0; src = src->prev) {
3854 if (src->varkind == ARGVAR) {
3858 if (IS_INT_LNG_TYPE(src->type)) {
3859 if (s3 < rd->intreg_argnum) {
3860 panic("No integer argument registers available!");
3863 if (!IS_2_WORD_TYPE(src->type)) {
3864 if (src->flags & INMEMORY) {
3865 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
3866 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, s3 * 8);
3869 i386_mov_reg_membase(cd, src->regoff, REG_SP, s3 * 8);
3873 if (src->flags & INMEMORY) {
3874 M_LNGMEMMOVE(src->regoff, s3);
3877 panic("copy arguments: longs have to be in memory");
3883 if (s3 < rd->fltreg_argnum) {
3884 panic("No float argument registers available!");
3887 var_to_reg_flt(d, src, REG_FTMP1);
3888 if (src->type == TYPE_FLT) {
3889 i386_fstps_membase(cd, REG_SP, s3 * 8);
3892 i386_fstpl_membase(cd, REG_SP, s3 * 8);
3899 switch (iptr->opc) {
3906 i386_mov_imm_reg(cd, a, REG_ITMP1);
3907 i386_call_reg(cd, REG_ITMP1);
3910 case ICMD_INVOKESTATIC:
3911 a = (u4) lm->stubroutine;
3914 i386_mov_imm_reg(cd, a, REG_ITMP2);
3915 i386_call_reg(cd, REG_ITMP2);
3918 case ICMD_INVOKESPECIAL:
3919 a = (u4) lm->stubroutine;
3922 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3923 gen_nullptr_check(REG_ITMP1);
3924 i386_mov_membase_reg(cd, REG_ITMP1, 0, REG_ITMP1); /* access memory for hardware nullptr */
3926 i386_mov_imm_reg(cd, a, REG_ITMP2);
3927 i386_call_reg(cd, REG_ITMP2);
3930 case ICMD_INVOKEVIRTUAL:
3933 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3934 gen_nullptr_check(REG_ITMP1);
3935 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP2);
3936 i386_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3938 i386_call_reg(cd, REG_ITMP1);
3941 case ICMD_INVOKEINTERFACE:
3944 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP1);
3945 gen_nullptr_check(REG_ITMP1);
3946 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3947 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * lm->class->index, REG_ITMP2);
3948 i386_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - lm->class->methods), REG_ITMP1);
3950 i386_call_reg(cd, REG_ITMP1);
3954 /* d contains return type */
3956 if (d != TYPE_VOID) {
3957 d = reg_of_var(rd, iptr->dst, REG_NULL);
3959 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3960 if (IS_2_WORD_TYPE(iptr->dst->type)) {
3961 if (iptr->dst->flags & INMEMORY) {
3962 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3963 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, iptr->dst->regoff * 8 + 4);
3966 panic("RETURN: longs have to be in memory");
3970 if (iptr->dst->flags & INMEMORY) {
3971 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, iptr->dst->regoff * 8);
3974 M_INTMOVE(REG_RESULT, iptr->dst->regoff);
3979 /* fld from called function -- has other fpu_st_offset counter */
3981 store_reg_to_var_flt(iptr->dst, d);
3988 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3990 /* op1: 0 == array, 1 == class */
3991 /* val.a: (classinfo*) superclass */
3993 /* superclass is an interface:
3995 * return (sub != NULL) &&
3996 * (sub->vftbl->interfacetablelength > super->index) &&
3997 * (sub->vftbl->interfacetable[-super->index] != NULL);
3999 * superclass is a class:
4001 * return ((sub != NULL) && (0
4002 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4003 * super->vftbl->diffvall));
4007 classinfo *super = (classinfo*) iptr->val.a;
4009 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4010 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4012 var_to_reg_int(s1, src, REG_ITMP1);
4013 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4015 M_INTMOVE(s1, REG_ITMP1);
4018 i386_alu_reg_reg(cd, I386_XOR, d, d);
4019 if (iptr->op1) { /* class/interface */
4020 if (super->flags & ACC_INTERFACE) { /* interface */
4021 i386_test_reg_reg(cd, s1, s1);
4023 /* TODO: clean up this calculation */
4025 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4028 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4031 /* CALCOFFSETBYTES(a, super->index); */
4032 CALCIMMEDIATEBYTES(a, super->index);
4038 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4045 i386_jcc(cd, I386_CC_E, a);
4047 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4048 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4049 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4051 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4053 /* TODO: clean up this calculation */
4056 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4063 i386_jcc(cd, I386_CC_LE, a);
4064 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
4066 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP1);
4067 /* i386_setcc_reg(cd, I386_CC_A, d); */
4068 /* i386_jcc(cd, I386_CC_BE, 5); */
4069 i386_jcc(cd, I386_CC_E, 5);
4070 i386_mov_imm_reg(cd, 1, d);
4073 } else { /* class */
4074 i386_test_reg_reg(cd, s1, s1);
4076 /* TODO: clean up this calculation */
4078 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4081 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4083 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4086 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4096 i386_jcc(cd, I386_CC_E, a);
4098 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4099 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4100 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4101 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4103 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4104 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4105 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4106 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4107 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4109 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4110 i386_alu_reg_reg(cd, I386_XOR, d, d);
4112 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4113 i386_jcc(cd, I386_CC_A, 5);
4114 i386_mov_imm_reg(cd, 1, d);
4118 panic ("internal error: no inlined array instanceof");
4120 store_reg_to_var_int(iptr->dst, d);
4123 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
4125 /* op1: 0 == array, 1 == class */
4126 /* val.a: (classinfo*) superclass */
4128 /* superclass is an interface:
4130 * OK if ((sub == NULL) ||
4131 * (sub->vftbl->interfacetablelength > super->index) &&
4132 * (sub->vftbl->interfacetable[-super->index] != NULL));
4134 * superclass is a class:
4136 * OK if ((sub == NULL) || (0
4137 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
4138 * super->vftbl->diffvall));
4142 classinfo *super = (classinfo*) iptr->val.a;
4144 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4145 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
4147 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
4148 var_to_reg_int(s1, src, d);
4149 if (iptr->op1) { /* class/interface */
4150 if (super->flags & ACC_INTERFACE) { /* interface */
4151 i386_test_reg_reg(cd, s1, s1);
4153 /* TODO: clean up this calculation */
4155 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4158 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
4161 /* CALCOFFSETBYTES(a, super->index); */
4162 CALCIMMEDIATEBYTES(a, super->index);
4168 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
4173 i386_jcc(cd, I386_CC_E, a);
4175 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4176 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
4177 i386_alu_imm_reg(cd, I386_SUB, super->index, REG_ITMP2);
4179 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4180 i386_jcc(cd, I386_CC_LE, 0);
4181 codegen_addxcastrefs(cd, cd->mcodeptr);
4182 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
4184 i386_alu_imm_reg(cd, I386_CMP, 0, REG_ITMP2);
4185 i386_jcc(cd, I386_CC_E, 0);
4186 codegen_addxcastrefs(cd, cd->mcodeptr);
4188 } else { /* class */
4189 i386_test_reg_reg(cd, s1, s1);
4191 /* TODO: clean up this calculation */
4193 CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
4198 CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
4200 if (d != REG_ITMP3) {
4202 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4205 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4211 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
4218 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
4225 i386_jcc(cd, I386_CC_E, a);
4227 i386_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
4228 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4229 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4230 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
4232 i386_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
4233 if (d != REG_ITMP3) {
4234 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
4235 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4236 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4237 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4239 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP3, REG_ITMP1);
4242 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
4243 i386_alu_reg_reg(cd, I386_SUB, REG_ITMP2, REG_ITMP1);
4244 i386_mov_imm_reg(cd, (s4) super->vftbl, REG_ITMP2);
4245 i386_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
4246 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4247 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
4251 i386_alu_reg_reg(cd, I386_CMP, REG_ITMP2, REG_ITMP1);
4252 i386_jcc(cd, I386_CC_A, 0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
4253 codegen_addxcastrefs(cd, cd->mcodeptr);
4257 panic ("internal error: no inlined array checkcast");
4260 store_reg_to_var_int(iptr->dst, d);
4263 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
4265 if (src->flags & INMEMORY) {
4266 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4269 i386_test_reg_reg(cd, src->regoff, src->regoff);
4271 i386_jcc(cd, I386_CC_L, 0);
4272 codegen_addxcheckarefs(cd, cd->mcodeptr);
4275 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
4277 i386_test_reg_reg(cd, REG_RESULT, REG_RESULT);
4278 i386_jcc(cd, I386_CC_E, 0);
4279 codegen_addxexceptionrefs(cd, cd->mcodeptr);
4282 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
4283 /* op1 = dimension, val.a = array descriptor */
4285 /* check for negative sizes and copy sizes to stack if necessary */
4287 MCODECHECK((iptr->op1 << 1) + 64);
4289 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
4290 if (src->flags & INMEMORY) {
4291 i386_alu_imm_membase(cd, I386_CMP, 0, REG_SP, src->regoff * 8);
4294 i386_test_reg_reg(cd, src->regoff, src->regoff);
4296 i386_jcc(cd, I386_CC_L, 0);
4297 codegen_addxcheckarefs(cd, cd->mcodeptr);
4300 * copy sizes to new stack location, be cause native function
4301 * builtin_nmultianewarray access them as (int *)
4303 i386_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
4304 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, -(iptr->op1 - s1) * 4);
4306 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
4308 if (src->varkind != ARGVAR) {
4309 if (src->flags & INMEMORY) {
4310 i386_mov_membase_reg(cd, REG_SP, (src->regoff + INT_ARG_CNT) * 8, REG_ITMP1);
4311 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, (s1 + INT_ARG_CNT) * 8);
4314 i386_mov_reg_membase(cd, src->regoff, REG_SP, (s1 + INT_ARG_CNT) * 8);
4318 i386_alu_imm_reg(cd, I386_SUB, iptr->op1 * 4, REG_SP);
4320 /* a0 = dimension count */
4322 /* save stack pointer */
4323 M_INTMOVE(REG_SP, REG_ITMP1);
4325 i386_alu_imm_reg(cd, I386_SUB, 12, REG_SP);
4326 i386_mov_imm_membase(cd, iptr->op1, REG_SP, 0);
4328 /* a1 = arraydescriptor */
4330 i386_mov_imm_membase(cd, (s4) iptr->val.a, REG_SP, 4);
4332 /* a2 = pointer to dimensions = stack pointer */
4334 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 8);
4336 i386_mov_imm_reg(cd, (s4) (builtin_nmultianewarray), REG_ITMP1);
4337 i386_call_reg(cd, REG_ITMP1);
4338 i386_alu_imm_reg(cd, I386_ADD, 12 + iptr->op1 * 4, REG_SP);
4340 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
4341 M_INTMOVE(REG_RESULT, s1);
4342 store_reg_to_var_int(iptr->dst, s1);
4345 case ICMD_INLINE_START:
4346 case ICMD_INLINE_END:
4349 error ("Unknown pseudo command: %d", iptr->opc);
4352 } /* for instruction */
4354 /* copy values to interface registers */
4356 src = bptr->outstack;
4357 len = bptr->outdepth;
4361 if ((src->varkind != STACKVAR)) {
4363 if (IS_FLT_DBL_TYPE(s2)) {
4364 var_to_reg_flt(s1, src, REG_FTMP1);
4365 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4366 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
4369 panic("double store");
4370 /* M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff); */
4374 var_to_reg_int(s1, src, REG_ITMP1);
4375 if (!IS_2_WORD_TYPE(rd->interfaces[len][s2].type)) {
4376 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
4377 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
4380 i386_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
4384 if (rd->interfaces[len][s2].flags & INMEMORY) {
4385 M_LNGMEMMOVE(s1, rd->interfaces[len][s2].regoff);
4388 panic("copy interface registers: longs have to be in memory (end)");
4395 } /* if (bptr -> flags >= BBREACHED) */
4396 } /* for basic block */
4398 codegen_createlinenumbertable(cd);
4402 /* generate bound check stubs */
4404 u1 *xcodeptr = NULL;
4407 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
4408 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4410 cd->mcodeptr - cd->mcodebase);
4414 /* move index register into REG_ITMP1 */
4415 i386_mov_reg_reg(cd, bref->reg, REG_ITMP1); /* 2 bytes */
4417 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4418 dseg_adddata(cd, cd->mcodeptr);
4419 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3); /* 5 bytes */
4420 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 2 bytes */
4422 if (xcodeptr != NULL) {
4423 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4426 xcodeptr = cd->mcodeptr;
4428 i386_push_reg(cd, REG_ITMP2_XPC);
4430 PREPARE_NATIVE_STACKINFO;
4432 i386_alu_imm_reg(cd, I386_SUB, 1 * 4, REG_SP);
4433 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 4);
4434 i386_mov_imm_reg(cd, (u4) new_arrayindexoutofboundsexception, REG_ITMP1);
4435 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4436 i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);
4438 REMOVE_NATIVE_STACKINFO;
4440 i386_pop_reg(cd, REG_ITMP2_XPC);
4442 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4443 i386_jmp_reg(cd, REG_ITMP3);
4447 /* generate negative array size check stubs */
4451 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
4452 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4453 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4455 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4459 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4461 cd->mcodeptr - cd->mcodebase);
4465 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4466 dseg_adddata(cd, cd->mcodeptr);
4467 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4468 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4470 if (xcodeptr != NULL) {
4471 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4474 xcodeptr = cd->mcodeptr;
4476 i386_push_reg(cd, REG_ITMP2_XPC);
4478 PREPARE_NATIVE_STACKINFO;
4480 i386_mov_imm_reg(cd, (u4) new_negativearraysizeexception, REG_ITMP1);
4481 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4482 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4485 REMOVE_NATIVE_STACKINFO;
4487 i386_pop_reg(cd, REG_ITMP2_XPC);
4489 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4490 i386_jmp_reg(cd, REG_ITMP3);
4494 /* generate cast check stubs */
4498 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
4499 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4500 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4502 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4506 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4508 cd->mcodeptr - cd->mcodebase);
4512 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4513 dseg_adddata(cd, cd->mcodeptr);
4514 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4515 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4517 if (xcodeptr != NULL) {
4518 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4521 xcodeptr = cd->mcodeptr;
4523 i386_push_reg(cd, REG_ITMP2_XPC);
4525 PREPARE_NATIVE_STACKINFO;
4527 i386_mov_imm_reg(cd, (u4) new_classcastexception, REG_ITMP1);
4528 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4529 /*i386_alu_imm_reg(cd, I386_ADD, 1 * 4, REG_SP);*/
4532 REMOVE_NATIVE_STACKINFO;
4534 i386_pop_reg(cd, REG_ITMP2_XPC);
4536 i386_mov_imm_reg(cd, (u4) asm_handle_exception, REG_ITMP3);
4537 i386_jmp_reg(cd, REG_ITMP3);
4541 /* generate divide by zero check stubs */
4545 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
4546 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4547 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4549 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4553 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4555 cd->mcodeptr - cd->mcodebase);
4559 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4560 dseg_adddata(cd, cd->mcodeptr);
4561 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4562 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4564 if (xcodeptr != NULL) {
4565 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4568 xcodeptr = cd->mcodeptr;
4570 i386_push_reg(cd, REG_ITMP2_XPC);
4572 PREPARE_NATIVE_STACKINFO;
4574 i386_mov_imm_reg(cd, (u4) new_arithmeticexception, REG_ITMP1);
4575 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4577 REMOVE_NATIVE_STACKINFO;
4579 i386_pop_reg(cd, REG_ITMP2_XPC);
4581 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4582 i386_jmp_reg(cd, REG_ITMP3);
4586 /* generate exception check stubs */
4590 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4591 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4592 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4594 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4598 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4600 cd->mcodeptr - cd->mcodebase);
4604 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4605 dseg_adddata(cd, cd->mcodeptr);
4606 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4607 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4609 if (xcodeptr != NULL) {
4610 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4613 xcodeptr = cd->mcodeptr;
4615 i386_push_reg(cd, REG_ITMP2_XPC);
4617 PREPARE_NATIVE_STACKINFO;
4619 i386_mov_imm_reg(cd, (s4) codegen_general_stubcalled, REG_ITMP1);
4620 i386_call_reg(cd, REG_ITMP1);
4622 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4623 i386_mov_imm_reg(cd, (s4) &builtin_get_exceptionptrptr, REG_ITMP1);
4624 i386_call_reg(cd, REG_ITMP1);
4625 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4626 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
4627 i386_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4629 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP3);
4630 i386_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
4631 i386_mov_imm_membase(cd, 0, REG_ITMP3, 0);
4633 i386_push_imm(cd, 0);
4634 i386_push_reg(cd, REG_ITMP1_XPTR);
4636 /*get the fillInStackTrace Method ID. I simulate a native call here, because I do not want to mess around with the
4637 java stack at this point*/
4638 i386_mov_membase_reg(cd, REG_ITMP1_XPTR, OFFSET(java_objectheader, vftbl), REG_ITMP3);
4639 i386_mov_membase_reg(cd, REG_ITMP3, OFFSET(vftbl_t, class), REG_ITMP1);
4640 i386_push_imm(cd, (u4) utf_fillInStackTrace_desc);
4641 i386_push_imm(cd, (u4) utf_fillInStackTrace_name);
4642 i386_push_reg(cd, REG_ITMP1);
4643 i386_mov_imm_reg(cd, (s4) class_resolvemethod, REG_ITMP3);
4644 i386_call_reg(cd, REG_ITMP3);
4645 /*cleanup parameters of class_resolvemethod*/
4646 i386_alu_imm_reg(cd, I386_ADD,3*4 /*class reference + 2x string reference*/,REG_SP);
4647 /*prepare call to asm_calljavafunction2 */
4648 i386_push_imm(cd, 0);
4649 i386_push_imm(cd, TYPE_ADR); /* --> call block (TYPE,Exceptionptr), each 8 byte (make this dynamic) (JOWENN)*/
4650 i386_push_reg(cd, REG_SP);
4651 i386_push_imm(cd, sizeof(jni_callblock));
4652 i386_push_imm(cd, 1);
4653 i386_push_reg(cd, REG_RESULT);
4655 i386_mov_imm_reg(cd, (s4) asm_calljavafunction2, REG_ITMP3);
4656 i386_call_reg(cd, REG_ITMP3);
4658 /* check exceptionptr + fail (JOWENN)*/
4660 i386_alu_imm_reg(cd, I386_ADD,6*4,REG_SP);
4662 i386_pop_reg(cd, REG_ITMP1_XPTR);
4663 i386_pop_reg(cd, REG_ITMP3); /* just remove the no longer needed 0 from the stack*/
4665 REMOVE_NATIVE_STACKINFO;
4667 i386_pop_reg(cd, REG_ITMP2_XPC);
4669 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4670 i386_jmp_reg(cd, REG_ITMP3);
4674 /* generate null pointer check stubs */
4678 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
4679 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
4680 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4682 xcodeptr - cd->mcodebase - (5 + 5 + 2));
4686 gen_resolvebranch(cd->mcodebase + bref->branchpos,
4688 cd->mcodeptr - cd->mcodebase);
4692 i386_mov_imm_reg(cd, 0, REG_ITMP2_XPC); /* 5 bytes */
4693 dseg_adddata(cd, cd->mcodeptr);
4694 i386_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1); /* 5 bytes */
4695 i386_alu_reg_reg(cd, I386_ADD, REG_ITMP1, REG_ITMP2_XPC); /* 2 bytes */
4697 if (xcodeptr != NULL) {
4698 i386_jmp_imm(cd, (xcodeptr - cd->mcodeptr) - 5);
4701 xcodeptr = cd->mcodeptr;
4703 i386_push_reg(cd, REG_ITMP2_XPC);
4705 PREPARE_NATIVE_STACKINFO;
4708 /* create native call block*/
4709 i386_alu_imm_reg(cd, I386_SUB, 3*4, REG_SP); /* build stack frame (4 * 4 bytes) */
4712 i386_mov_imm_reg(cd, (s4) codegen_stubcalled,REG_ITMP1);
4713 i386_call_reg(cd, REG_ITMP1); /*call codegen_stubcalled*/
4715 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo,REG_ITMP1);
4716 i386_call_reg(cd, REG_ITMP1); /*call builtin_asm_get_stackframeinfo*/
4717 i386_mov_imm_membase(cd, 0,REG_SP, 2*4); /* builtin */
4718 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,1*4); /* save thread pointer to native call stack*/
4719 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2); /* get old value of thread specific native call stack */
4720 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,0*4); /* store value on stack */
4721 i386_mov_reg_membase(cd, REG_SP,REG_RESULT,0); /* store pointer to new stack frame information */
4724 i386_mov_imm_reg(cd, (u4) new_nullpointerexception, REG_ITMP1);
4725 i386_call_reg(cd, REG_ITMP1); /* return value is REG_ITMP1_XPTR */
4727 REMOVE_NATIVE_STACKINFO;
4730 /* restore native call stack */
4731 i386_mov_membase_reg(cd, REG_SP,0,REG_ITMP2);
4732 i386_mov_membase_reg(cd, REG_SP,4,REG_ITMP3);
4733 i386_mov_reg_membase(cd, REG_ITMP2,REG_ITMP3,0);
4734 i386_alu_imm_reg(cd, I386_ADD,3*4,REG_SP);
4737 i386_pop_reg(cd, REG_ITMP2_XPC);
4739 i386_mov_imm_reg(cd, (s4) asm_handle_exception, REG_ITMP3);
4740 i386_jmp_reg(cd, REG_ITMP3);
4744 /* generate put/getstatic stub call code */
4750 tmpcd = DNEW(codegendata);
4752 for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
4753 /* Get machine code which is patched back in later. A */
4754 /* `call rel32' is 5 bytes long. */
4755 xcodeptr = cd->mcodebase + cref->branchpos;
4756 cref->xmcode = *xcodeptr;
4757 cref->mcode = *((u4 *) (xcodeptr + 1));
4761 /* patch in `call rel32' to call the following code */
4762 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
4763 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
4765 /* Save current stack pointer into a temporary register. */
4766 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
4768 /* Push machine code bytes to patch onto the stack. */
4769 i386_push_imm(cd, (u4) cref->xmcode);
4770 i386_push_imm(cd, (u4) cref->mcode);
4772 i386_push_imm(cd, (u4) cref->class);
4774 /* Push previously saved stack pointer onto stack. */
4775 i386_push_reg(cd, REG_ITMP1);
4777 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
4778 i386_jmp_reg(cd, REG_ITMP1);
4783 codegen_finish(m, cd, (u4) (cd->mcodeptr - cd->mcodebase));
4787 /* function createcompilerstub *************************************************
4789 creates a stub routine which calls the compiler
4791 *******************************************************************************/
4793 #define COMPSTUBSIZE 12
4795 u1 *createcompilerstub(methodinfo *m)
4797 u1 *s = CNEW(u1, COMPSTUBSIZE); /* memory to hold the stub */
4801 /* mark start of dump memory area */
4803 dumpsize = dump_size();
4805 cd = DNEW(codegendata);
4808 /* code for the stub */
4809 i386_mov_imm_reg(cd, (u4) m, REG_ITMP1);/* pass method pointer to compiler*/
4811 /* we use REG_ITMP3 cause ECX (REG_ITMP2) is used for patching */
4812 i386_mov_imm_reg(cd, (u4) asm_call_jit_compiler, REG_ITMP3);
4813 i386_jmp_reg(cd, REG_ITMP3); /* jump to compiler */
4815 #if defined(STATISTICS)
4817 count_cstub_len += COMPSTUBSIZE;
4820 /* release dump area */
4822 dump_release(dumpsize);
4828 /* function removecompilerstub *************************************************
4830 deletes a compilerstub from memory (simply by freeing it)
4832 *******************************************************************************/
4834 void removecompilerstub(u1 *stub)
4836 CFREE(stub, COMPSTUBSIZE);
4840 /* function: createnativestub **************************************************
4842 creates a stub routine which calls a native method
4844 *******************************************************************************/
4846 #define NATIVESTUBSIZE 370 + 36
4849 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4850 static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr;
4853 void i386_native_stub_debug(void **p) {
4854 printf("Pos on stack: %p\n",p);
4855 printf("Return adress should be: %p\n",*p);
4858 void i386_native_stub_debug2(void **p) {
4859 printf("Pos on stack: %p\n",p);
4860 printf("Return for lookup is: %p\n",*p);
4863 void traverseStackInfo() {
4864 void **p=builtin_asm_get_stackframeinfo();
4868 printf("base addr:%p, methodinfo:%p\n",*p,(methodinfo*)((*p)+8));
4869 m=*((methodinfo**)((*p)+8));
4870 utf_display(m->name);
4879 u1 *createnativestub(functionptr f, methodinfo *m)
4881 u1 *s = CNEW(u1, NATIVESTUBSIZE); /* memory to hold the stub */
4884 t_inlining_globals *id;
4890 int stackframesize = 4+12; /* initial 4 bytes is space for jni env,
4891 + 4 byte thread pointer + 4 byte previous pointer + method info*/
4892 int stackframeoffset = 4;
4896 void** callAddrPatchPos=0;
4898 void** jmpInstrPatchPos=0;
4900 /* mark start of dump memory area */
4902 dumpsize = dump_size();
4904 /* allocate required dump memory */
4906 cd = DNEW(codegendata);
4907 rd = DNEW(registerdata);
4908 id = DNEW(t_inlining_globals);
4910 /* setup registers before using it */
4912 inlining_setup(m, id);
4913 reg_setup(m, rd, id);
4915 /* set some required varibles which are normally set by codegen_setup */
4918 cd->clinitrefs = NULL;
4920 if (m->flags & ACC_STATIC) {
4921 stackframesize += 4;
4922 stackframeoffset += 4;
4925 descriptor2types(m); /* set paramcount and paramtypes */
4928 /* i386_push_reg(cd, REG_SP);
4929 i386_mov_imm_reg(cd, (s4) i386_native_stub_debug, REG_ITMP1);
4930 i386_call_reg(cd, REG_ITMP1);
4931 i386_pop_reg(cd, REG_ITMP1);*/
4934 /* if function is static, check for initialized */
4936 if (m->flags & ACC_STATIC) {
4937 /* if class isn't yet initialized, do it */
4938 if (!m->class->initialized) {
4939 s4 *header = (s4 *) s;
4940 *header = 0;/*extablesize*/
4942 *header = 0;/*line number table start*/
4944 *header = 0;/*line number table size*/
4946 *header = 0;/*fltsave*/
4948 *header = 0;/*intsave*/
4950 *header = 0;/*isleaf*/
4952 *header = 0;/*issync*/
4954 *header = 0;/*framesize*/
4956 *header = (u4) m;/*methodpointer*/
4965 codegen_addclinitref(cd, cd->mcodeptr, m->class);
4970 i386_alu_imm_reg(cd, I386_SUB, TRACE_ARGS_NUM * 8 + 4, REG_SP);
4972 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
4973 t = m->paramtypes[p];
4974 if (IS_INT_LNG_TYPE(t)) {
4975 if (IS_2_WORD_TYPE(t)) {
4976 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4977 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4 + 4, REG_ITMP2);
4978 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4979 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4981 } else if (t == TYPE_ADR) {
4982 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, REG_ITMP1);
4983 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4984 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
4985 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
4988 i386_mov_membase_reg(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4, EAX);
4990 i386_mov_reg_membase(cd, EAX, REG_SP, p * 8);
4991 i386_mov_reg_membase(cd, EDX, REG_SP, p * 8 + 4);
4995 if (!IS_2_WORD_TYPE(t)) {
4996 i386_flds_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
4997 i386_fstps_membase(cd, REG_SP, p * 8);
4998 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP2, REG_ITMP2);
4999 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, p * 8 + 4);
5002 i386_fldl_membase(cd, REG_SP, 4 + (TRACE_ARGS_NUM + p) * 8 + 4);
5003 i386_fstpl_membase(cd, REG_SP, p * 8);
5008 i386_alu_reg_reg(cd, I386_XOR, REG_ITMP1, REG_ITMP1);
5009 for (p = m->paramcount; p < TRACE_ARGS_NUM; p++) {
5010 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8);
5011 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, p * 8 + 4);
5014 i386_mov_imm_membase(cd, (s4) m, REG_SP, TRACE_ARGS_NUM * 8);
5016 i386_mov_imm_reg(cd, (s4) builtin_trace_args, REG_ITMP1);
5017 i386_call_reg(cd, REG_ITMP1);
5019 i386_alu_imm_reg(cd, I386_ADD, TRACE_ARGS_NUM * 8 + 4, REG_SP);
5023 * mark the whole fpu stack as free for native functions
5024 * (only for saved register count == 0)
5026 i386_ffree_reg(cd, 0);
5027 i386_ffree_reg(cd, 1);
5028 i386_ffree_reg(cd, 2);
5029 i386_ffree_reg(cd, 3);
5030 i386_ffree_reg(cd, 4);
5031 i386_ffree_reg(cd, 5);
5032 i386_ffree_reg(cd, 6);
5033 i386_ffree_reg(cd, 7);
5035 /* calculate stackframe size for native function */
5036 tptr = m->paramtypes;
5037 for (i = 0; i < m->paramcount; i++) {
5042 stackframesize += 4;
5047 stackframesize += 8;
5051 panic("unknown parameter type in native function");
5055 i386_alu_imm_reg(cd, I386_SUB, stackframesize, REG_SP);
5057 /* CREATE DYNAMIC STACK INFO -- BEGIN*/
5058 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
5059 i386_mov_imm_reg(cd, (s4) builtin_asm_get_stackframeinfo, REG_ITMP1);
5060 i386_call_reg(cd, REG_ITMP1);
5061 i386_mov_reg_membase(cd, REG_RESULT,REG_SP,stackframesize-8); /*save thread specific pointer*/
5062 i386_mov_membase_reg(cd, REG_RESULT,0,REG_ITMP2);
5063 i386_mov_reg_membase(cd, REG_ITMP2,REG_SP,stackframesize-12); /*save previous value of memory adress pointed to by thread specific pointer*/
5064 i386_mov_reg_reg(cd, REG_SP,REG_ITMP2);
5065 i386_alu_imm_reg(cd, I386_ADD,stackframesize-12,REG_ITMP2);
5066 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT,0);
5069 /* i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-4);
5070 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-8);
5071 i386_mov_imm_membase(cd, (s4) m, REG_SP,stackframesize-12);*/
5073 /* CREATE DYNAMIC STACK INFO -- END*/
5075 /* RESOLVE NATIVE METHOD -- BEGIN*/
5076 #ifndef STATIC_CLASSPATH
5078 log_text("Dynamic classpath: preparing for delayed native function resolving");
5080 jmpInstrPos=cd->mcodeptr-4;
5082 i386_mov_imm_reg(cd,jmpInstrPos,REG_ITMP1);
5083 i386_push_reg(cd,REG_ITMP1);
5085 i386_mov_imm_reg(cd,0,REG_ITMP1);
5086 jmpInstrPatchPos=cd->mcodeptr-4;
5087 i386_push_reg(cd,REG_ITMP1);
5088 /*position of call address to patch*/
5089 i386_mov_imm_reg(cd,0,REG_ITMP1);
5090 callAddrPatchPos=(cd->mcodeptr-4);
5091 i386_push_reg(cd,REG_ITMP1);
5092 /*method info structure*/
5093 i386_mov_imm_reg(cd,(s4) m, REG_ITMP1);
5094 i386_push_reg(cd,REG_ITMP1);
5095 /*call resolve functions*/
5096 i386_mov_imm_reg(cd, (s4)codegen_resolve_native,REG_ITMP1);
5097 i386_call_reg(cd,REG_ITMP1);
5099 i386_pop_reg(cd,REG_ITMP1);
5100 i386_pop_reg(cd,REG_ITMP1);
5101 i386_pop_reg(cd,REG_ITMP1);
5102 i386_pop_reg(cd,REG_ITMP1);
5103 /*fix jmp offset replacement*/
5104 (*jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-4;
5105 } else log_text("Dynamic classpath: immediate native function resolution possible");
5107 /* RESOLVE NATIVE METHOD -- END*/
5111 tptr = m->paramtypes;
5112 for (i = 0; i < m->paramcount; i++) {
5117 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5118 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5119 stackframeoffset += 4;
5124 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8, REG_ITMP1);
5125 i386_mov_membase_reg(cd, REG_SP, stackframesize + (1 * 4) + i * 8 + 4, REG_ITMP2);
5126 i386_mov_reg_membase(cd, REG_ITMP1, REG_SP, stackframeoffset);
5127 i386_mov_reg_membase(cd, REG_ITMP2, REG_SP, stackframeoffset + 4);
5128 stackframeoffset += 8;
5132 panic("unknown parameter type in native function");
5136 if (m->flags & ACC_STATIC) {
5137 /* put class into second argument */
5138 i386_mov_imm_membase(cd, (s4) m->class, REG_SP, 4);
5141 /* put env into first argument */
5142 i386_mov_imm_membase(cd, (s4) &env, REG_SP, 0);
5144 i386_mov_imm_reg(cd, (s4) f, REG_ITMP1);
5145 #ifndef STATIC_CLASSPATH
5147 (*callAddrPatchPos)=(cd->mcodeptr-4);
5149 i386_call_reg(cd, REG_ITMP1);
5151 /*REMOVE DYNAMIC STACK INFO -BEGIN */
5152 i386_push_reg(cd, REG_RESULT2);
5153 i386_mov_membase_reg(cd, REG_SP,stackframesize-8,REG_ITMP2); /*old value*/
5154 i386_mov_membase_reg(cd, REG_SP,stackframesize-4,REG_RESULT2); /*pointer*/
5155 i386_mov_reg_membase(cd, REG_ITMP2,REG_RESULT2,0);
5156 i386_pop_reg(cd, REG_RESULT2);
5157 /*REMOVE DYNAMIC STACK INFO -END */
5159 i386_alu_imm_reg(cd, I386_ADD, stackframesize, REG_SP);
5163 i386_alu_imm_reg(cd, I386_SUB, 4 + 8 + 8 + 4, REG_SP);
5165 i386_mov_imm_membase(cd, (u4) m, REG_SP, 0);
5167 i386_mov_reg_membase(cd, REG_RESULT, REG_SP, 4);
5168 i386_mov_reg_membase(cd, REG_RESULT2, REG_SP, 4 + 4);
5170 i386_fstl_membase(cd, REG_SP, 4 + 8);
5171 i386_fsts_membase(cd, REG_SP, 4 + 8 + 8);
5173 i386_mov_imm_reg(cd, (u4) builtin_displaymethodstop, REG_ITMP1);
5174 i386_call_reg(cd, REG_ITMP1);
5176 i386_mov_membase_reg(cd, REG_SP, 4, REG_RESULT);
5177 i386_mov_membase_reg(cd, REG_SP, 4 + 4, REG_RESULT2);
5179 i386_alu_imm_reg(cd, I386_ADD, 4 + 8 + 8 + 4, REG_SP);
5182 /* we can't use REG_ITMP3 == REG_RESULT2 */
5183 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5184 i386_push_reg(cd, REG_RESULT);
5185 i386_push_reg(cd, REG_RESULT2);
5186 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5187 i386_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP2);
5188 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5189 i386_pop_reg(cd, REG_RESULT2);
5190 i386_pop_reg(cd, REG_RESULT);
5192 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5193 i386_mov_membase_reg(cd, REG_ITMP2, 0, REG_ITMP2);
5194 i386_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
5196 i386_jcc(cd, I386_CC_NE, 1);
5200 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
5201 i386_push_reg(cd, REG_ITMP2);
5202 i386_call_mem(cd, (s4) &callgetexceptionptrptr);
5203 i386_mov_imm_membase(cd, 0, REG_RESULT, 0);
5204 i386_pop_reg(cd, REG_ITMP1_XPTR);
5206 i386_mov_reg_reg(cd, REG_ITMP2, REG_ITMP1_XPTR);
5207 i386_mov_imm_reg(cd, (s4) &_exceptionptr, REG_ITMP2);
5208 i386_mov_imm_membase(cd, 0, REG_ITMP2, 0);
5210 i386_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
5211 i386_alu_imm_reg(cd, I386_SUB, 2, REG_ITMP2_XPC);
5213 i386_mov_imm_reg(cd, (s4) asm_handle_nat_exception, REG_ITMP3);
5214 i386_jmp_reg(cd, REG_ITMP3);
5217 codegen_insertmethod(s, cd->mcodeptr);
5225 tmpcd = DNEW(codegendata);
5227 /* there can only be one clinit ref entry */
5228 cref = cd->clinitrefs;
5231 /* Get machine code which is patched back in later. A */
5232 /* `call rel32' is 5 bytes long. */
5233 xcodeptr = cd->mcodebase + cref->branchpos;
5234 cref->xmcode = *xcodeptr;
5235 cref->mcode = *((u4 *) (xcodeptr + 1));
5237 /* patch in `call rel32' to call the following code */
5238 tmpcd->mcodeptr = xcodeptr; /* set dummy mcode pointer */
5239 i386_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
5241 /* Save current stack pointer into a temporary register. */
5242 i386_mov_reg_reg(cd, REG_SP, REG_ITMP1);
5244 /* Push machine code bytes to patch onto the stack. */
5245 i386_push_imm(cd, (u4) cref->xmcode);
5246 i386_push_imm(cd, (u4) cref->mcode);
5248 i386_push_imm(cd, (u4) cref->class);
5250 /* Push previously saved stack pointer onto stack. */
5251 i386_push_reg(cd, REG_ITMP1);
5253 i386_mov_imm_reg(cd, (u4) asm_check_clinit, REG_ITMP1);
5254 i386_jmp_reg(cd, REG_ITMP1);
5259 dolog_plain("native stubentry: %p, stubsize: %d (for %d params) --", (s4)s,(s4) (cd->mcodeptr - s), m->paramcount);
5260 utf_display(m->name);
5264 #if defined(STATISTICS)
5266 count_nstub_len += NATIVESTUBSIZE;
5269 /* release dump area */
5271 dump_release(dumpsize);
5277 /* function: removenativestub **************************************************
5279 removes a previously created native-stub from memory
5281 *******************************************************************************/
5283 void removenativestub(u1 *stub)
5285 CFREE(stub, NATIVESTUBSIZE);
5290 * These are local overrides for various environment variables in Emacs.
5291 * Please do not remove this and leave it at the end of the file, where
5292 * Emacs will automagically detect them.
5293 * ---------------------------------------------------------------------
5296 * indent-tabs-mode: t