use two functions for creating/removing items of the native stackframe list (i386...
[cacao.git] / src / vm / jit / x86_64 / codegen.c
1 /* jit/x86_64/codegen.c - machine code generator for x86_64
2
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,
7    J. Wenninger
8
9    This file is part of CACAO.
10
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.
15
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.
20
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
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Andreas Krall
29             Christian Thalinger
30
31    $Id: codegen.c 1680 2004-12-04 12:02:08Z jowenn $
32
33 */
34
35
36 #define _GNU_SOURCE
37
38 #include <stdio.h>
39 #include <ucontext.h>
40
41 #include "native/native.h"
42 /*  #include "native/jni.h" */
43 #include "vm/global.h"
44 #include "vm/builtin.h"
45 #include "vm/loader.h"
46 #include "vm/tables.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/jit.h"
49 #include "vm/jit/reg.h"
50 #include "vm/jit/parse.h"
51 #include "vm/jit/x86_64/arch.h"
52 #include "vm/jit/x86_64/codegen.h"
53 #include "vm/jit/x86_64/emitfuncs.h"
54 #include "vm/jit/x86_64/types.h"
55 #include "vm/jit/x86_64/asmoffsets.h"
56 #if 0
57 #include "vm/jit/stacktrace.inc"
58 #endif
59
60 /* register descripton - array ************************************************/
61
62 /* #define REG_RES   0         reserved register for OS or code generator     */
63 /* #define REG_RET   1         return value register                          */
64 /* #define REG_EXC   2         exception value register (only old jit)        */
65 /* #define REG_SAV   3         (callee) saved register                        */
66 /* #define REG_TMP   4         scratch temporary register (caller saved)      */
67 /* #define REG_ARG   5         argument register (caller saved)               */
68
69 /* #define REG_END   -1        last entry in tables                           */
70
71 static int nregdescint[] = {
72     REG_RET, REG_ARG, REG_ARG, REG_TMP, REG_RES, REG_SAV, REG_ARG, REG_ARG,
73     REG_ARG, REG_ARG, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
74     REG_END
75 };
76
77
78 static int nregdescfloat[] = {
79 /*      REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP, */
80 /*      REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, */
81     REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
82     REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
83     REG_END
84 };
85
86
87 /* Include independent code generation stuff -- include after register        */
88 /* descriptions to avoid extern definitions.                                  */
89
90 #include "vm/jit/codegen.inc"
91 #include "vm/jit/reg.inc"
92 #ifdef LSRA
93 #include "vm/jit/lsra.inc"
94 #endif
95
96
97 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
98 void thread_restartcriticalsection(ucontext_t *uc)
99 {
100         void *critical;
101
102         critical = thread_checkcritical((void *) uc->uc_mcontext.gregs[REG_RIP]);
103
104         if (critical)
105                 uc->uc_mcontext.gregs[REG_RIP] = (u8) critical;
106 }
107 #endif
108
109
110 /* NullPointerException signal handler for hardware null pointer check */
111
112 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
113 {
114         sigset_t nsig;
115         /*      int      instr; */
116         /*      long     faultaddr; */
117
118         struct ucontext *_uc = (struct ucontext *) _p;
119         struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
120         struct sigaction act;
121         java_objectheader *xptr;
122
123         /* Reset signal handler - necessary for SysV, does no harm for BSD */
124
125         
126 /*      instr = *((int*)(sigctx->rip)); */
127 /*      faultaddr = sigctx->sc_regs[(instr >> 16) & 0x1f]; */
128
129 /*      if (faultaddr == 0) { */
130         act.sa_sigaction = (functionptr) catch_NullPointerException; /* reinstall handler */
131         act.sa_flags = SA_SIGINFO;
132         sigaction(sig, &act, NULL);
133         
134         sigemptyset(&nsig);
135         sigaddset(&nsig, sig);
136         sigprocmask(SIG_UNBLOCK, &nsig, NULL);               /* unblock signal    */
137
138         xptr = new_nullpointerexception();
139
140         sigctx->rax = (u8) xptr;                             /* REG_ITMP1_XPTR    */
141         sigctx->r10 = sigctx->rip;                           /* REG_ITMP2_XPC     */
142         sigctx->rip = (u8) asm_handle_exception;
143
144         return;
145
146 /*      } else { */
147 /*              faultaddr += (long) ((instr << 16) >> 16); */
148 /*              fprintf(stderr, "faulting address: 0x%08x\n", faultaddr); */
149 /*              panic("Stack overflow"); */
150 /*      } */
151 }
152
153
154 /* ArithmeticException signal handler for hardware divide by zero check */
155
156 void catch_ArithmeticException(int sig, siginfo_t *siginfo, void *_p)
157 {
158         sigset_t nsig;
159
160         struct ucontext *_uc = (struct ucontext *) _p;
161         struct sigcontext *sigctx = (struct sigcontext *) &_uc->uc_mcontext;
162         struct sigaction act;
163         java_objectheader *xptr;
164
165         /* Reset signal handler - necessary for SysV, does no harm for BSD */
166
167         act.sa_sigaction = (functionptr) catch_ArithmeticException; /* reinstall handler */
168         act.sa_flags = SA_SIGINFO;
169         sigaction(sig, &act, NULL);
170
171         sigemptyset(&nsig);
172         sigaddset(&nsig, sig);
173         sigprocmask(SIG_UNBLOCK, &nsig, NULL);               /* unblock signal    */
174
175         xptr = new_arithmeticexception();
176
177         sigctx->rax = (u8) xptr;                             /* REG_ITMP1_XPTR    */
178         sigctx->r10 = sigctx->rip;                           /* REG_ITMP2_XPC     */
179         sigctx->rip = (u8) asm_handle_exception;
180
181         return;
182 }
183
184
185 void init_exceptions(void)
186 {
187         struct sigaction act;
188
189         /* install signal handlers we need to convert to exceptions */
190         sigemptyset(&act.sa_mask);
191
192         if (!checknull) {
193 #if defined(SIGSEGV)
194                 act.sa_sigaction = (functionptr) catch_NullPointerException;
195                 act.sa_flags = SA_SIGINFO;
196                 sigaction(SIGSEGV, &act, NULL);
197 #endif
198
199 #if defined(SIGBUS)
200                 act.sa_sigaction = (functionptr) catch_NullPointerException;
201                 act.sa_flags = SA_SIGINFO;
202                 sigaction(SIGBUS, &act, NULL);
203 #endif
204         }
205
206         act.sa_sigaction = (functionptr) catch_ArithmeticException;
207         act.sa_flags = SA_SIGINFO;
208         sigaction(SIGFPE, &act, NULL);
209 }
210
211
212 /* function gen_mcode **********************************************************
213
214         generates machine code
215
216 *******************************************************************************/
217
218 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
219 {
220         s4 len, s1, s2, s3, d;
221         s8 a;
222         s4 parentargs_base;
223         stackptr        src;
224         varinfo        *var;
225         basicblock     *bptr;
226         instruction    *iptr;
227         exceptiontable *ex;
228
229         {
230         s4 i, p, pa, t, l;
231         s4 savedregs_num;
232
233         savedregs_num = 0;
234
235         /* space to save used callee saved registers */
236
237         savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
238         savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
239
240         parentargs_base = rd->maxmemuse + savedregs_num;
241
242 #if defined(USE_THREADS)           /* space to save argument of monitor_enter */
243
244         if (checksync && (m->flags & ACC_SYNCHRONIZED))
245                 parentargs_base++;
246
247 #endif
248
249     /* keep stack 16-byte aligned for calls into native code e.g. libc or jni */
250     /* (alignment problems with movaps)                                       */
251
252         if (!(parentargs_base & 0x1)) {
253                 parentargs_base++;
254         }
255
256         /* create method header */
257
258         (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
259         (void) dseg_adds4(cd, parentargs_base * 8);             /* FrameSize      */
260
261 #if defined(USE_THREADS)
262
263         /* IsSync contains the offset relative to the stack pointer for the
264            argument of monitor_exit used in the exception handler. Since the
265            offset could be zero and give a wrong meaning of the flag it is
266            offset by one.
267         */
268
269         if (checksync && (m->flags & ACC_SYNCHRONIZED))
270                 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8);     /* IsSync         */
271         else
272
273 #endif
274
275                 (void) dseg_adds4(cd, 0);                           /* IsSync         */
276                                                
277         (void) dseg_adds4(cd, m->isleafmethod);                 /* IsLeaf         */
278         (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse);/* IntSave  */
279         (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse);/* FltSave  */
280         (void) dseg_adds4(cd, cd->exceptiontablelength);        /* ExTableSize    */
281
282         /* create exception table */
283
284         for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
285                 dseg_addtarget(cd, ex->start);
286                 dseg_addtarget(cd, ex->end);
287                 dseg_addtarget(cd, ex->handler);
288                 (void) dseg_addaddress(cd, ex->catchtype);
289         }
290         
291         /* initialize mcode variables */
292         
293         cd->mcodeptr = (u1 *) cd->mcodebase;
294         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
295         MCODECHECK(128 + m->paramcount);
296
297         /* create stack frame (if necessary) */
298
299         if (parentargs_base) {
300                 x86_64_alu_imm_reg(cd, X86_64_SUB, parentargs_base * 8, REG_SP);
301         }
302
303         /* save return address and used callee saved registers */
304
305         p = parentargs_base;
306         for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
307                 p--; x86_64_mov_reg_membase(cd, rd->savintregs[i], REG_SP, p * 8);
308         }
309         for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
310                 p--; x86_64_movq_reg_membase(cd, rd->savfltregs[i], REG_SP, p * 8);
311         }
312
313         /* save monitorenter argument */
314
315 #if defined(USE_THREADS)
316         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
317                 if (m->flags & ACC_STATIC) {
318                         x86_64_mov_imm_reg(cd, (s8) m->class, REG_ITMP1);
319                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, rd->maxmemuse * 8);
320
321                 } else {
322                         x86_64_mov_reg_membase(cd, rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
323                 }
324         }
325 #endif
326
327         /* copy argument registers to stack and call trace function with pointer
328            to arguments on stack.
329         */
330         if (runverbose) {
331                 x86_64_alu_imm_reg(cd, X86_64_SUB, (6 + 8 + 1 + 1) * 8, REG_SP);
332
333                 x86_64_mov_reg_membase(cd, rd->argintregs[0], REG_SP, 1 * 8);
334                 x86_64_mov_reg_membase(cd, rd->argintregs[1], REG_SP, 2 * 8);
335                 x86_64_mov_reg_membase(cd, rd->argintregs[2], REG_SP, 3 * 8);
336                 x86_64_mov_reg_membase(cd, rd->argintregs[3], REG_SP, 4 * 8);
337                 x86_64_mov_reg_membase(cd, rd->argintregs[4], REG_SP, 5 * 8);
338                 x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 6 * 8);
339
340                 x86_64_movq_reg_membase(cd, rd->argfltregs[0], REG_SP, 7 * 8);
341                 x86_64_movq_reg_membase(cd, rd->argfltregs[1], REG_SP, 8 * 8);
342                 x86_64_movq_reg_membase(cd, rd->argfltregs[2], REG_SP, 9 * 8);
343                 x86_64_movq_reg_membase(cd, rd->argfltregs[3], REG_SP, 10 * 8);
344 /*              x86_64_movq_reg_membase(cd, rd->argfltregs[4], REG_SP, 11 * 8); */
345 /*              x86_64_movq_reg_membase(cd, rd->argfltregs[5], REG_SP, 12 * 8); */
346 /*              x86_64_movq_reg_membase(cd, rd->argfltregs[6], REG_SP, 13 * 8); */
347 /*              x86_64_movq_reg_membase(cd, rd->argfltregs[7], REG_SP, 14 * 8); */
348
349                 for (p = 0, l = 0; p < m->paramcount; p++) {
350                         t = m->paramtypes[p];
351
352                         if (IS_FLT_DBL_TYPE(t)) {
353                                 for (s1 = (m->paramcount > INT_ARG_CNT) ? INT_ARG_CNT - 2 : m->paramcount - 2; s1 >= p; s1--) {
354                                         x86_64_mov_reg_reg(cd, rd->argintregs[s1], rd->argintregs[s1 + 1]);
355                                 }
356
357                                 x86_64_movd_freg_reg(cd, rd->argfltregs[l], rd->argintregs[p]);
358                                 l++;
359                         }
360                 }
361
362                 x86_64_mov_imm_reg(cd, (s8) m, REG_ITMP2);
363                 x86_64_mov_reg_membase(cd, REG_ITMP2, REG_SP, 0 * 8);
364                 x86_64_mov_imm_reg(cd, (s8) builtin_trace_args, REG_ITMP1);
365                 x86_64_call_reg(cd, REG_ITMP1);
366
367                 x86_64_mov_membase_reg(cd, REG_SP, 1 * 8, rd->argintregs[0]);
368                 x86_64_mov_membase_reg(cd, REG_SP, 2 * 8, rd->argintregs[1]);
369                 x86_64_mov_membase_reg(cd, REG_SP, 3 * 8, rd->argintregs[2]);
370                 x86_64_mov_membase_reg(cd, REG_SP, 4 * 8, rd->argintregs[3]);
371                 x86_64_mov_membase_reg(cd, REG_SP, 5 * 8, rd->argintregs[4]);
372                 x86_64_mov_membase_reg(cd, REG_SP, 6 * 8, rd->argintregs[5]);
373
374                 x86_64_movq_membase_reg(cd, REG_SP, 7 * 8, rd->argfltregs[0]);
375                 x86_64_movq_membase_reg(cd, REG_SP, 8 * 8, rd->argfltregs[1]);
376                 x86_64_movq_membase_reg(cd, REG_SP, 9 * 8, rd->argfltregs[2]);
377                 x86_64_movq_membase_reg(cd, REG_SP, 10 * 8, rd->argfltregs[3]);
378 /*              x86_64_movq_membase_reg(cd, REG_SP, 11 * 8, rd->argfltregs[4]); */
379 /*              x86_64_movq_membase_reg(cd, REG_SP, 12 * 8, rd->argfltregs[5]); */
380 /*              x86_64_movq_membase_reg(cd, REG_SP, 13 * 8, rd->argfltregs[6]); */
381 /*              x86_64_movq_membase_reg(cd, REG_SP, 14 * 8, rd->argfltregs[7]); */
382
383                 x86_64_alu_imm_reg(cd, X86_64_ADD, (6 + 8 + 1 + 1) * 8, REG_SP);
384         }
385
386         /* take arguments out of register or stack frame */
387
388         for (p = 0, l = 0, s1 = 0, s2 = 0; p < m->paramcount; p++) {
389                 t = m->paramtypes[p];
390                 var = &(rd->locals[l][t]);
391                 l++;
392                 if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
393                         l++;
394                 if (var->type < 0) {
395                         if (IS_INT_LNG_TYPE(t)) {
396                                 s1++;
397                         } else {
398                                 s2++;
399                         }
400                         continue;
401                 }
402                 if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
403                         if (s1 < INT_ARG_CNT) {                  /* register arguments    */
404                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
405                                         M_INTMOVE(rd->argintregs[s1], var->regoff);
406
407                                 } else {                             /* reg arg -> spilled    */
408                                     x86_64_mov_reg_membase(cd, rd->argintregs[s1], REG_SP, var->regoff * 8);
409                                 }
410
411                         } else {                                 /* stack arguments       */
412                                 pa = s1 - INT_ARG_CNT;
413                                 if (s2 >= FLT_ARG_CNT) {
414                                         pa += s2 - FLT_ARG_CNT;
415                                 }
416                                 if (!(var->flags & INMEMORY)) {      /* stack arg -> register */ 
417                                         x86_64_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 8, var->regoff);    /* + 8 for return address */
418                                 } else {                             /* stack arg -> spilled  */
419                                         x86_64_mov_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 8, REG_ITMP1);    /* + 8 for return address */
420                                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, var->regoff * 8);
421                                 }
422                         }
423                         s1++;
424
425                 } else {                                     /* floating args         */   
426                         if (s2 < FLT_ARG_CNT) {                /* register arguments    */
427                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
428                                         M_FLTMOVE(rd->argfltregs[s2], var->regoff);
429
430                                 } else {                                         /* reg arg -> spilled    */
431                                         x86_64_movq_reg_membase(cd, rd->argfltregs[s2], REG_SP, var->regoff * 8);
432                                 }
433
434                         } else {                                 /* stack arguments       */
435                                 pa = s2 - FLT_ARG_CNT;
436                                 if (s1 >= INT_ARG_CNT) {
437                                         pa += s1 - INT_ARG_CNT;
438                                 }
439                                 if (!(var->flags & INMEMORY)) {      /* stack-arg -> register */
440                                         x86_64_movq_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 8, var->regoff);
441
442                                 } else {
443                                         x86_64_movq_membase_reg(cd, REG_SP, (parentargs_base + pa) * 8 + 8, REG_FTMP1);
444                                         x86_64_movq_reg_membase(cd, REG_FTMP1, REG_SP, var->regoff * 8);
445                                 }
446                         }
447                         s2++;
448                 }
449         }  /* end for */
450
451         /* call monitorenter function */
452
453 #if defined(USE_THREADS)
454         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
455                 s8 func_enter = (m->flags & ACC_STATIC) ?
456                         (s8) builtin_staticmonitorenter : (s8) builtin_monitorenter;
457                 x86_64_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, rd->argintregs[0]);
458                 x86_64_mov_imm_reg(cd, func_enter, REG_ITMP1);
459                 x86_64_call_reg(cd, REG_ITMP1);
460         }                       
461 #endif
462         }
463
464         /* end of header generation */
465
466         /* walk through all basic blocks */
467         for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
468
469                 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
470
471                 if (bptr->flags >= BBREACHED) {
472
473                         /* branch resolving */
474
475                         branchref *bref;
476                         for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
477                                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
478                                                                   bref->branchpos,
479                                                                   bptr->mpc);
480                         }
481
482                 /* copy interface registers to their destination */
483
484                 src = bptr->instack;
485                 len = bptr->indepth;
486                 MCODECHECK(64 + len);
487                 while (src != NULL) {
488                         len--;
489                         if ((len == 0) && (bptr->type != BBTYPE_STD)) {
490                                 if (bptr->type == BBTYPE_SBR) {
491                                         d = reg_of_var(rd, src, REG_ITMP1);
492                                         x86_64_pop_reg(cd, d);
493                                         store_reg_to_var_int(src, d);
494
495                                 } else if (bptr->type == BBTYPE_EXH) {
496                                         d = reg_of_var(rd, src, REG_ITMP1);
497                                         M_INTMOVE(REG_ITMP1, d);
498                                         store_reg_to_var_int(src, d);
499                                 }
500
501                         } else {
502                                 d = reg_of_var(rd, src, REG_ITMP1);
503                                 if ((src->varkind != STACKVAR)) {
504                                         s2 = src->type;
505                                         if (IS_FLT_DBL_TYPE(s2)) {
506                                                 s1 = rd->interfaces[len][s2].regoff;
507                                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
508                                                         M_FLTMOVE(s1, d);
509
510                                                 } else {
511                                                         x86_64_movq_membase_reg(cd, REG_SP, s1 * 8, d);
512                                                 }
513                                                 store_reg_to_var_flt(src, d);
514
515                                         } else {
516                                                 s1 = rd->interfaces[len][s2].regoff;
517                                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
518                                                         M_INTMOVE(s1, d);
519
520                                                 } else {
521                                                         x86_64_mov_membase_reg(cd, REG_SP, s1 * 8, d);
522                                                 }
523                                                 store_reg_to_var_int(src, d);
524                                         }
525                                 }
526                         }
527                         src = src->prev;
528                 }
529
530                 /* walk through all instructions */
531                 
532                 src = bptr->instack;
533                 len = bptr->icount;
534                 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
535
536                         MCODECHECK(64);   /* an instruction usually needs < 64 words      */
537                         switch (iptr->opc) {
538
539                         case ICMD_NOP:    /* ...  ==> ...                                 */
540                                 break;
541
542                         case ICMD_NULLCHECKPOP: /* ..., objectref  ==> ...                */
543                                 if (src->flags & INMEMORY) {
544                                         x86_64_alu_imm_membase(cd, X86_64_CMP, 0, REG_SP, src->regoff * 8);
545
546                                 } else {
547                                         x86_64_test_reg_reg(cd, src->regoff, src->regoff);
548                                 }
549                                 x86_64_jcc(cd, X86_64_CC_E, 0);
550                                 codegen_addxnullrefs(cd, cd->mcodeptr);
551                                 break;
552
553                 /* constant operations ************************************************/
554
555                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
556                                       /* op1 = 0, val.i = constant                    */
557
558                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
559                         if (iptr->val.i == 0) {
560                                 x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
561                         } else {
562                                 x86_64_movl_imm_reg(cd, iptr->val.i, d);
563                         }
564                         store_reg_to_var_int(iptr->dst, d);
565                         break;
566
567                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
568                                       /* op1 = 0, val.a = constant                    */
569
570                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
571                         if (iptr->val.a == 0) {
572                                 x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
573                         } else {
574                                 x86_64_mov_imm_reg(cd, (s8) iptr->val.a, d);
575                         }
576                         store_reg_to_var_int(iptr->dst, d);
577                         break;
578
579                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
580                                       /* op1 = 0, val.l = constant                    */
581
582                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
583                         if (iptr->val.l == 0) {
584                                 x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
585                         } else {
586                                 x86_64_mov_imm_reg(cd, iptr->val.l, d);
587                         }
588                         store_reg_to_var_int(iptr->dst, d);
589                         break;
590
591                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
592                                       /* op1 = 0, val.f = constant                    */
593
594                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
595                         a = dseg_addfloat(cd, iptr->val.f);
596                         x86_64_movdl_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + ((d > 7) ? 9 : 8)) - (s8) cd->mcodebase) + a, d);
597                         store_reg_to_var_flt(iptr->dst, d);
598                         break;
599                 
600                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
601                                       /* op1 = 0, val.d = constant                    */
602
603                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
604                         a = dseg_adddouble(cd, iptr->val.d);
605                         x86_64_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + a, d);
606                         store_reg_to_var_flt(iptr->dst, d);
607                         break;
608
609
610                 /* load/store operations **********************************************/
611
612                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
613                                       /* op1 = local variable                         */
614
615                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
616                         if ((iptr->dst->varkind == LOCALVAR) &&
617                             (iptr->dst->varnum == iptr->op1)) {
618                                 break;
619                         }
620                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
621                         if (var->flags & INMEMORY) {
622                                 x86_64_movl_membase_reg(cd, REG_SP, var->regoff * 8, d);
623                                 store_reg_to_var_int(iptr->dst, d);
624
625                         } else {
626                                 if (iptr->dst->flags & INMEMORY) {
627                                         x86_64_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
628
629                                 } else {
630                                         M_INTMOVE(var->regoff, d);
631                                 }
632                         }
633                         break;
634
635                 case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
636                 case ICMD_ALOAD:      /* op1 = local variable                         */
637
638                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
639                         if ((iptr->dst->varkind == LOCALVAR) &&
640                             (iptr->dst->varnum == iptr->op1)) {
641                                 break;
642                         }
643                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
644                         if (var->flags & INMEMORY) {
645                                 x86_64_mov_membase_reg(cd, REG_SP, var->regoff * 8, d);
646                                 store_reg_to_var_int(iptr->dst, d);
647
648                         } else {
649                                 if (iptr->dst->flags & INMEMORY) {
650                                         x86_64_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
651
652                                 } else {
653                                         M_INTMOVE(var->regoff, d);
654                                 }
655                         }
656                         break;
657
658                 case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
659                 case ICMD_DLOAD:      /* op1 = local variable                         */
660
661                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
662                         if ((iptr->dst->varkind == LOCALVAR) &&
663                             (iptr->dst->varnum == iptr->op1)) {
664                                 break;
665                         }
666                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
667                         if (var->flags & INMEMORY) {
668                                 x86_64_movq_membase_reg(cd, REG_SP, var->regoff * 8, d);
669                                 store_reg_to_var_flt(iptr->dst, d);
670
671                         } else {
672                                 if (iptr->dst->flags & INMEMORY) {
673                                         x86_64_movq_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
674
675                                 } else {
676                                         M_FLTMOVE(var->regoff, d);
677                                 }
678                         }
679                         break;
680
681                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
682                 case ICMD_LSTORE:     /* op1 = local variable                         */
683                 case ICMD_ASTORE:
684
685                         if ((src->varkind == LOCALVAR) &&
686                             (src->varnum == iptr->op1)) {
687                                 break;
688                         }
689                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
690                         if (var->flags & INMEMORY) {
691                                 var_to_reg_int(s1, src, REG_ITMP1);
692                                 x86_64_mov_reg_membase(cd, s1, REG_SP, var->regoff * 8);
693
694                         } else {
695                                 var_to_reg_int(s1, src, var->regoff);
696                                 M_INTMOVE(s1, var->regoff);
697                         }
698                         break;
699
700                 case ICMD_FSTORE:     /* ..., value  ==> ...                          */
701                 case ICMD_DSTORE:     /* op1 = local variable                         */
702
703                         if ((src->varkind == LOCALVAR) &&
704                             (src->varnum == iptr->op1)) {
705                                 break;
706                         }
707                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
708                         if (var->flags & INMEMORY) {
709                                 var_to_reg_flt(s1, src, REG_FTMP1);
710                                 x86_64_movq_reg_membase(cd, s1, REG_SP, var->regoff * 8);
711
712                         } else {
713                                 var_to_reg_flt(s1, src, var->regoff);
714                                 M_FLTMOVE(s1, var->regoff);
715                         }
716                         break;
717
718
719                 /* pop/dup/swap operations ********************************************/
720
721                 /* attention: double and longs are only one entry in CACAO ICMDs      */
722
723                 case ICMD_POP:        /* ..., value  ==> ...                          */
724                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
725                         break;
726
727                 case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
728                         M_COPY(src, iptr->dst);
729                         break;
730
731                 case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
732
733                         M_COPY(src,       iptr->dst);
734                         M_COPY(src->prev, iptr->dst->prev);
735                         M_COPY(iptr->dst, iptr->dst->prev->prev);
736                         break;
737
738                 case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
739
740                         M_COPY(src,             iptr->dst);
741                         M_COPY(src->prev,       iptr->dst->prev);
742                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
743                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
744                         break;
745
746                 case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
747
748                         M_COPY(src,       iptr->dst);
749                         M_COPY(src->prev, iptr->dst->prev);
750                         break;
751
752                 case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
753
754                         M_COPY(src,             iptr->dst);
755                         M_COPY(src->prev,       iptr->dst->prev);
756                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
757                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
758                         M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
759                         break;
760
761                 case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
762
763                         M_COPY(src,                   iptr->dst);
764                         M_COPY(src->prev,             iptr->dst->prev);
765                         M_COPY(src->prev->prev,       iptr->dst->prev->prev);
766                         M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
767                         M_COPY(iptr->dst,             iptr->dst->prev->prev->prev->prev);
768                         M_COPY(iptr->dst->prev,       iptr->dst->prev->prev->prev->prev->prev);
769                         break;
770
771                 case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
772
773                         M_COPY(src,       iptr->dst->prev);
774                         M_COPY(src->prev, iptr->dst);
775                         break;
776
777
778                 /* integer operations *************************************************/
779
780                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
781
782                         d = reg_of_var(rd, iptr->dst, REG_NULL);
783                         if (iptr->dst->flags & INMEMORY) {
784                                 if (src->flags & INMEMORY) {
785                                         if (src->regoff == iptr->dst->regoff) {
786                                                 x86_64_negl_membase(cd, REG_SP, iptr->dst->regoff * 8);
787
788                                         } else {
789                                                 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
790                                                 x86_64_negl_reg(cd, REG_ITMP1);
791                                                 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
792                                         }
793
794                                 } else {
795                                         x86_64_movl_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
796                                         x86_64_negl_membase(cd, REG_SP, iptr->dst->regoff * 8);
797                                 }
798
799                         } else {
800                                 if (src->flags & INMEMORY) {
801                                         x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
802                                         x86_64_negl_reg(cd, d);
803
804                                 } else {
805                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
806                                         x86_64_negl_reg(cd, iptr->dst->regoff);
807                                 }
808                         }
809                         break;
810
811                 case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
812
813                         d = reg_of_var(rd, iptr->dst, REG_NULL);
814                         if (iptr->dst->flags & INMEMORY) {
815                                 if (src->flags & INMEMORY) {
816                                         if (src->regoff == iptr->dst->regoff) {
817                                                 x86_64_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
818
819                                         } else {
820                                                 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
821                                                 x86_64_neg_reg(cd, REG_ITMP1);
822                                                 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
823                                         }
824
825                                 } else {
826                                         x86_64_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
827                                         x86_64_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
828                                 }
829
830                         } else {
831                                 if (src->flags & INMEMORY) {
832                                         x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
833                                         x86_64_neg_reg(cd, iptr->dst->regoff);
834
835                                 } else {
836                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
837                                         x86_64_neg_reg(cd, iptr->dst->regoff);
838                                 }
839                         }
840                         break;
841
842                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
843
844                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
845                         if (src->flags & INMEMORY) {
846                                 x86_64_movslq_membase_reg(cd, REG_SP, src->regoff * 8, d);
847
848                         } else {
849                                 x86_64_movslq_reg_reg(cd, src->regoff, d);
850                         }
851                         store_reg_to_var_int(iptr->dst, d);
852                         break;
853
854                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
855
856                         var_to_reg_int(s1, src, REG_ITMP1);
857                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
858                         M_INTMOVE(s1, d);
859                         store_reg_to_var_int(iptr->dst, d);
860                         break;
861
862                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
863
864                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
865                         if (src->flags & INMEMORY) {
866                                 x86_64_movsbq_membase_reg(cd, REG_SP, src->regoff * 8, d);
867
868                         } else {
869                                 x86_64_movsbq_reg_reg(cd, src->regoff, d);
870                         }
871                         store_reg_to_var_int(iptr->dst, d);
872                         break;
873
874                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
875
876                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
877                         if (src->flags & INMEMORY) {
878                                 x86_64_movzwq_membase_reg(cd, REG_SP, src->regoff * 8, d);
879
880                         } else {
881                                 x86_64_movzwq_reg_reg(cd, src->regoff, d);
882                         }
883                         store_reg_to_var_int(iptr->dst, d);
884                         break;
885
886                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
887
888                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
889                         if (src->flags & INMEMORY) {
890                                 x86_64_movswq_membase_reg(cd, REG_SP, src->regoff * 8, d);
891
892                         } else {
893                                 x86_64_movswq_reg_reg(cd, src->regoff, d);
894                         }
895                         store_reg_to_var_int(iptr->dst, d);
896                         break;
897
898
899                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
900
901                         d = reg_of_var(rd, iptr->dst, REG_NULL);
902                         x86_64_emit_ialu(cd, X86_64_ADD, src, iptr);
903                         break;
904
905                 case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
906                                       /* val.i = constant                             */
907
908                         d = reg_of_var(rd, iptr->dst, REG_NULL);
909                         x86_64_emit_ialuconst(cd, X86_64_ADD, src, iptr);
910                         break;
911
912                 case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
913
914                         d = reg_of_var(rd, iptr->dst, REG_NULL);
915                         x86_64_emit_lalu(cd, X86_64_ADD, src, iptr);
916                         break;
917
918                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
919                                       /* val.l = constant                             */
920
921                         d = reg_of_var(rd, iptr->dst, REG_NULL);
922                         x86_64_emit_laluconst(cd, X86_64_ADD, src, iptr);
923                         break;
924
925                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
926
927                         d = reg_of_var(rd, iptr->dst, REG_NULL);
928                         if (iptr->dst->flags & INMEMORY) {
929                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
930                                         if (src->prev->regoff == iptr->dst->regoff) {
931                                                 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
932                                                 x86_64_alul_reg_membase(cd, X86_64_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
933
934                                         } else {
935                                                 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
936                                                 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
937                                                 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
938                                         }
939
940                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
941                                         M_INTMOVE(src->prev->regoff, REG_ITMP1);
942                                         x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
943                                         x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
944
945                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
946                                         if (src->prev->regoff == iptr->dst->regoff) {
947                                                 x86_64_alul_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
948
949                                         } else {
950                                                 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
951                                                 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
952                                                 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
953                                         }
954
955                                 } else {
956                                         x86_64_movl_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
957                                         x86_64_alul_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
958                                 }
959
960                         } else {
961                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
962                                         x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
963                                         x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
964
965                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
966                                         M_INTMOVE(src->prev->regoff, d);
967                                         x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
968
969                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
970                                         /* workaround for reg alloc */
971                                         if (src->regoff == iptr->dst->regoff) {
972                                                 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
973                                                 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
974                                                 M_INTMOVE(REG_ITMP1, d);
975
976                                         } else {
977                                                 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
978                                                 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, d);
979                                         }
980
981                                 } else {
982                                         /* workaround for reg alloc */
983                                         if (src->regoff == iptr->dst->regoff) {
984                                                 M_INTMOVE(src->prev->regoff, REG_ITMP1);
985                                                 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
986                                                 M_INTMOVE(REG_ITMP1, d);
987
988                                         } else {
989                                                 M_INTMOVE(src->prev->regoff, d);
990                                                 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, d);
991                                         }
992                                 }
993                         }
994                         break;
995
996                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
997                                       /* val.i = constant                             */
998
999                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1000                         x86_64_emit_ialuconst(cd, X86_64_SUB, src, iptr);
1001                         break;
1002
1003                 case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1004
1005                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1006                         if (iptr->dst->flags & INMEMORY) {
1007                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1008                                         if (src->prev->regoff == iptr->dst->regoff) {
1009                                                 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1010                                                 x86_64_alu_reg_membase(cd, X86_64_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1011
1012                                         } else {
1013                                                 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1014                                                 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1015                                                 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1016                                         }
1017
1018                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1019                                         M_INTMOVE(src->prev->regoff, REG_ITMP1);
1020                                         x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1021                                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1022
1023                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1024                                         if (src->prev->regoff == iptr->dst->regoff) {
1025                                                 x86_64_alu_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1026
1027                                         } else {
1028                                                 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1029                                                 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1030                                                 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1031                                         }
1032
1033                                 } else {
1034                                         x86_64_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1035                                         x86_64_alu_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1036                                 }
1037
1038                         } else {
1039                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1040                                         x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1041                                         x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
1042
1043                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1044                                         M_INTMOVE(src->prev->regoff, d);
1045                                         x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
1046
1047                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1048                                         /* workaround for reg alloc */
1049                                         if (src->regoff == iptr->dst->regoff) {
1050                                                 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1051                                                 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1052                                                 M_INTMOVE(REG_ITMP1, d);
1053
1054                                         } else {
1055                                                 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1056                                                 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, d);
1057                                         }
1058
1059                                 } else {
1060                                         /* workaround for reg alloc */
1061                                         if (src->regoff == iptr->dst->regoff) {
1062                                                 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1063                                                 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1064                                                 M_INTMOVE(REG_ITMP1, d);
1065
1066                                         } else {
1067                                                 M_INTMOVE(src->prev->regoff, d);
1068                                                 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, d);
1069                                         }
1070                                 }
1071                         }
1072                         break;
1073
1074                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
1075                                       /* val.l = constant                             */
1076
1077                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1078                         x86_64_emit_laluconst(cd, X86_64_SUB, src, iptr);
1079                         break;
1080
1081                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1082
1083                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1084                         if (iptr->dst->flags & INMEMORY) {
1085                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1086                                         x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1087                                         x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1088                                         x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1089
1090                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1091                                         x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1092                                         x86_64_imull_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1093                                         x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1094
1095                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1096                                         x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1097                                         x86_64_imull_reg_reg(cd, src->regoff, REG_ITMP1);
1098                                         x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1099
1100                                 } else {
1101                                         M_INTMOVE(src->prev->regoff, REG_ITMP1);
1102                                         x86_64_imull_reg_reg(cd, src->regoff, REG_ITMP1);
1103                                         x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1104                                 }
1105
1106                         } else {
1107                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1108                                         x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1109                                         x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1110
1111                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1112                                         M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1113                                         x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1114
1115                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1116                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
1117                                         x86_64_imull_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1118
1119                                 } else {
1120                                         if (src->regoff == iptr->dst->regoff) {
1121                                                 x86_64_imull_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1122
1123                                         } else {
1124                                                 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1125                                                 x86_64_imull_reg_reg(cd, src->regoff, iptr->dst->regoff);
1126                                         }
1127                                 }
1128                         }
1129                         break;
1130
1131                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
1132                                       /* val.i = constant                             */
1133
1134                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1135                         if (iptr->dst->flags & INMEMORY) {
1136                                 if (src->flags & INMEMORY) {
1137                                         x86_64_imull_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1138                                         x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1139
1140                                 } else {
1141                                         x86_64_imull_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1142                                         x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1143                                 }
1144
1145                         } else {
1146                                 if (src->flags & INMEMORY) {
1147                                         x86_64_imull_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1148
1149                                 } else {
1150                                         if (iptr->val.i == 2) {
1151                                                 M_INTMOVE(src->regoff, iptr->dst->regoff);
1152                                                 x86_64_alul_reg_reg(cd, X86_64_ADD, iptr->dst->regoff, iptr->dst->regoff);
1153
1154                                         } else {
1155                                                 x86_64_imull_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff);    /* 3 cycles */
1156                                         }
1157                                 }
1158                         }
1159                         break;
1160
1161                 case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1162
1163                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1164                         if (iptr->dst->flags & INMEMORY) {
1165                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1166                                         x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1167                                         x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1168                                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1169
1170                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1171                                         x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1172                                         x86_64_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1173                                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1174
1175                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1176                                         x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1177                                         x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1178                                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1179
1180                                 } else {
1181                                         x86_64_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1182                                         x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1183                                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1184                                 }
1185
1186                         } else {
1187                                 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1188                                         x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1189                                         x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1190
1191                                 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1192                                         M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1193                                         x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1194
1195                                 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1196                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
1197                                         x86_64_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1198
1199                                 } else {
1200                                         if (src->regoff == iptr->dst->regoff) {
1201                                                 x86_64_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1202
1203                                         } else {
1204                                                 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1205                                                 x86_64_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1206                                         }
1207                                 }
1208                         }
1209                         break;
1210
1211                 case ICMD_LMULCONST:  /* ..., value  ==> ..., value * constant        */
1212                                       /* val.l = constant                             */
1213
1214                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1215                         if (iptr->dst->flags & INMEMORY) {
1216                                 if (src->flags & INMEMORY) {
1217                                         if (x86_64_is_imm32(iptr->val.l)) {
1218                                                 x86_64_imul_imm_membase_reg(cd, iptr->val.l, REG_SP, src->regoff * 8, REG_ITMP1);
1219
1220                                         } else {
1221                                                 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1222                                                 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1223                                         }
1224                                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1225                                         
1226                                 } else {
1227                                         if (x86_64_is_imm32(iptr->val.l)) {
1228                                                 x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, REG_ITMP1);
1229
1230                                         } else {
1231                                                 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1232                                                 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1233                                         }
1234                                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1235                                 }
1236
1237                         } else {
1238                                 if (src->flags & INMEMORY) {
1239                                         if (x86_64_is_imm32(iptr->val.l)) {
1240                                                 x86_64_imul_imm_membase_reg(cd, iptr->val.l, REG_SP, src->regoff * 8, iptr->dst->regoff);
1241
1242                                         } else {
1243                                                 x86_64_mov_imm_reg(cd, iptr->val.l, iptr->dst->regoff);
1244                                                 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1245                                         }
1246
1247                                 } else {
1248                                         /* should match in many cases */
1249                                         if (iptr->val.l == 2) {
1250                                                 M_INTMOVE(src->regoff, iptr->dst->regoff);
1251                                                 x86_64_alul_reg_reg(cd, X86_64_ADD, iptr->dst->regoff, iptr->dst->regoff);
1252
1253                                         } else {
1254                                                 if (x86_64_is_imm32(iptr->val.l)) {
1255                                                         x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, iptr->dst->regoff);    /* 4 cycles */
1256
1257                                                 } else {
1258                                                         x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1259                                                         M_INTMOVE(src->regoff, iptr->dst->regoff);
1260                                                         x86_64_imul_reg_reg(cd, REG_ITMP1, iptr->dst->regoff);
1261                                                 }
1262                                         }
1263                                 }
1264                         }
1265                         break;
1266
1267                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1268
1269                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1270                 if (src->prev->flags & INMEMORY) {
1271                                 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, RAX);
1272
1273                         } else {
1274                                 M_INTMOVE(src->prev->regoff, RAX);
1275                         }
1276                         
1277                         if (src->flags & INMEMORY) {
1278                                 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1279
1280                         } else {
1281                                 M_INTMOVE(src->regoff, REG_ITMP3);
1282                         }
1283                         gen_div_check(src);
1284
1285                         x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, RAX);    /* check as described in jvm spec */
1286                         x86_64_jcc(cd, X86_64_CC_NE, 4 + 6);
1287                         x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3);      /* 4 bytes */
1288                         x86_64_jcc(cd, X86_64_CC_E, 3 + 1 + 3);                  /* 6 bytes */
1289
1290                         x86_64_mov_reg_reg(cd, RDX, REG_ITMP2);    /* save %rdx, cause it's an argument register */
1291                         x86_64_cltd(cd);
1292                         x86_64_idivl_reg(cd, REG_ITMP3);
1293
1294                         if (iptr->dst->flags & INMEMORY) {
1295                                 x86_64_mov_reg_membase(cd, RAX, REG_SP, iptr->dst->regoff * 8);
1296                                 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX);    /* restore %rdx */
1297
1298                         } else {
1299                                 M_INTMOVE(RAX, iptr->dst->regoff);
1300
1301                                 if (iptr->dst->regoff != RDX) {
1302                                         x86_64_mov_reg_reg(cd, REG_ITMP2, RDX);    /* restore %rdx */
1303                                 }
1304                         }
1305                         break;
1306
1307                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
1308
1309                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1310                         if (src->prev->flags & INMEMORY) {
1311                                 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, RAX);
1312
1313                         } else {
1314                                 M_INTMOVE(src->prev->regoff, RAX);
1315                         }
1316                         
1317                         if (src->flags & INMEMORY) {
1318                                 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1319
1320                         } else {
1321                                 M_INTMOVE(src->regoff, REG_ITMP3);
1322                         }
1323                         gen_div_check(src);
1324
1325                         x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, RAX);    /* check as described in jvm spec */
1326                         x86_64_jcc(cd, X86_64_CC_NE, 2 + 4 + 6);
1327                         x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX);           /* 2 bytes */
1328                         x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3);      /* 4 bytes */
1329                         x86_64_jcc(cd, X86_64_CC_E, 3 + 1 + 3);                  /* 6 bytes */
1330
1331                         x86_64_mov_reg_reg(cd, RDX, REG_ITMP2);    /* save %rdx, cause it's an argument register */
1332                         x86_64_cltd(cd);
1333                         x86_64_idivl_reg(cd, REG_ITMP3);
1334
1335                         if (iptr->dst->flags & INMEMORY) {
1336                                 x86_64_mov_reg_membase(cd, RDX, REG_SP, iptr->dst->regoff * 8);
1337                                 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX);    /* restore %rdx */
1338
1339                         } else {
1340                                 M_INTMOVE(RDX, iptr->dst->regoff);
1341
1342                                 if (iptr->dst->regoff != RDX) {
1343                                         x86_64_mov_reg_reg(cd, REG_ITMP2, RDX);    /* restore %rdx */
1344                                 }
1345                         }
1346                         break;
1347
1348                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value >> constant       */
1349                                       /* val.i = constant                             */
1350
1351                         var_to_reg_int(s1, src, REG_ITMP1);
1352                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1353                         M_INTMOVE(s1, REG_ITMP1);
1354                         x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1355                         x86_64_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1356                         x86_64_cmovccl_reg_reg(cd, X86_64_CC_LE, REG_ITMP2, REG_ITMP1);
1357                         x86_64_shiftl_imm_reg(cd, X86_64_SAR, iptr->val.i, REG_ITMP1);
1358                         x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1359                         store_reg_to_var_int(iptr->dst, d);
1360                         break;
1361
1362                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
1363                                       /* val.i = constant                             */
1364
1365                         var_to_reg_int(s1, src, REG_ITMP1);
1366                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1367                         M_INTMOVE(s1, REG_ITMP1);
1368                         x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1369                         x86_64_leal_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1370                         x86_64_cmovccl_reg_reg(cd, X86_64_CC_G, REG_ITMP1, REG_ITMP2);
1371                         x86_64_alul_imm_reg(cd, X86_64_AND, -1 - (iptr->val.i), REG_ITMP2);
1372                         x86_64_alul_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
1373                         x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1374                         store_reg_to_var_int(iptr->dst, d);
1375                         break;
1376
1377
1378                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1379
1380                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1381                 if (src->prev->flags & INMEMORY) {
1382                                 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1383
1384                         } else {
1385                                 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1386                         }
1387                         
1388                         if (src->flags & INMEMORY) {
1389                                 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1390
1391                         } else {
1392                                 M_INTMOVE(src->regoff, REG_ITMP3);
1393                         }
1394                         gen_div_check(src);
1395
1396                         x86_64_mov_imm_reg(cd, 0x8000000000000000LL, REG_ITMP2);    /* check as described in jvm spec */
1397                         x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, REG_ITMP1);
1398                         x86_64_jcc(cd, X86_64_CC_NE, 4 + 6);
1399                         x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3);          /* 4 bytes */
1400                         x86_64_jcc(cd, X86_64_CC_E, 3 + 2 + 3);                     /* 6 bytes */
1401
1402                         x86_64_mov_reg_reg(cd, RDX, REG_ITMP2);    /* save %rdx, cause it's an argument register */
1403                         x86_64_cqto(cd);
1404                         x86_64_idiv_reg(cd, REG_ITMP3);
1405
1406                         if (iptr->dst->flags & INMEMORY) {
1407                                 x86_64_mov_reg_membase(cd, RAX, REG_SP, iptr->dst->regoff * 8);
1408                                 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX);    /* restore %rdx */
1409
1410                         } else {
1411                                 M_INTMOVE(RAX, iptr->dst->regoff);
1412
1413                                 if (iptr->dst->regoff != RDX) {
1414                                         x86_64_mov_reg_reg(cd, REG_ITMP2, RDX);    /* restore %rdx */
1415                                 }
1416                         }
1417                         break;
1418
1419                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
1420
1421                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1422                         if (src->prev->flags & INMEMORY) {
1423                                 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1424
1425                         } else {
1426                                 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1427                         }
1428                         
1429                         if (src->flags & INMEMORY) {
1430                                 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1431
1432                         } else {
1433                                 M_INTMOVE(src->regoff, REG_ITMP3);
1434                         }
1435                         gen_div_check(src);
1436
1437                         x86_64_mov_imm_reg(cd, 0x8000000000000000LL, REG_ITMP2);    /* check as described in jvm spec */
1438                         x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, REG_ITMP1);
1439                         x86_64_jcc(cd, X86_64_CC_NE, 2 + 4 + 6);
1440                         x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX);              /* 2 bytes */
1441                         x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3);          /* 4 bytes */
1442                         x86_64_jcc(cd, X86_64_CC_E, 3 + 2 + 3);                     /* 6 bytes */
1443
1444                         x86_64_mov_reg_reg(cd, RDX, REG_ITMP2);    /* save %rdx, cause it's an argument register */
1445                         x86_64_cqto(cd);
1446                         x86_64_idiv_reg(cd, REG_ITMP3);
1447
1448                         if (iptr->dst->flags & INMEMORY) {
1449                                 x86_64_mov_reg_membase(cd, RDX, REG_SP, iptr->dst->regoff * 8);
1450                                 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX);    /* restore %rdx */
1451
1452                         } else {
1453                                 M_INTMOVE(RDX, iptr->dst->regoff);
1454
1455                                 if (iptr->dst->regoff != RDX) {
1456                                         x86_64_mov_reg_reg(cd, REG_ITMP2, RDX);    /* restore %rdx */
1457                                 }
1458                         }
1459                         break;
1460
1461                 case ICMD_LDIVPOW2:   /* ..., value  ==> ..., value >> constant       */
1462                                       /* val.i = constant                             */
1463
1464                         var_to_reg_int(s1, src, REG_ITMP1);
1465                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1466                         M_INTMOVE(s1, REG_ITMP1);
1467                         x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1468                         x86_64_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1469                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_LE, REG_ITMP2, REG_ITMP1);
1470                         x86_64_shift_imm_reg(cd, X86_64_SAR, iptr->val.i, REG_ITMP1);
1471                         x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1472                         store_reg_to_var_int(iptr->dst, d);
1473                         break;
1474
1475                 case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
1476                                       /* val.l = constant                             */
1477
1478                         var_to_reg_int(s1, src, REG_ITMP1);
1479                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1480                         M_INTMOVE(s1, REG_ITMP1);
1481                         x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1482                         x86_64_lea_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1483                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_G, REG_ITMP1, REG_ITMP2);
1484                         x86_64_alu_imm_reg(cd, X86_64_AND, -1 - (iptr->val.i), REG_ITMP2);
1485                         x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
1486                         x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1487                         store_reg_to_var_int(iptr->dst, d);
1488                         break;
1489
1490                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
1491
1492                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1493                         x86_64_emit_ishift(cd, X86_64_SHL, src, iptr);
1494                         break;
1495
1496                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
1497                                       /* val.i = constant                             */
1498
1499                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1500                         x86_64_emit_ishiftconst(cd, X86_64_SHL, src, iptr);
1501                         break;
1502
1503                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
1504
1505                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1506                         x86_64_emit_ishift(cd, X86_64_SAR, src, iptr);
1507                         break;
1508
1509                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
1510                                       /* val.i = constant                             */
1511
1512                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1513                         x86_64_emit_ishiftconst(cd, X86_64_SAR, src, iptr);
1514                         break;
1515
1516                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
1517
1518                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1519                         x86_64_emit_ishift(cd, X86_64_SHR, src, iptr);
1520                         break;
1521
1522                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
1523                                       /* val.i = constant                             */
1524
1525                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1526                         x86_64_emit_ishiftconst(cd, X86_64_SHR, src, iptr);
1527                         break;
1528
1529                 case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
1530
1531                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1532                         x86_64_emit_lshift(cd, X86_64_SHL, src, iptr);
1533                         break;
1534
1535         case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
1536                                           /* val.i = constant                             */
1537
1538                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1539                         x86_64_emit_lshiftconst(cd, X86_64_SHL, src, iptr);
1540                         break;
1541
1542                 case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
1543
1544                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1545                         x86_64_emit_lshift(cd, X86_64_SAR, src, iptr);
1546                         break;
1547
1548                 case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant       */
1549                                       /* val.i = constant                             */
1550
1551                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1552                         x86_64_emit_lshiftconst(cd, X86_64_SAR, src, iptr);
1553                         break;
1554
1555                 case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
1556
1557                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1558                         x86_64_emit_lshift(cd, X86_64_SHR, src, iptr);
1559                         break;
1560
1561                 case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
1562                                       /* val.l = constant                             */
1563
1564                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1565                         x86_64_emit_lshiftconst(cd, X86_64_SHR, src, iptr);
1566                         break;
1567
1568                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1569
1570                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1571                         x86_64_emit_ialu(cd, X86_64_AND, src, iptr);
1572                         break;
1573
1574                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
1575                                       /* val.i = constant                             */
1576
1577                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1578                         x86_64_emit_ialuconst(cd, X86_64_AND, src, iptr);
1579                         break;
1580
1581                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1582
1583                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1584                         x86_64_emit_lalu(cd, X86_64_AND, src, iptr);
1585                         break;
1586
1587                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
1588                                       /* val.l = constant                             */
1589
1590                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1591                         x86_64_emit_laluconst(cd, X86_64_AND, src, iptr);
1592                         break;
1593
1594                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1595
1596                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1597                         x86_64_emit_ialu(cd, X86_64_OR, src, iptr);
1598                         break;
1599
1600                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
1601                                       /* val.i = constant                             */
1602
1603                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1604                         x86_64_emit_ialuconst(cd, X86_64_OR, src, iptr);
1605                         break;
1606
1607                 case ICMD_LOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1608
1609                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1610                         x86_64_emit_lalu(cd, X86_64_OR, src, iptr);
1611                         break;
1612
1613                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
1614                                       /* val.l = constant                             */
1615
1616                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1617                         x86_64_emit_laluconst(cd, X86_64_OR, src, iptr);
1618                         break;
1619
1620                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1621
1622                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1623                         x86_64_emit_ialu(cd, X86_64_XOR, src, iptr);
1624                         break;
1625
1626                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1627                                       /* val.i = constant                             */
1628
1629                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1630                         x86_64_emit_ialuconst(cd, X86_64_XOR, src, iptr);
1631                         break;
1632
1633                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1634
1635                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1636                         x86_64_emit_lalu(cd, X86_64_XOR, src, iptr);
1637                         break;
1638
1639                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1640                                       /* val.l = constant                             */
1641
1642                         d = reg_of_var(rd, iptr->dst, REG_NULL);
1643                         x86_64_emit_laluconst(cd, X86_64_XOR, src, iptr);
1644                         break;
1645
1646
1647                 case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
1648                                       /* op1 = variable, val.i = constant             */
1649
1650                         /* using inc and dec is definitely faster than add -- tested      */
1651                         /* with sieve                                                     */
1652
1653                         var = &(rd->locals[iptr->op1][TYPE_INT]);
1654                         d = var->regoff;
1655                         if (var->flags & INMEMORY) {
1656                                 if (iptr->val.i == 1) {
1657                                         x86_64_incl_membase(cd, REG_SP, d * 8);
1658  
1659                                 } else if (iptr->val.i == -1) {
1660                                         x86_64_decl_membase(cd, REG_SP, d * 8);
1661
1662                                 } else {
1663                                         x86_64_alul_imm_membase(cd, X86_64_ADD, iptr->val.i, REG_SP, d * 8);
1664                                 }
1665
1666                         } else {
1667                                 if (iptr->val.i == 1) {
1668                                         x86_64_incl_reg(cd, d);
1669  
1670                                 } else if (iptr->val.i == -1) {
1671                                         x86_64_decl_reg(cd, d);
1672
1673                                 } else {
1674                                         x86_64_alul_imm_reg(cd, X86_64_ADD, iptr->val.i, d);
1675                                 }
1676                         }
1677                         break;
1678
1679
1680                 /* floating operations ************************************************/
1681
1682                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
1683
1684                         var_to_reg_flt(s1, src, REG_FTMP1);
1685                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1686                         a = dseg_adds4(cd, 0x80000000);
1687                         M_FLTMOVE(s1, d);
1688                         x86_64_movss_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + a, REG_FTMP2);
1689                         x86_64_xorps_reg_reg(cd, REG_FTMP2, d);
1690                         store_reg_to_var_flt(iptr->dst, d);
1691                         break;
1692
1693                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
1694
1695                         var_to_reg_flt(s1, src, REG_FTMP1);
1696                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1697                         a = dseg_adds8(cd, 0x8000000000000000);
1698                         M_FLTMOVE(s1, d);
1699                         x86_64_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + a, REG_FTMP2);
1700                         x86_64_xorpd_reg_reg(cd, REG_FTMP2, d);
1701                         store_reg_to_var_flt(iptr->dst, d);
1702                         break;
1703
1704                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1705
1706                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1707                         var_to_reg_flt(s2, src, REG_FTMP2);
1708                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1709                         if (s1 == d) {
1710                                 x86_64_addss_reg_reg(cd, s2, d);
1711                         } else if (s2 == d) {
1712                                 x86_64_addss_reg_reg(cd, s1, d);
1713                         } else {
1714                                 M_FLTMOVE(s1, d);
1715                                 x86_64_addss_reg_reg(cd, s2, d);
1716                         }
1717                         store_reg_to_var_flt(iptr->dst, d);
1718                         break;
1719
1720                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1721
1722                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1723                         var_to_reg_flt(s2, src, REG_FTMP2);
1724                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1725                         if (s1 == d) {
1726                                 x86_64_addsd_reg_reg(cd, s2, d);
1727                         } else if (s2 == d) {
1728                                 x86_64_addsd_reg_reg(cd, s1, d);
1729                         } else {
1730                                 M_FLTMOVE(s1, d);
1731                                 x86_64_addsd_reg_reg(cd, s2, d);
1732                         }
1733                         store_reg_to_var_flt(iptr->dst, d);
1734                         break;
1735
1736                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1737
1738                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1739                         var_to_reg_flt(s2, src, REG_FTMP2);
1740                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1741                         if (s2 == d) {
1742                                 M_FLTMOVE(s2, REG_FTMP2);
1743                                 s2 = REG_FTMP2;
1744                         }
1745                         M_FLTMOVE(s1, d);
1746                         x86_64_subss_reg_reg(cd, s2, d);
1747                         store_reg_to_var_flt(iptr->dst, d);
1748                         break;
1749
1750                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1751
1752                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1753                         var_to_reg_flt(s2, src, REG_FTMP2);
1754                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1755                         if (s2 == d) {
1756                                 M_FLTMOVE(s2, REG_FTMP2);
1757                                 s2 = REG_FTMP2;
1758                         }
1759                         M_FLTMOVE(s1, d);
1760                         x86_64_subsd_reg_reg(cd, s2, d);
1761                         store_reg_to_var_flt(iptr->dst, d);
1762                         break;
1763
1764                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1765
1766                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1767                         var_to_reg_flt(s2, src, REG_FTMP2);
1768                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1769                         if (s1 == d) {
1770                                 x86_64_mulss_reg_reg(cd, s2, d);
1771                         } else if (s2 == d) {
1772                                 x86_64_mulss_reg_reg(cd, s1, d);
1773                         } else {
1774                                 M_FLTMOVE(s1, d);
1775                                 x86_64_mulss_reg_reg(cd, s2, d);
1776                         }
1777                         store_reg_to_var_flt(iptr->dst, d);
1778                         break;
1779
1780                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1781
1782                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1783                         var_to_reg_flt(s2, src, REG_FTMP2);
1784                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1785                         if (s1 == d) {
1786                                 x86_64_mulsd_reg_reg(cd, s2, d);
1787                         } else if (s2 == d) {
1788                                 x86_64_mulsd_reg_reg(cd, s1, d);
1789                         } else {
1790                                 M_FLTMOVE(s1, d);
1791                                 x86_64_mulsd_reg_reg(cd, s2, d);
1792                         }
1793                         store_reg_to_var_flt(iptr->dst, d);
1794                         break;
1795
1796                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1797
1798                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1799                         var_to_reg_flt(s2, src, REG_FTMP2);
1800                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1801                         if (s2 == d) {
1802                                 M_FLTMOVE(s2, REG_FTMP2);
1803                                 s2 = REG_FTMP2;
1804                         }
1805                         M_FLTMOVE(s1, d);
1806                         x86_64_divss_reg_reg(cd, s2, d);
1807                         store_reg_to_var_flt(iptr->dst, d);
1808                         break;
1809
1810                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1811
1812                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1813                         var_to_reg_flt(s2, src, REG_FTMP2);
1814                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1815                         if (s2 == d) {
1816                                 M_FLTMOVE(s2, REG_FTMP2);
1817                                 s2 = REG_FTMP2;
1818                         }
1819                         M_FLTMOVE(s1, d);
1820                         x86_64_divsd_reg_reg(cd, s2, d);
1821                         store_reg_to_var_flt(iptr->dst, d);
1822                         break;
1823
1824                 case ICMD_I2F:       /* ..., value  ==> ..., (float) value            */
1825
1826                         var_to_reg_int(s1, src, REG_ITMP1);
1827                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1828                         x86_64_cvtsi2ss_reg_reg(cd, s1, d);
1829                         store_reg_to_var_flt(iptr->dst, d);
1830                         break;
1831
1832                 case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
1833
1834                         var_to_reg_int(s1, src, REG_ITMP1);
1835                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1836                         x86_64_cvtsi2sd_reg_reg(cd, s1, d);
1837                         store_reg_to_var_flt(iptr->dst, d);
1838                         break;
1839
1840                 case ICMD_L2F:       /* ..., value  ==> ..., (float) value            */
1841
1842                         var_to_reg_int(s1, src, REG_ITMP1);
1843                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1844                         x86_64_cvtsi2ssq_reg_reg(cd, s1, d);
1845                         store_reg_to_var_flt(iptr->dst, d);
1846                         break;
1847                         
1848                 case ICMD_L2D:       /* ..., value  ==> ..., (double) value           */
1849
1850                         var_to_reg_int(s1, src, REG_ITMP1);
1851                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1852                         x86_64_cvtsi2sdq_reg_reg(cd, s1, d);
1853                         store_reg_to_var_flt(iptr->dst, d);
1854                         break;
1855                         
1856                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1857
1858                         var_to_reg_flt(s1, src, REG_FTMP1);
1859                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1860                         x86_64_cvttss2si_reg_reg(cd, s1, d);
1861                         x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, d);    /* corner cases */
1862                         a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1863                         x86_64_jcc(cd, X86_64_CC_NE, a);
1864                         M_FLTMOVE(s1, REG_FTMP1);
1865                         x86_64_mov_imm_reg(cd, (s8) asm_builtin_f2i, REG_ITMP2);
1866                         x86_64_call_reg(cd, REG_ITMP2);
1867                         M_INTMOVE(REG_RESULT, d);
1868                         store_reg_to_var_int(iptr->dst, d);
1869                         break;
1870
1871                 case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
1872
1873                         var_to_reg_flt(s1, src, REG_FTMP1);
1874                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1875                         x86_64_cvttsd2si_reg_reg(cd, s1, d);
1876                         x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, d);    /* corner cases */
1877                         a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1878                         x86_64_jcc(cd, X86_64_CC_NE, a);
1879                         M_FLTMOVE(s1, REG_FTMP1);
1880                         x86_64_mov_imm_reg(cd, (s8) asm_builtin_d2i, REG_ITMP2);
1881                         x86_64_call_reg(cd, REG_ITMP2);
1882                         M_INTMOVE(REG_RESULT, d);
1883                         store_reg_to_var_int(iptr->dst, d);
1884                         break;
1885
1886                 case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
1887
1888                         var_to_reg_flt(s1, src, REG_FTMP1);
1889                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1890                         x86_64_cvttss2siq_reg_reg(cd, s1, d);
1891                         x86_64_mov_imm_reg(cd, 0x8000000000000000, REG_ITMP2);
1892                         x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, d);     /* corner cases */
1893                         a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1894                         x86_64_jcc(cd, X86_64_CC_NE, a);
1895                         M_FLTMOVE(s1, REG_FTMP1);
1896                         x86_64_mov_imm_reg(cd, (s8) asm_builtin_f2l, REG_ITMP2);
1897                         x86_64_call_reg(cd, REG_ITMP2);
1898                         M_INTMOVE(REG_RESULT, d);
1899                         store_reg_to_var_int(iptr->dst, d);
1900                         break;
1901
1902                 case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
1903
1904                         var_to_reg_flt(s1, src, REG_FTMP1);
1905                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1906                         x86_64_cvttsd2siq_reg_reg(cd, s1, d);
1907                         x86_64_mov_imm_reg(cd, 0x8000000000000000, REG_ITMP2);
1908                         x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, d);     /* corner cases */
1909                         a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1910                         x86_64_jcc(cd, X86_64_CC_NE, a);
1911                         M_FLTMOVE(s1, REG_FTMP1);
1912                         x86_64_mov_imm_reg(cd, (s8) asm_builtin_d2l, REG_ITMP2);
1913                         x86_64_call_reg(cd, REG_ITMP2);
1914                         M_INTMOVE(REG_RESULT, d);
1915                         store_reg_to_var_int(iptr->dst, d);
1916                         break;
1917
1918                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1919
1920                         var_to_reg_flt(s1, src, REG_FTMP1);
1921                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1922                         x86_64_cvtss2sd_reg_reg(cd, s1, d);
1923                         store_reg_to_var_flt(iptr->dst, d);
1924                         break;
1925
1926                 case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
1927
1928                         var_to_reg_flt(s1, src, REG_FTMP1);
1929                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1930                         x86_64_cvtsd2ss_reg_reg(cd, s1, d);
1931                         store_reg_to_var_flt(iptr->dst, d);
1932                         break;
1933
1934                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1935                                           /* == => 0, < => 1, > => -1 */
1936
1937                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1938                         var_to_reg_flt(s2, src, REG_FTMP2);
1939                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1940                         x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
1941                         x86_64_mov_imm_reg(cd, 1, REG_ITMP1);
1942                         x86_64_mov_imm_reg(cd, -1, REG_ITMP2);
1943                         x86_64_ucomiss_reg_reg(cd, s1, s2);
1944                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_B, REG_ITMP1, d);
1945                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_A, REG_ITMP2, d);
1946                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_P, REG_ITMP2, d);    /* treat unordered as GT */
1947                         store_reg_to_var_int(iptr->dst, d);
1948                         break;
1949
1950                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1951                                           /* == => 0, < => 1, > => -1 */
1952
1953                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1954                         var_to_reg_flt(s2, src, REG_FTMP2);
1955                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1956                         x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
1957                         x86_64_mov_imm_reg(cd, 1, REG_ITMP1);
1958                         x86_64_mov_imm_reg(cd, -1, REG_ITMP2);
1959                         x86_64_ucomiss_reg_reg(cd, s1, s2);
1960                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_B, REG_ITMP1, d);
1961                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_A, REG_ITMP2, d);
1962                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_P, REG_ITMP1, d);    /* treat unordered as LT */
1963                         store_reg_to_var_int(iptr->dst, d);
1964                         break;
1965
1966                 case ICMD_DCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1967                                           /* == => 0, < => 1, > => -1 */
1968
1969                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1970                         var_to_reg_flt(s2, src, REG_FTMP2);
1971                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1972                         x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
1973                         x86_64_mov_imm_reg(cd, 1, REG_ITMP1);
1974                         x86_64_mov_imm_reg(cd, -1, REG_ITMP2);
1975                         x86_64_ucomisd_reg_reg(cd, s1, s2);
1976                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_B, REG_ITMP1, d);
1977                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_A, REG_ITMP2, d);
1978                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_P, REG_ITMP2, d);    /* treat unordered as GT */
1979                         store_reg_to_var_int(iptr->dst, d);
1980                         break;
1981
1982                 case ICMD_DCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1983                                           /* == => 0, < => 1, > => -1 */
1984
1985                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1986                         var_to_reg_flt(s2, src, REG_FTMP2);
1987                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1988                         x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
1989                         x86_64_mov_imm_reg(cd, 1, REG_ITMP1);
1990                         x86_64_mov_imm_reg(cd, -1, REG_ITMP2);
1991                         x86_64_ucomisd_reg_reg(cd, s1, s2);
1992                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_B, REG_ITMP1, d);
1993                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_A, REG_ITMP2, d);
1994                         x86_64_cmovcc_reg_reg(cd, X86_64_CC_P, REG_ITMP1, d);    /* treat unordered as LT */
1995                         store_reg_to_var_int(iptr->dst, d);
1996                         break;
1997
1998
1999                 /* memory operations **************************************************/
2000
2001                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., (int) length        */
2002
2003                         var_to_reg_int(s1, src, REG_ITMP1);
2004                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2005                         gen_nullptr_check(s1);
2006                         x86_64_movl_membase_reg(cd, s1, OFFSET(java_arrayheader, size), d);
2007                         store_reg_to_var_int(iptr->dst, d);
2008                         break;
2009
2010                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
2011
2012                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2013                         var_to_reg_int(s2, src, REG_ITMP2);
2014                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2015                         if (iptr->op1 == 0) {
2016                                 gen_nullptr_check(s1);
2017                                 gen_bound_check;
2018                         }
2019                         x86_64_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
2020                         store_reg_to_var_int(iptr->dst, d);
2021                         break;
2022
2023                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
2024
2025                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2026                         var_to_reg_int(s2, src, REG_ITMP2);
2027                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2028                         if (iptr->op1 == 0) {
2029                                 gen_nullptr_check(s1);
2030                                 gen_bound_check;
2031                         }
2032                         x86_64_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
2033                         store_reg_to_var_int(iptr->dst, d);
2034                         break;
2035
2036                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
2037
2038                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2039                         var_to_reg_int(s2, src, REG_ITMP2);
2040                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2041                         if (iptr->op1 == 0) {
2042                                 gen_nullptr_check(s1);
2043                                 gen_bound_check;
2044                         }
2045                         x86_64_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2046                         store_reg_to_var_int(iptr->dst, d);
2047                         break;
2048
2049                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
2050
2051                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2052                         var_to_reg_int(s2, src, REG_ITMP2);
2053                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2054                         if (iptr->op1 == 0) {
2055                                 gen_nullptr_check(s1);
2056                                 gen_bound_check;
2057                         }
2058                         x86_64_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
2059                         store_reg_to_var_flt(iptr->dst, d);
2060                         break;
2061
2062                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
2063
2064                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2065                         var_to_reg_int(s2, src, REG_ITMP2);
2066                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2067                         if (iptr->op1 == 0) {
2068                                 gen_nullptr_check(s1);
2069                                 gen_bound_check;
2070                         }
2071                         x86_64_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
2072                         store_reg_to_var_flt(iptr->dst, d);
2073                         break;
2074
2075                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
2076
2077                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2078                         var_to_reg_int(s2, src, REG_ITMP2);
2079                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2080                         if (iptr->op1 == 0) {
2081                                 gen_nullptr_check(s1);
2082                                 gen_bound_check;
2083                         }
2084                         x86_64_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2085                         store_reg_to_var_int(iptr->dst, d);
2086                         break;                  
2087
2088                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
2089
2090                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2091                         var_to_reg_int(s2, src, REG_ITMP2);
2092                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2093                         if (iptr->op1 == 0) {
2094                                 gen_nullptr_check(s1);
2095                                 gen_bound_check;
2096                         }
2097                         x86_64_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2098                         store_reg_to_var_int(iptr->dst, d);
2099                         break;
2100
2101                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
2102
2103                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2104                         var_to_reg_int(s2, src, REG_ITMP2);
2105                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2106                         if (iptr->op1 == 0) {
2107                                 gen_nullptr_check(s1);
2108                                 gen_bound_check;
2109                         }
2110                         x86_64_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2111                         store_reg_to_var_int(iptr->dst, d);
2112                         break;
2113
2114
2115                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
2116
2117                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2118                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2119                         if (iptr->op1 == 0) {
2120                                 gen_nullptr_check(s1);
2121                                 gen_bound_check;
2122                         }
2123                         var_to_reg_int(s3, src, REG_ITMP3);
2124                         x86_64_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2125                         break;
2126
2127                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
2128
2129                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2130                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2131                         if (iptr->op1 == 0) {
2132                                 gen_nullptr_check(s1);
2133                                 gen_bound_check;
2134                         }
2135                         var_to_reg_int(s3, src, REG_ITMP3);
2136                         x86_64_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2137                         break;
2138
2139                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
2140
2141                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2142                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2143                         if (iptr->op1 == 0) {
2144                                 gen_nullptr_check(s1);
2145                                 gen_bound_check;
2146                         }
2147                         var_to_reg_int(s3, src, REG_ITMP3);
2148                         x86_64_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2149                         break;
2150
2151                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
2152
2153                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2154                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2155                         if (iptr->op1 == 0) {
2156                                 gen_nullptr_check(s1);
2157                                 gen_bound_check;
2158                         }
2159                         var_to_reg_flt(s3, src, REG_FTMP3);
2160                         x86_64_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2161                         break;
2162
2163                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
2164
2165                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2166                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2167                         if (iptr->op1 == 0) {
2168                                 gen_nullptr_check(s1);
2169                                 gen_bound_check;
2170                         }
2171                         var_to_reg_flt(s3, src, REG_FTMP3);
2172                         x86_64_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2173                         break;
2174
2175                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
2176
2177                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2178                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2179                         if (iptr->op1 == 0) {
2180                                 gen_nullptr_check(s1);
2181                                 gen_bound_check;
2182                         }
2183                         var_to_reg_int(s3, src, REG_ITMP3);
2184                         x86_64_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2185                         break;
2186
2187                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
2188
2189                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2190                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2191                         if (iptr->op1 == 0) {
2192                                 gen_nullptr_check(s1);
2193                                 gen_bound_check;
2194                         }
2195                         var_to_reg_int(s3, src, REG_ITMP3);
2196                         x86_64_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2197                         break;
2198
2199                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
2200
2201                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2202                         var_to_reg_int(s2, src->prev, REG_ITMP2);
2203                         if (iptr->op1 == 0) {
2204                                 gen_nullptr_check(s1);
2205                                 gen_bound_check;
2206                         }
2207                         var_to_reg_int(s3, src, REG_ITMP3);
2208                         x86_64_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2209                         break;
2210
2211                 case ICMD_IASTORECONST: /* ..., arrayref, index  ==> ...              */
2212
2213                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2214                         var_to_reg_int(s2, src, REG_ITMP2);
2215                         if (iptr->op1 == 0) {
2216                                 gen_nullptr_check(s1);
2217                                 gen_bound_check;
2218                         }
2219                         x86_64_movl_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2220                         break;
2221
2222                 case ICMD_LASTORECONST: /* ..., arrayref, index  ==> ...              */
2223
2224                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2225                         var_to_reg_int(s2, src, REG_ITMP2);
2226                         if (iptr->op1 == 0) {
2227                                 gen_nullptr_check(s1);
2228                                 gen_bound_check;
2229                         }
2230
2231                         if (x86_64_is_imm32(iptr->val.l)) {
2232                                 x86_64_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2233
2234                         } else {
2235                                 x86_64_movl_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2236                                 x86_64_movl_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2237                         }
2238                         break;
2239
2240                 case ICMD_AASTORECONST: /* ..., arrayref, index  ==> ...              */
2241
2242                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2243                         var_to_reg_int(s2, src, REG_ITMP2);
2244                         if (iptr->op1 == 0) {
2245                                 gen_nullptr_check(s1);
2246                                 gen_bound_check;
2247                         }
2248                         x86_64_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2249                         break;
2250
2251                 case ICMD_BASTORECONST: /* ..., arrayref, index  ==> ...              */
2252
2253                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2254                         var_to_reg_int(s2, src, REG_ITMP2);
2255                         if (iptr->op1 == 0) {
2256                                 gen_nullptr_check(s1);
2257                                 gen_bound_check;
2258                         }
2259                         x86_64_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2260                         break;
2261
2262                 case ICMD_CASTORECONST:   /* ..., arrayref, index  ==> ...            */
2263
2264                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2265                         var_to_reg_int(s2, src, REG_ITMP2);
2266                         if (iptr->op1 == 0) {
2267                                 gen_nullptr_check(s1);
2268                                 gen_bound_check;
2269                         }
2270                         x86_64_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2271                         break;
2272
2273                 case ICMD_SASTORECONST:   /* ..., arrayref, index  ==> ...            */
2274
2275                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2276                         var_to_reg_int(s2, src, REG_ITMP2);
2277                         if (iptr->op1 == 0) {
2278                                 gen_nullptr_check(s1);
2279                                 gen_bound_check;
2280                         }
2281                         x86_64_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2282                         break;
2283
2284
2285                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
2286                                       /* op1 = type, val.a = field address            */
2287
2288                         /* If the static fields' class is not yet initialized, we do it   */
2289                         /* now. The call code is generated later.                         */
2290                         if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2291                                 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2292
2293                                 /* This is just for debugging purposes. Is very difficult to  */
2294                                 /* read patched code. Here we patch the following 5 nop's     */
2295                                 /* so that the real code keeps untouched.                     */
2296                                 if (showdisassemble) {
2297                                         x86_64_nop(cd);
2298                                         x86_64_nop(cd);
2299                                         x86_64_nop(cd);
2300                                         x86_64_nop(cd);
2301                                         x86_64_nop(cd);
2302                                 }
2303                         }
2304
2305                         /* This approach is much faster than moving the field address     */
2306                         /* inline into a register. */
2307                         a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
2308                         x86_64_mov_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 7) - (s8) cd->mcodebase) + a, REG_ITMP2);
2309                         switch (iptr->op1) {
2310                         case TYPE_INT:
2311                                 var_to_reg_int(s2, src, REG_ITMP1);
2312                                 x86_64_movl_reg_membase(cd, s2, REG_ITMP2, 0);
2313                                 break;
2314                         case TYPE_LNG:
2315                         case TYPE_ADR:
2316                                 var_to_reg_int(s2, src, REG_ITMP1);
2317                                 x86_64_mov_reg_membase(cd, s2, REG_ITMP2, 0);
2318                                 break;
2319                         case TYPE_FLT:
2320                                 var_to_reg_flt(s2, src, REG_FTMP1);
2321                                 x86_64_movss_reg_membase(cd, s2, REG_ITMP2, 0);
2322                                 break;
2323                         case TYPE_DBL:
2324                                 var_to_reg_flt(s2, src, REG_FTMP1);
2325                                 x86_64_movsd_reg_membase(cd, s2, REG_ITMP2, 0);
2326                                 break;
2327                         default:
2328                                 throw_cacao_exception_exit(string_java_lang_InternalError,
2329                                                                                    "Unknown PUTSTATIC operand type %d",
2330                                                                                    iptr->op1);
2331                         }
2332                         break;
2333
2334                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
2335                                       /* op1 = type, val.a = field address            */
2336
2337                         /* If the static fields' class is not yet initialized, we do it   */
2338                         /* now. The call code is generated later.                         */
2339                         if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2340                                 codegen_addclinitref(cd, cd->mcodeptr, ((fieldinfo *) iptr->val.a)->class);
2341
2342                                 /* This is just for debugging purposes. Is very difficult to  */
2343                                 /* read patched code. Here we patch the following 5 nop's     */
2344                                 /* so that the real code keeps untouched.                     */
2345                                 if (showdisassemble) {
2346                                         x86_64_nop(cd);
2347                                         x86_64_nop(cd);
2348                                         x86_64_nop(cd);
2349                                         x86_64_nop(cd);
2350                                         x86_64_nop(cd);
2351                                 }
2352                         }
2353
2354                         /* This approach is much faster than moving the field address     */
2355                         /* inline into a register. */
2356                         a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
2357                         x86_64_mov_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 7) - (s8) cd->mcodebase) + a, REG_ITMP2);
2358                         switch (iptr->op1) {
2359                         case TYPE_INT:
2360                                 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2361                                 x86_64_movl_membase_reg(cd, REG_ITMP2, 0, d);
2362                                 store_reg_to_var_int(iptr->dst, d);
2363                                 break;
2364                         case TYPE_LNG:
2365                         case TYPE_ADR:
2366                                 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2367                                 x86_64_mov_membase_reg(cd, REG_ITMP2, 0, d);
2368                                 store_reg_to_var_int(iptr->dst, d);
2369                                 break;
2370                         case TYPE_FLT:
2371                                 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2372                                 x86_64_movss_membase_reg(cd, REG_ITMP2, 0, d);
2373                                 store_reg_to_var_flt(iptr->dst, d);
2374                                 break;
2375                         case TYPE_DBL:                          
2376                                 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2377                                 x86_64_movsd_membase_reg(cd, REG_ITMP2, 0, d);
2378                                 store_reg_to_var_flt(iptr->dst, d);
2379                                 break;
2380                         default:
2381                                 throw_cacao_exception_exit(string_java_lang_InternalError,
2382                                                                                    "Unknown GETSTATIC operand type %d",
2383                                                                                    iptr->op1);
2384                         }
2385                         break;
2386
2387                 case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
2388                                       /* op1 = type, val.i = field offset             */
2389
2390                         a = ((fieldinfo *)(iptr->val.a))->offset;
2391                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2392                         switch (iptr->op1) {
2393                         case TYPE_INT:
2394                                 var_to_reg_int(s2, src, REG_ITMP2);
2395                                 gen_nullptr_check(s1);
2396                                 x86_64_movl_reg_membase(cd, s2, s1, a);
2397                                 break;
2398                         case TYPE_LNG:
2399                         case TYPE_ADR:
2400                                 var_to_reg_int(s2, src, REG_ITMP2);
2401                                 gen_nullptr_check(s1);
2402                                 x86_64_mov_reg_membase(cd, s2, s1, a);
2403                                 break;
2404                         case TYPE_FLT:
2405                                 var_to_reg_flt(s2, src, REG_FTMP2);
2406                                 gen_nullptr_check(s1);
2407                                 x86_64_movss_reg_membase(cd, s2, s1, a);
2408                                 break;
2409                         case TYPE_DBL:
2410                                 var_to_reg_flt(s2, src, REG_FTMP2);
2411                                 gen_nullptr_check(s1);
2412                                 x86_64_movsd_reg_membase(cd, s2, s1, a);
2413                                 break;
2414                         default:
2415                                 throw_cacao_exception_exit(string_java_lang_InternalError,
2416                                                                                    "Unknown PUTFIELD operand type %d",
2417                                                                                    iptr->op1);
2418                         }
2419                         break;
2420
2421                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
2422                                       /* op1 = type, val.i = field offset             */
2423
2424                         a = ((fieldinfo *)(iptr->val.a))->offset;
2425                         var_to_reg_int(s1, src, REG_ITMP1);
2426                         switch (iptr->op1) {
2427                         case TYPE_INT:
2428                                 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2429                                 gen_nullptr_check(s1);
2430                                 x86_64_movl_membase_reg(cd, s1, a, d);
2431                                 store_reg_to_var_int(iptr->dst, d);
2432                                 break;
2433                         case TYPE_LNG:
2434                         case TYPE_ADR:
2435                                 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2436                                 gen_nullptr_check(s1);
2437                                 x86_64_mov_membase_reg(cd, s1, a, d);
2438                                 store_reg_to_var_int(iptr->dst, d);
2439                                 break;
2440                         case TYPE_FLT:
2441                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2442                                 gen_nullptr_check(s1);
2443                                 x86_64_movss_membase_reg(cd, s1, a, d);
2444                                 store_reg_to_var_flt(iptr->dst, d);
2445                                 break;
2446                         case TYPE_DBL:                          
2447                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2448                                 gen_nullptr_check(s1);
2449                                 x86_64_movsd_membase_reg(cd, s1, a, d);
2450                                 store_reg_to_var_flt(iptr->dst, d);
2451                                 break;
2452                         default:
2453                                 throw_cacao_exception_exit(string_java_lang_InternalError,
2454                                                                                    "Unknown GETFIELD operand type %d",
2455                                                                                    iptr->op1);
2456                         }
2457                         break;
2458
2459
2460                 /* branch operations **************************************************/
2461
2462                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
2463
2464                         var_to_reg_int(s1, src, REG_ITMP1);
2465                         M_INTMOVE(s1, REG_ITMP1_XPTR);
2466
2467                         x86_64_call_imm(cd, 0); /* passing exception pointer              */
2468                         x86_64_pop_reg(cd, REG_ITMP2_XPC);
2469
2470                         x86_64_mov_imm_reg(cd, (s8) asm_handle_exception, REG_ITMP3);
2471                         x86_64_jmp_reg(cd, REG_ITMP3);
2472                         ALIGNCODENOP;
2473                         break;
2474
2475                 case ICMD_GOTO:         /* ... ==> ...                                */
2476                                         /* op1 = target JavaVM pc                     */
2477
2478                         x86_64_jmp_imm(cd, 0);
2479                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
2480                         ALIGNCODENOP;
2481                         break;
2482
2483                 case ICMD_JSR:          /* ... ==> ...                                */
2484                                         /* op1 = target JavaVM pc                     */
2485
2486                         x86_64_call_imm(cd, 0);
2487                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
2488                         break;
2489                         
2490                 case ICMD_RET:          /* ... ==> ...                                */
2491                                         /* op1 = local variable                       */
2492
2493                         var = &(rd->locals[iptr->op1][TYPE_ADR]);
2494                         var_to_reg_int(s1, var, REG_ITMP1);
2495                         x86_64_jmp_reg(cd, s1);
2496                         break;
2497
2498                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
2499                                         /* op1 = target JavaVM pc                     */
2500
2501                         if (src->flags & INMEMORY) {
2502                                 x86_64_alu_imm_membase(cd, X86_64_CMP, 0, REG_SP, src->regoff * 8);
2503
2504                         } else {
2505                                 x86_64_test_reg_reg(cd, src->regoff, src->regoff);
2506                         }
2507                         x86_64_jcc(cd, X86_64_CC_E, 0);
2508                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
2509                         break;
2510
2511                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
2512                                         /* op1 = target JavaVM pc                     */
2513
2514                         if (src->flags & INMEMORY) {
2515                                 x86_64_alu_imm_membase(cd, X86_64_CMP, 0, REG_SP, src->regoff * 8);
2516
2517                         } else {
2518                                 x86_64_test_reg_reg(cd, src->regoff, src->regoff);
2519                         }
2520                         x86_64_jcc(cd, X86_64_CC_NE, 0);
2521                         codegen_addreference(cd, BlockPtrOfPC(iptr->op1), cd->mcodeptr);
2522                         break;
2523
2524                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
2525                                         /* op1 = target JavaVM pc, val.i = constant   */
2526
2527                         x86_64_emit_ifcc(cd, X86_64_CC_E, src, iptr);
2528                         break;
2529
2530                 case ICMD_IFLT:         /* ..., value ==> ...                         */
2531                                         /* op1 = target JavaVM pc, val.i = constant   */
2532
2533                         x86_64_emit_ifcc(cd, X86_64_CC_L, src, iptr);
2534                         break;
2535
2536                 case ICMD_IFLE:         /* ..., value ==> ...                         */
2537                                         /* op1 = target JavaVM pc, val.i = constant   */
2538
2539                         x86_64_emit_ifcc(cd, X86_64_CC_LE, src, iptr);
2540                         break;
2541
2542                 case ICMD_IFNE:         /* ..., value ==> ...                         */
2543                                         /* op1 = target JavaVM pc, val.i = constant   */
2544
2545                         x86_64_emit_ifcc(cd, X86_64_CC_NE, src, iptr);
2546                         break;
2547
2548                 case ICMD_IFGT:         /* ..., value ==> ...                         */
2549                                         /* op1 = target JavaVM pc, val.i = constant   */
2550
2551                         x86_64_emit_ifcc(cd, X86_64_CC_G, src, iptr);
2552                         break;
2553
2554                 case ICMD_IFGE:         /* ..., value ==> ...                         */
2555                                         /* op1 = target JavaVM pc, val.i = constant   */
2556
2557                         x86_64_emit_ifcc(cd, X86_64_CC_GE, src, iptr);
2558                         break;
2559
2560                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
2561                                         /* op1 = target JavaVM pc, val.l = constant   */
2562
2563                         x86_64_emit_if_lcc(cd, X86_64_CC_E, src, iptr);
2564                         break;
2565
2566                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
2567                                         /* op1 = target JavaVM pc, val.l = constant   */
2568
2569                         x86_64_emit_if_lcc(cd, X86_64_CC_L, src, iptr);
2570                         break;
2571
2572                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
2573                                         /* op1 = target JavaVM pc, val.l = constant   */
2574
2575                         x86_64_emit_if_lcc(cd, X86_64_CC_LE, src, iptr);
2576                         break;
2577
2578                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
2579                                         /* op1 = target JavaVM pc, val.l = constant   */
2580
2581                         x86_64_emit_if_lcc(cd, X86_64_CC_NE, src, iptr);
2582                         break;
2583
2584                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
2585                                         /* op1 = target JavaVM pc, val.l = constant   */
2586
2587                         x86_64_emit_if_lcc(cd, X86_64_CC_G, src, iptr);
2588                         break;
2589
2590                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
2591                                         /* op1 = target JavaVM pc, val.l = constant   */
2592
2593                         x86_64_emit_if_lcc(cd, X86_64_CC_GE, src, iptr);
2594                         break;
2595
2596                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
2597                                         /* op1 = target JavaVM pc                     */
2598
2599                         x86_64_emit_if_icmpcc(cd, X86_64_CC_E, src, iptr);
2600                         break;
2601
2602                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
2603                 case ICMD_IF_ACMPEQ:    /* op1 = target JavaVM pc                     */
2604
2605                         x86_64_emit_if_lcmpcc(cd, X86_64_CC_E, src, iptr);
2606                         break;
2607
2608                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
2609                                         /* op1 = target JavaVM pc                     */
2610
2611                         x86_64_emit_if_icmpcc(cd, X86_64_CC_NE, src, iptr);
2612                         break;
2613
2614                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
2615                 case ICMD_IF_ACMPNE:    /* op1 = target JavaVM pc                     */
2616
2617                         x86_64_emit_if_lcmpcc(cd, X86_64_CC_NE, src, iptr);
2618                         break;
2619
2620                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
2621                                         /* op1 = target JavaVM pc                     */
2622
2623                         x86_64_emit_if_icmpcc(cd, X86_64_CC_L, src, iptr);
2624                         break;
2625
2626                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
2627                                     /* op1 = target JavaVM pc                     */
2628
2629                         x86_64_emit_if_lcmpcc(cd, X86_64_CC_L, src, iptr);
2630                         break;
2631
2632                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
2633                                         /* op1 = target JavaVM pc                     */
2634
2635                         x86_64_emit_if_icmpcc(cd, X86_64_CC_G, src, iptr);
2636                         break;
2637
2638                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
2639                                 /* op1 = target JavaVM pc                     */
2640
2641                         x86_64_emit_if_lcmpcc(cd, X86_64_CC_G, src, iptr);
2642                         break;
2643
2644                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
2645                                         /* op1 = target JavaVM pc                     */
2646
2647                         x86_64_emit_if_icmpcc(cd, X86_64_CC_LE, src, iptr);
2648                         break;
2649
2650                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
2651                                         /* op1 = target JavaVM pc                     */
2652
2653                         x86_64_emit_if_lcmpcc(cd, X86_64_CC_LE, src, iptr);
2654                         break;
2655
2656                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
2657                                         /* op1 = target JavaVM pc                     */
2658
2659                         x86_64_emit_if_icmpcc(cd, X86_64_CC_GE, src, iptr);
2660                         break;
2661
2662                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
2663                                     /* op1 = target JavaVM pc                     */
2664
2665                         x86_64_emit_if_lcmpcc(cd, X86_64_CC_GE, src, iptr);
2666                         break;
2667
2668                 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST                           */
2669
2670                 case ICMD_ELSE_ICONST:  /* handled by IFxx_ICONST                     */
2671                         break;
2672
2673                 case ICMD_IFEQ_ICONST:  /* ..., value ==> ..., constant               */
2674                                         /* val.i = constant                           */
2675
2676                         var_to_reg_int(s1, src, REG_ITMP1);
2677                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2678                         s3 = iptr->val.i;
2679                         if (iptr[1].opc == ICMD_ELSE_ICONST) {
2680                                 if (s1 == d) {
2681                                         M_INTMOVE(s1, REG_ITMP1);
2682                                         s1 = REG_ITMP1;
2683                                 }
2684                                 x86_64_movl_imm_reg(cd, iptr[1].val.i, d);
2685                         }
2686                         x86_64_movl_imm_reg(cd, s3, REG_ITMP2);
2687                         x86_64_testl_reg_reg(cd, s1, s1);
2688                         x86_64_cmovccl_reg_reg(cd, X86_64_CC_E, REG_ITMP2, d);
2689                         store_reg_to_var_int(iptr->dst, d);
2690                         break;
2691
2692                 case ICMD_IFNE_ICONST:  /* ..., value ==> ..., constant               */
2693                                         /* val.i = constant                           */
2694
2695                         var_to_reg_int(s1, src, REG_ITMP1);
2696                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2697                         s3 = iptr->val.i;
2698                         if (iptr[1].opc == ICMD_ELSE_ICONST) {
2699                                 if (s1 == d) {
2700                                         M_INTMOVE(s1, REG_ITMP1);
2701                                         s1 = REG_ITMP1;
2702                                 }
2703                                 x86_64_movl_imm_reg(cd, iptr[1].val.i, d);
2704                         }
2705                         x86_64_movl_imm_reg(cd, s3, REG_ITMP2);
2706                         x86_64_testl_reg_reg(cd, s1, s1);
2707                         x86_64_cmovccl_reg_reg(cd, X86_64_CC_NE, REG_ITMP2, d);
2708                         store_reg_to_var_int(iptr->dst, d);
2709                         break;
2710
2711                 case ICMD_IFLT_ICONST:  /* ..., value ==> ..., constant               */
2712                                         /* val.i = constant                           */
2713
2714                         var_to_reg_int(s1, src, REG_ITMP1);
2715                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2716                         s3 = iptr->val.i;
2717                         if (iptr[1].opc == ICMD_ELSE_ICONST) {
2718                                 if (s1 == d) {
2719                                         M_INTMOVE(s1, REG_ITMP1);
2720                                         s1 = REG_ITMP1;
2721                                 }
2722                                 x86_64_movl_imm_reg(cd, iptr[1].val.i, d);
2723                         }
2724                         x86_64_movl_imm_reg(cd, s3, REG_ITMP2);
2725                         x86_64_testl_reg_reg(cd, s1, s1);
2726                         x86_64_cmovccl_reg_reg(cd, X86_64_CC_L, REG_ITMP2, d);
2727                         store_reg_to_var_int(iptr->dst, d);
2728                         break;
2729
2730                 case ICMD_IFGE_ICONST:  /* ..., value ==> ..., constant               */
2731                                         /* val.i = constant                           */
2732
2733                         var_to_reg_int(s1, src, REG_ITMP1);
2734                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2735                         s3 = iptr->val.i;
2736                         if (iptr[1].opc == ICMD_ELSE_ICONST) {
2737                                 if (s1 == d) {
2738                                         M_INTMOVE(s1, REG_ITMP1);
2739                                         s1 = REG_ITMP1;
2740                                 }
2741                                 x86_64_movl_imm_reg(cd, iptr[1].val.i, d);
2742                         }
2743                         x86_64_movl_imm_reg(cd, s3, REG_ITMP2);
2744                         x86_64_testl_reg_reg(cd, s1, s1);
2745                         x86_64_cmovccl_reg_reg(cd, X86_64_CC_GE, REG_ITMP2, d);
2746                         store_reg_to_var_int(iptr->dst, d);
2747                         break;
2748
2749                 case ICMD_IFGT_ICONST:  /* ..., value ==> ..., constant               */
2750                                         /* val.i = constant                           */
2751
2752                         var_to_reg_int(s1, src, REG_ITMP1);
2753                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2754                         s3 = iptr->val.i;
2755                         if (iptr[1].opc == ICMD_ELSE_ICONST) {
2756                                 if (s1 == d) {
2757                                         M_INTMOVE(s1, REG_ITMP1);
2758                                         s1 = REG_ITMP1;
2759                                 }
2760                                 x86_64_movl_imm_reg(cd, iptr[1].val.i, d);
2761                         }
2762                         x86_64_movl_imm_reg(cd, s3, REG_ITMP2);
2763                         x86_64_testl_reg_reg(cd, s1, s1);
2764                         x86_64_cmovccl_reg_reg(cd, X86_64_CC_G, REG_ITMP2, d);
2765                         store_reg_to_var_int(iptr->dst, d);
2766                         break;
2767
2768                 case ICMD_IFLE_ICONST:  /* ..., value ==> ..., constant               */
2769                                         /* val.i = constant                           */
2770
2771                         var_to_reg_int(s1, src, REG_ITMP1);
2772                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2773                         s3 = iptr->val.i;
2774                         if (iptr[1].opc == ICMD_ELSE_ICONST) {
2775                                 if (s1 == d) {
2776                                         M_INTMOVE(s1, REG_ITMP1);
2777                                         s1 = REG_ITMP1;
2778                                 }
2779                                 x86_64_movl_imm_reg(cd, iptr[1].val.i, d);
2780                         }
2781                         x86_64_movl_imm_reg(cd, s3, REG_ITMP2);
2782                         x86_64_testl_reg_reg(cd, s1, s1);
2783                         x86_64_cmovccl_reg_reg(cd, X86_64_CC_LE, REG_ITMP2, d);
2784                         store_reg_to_var_int(iptr->dst, d);
2785                         break;
2786
2787
2788                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
2789                 case ICMD_LRETURN:
2790                 case ICMD_ARETURN:
2791
2792                         var_to_reg_int(s1, src, REG_RESULT);
2793                         M_INTMOVE(s1, REG_RESULT);
2794
2795 #if defined(USE_THREADS)
2796                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2797                                 x86_64_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, rd->argintregs[0]);
2798                                 x86_64_mov_reg_membase(cd, REG_RESULT, REG_SP, rd->maxmemuse * 8);
2799                                 x86_64_mov_imm_reg(cd, (u8) builtin_monitorexit, REG_ITMP1);
2800                                 x86_64_call_reg(cd, REG_ITMP1);
2801                                 x86_64_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_RESULT);
2802                         }
2803 #endif
2804
2805                         goto nowperformreturn;
2806
2807                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
2808                 case ICMD_DRETURN:
2809
2810                         var_to_reg_flt(s1, src, REG_FRESULT);
2811                         M_FLTMOVE(s1, REG_FRESULT);
2812
2813 #if defined(USE_THREADS)
2814                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2815                                 x86_64_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, rd->argintregs[0]);
2816                                 x86_64_movq_reg_membase(cd, REG_FRESULT, REG_SP, rd->maxmemuse * 8);
2817                                 x86_64_mov_imm_reg(cd, (u8) builtin_monitorexit, REG_ITMP1);
2818                                 x86_64_call_reg(cd, REG_ITMP1);
2819                                 x86_64_movq_membase_reg(cd, REG_SP, rd->maxmemuse * 8, REG_FRESULT);
2820                         }
2821 #endif
2822
2823                         goto nowperformreturn;
2824
2825                 case ICMD_RETURN:      /* ...  ==> ...                                */
2826
2827 #if defined(USE_THREADS)
2828                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2829                                 x86_64_mov_membase_reg(cd, REG_SP, rd->maxmemuse * 8, rd->argintregs[0]);
2830                                 x86_64_mov_imm_reg(cd, (u8) builtin_monitorexit, REG_ITMP1);
2831                                 x86_64_call_reg(cd, REG_ITMP1);
2832                         }
2833 #endif
2834
2835 nowperformreturn:
2836                         {
2837                         s4 i, p;
2838                         
2839                         p = parentargs_base;
2840                         
2841                         /* call trace function */
2842                         if (runverbose) {
2843                                 x86_64_alu_imm_reg(cd, X86_64_SUB, 2 * 8, REG_SP);
2844
2845                                 x86_64_mov_reg_membase(cd, REG_RESULT, REG_SP, 0 * 8);
2846                                 x86_64_movq_reg_membase(cd, REG_FRESULT, REG_SP, 1 * 8);
2847
2848                                 x86_64_mov_imm_reg(cd, (s8) m, rd->argintregs[0]);
2849                                 x86_64_mov_reg_reg(cd, REG_RESULT, rd->argintregs[1]);
2850                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2851                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2852
2853                                 x86_64_mov_imm_reg(cd, (s8) builtin_displaymethodstop, REG_ITMP1);
2854                                 x86_64_call_reg(cd, REG_ITMP1);
2855
2856                                 x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_RESULT);
2857                                 x86_64_movq_membase_reg(cd, REG_SP, 1 * 8, REG_FRESULT);
2858
2859                                 x86_64_alu_imm_reg(cd, X86_64_ADD, 2 * 8, REG_SP);
2860                         }
2861
2862                         /* restore saved registers                                        */
2863                         for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2864                                 p--; x86_64_mov_membase_reg(cd, REG_SP, p * 8, rd->savintregs[i]);
2865                         }
2866                         for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2867                                 p--; x86_64_movq_membase_reg(cd, REG_SP, p * 8, rd->savfltregs[i]);
2868                         }
2869
2870                         /* deallocate stack                                               */
2871                         if (parentargs_base) {
2872                                 x86_64_alu_imm_reg(cd, X86_64_ADD, parentargs_base * 8, REG_SP);
2873                         }
2874
2875                         x86_64_ret(cd);
2876                         ALIGNCODENOP;
2877                         }
2878                         break;
2879
2880
2881                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2882                         {
2883                                 s4 i, l, *s4ptr;
2884                                 void **tptr;
2885
2886                                 tptr = (void **) iptr->target;
2887
2888                                 s4ptr = iptr->val.a;
2889                                 l = s4ptr[1];                          /* low     */
2890                                 i = s4ptr[2];                          /* high    */
2891
2892                                 var_to_reg_int(s1, src, REG_ITMP1);
2893                                 M_INTMOVE(s1, REG_ITMP1);
2894                                 if (l != 0) {
2895                                         x86_64_alul_imm_reg(cd, X86_64_SUB, l, REG_ITMP1);
2896                                 }
2897                                 i = i - l + 1;
2898
2899                 /* range check */
2900                                 x86_64_alul_imm_reg(cd, X86_64_CMP, i - 1, REG_ITMP1);
2901                                 x86_64_jcc(cd, X86_64_CC_A, 0);
2902
2903                 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
2904                                 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
2905
2906                                 /* build jump table top down and use address of lowest entry */
2907
2908                 /* s4ptr += 3 + i; */
2909                                 tptr += i;
2910
2911                                 while (--i >= 0) {
2912                                         /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2913                                         dseg_addtarget(cd, (basicblock *) tptr[0]); 
2914                                         --tptr;
2915                                 }
2916
2917                                 /* length of dataseg after last dseg_addtarget is used by load */
2918
2919                                 x86_64_mov_imm_reg(cd, 0, REG_ITMP2);
2920                                 dseg_adddata(cd, cd->mcodeptr);
2921                                 x86_64_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2922                                 x86_64_jmp_reg(cd, REG_ITMP1);
2923                                 ALIGNCODENOP;
2924                         }
2925                         break;
2926
2927
2928                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
2929                         {
2930                                 s4 i, l, val, *s4ptr;
2931                                 void **tptr;
2932
2933                                 tptr = (void **) iptr->target;
2934
2935                                 s4ptr = iptr->val.a;
2936                                 l = s4ptr[0];                          /* default  */
2937                                 i = s4ptr[1];                          /* count    */
2938                         
2939                                 MCODECHECK((i<<2)+8);
2940                                 var_to_reg_int(s1, src, REG_ITMP1);    /* reg compare should always be faster */
2941                                 while (--i >= 0) {
2942                                         s4ptr += 2;
2943                                         ++tptr;
2944
2945                                         val = s4ptr[0];
2946                                         x86_64_alul_imm_reg(cd, X86_64_CMP, val, s1);
2947                                         x86_64_jcc(cd, X86_64_CC_E, 0);
2948                                         /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), cd->mcodeptr); */
2949                                         codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr); 
2950                                 }
2951
2952                                 x86_64_jmp_imm(cd, 0);
2953                                 /* codegen_addreference(cd, BlockPtrOfPC(l), cd->mcodeptr); */
2954                         
2955                                 tptr = (void **) iptr->target;
2956                                 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
2957
2958                                 ALIGNCODENOP;
2959                         }
2960                         break;
2961
2962
2963                 case ICMD_BUILTIN3:     /* ..., arg1, arg2, arg3 ==> ...              */
2964                                         /* op1 = return type, val.a = function pointer*/
2965                         s3 = 3;
2966                         goto gen_method;
2967
2968                 case ICMD_BUILTIN2:     /* ..., arg1, arg2 ==> ...                    */
2969                                         /* op1 = return type, val.a = function pointer*/
2970                         s3 = 2;
2971                         goto gen_method;
2972
2973                 case ICMD_BUILTIN1:     /* ..., arg1 ==> ...                          */
2974                                         /* op1 = return type, val.a = function pointer*/
2975                         s3 = 1;
2976                         goto gen_method;
2977
2978                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2979                                         /* op1 = arg count, val.a = method pointer    */
2980
2981                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2982                                         /* op1 = arg count, val.a = method pointer    */
2983
2984                 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2985                                         /* op1 = arg count, val.a = method pointer    */
2986
2987                 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2988                                         /* op1 = arg count, val.a = method pointer    */
2989
2990                         s3 = iptr->op1;
2991
2992 gen_method: {
2993                         methodinfo   *lm;
2994                         classinfo    *ci;
2995                         stackptr      tmpsrc;
2996                         s4 iarg, farg;
2997
2998                         MCODECHECK((s3 << 1) + 64);
2999
3000                         tmpsrc = src;
3001                         s2 = s3;
3002                         iarg = 0;
3003                         farg = 0;
3004
3005                         /* copy arguments to registers or stack location                  */
3006                         for (; --s3 >= 0; src = src->prev) {
3007                                 IS_INT_LNG_TYPE(src->type) ? iarg++ : farg++;
3008                         }
3009
3010                         src = tmpsrc;
3011                         s3 = s2;
3012
3013                         s2 = (iarg > INT_ARG_CNT) ? iarg - INT_ARG_CNT : 0 + (farg > FLT_ARG_CNT) ? farg - FLT_ARG_CNT : 0;
3014
3015                         for (; --s3 >= 0; src = src->prev) {
3016                                 IS_INT_LNG_TYPE(src->type) ? iarg-- : farg--;
3017                                 if (src->varkind == ARGVAR) {
3018                                         if (IS_INT_LNG_TYPE(src->type)) {
3019                                                 if (iarg >= INT_ARG_CNT) {
3020                                                         s2--;
3021                                                 }
3022                                         } else {
3023                                                 if (farg >= FLT_ARG_CNT) {
3024                                                         s2--;
3025                                                 }
3026                                         }
3027                                         continue;
3028                                 }
3029
3030                                 if (IS_INT_LNG_TYPE(src->type)) {
3031                                         if (iarg < INT_ARG_CNT) {
3032                                                 s1 = rd->argintregs[iarg];
3033                                                 var_to_reg_int(d, src, s1);
3034                                                 M_INTMOVE(d, s1);
3035
3036                                         } else {
3037                                                 var_to_reg_int(d, src, REG_ITMP1);
3038                                                 s2--;
3039                                                 x86_64_mov_reg_membase(cd, d, REG_SP, s2 * 8);
3040                                         }
3041
3042                                 } else {
3043                                         if (farg < FLT_ARG_CNT) {
3044                                                 s1 = rd->argfltregs[farg];
3045                                                 var_to_reg_flt(d, src, s1);
3046                                                 M_FLTMOVE(d, s1);
3047
3048                                         } else {
3049                                                 var_to_reg_flt(d, src, REG_FTMP1);
3050                                                 s2--;
3051                                                 x86_64_movq_reg_membase(cd, d, REG_SP, s2 * 8);
3052                                         }
3053                                 }
3054                         } /* end of for */
3055
3056                         lm = iptr->val.a;
3057                         switch (iptr->opc) {
3058                                 case ICMD_BUILTIN3:
3059                                 case ICMD_BUILTIN2:
3060                                 case ICMD_BUILTIN1:
3061
3062                                         a = (s8) lm;
3063                                         d = iptr->op1;
3064
3065                                         x86_64_mov_imm_reg(cd, a, REG_ITMP1);
3066                                         x86_64_call_reg(cd, REG_ITMP1);
3067                                         break;
3068
3069                                 case ICMD_INVOKESTATIC:
3070
3071                                         a = (s8) lm->stubroutine;
3072                                         d = lm->returntype;
3073
3074                                         x86_64_mov_imm_reg(cd, a, REG_ITMP2);
3075                                         x86_64_call_reg(cd, REG_ITMP2);
3076                                         break;
3077
3078                                 case ICMD_INVOKESPECIAL:
3079
3080                                         a = (s8) lm->stubroutine;
3081                                         d = lm->returntype;
3082
3083                                         gen_nullptr_check(rd->argintregs[0]);    /* first argument contains pointer */
3084                                         x86_64_mov_membase_reg(cd, rd->argintregs[0], 0, REG_ITMP2); /* access memory for hardware nullptr */
3085                                         x86_64_mov_imm_reg(cd, a, REG_ITMP2);
3086                                         x86_64_call_reg(cd, REG_ITMP2);
3087                                         break;
3088
3089                                 case ICMD_INVOKEVIRTUAL:
3090
3091                                         d = lm->returntype;
3092
3093                                         gen_nullptr_check(rd->argintregs[0]);
3094                                         x86_64_mov_membase_reg(cd, rd->argintregs[0], OFFSET(java_objectheader, vftbl), REG_ITMP2);
3095                                         x86_64_mov_membase32_reg(cd, REG_ITMP2, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex, REG_ITMP1);
3096                                         x86_64_call_reg(cd, REG_ITMP1);
3097                                         break;
3098
3099                                 case ICMD_INVOKEINTERFACE:
3100
3101                                         ci = lm->class;
3102                                         d = lm->returntype;
3103
3104                                         gen_nullptr_check(rd->argintregs[0]);
3105                                         x86_64_mov_membase_reg(cd, rd->argintregs[0], OFFSET(java_objectheader, vftbl), REG_ITMP2);
3106                                         x86_64_mov_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * ci->index, REG_ITMP2);
3107                                         x86_64_mov_membase32_reg(cd, REG_ITMP2, sizeof(methodptr) * (lm - ci->methods), REG_ITMP1);
3108                                         x86_64_call_reg(cd, REG_ITMP1);
3109                                         break;
3110
3111                                 default:
3112                                         d = 0;
3113                                         error("Unkown ICMD-Command: %d", iptr->opc);
3114                                 }
3115
3116                         /* d contains return type */
3117
3118                         if (d != TYPE_VOID) {
3119                                 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3120                                         s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3121                                         M_INTMOVE(REG_RESULT, s1);
3122                                         store_reg_to_var_int(iptr->dst, s1);
3123
3124                                 } else {
3125                                         s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3126                                         M_FLTMOVE(REG_FRESULT, s1);
3127                                         store_reg_to_var_flt(iptr->dst, s1);
3128                                 }
3129                         }
3130                         }
3131                         break;
3132
3133
3134                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
3135
3136                                       /* op1:   0 == array, 1 == class                */
3137                                       /* val.a: (classinfo*) superclass               */
3138
3139 /*          superclass is an interface:
3140  *
3141  *          return (sub != NULL) &&
3142  *                 (sub->vftbl->interfacetablelength > super->index) &&
3143  *                 (sub->vftbl->interfacetable[-super->index] != NULL);
3144  *
3145  *          superclass is a class:
3146  *
3147  *          return ((sub != NULL) && (0
3148  *                  <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3149  *                  super->vftbl->diffvall));
3150  */
3151
3152                         {
3153                         classinfo *super = (classinfo*) iptr->val.a;
3154                         
3155 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3156             codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3157 #endif
3158
3159                         var_to_reg_int(s1, src, REG_ITMP1);
3160                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3161                         if (s1 == d) {
3162                                 M_INTMOVE(s1, REG_ITMP1);
3163                                 s1 = REG_ITMP1;
3164                         }
3165                         x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
3166                         if (iptr->op1) {                               /* class/interface */
3167                                 if (super->flags & ACC_INTERFACE) {        /* interface       */
3168                                         x86_64_test_reg_reg(cd, s1, s1);
3169
3170                                         /* TODO: clean up this calculation */
3171                                         a = 3;    /* mov_membase_reg */
3172                                         CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
3173
3174                                         a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
3175                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3176                                         
3177                                         a += 3;    /* sub */
3178                                         CALCIMMEDIATEBYTES(a, super->index);
3179                                         
3180                                         a += 3;    /* test */
3181
3182                                         a += 6;    /* jcc */
3183                                         a += 3;    /* mov_membase_reg */
3184                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
3185
3186                                         a += 3;    /* test */
3187                                         a += 4;    /* setcc */
3188
3189                                         x86_64_jcc(cd, X86_64_CC_E, a);
3190
3191                                         x86_64_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3192                                         x86_64_movl_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
3193                                         x86_64_alu_imm_reg(cd, X86_64_SUB, super->index, REG_ITMP2);
3194                                         x86_64_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
3195
3196                                         /* TODO: clean up this calculation */
3197                                         a = 0;
3198                                         a += 3;    /* mov_membase_reg */
3199                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
3200
3201                                         a += 3;    /* test */
3202                                         a += 4;    /* setcc */
3203
3204                                         x86_64_jcc(cd, X86_64_CC_LE, a);
3205                                         x86_64_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP1);
3206                                         x86_64_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3207                                         x86_64_setcc_reg(cd, X86_64_CC_NE, d);
3208
3209                                 } else {                                   /* class           */
3210                                         x86_64_test_reg_reg(cd, s1, s1);
3211
3212                                         /* TODO: clean up this calculation */
3213                                         a = 3;    /* mov_membase_reg */
3214                                         CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
3215
3216                                         a += 10;   /* mov_imm_reg */
3217
3218                                         a += 2;    /* movl_membase_reg - only if REG_ITMP1 == RAX */
3219                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
3220                                         
3221                                         a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
3222                                         CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
3223                                         
3224                                         a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
3225                                         CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
3226                                         
3227                                         a += 3;    /* sub */
3228                                         a += 3;    /* xor */
3229                                         a += 3;    /* cmp */
3230                                         a += 4;    /* setcc */
3231
3232                                         x86_64_jcc(cd, X86_64_CC_E, a);
3233
3234                                         x86_64_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3235                                         x86_64_mov_imm_reg(cd, (s8) super->vftbl, REG_ITMP2);
3236 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3237                                         codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3238 #endif
3239                                         x86_64_movl_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
3240                                         x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
3241                                         x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
3242 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3243                     codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3244 #endif
3245                                         x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP3, REG_ITMP1);
3246                                         x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
3247                                         x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, REG_ITMP1);
3248                                         x86_64_setcc_reg(cd, X86_64_CC_BE, d);
3249                                 }
3250                         }
3251                         else
3252                                 panic("internal error: no inlined array instanceof");
3253                         }
3254                         store_reg_to_var_int(iptr->dst, d);
3255                         break;
3256
3257                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
3258
3259                                       /* op1:   0 == array, 1 == class                */
3260                                       /* val.a: (classinfo*) superclass               */
3261
3262 /*          superclass is an interface:
3263  *
3264  *          OK if ((sub == NULL) ||
3265  *                 (sub->vftbl->interfacetablelength > super->index) &&
3266  *                 (sub->vftbl->interfacetable[-super->index] != NULL));
3267  *
3268  *          superclass is a class:
3269  *
3270  *          OK if ((sub == NULL) || (0
3271  *                 <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3272  *                 super->vftbl->diffvall));
3273  */
3274
3275                         {
3276                         classinfo *super = (classinfo*) iptr->val.a;
3277                         
3278 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3279             codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3280 #endif
3281                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3282                         var_to_reg_int(s1, src, d);
3283                         if (iptr->op1) {                               /* class/interface */
3284                                 if (super->flags & ACC_INTERFACE) {        /* interface       */
3285                                         x86_64_test_reg_reg(cd, s1, s1);
3286
3287                                         /* TODO: clean up this calculation */
3288                                         a = 3;    /* mov_membase_reg */
3289                                         CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
3290
3291                                         a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
3292                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3293
3294                                         a += 3;    /* sub */
3295                                         CALCIMMEDIATEBYTES(a, super->index);
3296
3297                                         a += 3;    /* test */
3298                                         a += 6;    /* jcc */
3299
3300                                         a += 3;    /* mov_membase_reg */
3301                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*));
3302
3303                                         a += 3;    /* test */
3304                                         a += 6;    /* jcc */
3305
3306                                         x86_64_jcc(cd, X86_64_CC_E, a);
3307
3308                                         x86_64_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3309                                         x86_64_movl_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength), REG_ITMP2);
3310                                         x86_64_alu_imm_reg(cd, X86_64_SUB, super->index, REG_ITMP2);
3311                                         x86_64_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
3312                                         x86_64_jcc(cd, X86_64_CC_LE, 0);
3313                                         codegen_addxcastrefs(cd, cd->mcodeptr);
3314                                         x86_64_mov_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, interfacetable[0]) - super->index * sizeof(methodptr*), REG_ITMP2);
3315                                         x86_64_test_reg_reg(cd, REG_ITMP2, REG_ITMP2);
3316                                         x86_64_jcc(cd, X86_64_CC_E, 0);
3317                                         codegen_addxcastrefs(cd, cd->mcodeptr);
3318
3319                                 } else {                                     /* class           */
3320                                         x86_64_test_reg_reg(cd, s1, s1);
3321
3322                                         /* TODO: clean up this calculation */
3323                                         a = 3;    /* mov_membase_reg */
3324                                         CALCOFFSETBYTES(a, s1, OFFSET(java_objectheader, vftbl));
3325                                         a += 10;   /* mov_imm_reg */
3326                                         a += 2;    /* movl_membase_reg - only if REG_ITMP1 == RAX */
3327                                         CALCOFFSETBYTES(a, REG_ITMP1, OFFSET(vftbl_t, baseval));
3328
3329                                         if (d != REG_ITMP3) {
3330                                                 a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
3331                                                 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
3332                                                 a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
3333                                                 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
3334                                                 a += 3;    /* sub */
3335                                                 
3336                                         } else {
3337                                                 a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
3338                                                 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, baseval));
3339                                                 a += 3;    /* sub */
3340                                                 a += 10;   /* mov_imm_reg */
3341                                                 a += 3;    /* movl_membase_reg - only if REG_ITMP2 == R10 */
3342                                                 CALCOFFSETBYTES(a, REG_ITMP2, OFFSET(vftbl_t, diffval));
3343                                         }
3344
3345                                         a += 3;    /* cmp */
3346                                         a += 6;    /* jcc */
3347
3348                                         x86_64_jcc(cd, X86_64_CC_E, a);
3349
3350                                         x86_64_mov_membase_reg(cd, s1, OFFSET(java_objectheader, vftbl), REG_ITMP1);
3351                                         x86_64_mov_imm_reg(cd, (s8) super->vftbl, REG_ITMP2);
3352 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3353                     codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3354 #endif
3355                                         x86_64_movl_membase_reg(cd, REG_ITMP1, OFFSET(vftbl_t, baseval), REG_ITMP1);
3356                                         if (d != REG_ITMP3) {
3357                                                 x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP3);
3358                                                 x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
3359 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3360                         codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3361 #endif
3362                                                 x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP3, REG_ITMP1);
3363
3364                                         } else {
3365                                                 x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, baseval), REG_ITMP2);
3366                                                 x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
3367                                                 x86_64_mov_imm_reg(cd, (s8) super->vftbl, REG_ITMP2);
3368                                                 x86_64_movl_membase_reg(cd, REG_ITMP2, OFFSET(vftbl_t, diffval), REG_ITMP2);
3369 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3370                         codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3371 #endif
3372                                         }
3373                                         x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, REG_ITMP1);
3374                                         x86_64_jcc(cd, X86_64_CC_A, 0);    /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
3375                                         codegen_addxcastrefs(cd, cd->mcodeptr);
3376                                 }
3377
3378                         } else
3379                                 panic("internal error: no inlined array checkcast");
3380                         }
3381                         M_INTMOVE(s1, d);
3382                         store_reg_to_var_int(iptr->dst, d);
3383                         break;
3384
3385                 case ICMD_CHECKASIZE:  /* ..., size ==> ..., size                     */
3386
3387                         if (src->flags & INMEMORY) {
3388                                 x86_64_alul_imm_membase(cd, X86_64_CMP, 0, REG_SP, src->regoff * 8);
3389                                 
3390                         } else {
3391                                 x86_64_testl_reg_reg(cd, src->regoff, src->regoff);
3392                         }
3393                         x86_64_jcc(cd, X86_64_CC_L, 0);
3394                         codegen_addxcheckarefs(cd, cd->mcodeptr);
3395                         break;
3396
3397                 case ICMD_CHECKEXCEPTION:    /* ... ==> ...                           */
3398
3399                         x86_64_test_reg_reg(cd, REG_RESULT, REG_RESULT);
3400                         x86_64_jcc(cd, X86_64_CC_E, 0);
3401                         codegen_addxexceptionrefs(cd, cd->mcodeptr);
3402                         break;
3403
3404                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
3405                                          /* op1 = dimension, val.a = array descriptor */
3406
3407                         /* check for negative sizes and copy sizes to stack if necessary  */
3408
3409                         MCODECHECK((iptr->op1 << 1) + 64);
3410
3411                         for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3412                                 var_to_reg_int(s2, src, REG_ITMP1);
3413                                 x86_64_testl_reg_reg(cd, s2, s2);
3414                                 x86_64_jcc(cd, X86_64_CC_L, 0);
3415                                 codegen_addxcheckarefs(cd, cd->mcodeptr);
3416
3417                                 /* copy sizes to stack (argument numbers >= INT_ARG_CNT)      */
3418
3419                                 if (src->varkind != ARGVAR) {
3420                                         x86_64_mov_reg_membase(cd, s2, REG_SP, (s1 + INT_ARG_CNT) * 8);
3421                                 }
3422                         }
3423
3424                         /* a0 = dimension count */
3425                         x86_64_mov_imm_reg(cd, iptr->op1, rd->argintregs[0]);
3426
3427                         /* a1 = arraydescriptor */
3428                         x86_64_mov_imm_reg(cd, (s8) iptr->val.a, rd->argintregs[1]);
3429
3430                         /* a2 = pointer to dimensions = stack pointer */
3431                         x86_64_mov_reg_reg(cd, REG_SP, rd->argintregs[2]);
3432
3433                         x86_64_mov_imm_reg(cd, (s8) builtin_nmultianewarray, REG_ITMP1);
3434                         x86_64_call_reg(cd, REG_ITMP1);
3435
3436                         s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3437                         M_INTMOVE(REG_RESULT, s1);
3438                         store_reg_to_var_int(iptr->dst, s1);
3439                         break;
3440
3441                 default:
3442                         throw_cacao_exception_exit(string_java_lang_InternalError,
3443                                                                            "Unknown ICMD %d", iptr->opc);
3444         } /* switch */
3445                 
3446         } /* for instruction */
3447                 
3448         /* copy values to interface registers */
3449
3450         src = bptr->outstack;
3451         len = bptr->outdepth;
3452         MCODECHECK(64 + len);
3453         while (src) {
3454                 len--;
3455                 if ((src->varkind != STACKVAR)) {
3456                         s2 = src->type;
3457                         if (IS_FLT_DBL_TYPE(s2)) {
3458                                 var_to_reg_flt(s1, src, REG_FTMP1);
3459                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3460                                         M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3461
3462                                 } else {
3463                                         x86_64_movq_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3464                                 }
3465
3466                         } else {
3467                                 var_to_reg_int(s1, src, REG_ITMP1);
3468                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3469                                         M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3470
3471                                 } else {
3472                                         x86_64_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3473                                 }
3474                         }
3475                 }
3476                 src = src->prev;
3477         }
3478         } /* if (bptr -> flags >= BBREACHED) */
3479         } /* for basic block */
3480
3481         {
3482
3483         /* generate bound check stubs */
3484
3485         u1 *xcodeptr = NULL;
3486         branchref *bref;
3487
3488         for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3489                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3490                                   bref->branchpos,
3491                                                   cd->mcodeptr - cd->mcodebase);
3492
3493                 MCODECHECK(50);
3494
3495                 /* move index register into REG_ITMP1 */
3496                 x86_64_mov_reg_reg(cd, bref->reg, REG_ITMP1);              /* 3 bytes  */
3497
3498                 x86_64_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                  /* 10 bytes */
3499                 dseg_adddata(cd, cd->mcodeptr);
3500                 x86_64_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3);    /* 10 bytes */
3501                 x86_64_alu_reg_reg(cd, X86_64_ADD, REG_ITMP3, REG_ITMP2_XPC); /* 3 bytes  */
3502
3503                 if (xcodeptr != NULL) {
3504                         x86_64_jmp_imm(cd, xcodeptr - cd->mcodeptr - 5);
3505
3506                 } else {
3507                         xcodeptr = cd->mcodeptr;
3508
3509                         x86_64_alu_imm_reg(cd, X86_64_SUB, 2 * 8, REG_SP);
3510                         x86_64_mov_reg_membase(cd, REG_ITMP2_XPC, REG_SP, 0 * 8);
3511
3512                         x86_64_mov_reg_reg(cd, REG_ITMP1, rd->argintregs[0]);
3513                         x86_64_mov_imm_reg(cd, (s8) new_arrayindexoutofboundsexception, REG_ITMP3);
3514                         x86_64_call_reg(cd, REG_ITMP3);
3515
3516                         x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_ITMP2_XPC);
3517                         x86_64_alu_imm_reg(cd, X86_64_ADD, 2 * 8, REG_SP);
3518
3519                         x86_64_mov_imm_reg(cd, (s8) asm_handle_exception, REG_ITMP3);
3520                         x86_64_jmp_reg(cd, REG_ITMP3);
3521                 }
3522         }
3523
3524         /* generate negative array size check stubs */
3525
3526         xcodeptr = NULL;
3527         
3528         for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3529                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3530                         gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3531                                                           bref->branchpos,
3532                                                           xcodeptr - cd->mcodebase - (10 + 10 + 3));
3533                         continue;
3534                 }
3535
3536                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3537                                   bref->branchpos,
3538                                                   cd->mcodeptr - cd->mcodebase);
3539
3540                 MCODECHECK(50);
3541
3542                 x86_64_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                         /* 10 bytes */
3543                 dseg_adddata(cd, cd->mcodeptr);
3544                 x86_64_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3);    /* 10 bytes */
3545                 x86_64_alu_reg_reg(cd, X86_64_ADD, REG_ITMP3, REG_ITMP2_XPC);     /* 3 bytes  */
3546
3547                 if (xcodeptr != NULL) {
3548                         x86_64_jmp_imm(cd, xcodeptr - cd->mcodeptr - 5);
3549
3550                 } else {
3551                         xcodeptr = cd->mcodeptr;
3552
3553                         x86_64_alu_imm_reg(cd, X86_64_SUB, 2 * 8, REG_SP);
3554                         x86_64_mov_reg_membase(cd, REG_ITMP2_XPC, REG_SP, 0 * 8);
3555
3556                         x86_64_mov_imm_reg(cd, (s8) new_negativearraysizeexception, REG_ITMP3);
3557                         x86_64_call_reg(cd, REG_ITMP3);
3558
3559                         x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_ITMP2_XPC);
3560                         x86_64_alu_imm_reg(cd, X86_64_ADD, 2 * 8, REG_SP);
3561
3562                         x86_64_mov_imm_reg(cd, (s8) asm_handle_exception, REG_ITMP3);
3563                         x86_64_jmp_reg(cd, REG_ITMP3);
3564                 }
3565         }
3566
3567         /* generate cast check stubs */
3568
3569         xcodeptr = NULL;
3570         
3571         for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3572                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3573                         gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3574                                                           bref->branchpos,
3575                                                           xcodeptr - cd->mcodebase - (10 + 10 + 3));
3576                         continue;
3577                 }
3578
3579                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3580                                   bref->branchpos,
3581                                                   cd->mcodeptr - cd->mcodebase);
3582
3583                 MCODECHECK(50);
3584
3585                 x86_64_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                        /* 10 bytes */
3586                 dseg_adddata(cd, cd->mcodeptr);
3587                 x86_64_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3);     /* 10 bytes */
3588                 x86_64_alu_reg_reg(cd, X86_64_ADD, REG_ITMP3, REG_ITMP2_XPC);    /* 3 bytes  */
3589
3590                 if (xcodeptr != NULL) {
3591                         x86_64_jmp_imm(cd, xcodeptr - cd->mcodeptr - 5);
3592                 
3593                 } else {
3594                         xcodeptr = cd->mcodeptr;
3595
3596                         x86_64_alu_imm_reg(cd, X86_64_SUB, 2 * 8, REG_SP);
3597                         x86_64_mov_reg_membase(cd, REG_ITMP2_XPC, REG_SP, 0 * 8);
3598
3599                         x86_64_mov_imm_reg(cd, (s8) new_classcastexception, REG_ITMP3);
3600                         x86_64_call_reg(cd, REG_ITMP3);
3601
3602                         x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_ITMP2_XPC);
3603                         x86_64_alu_imm_reg(cd, X86_64_ADD, 2 * 8, REG_SP);
3604
3605                         x86_64_mov_imm_reg(cd, (s8) asm_handle_exception, REG_ITMP3);
3606                         x86_64_jmp_reg(cd, REG_ITMP3);
3607                 }
3608         }
3609
3610         /* generate divide by zero check stubs */
3611
3612         xcodeptr = NULL;
3613         
3614         for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3615                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3616                         gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3617                                                           bref->branchpos,
3618                                                           xcodeptr - cd->mcodebase - (10 + 10 + 3));
3619                         continue;
3620                 }
3621
3622                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3623                                   bref->branchpos,
3624                                                   cd->mcodeptr - cd->mcodebase);
3625
3626                 MCODECHECK(50);
3627
3628                 x86_64_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                        /* 10 bytes */
3629                 dseg_adddata(cd, cd->mcodeptr);
3630                 x86_64_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP3);      /* 10 bytes */
3631                 x86_64_alu_reg_reg(cd, X86_64_ADD, REG_ITMP3, REG_ITMP2_XPC);    /* 3 bytes  */
3632
3633                 if (xcodeptr != NULL) {
3634                         x86_64_jmp_imm(cd, xcodeptr - cd->mcodeptr - 5);
3635                 
3636                 } else {
3637                         xcodeptr = cd->mcodeptr;
3638
3639                         x86_64_alu_imm_reg(cd, X86_64_SUB, 2 * 8, REG_SP);
3640                         x86_64_mov_reg_membase(cd, REG_ITMP2_XPC, REG_SP, 0 * 8);
3641
3642                         x86_64_mov_imm_reg(cd, (u8) new_arithmeticexception, REG_ITMP3);
3643                         x86_64_call_reg(cd, REG_ITMP3);
3644
3645                         x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_ITMP2_XPC);
3646                         x86_64_alu_imm_reg(cd, X86_64_ADD, 2 * 8, REG_SP);
3647
3648                         x86_64_mov_imm_reg(cd, (u8) asm_handle_exception, REG_ITMP3);
3649                         x86_64_jmp_reg(cd, REG_ITMP3);
3650                 }
3651         }
3652
3653         /* generate exception check stubs */
3654
3655         xcodeptr = NULL;
3656         
3657         for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3658                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3659                         gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3660                                                           bref->branchpos,
3661                                                           xcodeptr - cd->mcodebase - (10 + 10 + 3));
3662                         continue;
3663                 }
3664
3665                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3666                                   bref->branchpos,
3667                                                   cd->mcodeptr - cd->mcodebase);
3668
3669                 MCODECHECK(50);
3670
3671                 x86_64_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                        /* 10 bytes */
3672                 dseg_adddata(cd, cd->mcodeptr);
3673                 x86_64_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1);     /* 10 bytes */
3674                 x86_64_alu_reg_reg(cd, X86_64_ADD, REG_ITMP1, REG_ITMP2_XPC);    /* 3 bytes  */
3675
3676                 if (xcodeptr != NULL) {
3677                         x86_64_jmp_imm(cd, xcodeptr - cd->mcodeptr - 5);
3678                 
3679                 } else {
3680                         xcodeptr = cd->mcodeptr;
3681
3682 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3683                         x86_64_alu_imm_reg(cd, X86_64_SUB, 8, REG_SP);
3684                         x86_64_mov_reg_membase(cd, REG_ITMP2_XPC, REG_SP, 0);
3685                         x86_64_mov_imm_reg(cd, (u8) &builtin_get_exceptionptrptr, REG_ITMP1);
3686                         x86_64_call_reg(cd, REG_ITMP1);
3687                         x86_64_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
3688                         x86_64_mov_imm_membase(cd, 0, REG_RESULT, 0);
3689                         x86_64_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
3690                         x86_64_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);
3691                         x86_64_alu_imm_reg(cd, X86_64_ADD, 8, REG_SP);
3692 #else
3693                         x86_64_mov_imm_reg(cd, (u8) &_exceptionptr, REG_ITMP3);
3694                         x86_64_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP1_XPTR);
3695                         x86_64_mov_imm_membase(cd, 0, REG_ITMP3, 0);
3696 #endif
3697
3698                         x86_64_mov_imm_reg(cd, (u8) asm_handle_exception, REG_ITMP3);
3699                         x86_64_jmp_reg(cd, REG_ITMP3);
3700                 }
3701         }
3702
3703         /* generate null pointer check stubs */
3704
3705         xcodeptr = NULL;
3706         
3707         for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3708                 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3709                         gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3710                                                           bref->branchpos,
3711                                                           xcodeptr - cd->mcodebase - (10 + 10 + 3));
3712                         continue;
3713                 }
3714
3715                 gen_resolvebranch(cd->mcodebase + bref->branchpos, 
3716                                   bref->branchpos,
3717                                                   cd->mcodeptr - cd->mcodebase);
3718
3719                 MCODECHECK(50);
3720
3721                 x86_64_mov_imm_reg(cd, 0, REG_ITMP2_XPC);                        /* 10 bytes */
3722                 dseg_adddata(cd, cd->mcodeptr);
3723                 x86_64_mov_imm_reg(cd, bref->branchpos - 6, REG_ITMP1);     /* 10 bytes */
3724                 x86_64_alu_reg_reg(cd, X86_64_ADD, REG_ITMP1, REG_ITMP2_XPC);    /* 3 bytes  */
3725
3726                 if (xcodeptr != NULL) {
3727                         x86_64_jmp_imm(cd, xcodeptr - cd->mcodeptr - 5);
3728                 
3729                 } else {
3730                         xcodeptr = cd->mcodeptr;
3731
3732                         x86_64_alu_imm_reg(cd, X86_64_SUB, 2 * 8, REG_SP);
3733                         x86_64_mov_reg_membase(cd, REG_ITMP2_XPC, REG_SP, 0 * 8);
3734
3735                         x86_64_mov_imm_reg(cd, (s8) new_nullpointerexception, REG_ITMP3);
3736                         x86_64_call_reg(cd, REG_ITMP3);
3737
3738                         x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_ITMP2_XPC);
3739                         x86_64_alu_imm_reg(cd, X86_64_ADD, 2 * 8, REG_SP);
3740
3741                         x86_64_mov_imm_reg(cd, (s8) asm_handle_exception, REG_ITMP3);
3742                         x86_64_jmp_reg(cd, REG_ITMP3);
3743                 }
3744         }
3745
3746         /* generate put/getstatic stub call code */
3747
3748         {
3749                 clinitref   *cref;
3750                 codegendata *tmpcd;
3751                 u1           xmcode;
3752                 u4           mcode;
3753
3754                 tmpcd = DNEW(codegendata);
3755
3756                 for (cref = cd->clinitrefs; cref != NULL; cref = cref->next) {
3757                         /* Get machine code which is patched back in later. A             */
3758                         /* `call rel32' is 5 bytes long.                                  */
3759                         xcodeptr = cd->mcodebase + cref->branchpos;
3760                         xmcode = *xcodeptr;
3761                         mcode = *((u4 *) (xcodeptr + 1));
3762
3763                         MCODECHECK(50);
3764
3765                         /* patch in `call rel32' to call the following code               */
3766                         tmpcd->mcodeptr = xcodeptr;     /* set dummy mcode pointer        */
3767                         x86_64_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
3768
3769                         /* Save current stack pointer into a temporary register.          */
3770                         x86_64_mov_reg_reg(cd, REG_SP, REG_ITMP1);
3771
3772                         /* Push machine code bytes to patch onto the stack.               */
3773                         x86_64_push_imm(cd, (u1) xmcode);
3774                         x86_64_push_imm(cd, (u4) mcode);
3775
3776                         x86_64_push_imm(cd, (u8) cref->class);
3777
3778                         /* Push previously saved stack pointer onto stack.                */
3779                         x86_64_push_reg(cd, REG_ITMP1);
3780
3781                         x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP1);
3782                         x86_64_jmp_reg(cd, REG_ITMP1);
3783                 }
3784         }
3785         }
3786
3787         codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
3788 }
3789
3790
3791 /* function createcompilerstub *************************************************
3792
3793         creates a stub routine which calls the compiler
3794         
3795 *******************************************************************************/
3796
3797 #define COMPSTUBSIZE 23
3798
3799 u1 *createcompilerstub(methodinfo *m)
3800 {
3801         u1 *s = CNEW(u1, COMPSTUBSIZE);     /* memory to hold the stub            */
3802         codegendata *cd;
3803         s4 dumpsize;
3804
3805         /* mark start of dump memory area */
3806
3807         dumpsize = dump_size();
3808
3809         cd = DNEW(codegendata);
3810         cd->mcodeptr = s;
3811
3812         /* code for the stub */
3813         x86_64_mov_imm_reg(cd, (u8) m, REG_ITMP1); /* pass method to compiler     */
3814         x86_64_mov_imm_reg(cd, (u8) asm_call_jit_compiler, REG_ITMP3);/* load address */
3815         x86_64_jmp_reg(cd, REG_ITMP3);      /* jump to compiler                   */
3816
3817 #if defined(STATISTICS)
3818         if (opt_stat)
3819                 count_cstub_len += COMPSTUBSIZE;
3820 #endif
3821
3822         /* release dump area */
3823
3824         dump_release(dumpsize);
3825
3826         return s;
3827 }
3828
3829
3830 /* function removecompilerstub *************************************************
3831
3832      deletes a compilerstub from memory  (simply by freeing it)
3833
3834 *******************************************************************************/
3835
3836 void removecompilerstub(u1 *stub) 
3837 {
3838         CFREE(stub, COMPSTUBSIZE);
3839 }
3840
3841
3842 /* function: createnativestub **************************************************
3843
3844         creates a stub routine which calls a native method
3845
3846 *******************************************************************************/
3847
3848 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3849 /* static java_objectheader **(*callgetexceptionptrptr)() = builtin_get_exceptionptrptr; */
3850 /* #endif */
3851
3852 #define NATIVESTUBSIZE 420
3853
3854 u1 *createnativestub(functionptr f, methodinfo *m)
3855 {
3856         u1 *s = CNEW(u1, NATIVESTUBSIZE);   /* memory to hold the stub            */
3857         s4 stackframesize;                  /* size of stackframe if needed       */
3858         codegendata *cd;
3859         registerdata *rd;
3860         t_inlining_globals *id;
3861         s4 dumpsize;
3862
3863         void **callAddrPatchPos=0;
3864         u1 *jmpInstrPos=0;
3865         void **jmpInstrPatchPos=0;
3866
3867         /* mark start of dump memory area */
3868
3869         dumpsize = dump_size();
3870
3871         cd = DNEW(codegendata);
3872         rd = DNEW(registerdata);
3873         id = DNEW(t_inlining_globals);
3874
3875         /* setup registers before using it */
3876
3877         inlining_setup(m, id);
3878         reg_setup(m, rd, id);
3879
3880         /* set some required varibles which are normally set by codegen_setup */
3881         cd->mcodebase = s;
3882         cd->mcodeptr = s;
3883         cd->clinitrefs = NULL;
3884
3885     descriptor2types(m);                /* set paramcount and paramtypes      */
3886
3887         /* if function is static, check for initialized */
3888
3889         if (m->flags & ACC_STATIC) {
3890                 /* if class isn't yet initialized, do it */
3891                 if (!m->class->initialized) {
3892                         codegen_addclinitref(cd, cd->mcodeptr, m->class);
3893                 }
3894         }
3895
3896
3897         x86_64_alu_imm_reg(cd, X86_64_SUB, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
3898
3899         x86_64_mov_reg_membase(cd, rd->argintregs[0], REG_SP, 1 * 8);
3900         x86_64_mov_reg_membase(cd, rd->argintregs[1], REG_SP, 2 * 8);
3901         x86_64_mov_reg_membase(cd, rd->argintregs[2], REG_SP, 3 * 8);
3902         x86_64_mov_reg_membase(cd, rd->argintregs[3], REG_SP, 4 * 8);
3903         x86_64_mov_reg_membase(cd, rd->argintregs[4], REG_SP, 5 * 8);
3904         x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 6 * 8);
3905
3906         x86_64_movq_reg_membase(cd, rd->argfltregs[0], REG_SP, 7 * 8);
3907         x86_64_movq_reg_membase(cd, rd->argfltregs[1], REG_SP, 8 * 8);
3908         x86_64_movq_reg_membase(cd, rd->argfltregs[2], REG_SP, 9 * 8);
3909         x86_64_movq_reg_membase(cd, rd->argfltregs[3], REG_SP, 10 * 8);
3910 /*              x86_64_movq_reg_membase(cd, rd->argfltregs[4], REG_SP, 11 * 8); */
3911 /*              x86_64_movq_reg_membase(cd, rd->argfltregs[5], REG_SP, 12 * 8); */
3912 /*              x86_64_movq_reg_membase(cd, rd->argfltregs[6], REG_SP, 13 * 8); */
3913 /*              x86_64_movq_reg_membase(cd, rd->argfltregs[7], REG_SP, 14 * 8); */
3914
3915         if (runverbose) {
3916                 s4 p, l, s1;
3917
3918                 /* show integer hex code for float arguments */
3919                 for (p = 0, l = 0; p < m->paramcount; p++) {
3920                         if (IS_FLT_DBL_TYPE(m->paramtypes[p])) {
3921                                 for (s1 = (m->paramcount > INT_ARG_CNT) ? INT_ARG_CNT - 2 : m->paramcount - 2; s1 >= p; s1--) {
3922                                         x86_64_mov_reg_reg(cd, rd->argintregs[s1], rd->argintregs[s1 + 1]);
3923                                 }
3924
3925                                 x86_64_movd_freg_reg(cd, rd->argfltregs[l], rd->argintregs[p]);
3926                                 l++;
3927                         }
3928                 }
3929
3930                 x86_64_mov_imm_reg(cd, (s8) m, REG_ITMP1);
3931                 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, 0 * 8);
3932                 x86_64_mov_imm_reg(cd, (s8) builtin_trace_args, REG_ITMP1);
3933                 x86_64_call_reg(cd, REG_ITMP1);
3934         }
3935 /* call method to resolve native function if needed */
3936 #ifndef STATIC_CLASSPATH
3937         if (f==0) { /* only if not already resolved */
3938                 x86_64_jmp_imm(cd,0);
3939                 jmpInstrPos=cd->mcodeptr-4; /*needed to patch a jump over this block*/
3940                 x86_64_mov_imm_reg(cd,(u8)m,rd->argintregs[0]);
3941                 x86_64_mov_imm_reg(cd,0,rd->argintregs[1]);
3942                 callAddrPatchPos=cd->mcodeptr-8; /* at this position the place is specified where the native function adress should be patched into*/
3943                 x86_64_mov_imm_reg(cd,0,rd->argintregs[2]);
3944                 jmpInstrPatchPos=cd->mcodeptr-8;
3945                 x86_64_mov_imm_reg(cd,jmpInstrPos,rd->argintregs[3]);
3946                 x86_64_mov_imm_reg(cd,(s8)codegen_resolve_native,REG_ITMP1);
3947                 x86_64_call_reg(cd,REG_ITMP1);
3948                 *(jmpInstrPatchPos)=cd->mcodeptr-jmpInstrPos-1; /*=opcode jmp_imm size*/
3949         }
3950 #endif
3951
3952         x86_64_mov_membase_reg(cd, REG_SP, 1 * 8, rd->argintregs[0]);
3953         x86_64_mov_membase_reg(cd, REG_SP, 2 * 8, rd->argintregs[1]);
3954         x86_64_mov_membase_reg(cd, REG_SP, 3 * 8, rd->argintregs[2]);
3955         x86_64_mov_membase_reg(cd, REG_SP, 4 * 8, rd->argintregs[3]);
3956         x86_64_mov_membase_reg(cd, REG_SP, 5 * 8, rd->argintregs[4]);
3957         x86_64_mov_membase_reg(cd, REG_SP, 6 * 8, rd->argintregs[5]);
3958
3959         x86_64_movq_membase_reg(cd, REG_SP, 7 * 8, rd->argfltregs[0]);
3960         x86_64_movq_membase_reg(cd, REG_SP, 8 * 8, rd->argfltregs[1]);
3961         x86_64_movq_membase_reg(cd, REG_SP, 9 * 8, rd->argfltregs[2]);
3962         x86_64_movq_membase_reg(cd, REG_SP, 10 * 8, rd->argfltregs[3]);
3963 /*              x86_64_movq_membase_reg(cd, REG_SP, 11 * 8, rd->argfltregs[4]); */
3964 /*              x86_64_movq_membase_reg(cd, REG_SP, 12 * 8, rd->argfltregs[5]); */
3965 /*              x86_64_movq_membase_reg(cd, REG_SP, 13 * 8, rd->argfltregs[6]); */
3966 /*              x86_64_movq_membase_reg(cd, REG_SP, 14 * 8, rd->argfltregs[7]); */
3967
3968         x86_64_alu_imm_reg(cd, X86_64_ADD, (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8, REG_SP);
3969         
3970
3971 #if 0
3972         x86_64_alu_imm_reg(cd, X86_64_SUB, 7 * 8, REG_SP);    /* keep stack 16-byte aligned */
3973
3974         /* save callee saved float registers */
3975         x86_64_movq_reg_membase(cd, XMM15, REG_SP, 0 * 8);
3976         x86_64_movq_reg_membase(cd, XMM14, REG_SP, 1 * 8);
3977         x86_64_movq_reg_membase(cd, XMM13, REG_SP, 2 * 8);
3978         x86_64_movq_reg_membase(cd, XMM12, REG_SP, 3 * 8);
3979         x86_64_movq_reg_membase(cd, XMM11, REG_SP, 4 * 8);
3980         x86_64_movq_reg_membase(cd, XMM10, REG_SP, 5 * 8);
3981 #endif
3982
3983         /* save argument registers on stack -- if we have to */
3984         if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
3985                 s4 i;
3986                 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3987                 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3988
3989                 stackframesize = stackparamcnt + paramshiftcnt;
3990
3991                 /* keep stack 16-byte aligned */
3992                 if (!(stackframesize & 0x1))
3993                         stackframesize++;
3994
3995                 x86_64_alu_imm_reg(cd, X86_64_SUB, stackframesize * 8, REG_SP);
3996
3997                 /* copy stack arguments into new stack frame -- if any */
3998                 for (i = 0; i < stackparamcnt; i++) {
3999                         x86_64_mov_membase_reg(cd, REG_SP, (stackparamcnt + 1 + i) * 8, REG_ITMP1);
4000                         x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
4001                 }
4002
4003                 if (m->flags & ACC_STATIC) {
4004                         x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 1 * 8);
4005                         x86_64_mov_reg_membase(cd, rd->argintregs[4], REG_SP, 0 * 8);
4006
4007                 } else {
4008                         x86_64_mov_reg_membase(cd, rd->argintregs[5], REG_SP, 0 * 8);
4009                 }
4010
4011         } else {
4012                 /* keep stack 16-byte aligned */
4013                 x86_64_alu_imm_reg(cd, X86_64_SUB, 8, REG_SP);
4014                 stackframesize = 1;
4015         }
4016
4017         if (m->flags & ACC_STATIC) {
4018                 x86_64_mov_reg_reg(cd, rd->argintregs[3], rd->argintregs[5]);
4019                 x86_64_mov_reg_reg(cd, rd->argintregs[2], rd->argintregs[4]);
4020                 x86_64_mov_reg_reg(cd, rd->argintregs[1], rd->argintregs[3]);
4021                 x86_64_mov_reg_reg(cd, rd->argintregs[0], rd->argintregs[2]);
4022
4023                 /* put class into second argument register */
4024                 x86_64_mov_imm_reg(cd, (u8) m->class, rd->argintregs[1]);
4025
4026         } else {
4027                 x86_64_mov_reg_reg(cd, rd->argintregs[4], rd->argintregs[5]);
4028                 x86_64_mov_reg_reg(cd, rd->argintregs[3], rd->argintregs[4]);
4029                 x86_64_mov_reg_reg(cd, rd->argintregs[2], rd->argintregs[3]);
4030                 x86_64_mov_reg_reg(cd, rd->argintregs[1], rd->argintregs[2]);
4031                 x86_64_mov_reg_reg(cd, rd->argintregs[0], rd->argintregs[1]);
4032         }
4033
4034         /* put env into first argument register */
4035         x86_64_mov_imm_reg(cd, (u8) &env, rd->argintregs[0]);
4036
4037         x86_64_mov_imm_reg(cd, (u8) f, REG_ITMP1);
4038 #ifndef STATIC_CLASSPATH
4039         if (f==0)
4040                 (*callAddrPatchPos)=cd->mcodeptr-8;
4041 #endif
4042         x86_64_call_reg(cd, REG_ITMP1);
4043
4044         /* remove stackframe if there is one */
4045         if (stackframesize) {
4046                 x86_64_alu_imm_reg(cd, X86_64_ADD, stackframesize * 8, REG_SP);
4047         }
4048
4049         if (runverbose) {
4050                 x86_64_alu_imm_reg(cd, X86_64_SUB, 3 * 8, REG_SP);    /* keep stack 16-byte aligned */
4051
4052                 x86_64_mov_reg_membase(cd, REG_RESULT, REG_SP, 0 * 8);
4053                 x86_64_movq_reg_membase(cd, REG_FRESULT, REG_SP, 1 * 8);
4054
4055                 x86_64_mov_imm_reg(cd, (u8) m, rd->argintregs[0]);
4056                 x86_64_mov_reg_reg(cd, REG_RESULT, rd->argintregs[1]);
4057                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4058                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4059
4060                 x86_64_mov_imm_reg(cd, (u8) builtin_displaymethodstop, REG_ITMP1);
4061                 x86_64_call_reg(cd, REG_ITMP1);
4062
4063                 x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_RESULT);
4064                 x86_64_movq_membase_reg(cd, REG_SP, 1 * 8, REG_FRESULT);
4065
4066                 x86_64_alu_imm_reg(cd, X86_64_ADD, 3 * 8, REG_SP);    /* keep stack 16-byte aligned */
4067         }
4068
4069 #if 0
4070         /* restore callee saved registers */
4071         x86_64_movq_membase_reg(cd, REG_SP, 0 * 8, XMM15);
4072         x86_64_movq_membase_reg(cd, REG_SP, 1 * 8, XMM14);
4073         x86_64_movq_membase_reg(cd, REG_SP, 2 * 8, XMM13);
4074         x86_64_movq_membase_reg(cd, REG_SP, 3 * 8, XMM12);
4075         x86_64_movq_membase_reg(cd, REG_SP, 4 * 8, XMM11);
4076         x86_64_movq_membase_reg(cd, REG_SP, 5 * 8, XMM10);
4077
4078         x86_64_alu_imm_reg(cd, X86_64_ADD, 7 * 8, REG_SP);    /* keep stack 16-byte aligned */
4079 #endif
4080
4081 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4082         x86_64_push_reg(cd, REG_RESULT);
4083 /*      x86_64_call_mem(cd, (u8) &callgetexceptionptrptr); */
4084         x86_64_mov_imm_reg(cd, (u8) builtin_get_exceptionptrptr, REG_ITMP3);
4085         x86_64_call_reg(cd, REG_ITMP3);
4086         x86_64_mov_membase_reg(cd, REG_RESULT, 0, REG_ITMP3);
4087         x86_64_pop_reg(cd, REG_RESULT);
4088 #else
4089         x86_64_mov_imm_reg(cd, (s8) &_exceptionptr, REG_ITMP3);
4090         x86_64_mov_membase_reg(cd, REG_ITMP3, 0, REG_ITMP3);
4091 #endif
4092         x86_64_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
4093         x86_64_jcc(cd, X86_64_CC_NE, 1);
4094
4095         x86_64_ret(cd);
4096
4097 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4098         x86_64_push_reg(cd, REG_ITMP3);
4099 /*      x86_64_call_mem(cd, (u8) &callgetexceptionptrptr); */
4100         x86_64_mov_imm_reg(cd, (u8) builtin_get_exceptionptrptr, REG_ITMP3);
4101         x86_64_call_reg(cd, REG_ITMP3);
4102         x86_64_mov_imm_membase(cd, 0, REG_RESULT, 0);
4103         x86_64_pop_reg(cd, REG_ITMP1_XPTR);
4104 #else
4105         x86_64_mov_reg_reg(cd, REG_ITMP3, REG_ITMP1_XPTR);
4106         x86_64_mov_imm_reg(cd, (s8) &_exceptionptr, REG_ITMP3);
4107         x86_64_alu_reg_reg(cd, X86_64_XOR, REG_ITMP2, REG_ITMP2);
4108         x86_64_mov_reg_membase(cd, REG_ITMP2, REG_ITMP3, 0);    /* clear exception pointer */
4109 #endif
4110
4111         x86_64_mov_membase_reg(cd, REG_SP, 0, REG_ITMP2_XPC);    /* get return address from stack */
4112         x86_64_alu_imm_reg(cd, X86_64_SUB, 3, REG_ITMP2_XPC);    /* callq */
4113
4114         x86_64_mov_imm_reg(cd, (s8) asm_handle_nat_exception, REG_ITMP3);
4115         x86_64_jmp_reg(cd, REG_ITMP3);
4116
4117         {
4118                 u1          *xcodeptr;
4119                 clinitref   *cref;
4120                 codegendata *tmpcd;
4121                 u1           xmcode;
4122                 u4           mcode;
4123
4124                 tmpcd = DNEW(codegendata);
4125
4126                 /* there can only be one clinit ref entry                             */
4127                 cref = cd->clinitrefs;
4128
4129                 if (cref) {
4130                         /* Get machine code which is patched back in later. A             */
4131                         /* `call rel32' is 5 bytes long.                                  */
4132                         xcodeptr = cd->mcodebase + cref->branchpos;
4133                         xmcode = *xcodeptr;
4134                         mcode = *((u4 *) (xcodeptr + 1));
4135
4136                         /* patch in `call rel32' to call the following code               */
4137                         tmpcd->mcodeptr = xcodeptr;     /* set dummy mcode pointer        */
4138                         x86_64_call_imm(tmpcd, cd->mcodeptr - (xcodeptr + 5));
4139
4140                         /* Save current stack pointer into a temporary register.          */
4141                         x86_64_mov_reg_reg(cd, REG_SP, REG_ITMP1);
4142
4143                         /* Push machine code bytes to patch onto the stack.               */
4144                         x86_64_push_imm(cd, (u1) xmcode);
4145                         x86_64_push_imm(cd, (u4) mcode);
4146
4147                         x86_64_push_imm(cd, (u8) cref->class);
4148
4149                         /* Push previously saved stack pointer onto stack.                */
4150                         x86_64_push_reg(cd, REG_ITMP1);
4151
4152                         x86_64_mov_imm_reg(cd, (u8) asm_check_clinit, REG_ITMP1);
4153                         x86_64_jmp_reg(cd, REG_ITMP1);
4154                 }
4155         }
4156
4157 #if 0
4158         {
4159                 static int stubprinted;
4160                 if (!stubprinted)
4161                         printf("stubsize: %d\n", ((long) cd->mcodeptr - (long) s));
4162                 stubprinted = 1;
4163         }
4164 #endif
4165
4166 #if defined(STATISTICS)
4167         if (opt_stat)
4168                 count_nstub_len += NATIVESTUBSIZE;
4169 #endif
4170
4171         /* release dump area */
4172
4173         dump_release(dumpsize);
4174
4175         return s;
4176 }
4177
4178
4179 /* function: removenativestub **************************************************
4180
4181     removes a previously created native-stub from memory
4182     
4183 *******************************************************************************/
4184
4185 void removenativestub(u1 *stub)
4186 {
4187         CFREE(stub, NATIVESTUBSIZE);
4188 }
4189
4190
4191 /*
4192  * These are local overrides for various environment variables in Emacs.
4193  * Please do not remove this and leave it at the end of the file, where
4194  * Emacs will automagically detect them.
4195  * ---------------------------------------------------------------------
4196  * Local variables:
4197  * mode: c
4198  * indent-tabs-mode: t
4199  * c-basic-offset: 4
4200  * tab-width: 4
4201  * End:
4202  */