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