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