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