* src/vm/vm.c (vm_array_store_int, vm_array_store_adr, vm_array_store_lng,
[cacao.git] / src / vm / jit / sparc64 / codegen.c
1 /* src/vm/jit/sparc64/codegen.c - machine code generator for Sparc
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: codegen.c 4644 2006-03-16 18:44:46Z edwin $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdio.h>
34
35 #include "vm/types.h"
36
37 #include "md-abi.h"
38
39 /* #include "vm/jit/sparc64/arch.h" */
40 #include "vm/jit/sparc64/codegen.h"
41
42 #include "mm/memory.h"
43
44 #include "native/jni.h"
45 #include "native/native.h"
46 #include "vm/builtin.h"
47 #include "vm/exceptions.h"
48 #include "vm/global.h"
49
50 #include "vm/jit/abi.h"
51 #include "vm/jit/asmpart.h"
52 #include "vm/jit/codegen-common.h"
53 #include "vm/jit/dseg.h"
54 #include "vm/jit/emit-common.h"
55 #include "vm/jit/sparc64/emit.h"
56 #include "vm/jit/jit.h"
57 #include "vm/jit/parse.h"
58 #include "vm/jit/patcher.h"
59 #include "vm/jit/reg.h"
60 #include "vm/jit/replace.h"
61 #include "vm/jit/stacktrace.h"
62 #include "vmcore/loader.h"
63 #include "vmcore/options.h"
64
65
66 #define BUILTIN_FLOAT_ARGS 1
67
68 /* XXX use something like this for window control ? 
69  * #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER)
70  */
71 #define REG_PV REG_PV_CALLEE
72
73 bool fits_13(s4 disp)
74 {
75         /*
76         if ((disp < -4096) || (disp > 4095))
77                 printf("disp %d\n", disp);
78         */
79
80         return (disp >= -4096) && (disp <= 4095);
81 }
82
83 s4 get_lopart_disp(disp)
84 {
85         s4 lodisp;
86         
87         if (disp > 0)
88                 lodisp = setlo_part(disp);
89         else {
90                 if (setlo_part(disp) == 0)
91                         lodisp = 0;
92                 else
93                         lodisp = setlo_part(disp) | 0x1c00;
94         }
95                 
96         return lodisp;
97 }
98         
99
100 /* codegen_emit ****************************************************************
101
102    Generates machine code.
103
104 *******************************************************************************/
105
106 bool codegen_emit(jitdata *jd)
107 {
108         methodinfo         *m;
109         codeinfo           *code;
110         codegendata        *cd;
111         registerdata       *rd;
112         s4                  len, s1, s2, s3, d, disp, slots;
113         varinfo            *var;
114         basicblock         *bptr;
115         instruction        *iptr;
116         exception_entry    *ex;
117         u2                  currentline;
118         constant_classref  *cr;
119         methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
120         unresolved_method  *um;
121         builtintable_entry *bte;
122         methoddesc         *md;
123         fieldinfo          *fi;
124         unresolved_field   *uf;
125         s4                  fieldtype;
126         s4                  varindex;
127
128         /* get required compiler data */
129
130         m  = jd->m;
131         code = jd->code;
132         cd = jd->cd;
133         rd = jd->rd;
134         
135         /* prevent compiler warnings */
136
137         d = 0;
138         currentline = 0;
139         lm = NULL;
140         bte = NULL;
141
142         {
143         s4 i, p, t, l;
144         s4 savedregs_num;
145
146 #if 0 /* no leaf optimization yet */
147         savedregs_num = (jd->isleafmethod) ? 0 : 1;       /* space to save the RA */
148 #endif
149         savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */ 
150
151
152         /* space to save used callee saved registers */
153
154         savedregs_num += (INT_SAV_CNT - rd->savintreguse);
155         savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
156
157         cd->stackframesize = rd->memuse + savedregs_num;
158
159 #if defined(ENABLE_THREADS)        /* space to save argument of monitor_enter */
160         if (checksync && (m->flags & ACC_SYNCHRONIZED))
161                 cd->stackframesize++;
162 #endif
163
164         /* keep stack 16-byte aligned (ABI requirement) */
165
166         if (cd->stackframesize & 1)
167                 cd->stackframesize++;
168
169         /* create method header */
170
171         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
172         (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
173
174 #if defined(ENABLE_THREADS)
175         /* IsSync contains the offset relative to the stack pointer for the
176            argument of monitor_exit used in the exception handler. Since the
177            offset could be zero and give a wrong meaning of the flag it is
178            offset by one.
179         */
180
181         if (checksync && (m->flags & ACC_SYNCHRONIZED))
182                 (void) dseg_add_unique_s4(cd, JITSTACK + (rd->memuse + 1) * 8); /* IsSync */
183         else
184 #endif
185                 (void) dseg_add_unique_s4(cd, 0);                  /* IsSync          */
186                                                
187         (void) dseg_add_unique_s4(cd, jd->isleafmethod);       /* IsLeaf          */
188         (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
189         (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
190         dseg_addlinenumbertablesize(cd);
191         (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize   */
192
193         /* create exception table */
194
195         for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
196                 dseg_add_target(cd, ex->start);
197                 dseg_add_target(cd, ex->end);
198                 dseg_add_target(cd, ex->handler);
199                 (void) dseg_add_unique_address(cd, ex->catchtype.any);
200         }
201
202         /* save register window and create stack frame (if necessary) */
203
204         if (cd->stackframesize)
205                 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
206
207
208         /* save callee saved float registers (none right now) */
209 #if 0
210         p = cd->stackframesize;
211         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
212                 p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
213         }
214 #endif
215
216 #if !defined(NDEBUG)
217         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
218                 emit_verbosecall_enter(jd);
219 #endif
220         
221         
222                 /* call monitorenter function */
223 #if defined(ENABLE_THREADS)
224         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
225                 /* stack offset for monitor argument */
226
227                 s1 = rd->memuse;
228
229                 /* save float argument registers */
230
231                 /* XXX jit-c-call */
232                 slots = FLT_ARG_CNT;
233                 ALIGN_STACK_SLOTS(slots);
234
235                 M_LDA(REG_SP, REG_SP, -(slots * 8));
236                 for (i = 0; i < FLT_ARG_CNT; i++)
237                         M_DST(abi_registers_float_argument[i], REG_SP, CSTACK +  i * 8);
238
239                 s1 += slots;
240
241                 /* get correct lock object */
242
243                 if (m->flags & ACC_STATIC) {
244                         disp = dseg_add_address(cd, &m->class->object.header);
245                         M_ALD(REG_OUT0, REG_PV, disp);
246                         disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
247                         M_ALD(REG_ITMP3, REG_PV, disp);
248                 }
249                 else {
250                         /* copy class pointer: $i0 -> $o0 */
251                         M_MOV(REG_RESULT_CALLEE, REG_OUT0);
252                         M_BNEZ(REG_OUT0, 3);
253                         disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
254                         M_ALD(REG_ITMP3, REG_PV, disp);                   /* branch delay */
255                         M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
256                 }
257
258                 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
259                 M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8);             /* branch delay */
260
261                 /* restore float argument registers */
262
263                 for (i = 0; i < FLT_ARG_CNT; i++)
264                         M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
265
266                 M_LDA(REG_SP, REG_SP, slots * 8);
267         }
268 #endif
269
270
271         /* take arguments out of register or stack frame */
272         
273         md = m->parseddesc;
274
275         for (p = 0, l = 0; p < md->paramcount; p++) {
276                 t = md->paramtypes[p].type;
277
278                 varindex = jd->local_map[l * 5 + t];
279
280                 l++;
281                 if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
282                         l++;
283
284                 if (varindex == UNUSED)
285                         continue;
286
287                 var = VAR(varindex);
288                 s1 = md->params[p].regoff;
289                 
290                 if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */                        
291
292                         s2 = var->vv.regoff;
293                         
294                         if (!md->params[p].inmemory) {           /* register arguments    */
295                                 s1 = REG_WINDOW_TRANSPOSE(s1);
296                                 
297                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
298
299                                         /* the register allocator does not know about the window. */
300                                         /* avoid copying the locals from save to save regs by     */
301                                         /* swapping variables.                                    */
302
303                                         {
304                                         int old_dest = var->vv.regoff;
305                                         int new_dest = p + 24;
306
307                                         /* run through all variables */
308
309                                         for (i = 0; i < jd->varcount; i++) {
310                                                 varinfo* uvar = VAR(i);
311
312                                                 if (IS_FLT_DBL_TYPE(uvar->type))
313                                                         continue;
314
315                                                 s2 = uvar->vv.regoff;
316
317                                                 /* free the in reg by moving all other references */
318
319                                                 if (s2 == new_dest) {
320                                                         uvar->vv.regoff = old_dest;
321                                                         /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
322                                                 }
323
324                                                 /* move all variables to the in reg */
325
326                                                 if (s2 == old_dest) {
327                                                         uvar->vv.regoff = new_dest;
328                                                         /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
329                                                 }
330                                         }
331                                         }
332
333
334
335                                 } 
336                                 else {                             /* reg arg -> spilled    */
337                                         M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
338                                 }
339
340                         } else {                                 /* stack arguments       */
341                                 if (!(var->flags & INMEMORY)) {      /* stack arg -> register */
342                                         M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1);
343
344                                 } else {                             /* stack arg -> spilled  */
345                                         /* add the callers window save registers */
346                                         var->vv.regoff = cd->stackframesize * 8 + s1;
347                                 }
348                         }
349                 
350                 } else {                                     /* floating args         */
351                         if (!md->params[p].inmemory) {           /* register arguments    */
352                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
353                                         M_FLTMOVE(s1, var->vv.regoff);
354
355                                 } else {                                         /* reg arg -> spilled    */
356                                         M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
357                                 }
358
359                         } else {                                 /* stack arguments       */
360                                 if (!(var->flags & INMEMORY)) {      /* stack-arg -> register */
361                                         M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1);
362
363                                 } else {                             /* stack-arg -> spilled  */
364                                         var->vv.regoff = cd->stackframesize * 8 + s1;
365                                 }
366                         }
367                 }
368         } /* end for */
369         
370         
371         }
372         
373         /* end of header generation */ 
374         
375         /* create replacement points */
376
377         REPLACEMENT_POINTS_INIT(cd, jd);
378
379         /* walk through all basic blocks */
380
381         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
382
383                 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
384
385                 if (bptr->flags >= BBREACHED) {
386
387                 /* branch resolving */
388
389                 codegen_resolve_branchrefs(cd, bptr);
390                 
391                 /* handle replacement points */
392
393 #if 0
394                 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
395                         replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
396                         
397                         replacementpoint++;
398                 }
399 #endif
400
401                 /* copy interface registers to their destination */
402
403                 len = bptr->indepth;
404                 MCODECHECK(64+len);
405                 
406 #if defined(ENABLE_LSRA)
407 #error XXX LSRA not tested yet
408                 if (opt_lsra) {
409                 while (len) {
410                         len--;
411                         src = bptr->invars[len];
412                         if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
413                                         /*                              d = reg_of_var(m, src, REG_ITMP1); */
414                                         if (!(src->flags & INMEMORY))
415                                                 d = src->vv.regoff;
416                                         else
417                                                 d = REG_ITMP1;
418                                         M_INTMOVE(REG_ITMP1, d);
419                                         emit_store(jd, NULL, src, d);
420                                 }
421                         }
422                 } else {
423 #endif
424                 while (len) {
425                         len--;
426                         var = VAR(bptr->invars[len]);
427                         if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
428                                 d = codegen_reg_of_var(0, var, REG_ITMP1);
429                                 M_INTMOVE(REG_ITMP2_XPTR, d);
430                                 emit_store(jd, NULL, var, d);
431                         }
432                         else {
433                                 assert((var->flags & INOUT));
434                         }
435                 }
436 #if defined(ENABLE_LSRA)
437                 }
438 #endif
439                 /* walk through all instructions */
440                 
441                 len = bptr->icount;
442
443                 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
444                         if (iptr->line != currentline) {
445                                 dseg_addlinenumber(cd, iptr->line);
446                                 currentline = iptr->line;
447                         }
448
449                 MCODECHECK(64);       /* an instruction usually needs < 64 words      */
450
451                 switch (iptr->opc) {
452
453                 case ICMD_INLINE_START:
454                 case ICMD_INLINE_END:
455                         break;
456
457                 case ICMD_NOP:        /* ...  ==> ...                                 */
458                         break;
459
460                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
461
462                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
463                         emit_nullpointer_check(cd, iptr, s1);
464                         break;
465         
466                 /* constant operations ************************************************/
467
468                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
469
470                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
471                         ICONST(d, iptr->sx.val.i);
472                         emit_store_dst(jd, iptr, d);
473                         break;
474
475                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
476
477                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
478                         LCONST(d, iptr->sx.val.l);
479                         emit_store_dst(jd, iptr, d);
480                         break;  
481
482                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
483
484                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
485                         disp = dseg_add_float(cd, iptr->sx.val.f);
486                         M_FLD(d, REG_PV, disp);
487                         emit_store_dst(jd, iptr, d);
488                         break;
489                         
490                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
491
492                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
493                         disp = dseg_add_double(cd, iptr->sx.val.d);
494                         M_DLD(d, REG_PV, disp);
495                         emit_store_dst(jd, iptr, d);
496                         break;
497
498                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
499
500                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
501
502                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
503                                 cr   = iptr->sx.val.c.ref;
504                                 disp = dseg_add_unique_address(cd, cr);
505
506                                 codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
507
508                                 M_ALD(d, REG_PV, disp);
509
510                         } 
511                         else {
512                                 if (iptr->sx.val.anyptr == NULL) {
513                                         M_INTMOVE(REG_ZERO, d);
514                                 } 
515                                 else {
516                                         disp = dseg_add_address(cd, iptr->sx.val.anyptr);
517                                         M_ALD(d, REG_PV, disp);
518                                 }
519                         }
520                         emit_store_dst(jd, iptr, d);
521                         break;
522
523
524                 /* load/store/copy/move operations ************************************/
525
526                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
527                 case ICMD_LLOAD:
528                 case ICMD_ALOAD:
529                 case ICMD_FLOAD:
530                 case ICMD_DLOAD:
531                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
532                 case ICMD_LSTORE:
533                 case ICMD_FSTORE:
534                 case ICMD_DSTORE:
535                 case ICMD_COPY:
536                 case ICMD_MOVE:
537
538                         emit_copy(jd, iptr);
539                         break;
540         
541                 case ICMD_ASTORE:
542                         if (!(iptr->flags.bits & INS_FLAG_RETADDR))
543                                 emit_copy(jd, iptr);
544                         break;
545
546
547                 /* pop/dup/swap operations ********************************************/
548
549                 /* attention: double and longs are only one entry in CACAO ICMDs      */
550
551                 case ICMD_POP:        /* ..., value  ==> ...                          */
552                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
553                         break;
554
555
556                 /* integer operations *************************************************/
557
558                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
559                 case ICMD_LNEG:
560
561                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
562                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
563                         M_SUB(REG_ZERO, s1, d);
564                         emit_store_dst(jd, iptr, d);
565                         break;
566
567                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
568
569                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
570                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
571                         M_INTMOVE(s1, d);
572                         emit_store_dst(jd, iptr, d);
573                         break;
574
575                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
576
577                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
578                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
579                         M_SRA_IMM(s1, 0, d); /* sign extend upper 32 bits */
580                         emit_store_dst(jd, iptr, d);
581                         break;
582
583                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
584
585                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
586                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
587                         M_SLLX_IMM(s1, 56, d);
588                         M_SRAX_IMM( d, 56, d);
589                         emit_store_dst(jd, iptr, d);
590                         break;
591
592                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
593                 
594                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
595                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
596                         M_SLLX_IMM(s1, 48, d);
597                         M_SRLX_IMM( d, 48, d);
598                         emit_store_dst(jd, iptr, d);
599                         break;
600                         
601                 case ICMD_INT2SHORT:   /* ..., value  ==> ..., value                   */
602
603                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
604                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
605                         M_SLLX_IMM(s1, 48, d);
606                         M_SRAX_IMM( d, 48, d);
607                         emit_store_dst(jd, iptr, d);
608                         break;
609
610                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
611                 case ICMD_LADD:
612
613                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
614                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
615                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
616                         M_ADD(s1, s2, d);
617                         emit_store_dst(jd, iptr, d);
618                         break;
619
620                 case ICMD_IINC:
621                 case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
622                                       /* sx.val.i = constant                             */
623
624                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
625                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
626                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
627                                 M_ADD_IMM(s1, iptr->sx.val.i, d);
628                         } else {
629                                 ICONST(REG_ITMP2, iptr->sx.val.i);
630                                 M_ADD(s1, REG_ITMP2, d);
631                         }
632                         emit_store_dst(jd, iptr, d);
633                         break;
634
635                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
636                                       /* sx.val.l = constant                             */
637
638                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
639                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
640                         if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
641                                 M_ADD_IMM(s1, iptr->sx.val.l, d);
642                         } else {
643                                 LCONST(REG_ITMP2, iptr->sx.val.l);
644                                 M_ADD(s1, REG_ITMP2, d);
645                         }
646                         emit_store_dst(jd, iptr, d);
647                         break;
648
649                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
650                 case ICMD_LSUB: 
651
652                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
653                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
654                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
655                         M_SUB(s1, s2, d);
656                         emit_store_dst(jd, iptr, d);
657                         break;
658
659                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
660                                       /* sx.val.i = constant                             */
661
662                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
663                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
664                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
665                                 M_SUB_IMM(s1, iptr->sx.val.i, d);
666                         } else {
667                                 ICONST(REG_ITMP2, iptr->sx.val.i);
668                                 M_SUB(s1, REG_ITMP2, d);
669                         }
670                         emit_store_dst(jd, iptr, d);
671                         break;
672
673                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
674                                       /* sx.val.l = constant                             */
675
676                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
677                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
678                         if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
679                                 M_SUB_IMM(s1, iptr->sx.val.l, d);
680                         } else {
681                                 LCONST(REG_ITMP2, iptr->sx.val.l);
682                                 M_SUB(s1, REG_ITMP2, d);
683                         }
684                         emit_store_dst(jd, iptr, d);
685                         break;
686
687                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
688                 case ICMD_LMUL:
689
690                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
691                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
692                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
693                         M_MULX(s1, s2, d);
694                         emit_store_dst(jd, iptr, d);
695                         break;
696
697                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
698                                       /* sx.val.i = constant                             */
699
700                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
701                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
702                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
703                                 M_MULX_IMM(s1, iptr->sx.val.i, d);
704                         } else {
705                                 ICONST(REG_ITMP2, iptr->sx.val.i);
706                                 M_MULX(s1, REG_ITMP2, d);
707                         }
708                         emit_store_dst(jd, iptr, d);
709                         break;
710
711                 case ICMD_LMULCONST:  /* ..., value  ==> ..., value * constant        */
712                                       /* sx.val.l = constant                             */
713
714                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
715                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
716                         if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
717                                 M_MULX_IMM(s1, iptr->sx.val.l, d);
718                         } else {
719                                 LCONST(REG_ITMP2, iptr->sx.val.l);
720                                 M_MULX(s1, REG_ITMP2, d);
721                         }
722                         emit_store_dst(jd, iptr, d);
723                         break;
724
725                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
726 /* XXX could also clear Y and use 32bit div */
727                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
728                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
729                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
730                         emit_arithmetic_check(cd, iptr, s2);
731                         M_ISEXT(s1, s1);
732                         /* XXX trim s2 like s1 ? */
733                         M_DIVX(s1, s2, d);
734                         emit_store_dst(jd, iptr, d);
735                         break;
736
737                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
738
739                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
740                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
741                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
742                         emit_arithmetic_check(cd, iptr, s2);
743                         M_DIVX(s1, s2, d);
744                         emit_store_dst(jd, iptr, d);
745                         break;
746
747                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
748
749                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
750                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
751                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
752                         emit_arithmetic_check(cd, iptr, s2);
753                         M_ISEXT(s1, s1);
754                         /* XXX trim s2 like s1 ? */
755                         M_DIVX(s1, s2, REG_ITMP3);
756                         M_MULX(s2, REG_ITMP3, REG_ITMP3);
757                         M_SUB(s1, REG_ITMP3, d);
758                         emit_store_dst(jd, iptr, d);
759                         break;
760
761                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
762
763                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
764                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
765                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
766                         emit_arithmetic_check(cd, iptr, s2);
767                         M_DIVX(s1, s2, REG_ITMP3);
768                         M_MULX(s2, REG_ITMP3, REG_ITMP3);
769                         M_SUB(s1, REG_ITMP3, d);
770                         emit_store_dst(jd, iptr, d);
771                         break;
772
773                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
774                 case ICMD_LDIVPOW2:   /* val.i = constant                             */
775                                       
776                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
777                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
778                         M_SRAX_IMM(s1, 63, REG_ITMP2);
779                         M_SRLX_IMM(REG_ITMP2, 64 - iptr->sx.val.i, REG_ITMP2);
780                         M_ADD(s1, REG_ITMP2, REG_ITMP2);
781                         M_SRAX_IMM(REG_ITMP2, iptr->sx.val.i, d);
782                         emit_store_dst(jd, iptr, d);
783                         break;
784
785                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
786
787                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
788                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
789                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
790                         M_SLL(s1, s2, d);
791                         emit_store_dst(jd, iptr, d);
792                         break;
793                         
794                 case ICMD_LSHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
795
796                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
797                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
798                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
799                         M_SLLX(s1, s2, d);
800                         emit_store_dst(jd, iptr, d);
801                         break;
802
803                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
804                                       /* val.i = constant                             */
805
806                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
807                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
808                         M_SLL_IMM(s1, iptr->sx.val.i, d);
809                         emit_store_dst(jd, iptr, d);
810                         break;
811                         
812                 case ICMD_LSHLCONST:  /* ..., value  ==> ..., value << constant       */
813                                       /* val.i = constant                             */
814
815                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
816                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
817                         M_SLLX_IMM(s1, iptr->sx.val.i, d);
818                         emit_store_dst(jd, iptr, d);
819                         break;
820
821                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
822
823                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
824                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
825                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
826                         M_SRA(s1, s2, d);
827                         emit_store_dst(jd, iptr, d);
828                         break;
829
830                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
831                                       /* sx.val.i = constant                             */
832
833                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
834                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
835                         M_SRA_IMM(s1, iptr->sx.val.i, d);
836                         emit_store_dst(jd, iptr, d);
837                         break;
838
839                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
840
841                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
842                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
843                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
844                         M_SRL(s1, s2, d);
845                         emit_store_dst(jd, iptr, d);
846                         break;
847
848                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
849                                       /* sx.val.i = constant                             */
850
851                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
852                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
853                         M_SRL_IMM(s1, iptr->sx.val.i, d);
854                         emit_store_dst(jd, iptr, d);
855                         break;
856
857                 case ICMD_LSHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
858
859                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
860                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
861                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
862                         M_SRAX(s1, s2, d);
863                         emit_store_dst(jd, iptr, d);
864                         break;
865
866                 case ICMD_LSHRCONST:  /* ..., value  ==> ..., value >> constant       */
867                                       /* sx.val.i = constant                             */
868
869                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
870                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
871                         M_SRAX_IMM(s1, iptr->sx.val.i, d);
872                         emit_store_dst(jd, iptr, d);
873                         break;
874
875                 case ICMD_LUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
876
877                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
878                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
879                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
880                         M_SRLX(s1, s2, d);
881                         emit_store_dst(jd, iptr, d);
882                         break;
883
884                 case ICMD_LUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
885                                       /* sx.val.i = constant                             */
886
887                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
888                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
889                         M_SRLX_IMM(s1, iptr->sx.val.i, d);
890                         emit_store_dst(jd, iptr, d);
891                         break;
892
893                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
894                 case ICMD_LAND:
895
896                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
897                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
898                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
899                         M_AND(s1, s2, d);
900                         emit_store_dst(jd, iptr, d);
901                         break;
902
903                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
904                                       /* sx.val.i = constant                             */
905
906                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
907                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
908                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
909                                 M_AND_IMM(s1, iptr->sx.val.i, d);
910                         } else {
911                                 ICONST(REG_ITMP2, iptr->sx.val.i);
912                                 M_AND(s1, REG_ITMP2, d);
913                         }
914                         emit_store_dst(jd, iptr, d);
915                         break;
916
917                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant           */
918                                       /* sx.val.i = constant                             */
919                                       /* constant is actually constant - 1               */
920
921                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
922                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
923                         if (s1 == d) {
924                                 M_MOV(s1, REG_ITMP1);
925                                 s1 = REG_ITMP1;
926                         }
927                         M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
928                         if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
929                                 M_AND_IMM(s1, iptr->sx.val.i, d);
930                                 M_BGEZ(s1, 5);
931                                 M_NOP;
932                                 M_SUB(REG_ZERO, s1, d);
933                                 M_AND_IMM(d, iptr->sx.val.i, d);
934                         } else {
935                                 ICONST(REG_ITMP2, iptr->sx.val.i);
936                                 M_AND(s1, REG_ITMP2, d);
937                                 M_BGEZ(s1, 5);
938                                 M_NOP;
939                                 M_SUB(REG_ZERO, s1, d);
940                                 M_AND(d, REG_ITMP2, d);
941                         }
942                         M_SUB(REG_ZERO, d, d);
943                         emit_store_dst(jd, iptr, d);
944                         break;
945
946                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
947                                       /* sx.val.l = constant                             */
948
949                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
950                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
951                         if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
952                                 M_AND_IMM(s1, iptr->sx.val.l, d);
953                         } else {
954                                 LCONST(REG_ITMP2, iptr->sx.val.l);
955                                 M_AND(s1, REG_ITMP2, d);
956                         }
957                         emit_store_dst(jd, iptr, d);
958                         break;
959
960                 case ICMD_LREMPOW2:   /* ..., value  ==> ..., value % constant        */
961                                       /* sx.val.l = constant                             */
962
963                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
964                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
965                         if (s1 == d) {
966                                 M_MOV(s1, REG_ITMP1);
967                                 s1 = REG_ITMP1;
968                         }
969                         if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
970                                 M_AND_IMM(s1, iptr->sx.val.l, d);
971                                 M_BGEZ(s1, 4);
972                                 M_NOP;
973                                 M_SUB(REG_ZERO, s1, d);
974                                 M_AND_IMM(d, iptr->sx.val.l, d);
975                         } else {
976                                 LCONST(REG_ITMP2, iptr->sx.val.l);
977                                 M_AND(s1, REG_ITMP2, d);
978                                 M_BGEZ(s1, 4);
979                                 M_NOP;
980                                 M_SUB(REG_ZERO, s1, d);
981                                 M_AND(d, REG_ITMP2, d);
982                         }
983                         M_SUB(REG_ZERO, d, d);
984                         emit_store_dst(jd, iptr, d);
985                         break;
986
987                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
988                 case ICMD_LOR:
989
990                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
991                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
992                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
993                         M_OR(s1,s2, d);
994                         emit_store_dst(jd, iptr, d);
995                         break;
996
997                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
998                                       /* sx.val.i = constant                             */
999
1000                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1001                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1002                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1003                                 M_OR_IMM(s1, iptr->sx.val.i, d);
1004                         } else {
1005                                 ICONST(REG_ITMP2, iptr->sx.val.i);
1006                                 M_OR(s1, REG_ITMP2, d);
1007                         }
1008                         emit_store_dst(jd, iptr, d);
1009                         break;
1010
1011                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
1012                                       /* sx.val.l = constant                             */
1013
1014                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1015                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1016                         if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1017                                 M_OR_IMM(s1, iptr->sx.val.l, d);
1018                         } else {
1019                                 LCONST(REG_ITMP2, iptr->sx.val.l);
1020                                 M_OR(s1, REG_ITMP2, d);
1021                         }
1022                         emit_store_dst(jd, iptr, d);
1023                         break;
1024
1025                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1026                 case ICMD_LXOR:
1027
1028                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1029                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1030                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1031                         M_XOR(s1, s2, d);
1032                         emit_store_dst(jd, iptr, d);
1033                         break;
1034
1035                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1036                                       /* sx.val.i = constant                             */
1037
1038                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1039                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1040                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1041                                 M_XOR_IMM(s1, iptr->sx.val.i, d);
1042                         } else {
1043                                 ICONST(REG_ITMP2, iptr->sx.val.i);
1044                                 M_XOR(s1, REG_ITMP2, d);
1045                         }
1046                         emit_store_dst(jd, iptr, d);
1047                         break;
1048
1049                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1050                                       /* sx.val.l = constant                             */
1051
1052                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1053                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1054                         if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1055                                 M_XOR_IMM(s1, iptr->sx.val.l, d);
1056                         } else {
1057                                 LCONST(REG_ITMP2, iptr->sx.val.l);
1058                                 M_XOR(s1, REG_ITMP2, d);
1059                         }
1060                         emit_store_dst(jd, iptr, d);
1061                         break;
1062
1063
1064                 case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
1065
1066                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1067                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1068                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1069                         M_CMP(s1, s2);
1070                         M_MOV(REG_ZERO, d);
1071                         M_XCMOVLT_IMM(-1, d);
1072                         M_XCMOVGT_IMM(1, d);
1073                         emit_store_dst(jd, iptr, d);
1074                         break;
1075
1076
1077                 /* floating operations ************************************************/
1078
1079                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
1080
1081                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1082                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1083                         M_FNEG(s1, d);
1084                         emit_store_dst(jd, iptr, d);
1085                         break;
1086
1087                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
1088
1089                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1090                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1091                         M_DNEG(s1, d);
1092                         emit_store_dst(jd, iptr, d);
1093                         break;
1094
1095                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1096
1097                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1098                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1099                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1100                         M_FADD(s1, s2, d);
1101                         emit_store_dst(jd, iptr, d);
1102                         break;
1103
1104                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1105
1106                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1107                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1108                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1109                         M_DADD(s1, s2, d);
1110                         emit_store_dst(jd, iptr, d);
1111                         break;
1112
1113                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1114
1115                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1116                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1117                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1118                         M_FSUB(s1, s2, d);
1119                         emit_store_dst(jd, iptr, d);
1120                         break;
1121
1122                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1123
1124                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1125                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1126                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1127                         M_DSUB(s1, s2, d);
1128                         emit_store_dst(jd, iptr, d);
1129                         break;
1130
1131                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1132
1133                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1134                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1135                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1136                         M_FMUL(s1, s2, d);
1137                         emit_store_dst(jd, iptr, d);
1138                         break;
1139
1140                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 *** val2      */
1141
1142                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1143                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1144                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1145                         M_DMUL(s1, s2, d);
1146                         emit_store_dst(jd, iptr, d);
1147                         break;
1148
1149                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1150
1151                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1152                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1153                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1154                         M_FDIV(s1, s2, d);
1155                         emit_store_dst(jd, iptr, d);
1156                         break;
1157
1158                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1159
1160                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1161                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1162                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1163                         M_DDIV(s1, s2, d);
1164                         emit_store_dst(jd, iptr, d);
1165                         break;  
1166
1167                 case ICMD_I2F:
1168                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1169                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1170                         disp = dseg_add_unique_float(cd, 0.0);
1171                         M_IST (s1, REG_PV_CALLEE, disp);
1172                         M_FLD (d, REG_PV_CALLEE, disp);
1173                         M_CVTIF (d, d); /* rd gets translated to double target register */
1174                         emit_store_dst(jd, iptr, d);
1175                         break;
1176                         
1177                 case ICMD_I2D:
1178                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1179                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1180                         disp = dseg_add_unique_float(cd, 0.0);
1181                         M_IST(s1, REG_PV_CALLEE, disp);
1182                         M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
1183                         M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
1184                         emit_store_dst(jd, iptr, d);
1185                         break;
1186                         
1187                 case ICMD_L2F:
1188                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1189                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1190                         disp = dseg_add_unique_double(cd, 0.0);
1191                         M_STX(s1, REG_PV_CALLEE, disp);
1192                         M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
1193                         M_CVTLF(REG_FTMP3, d);
1194                         emit_store_dst(jd, iptr, d);
1195                         break;
1196                         
1197                 case ICMD_L2D:
1198                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1199                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1200                         disp = dseg_add_unique_double(cd, 0.0);
1201                         M_STX(s1, REG_PV_CALLEE, disp);
1202                         M_DLD(d, REG_PV_CALLEE, disp);
1203                         M_CVTLD(d, d);
1204                         emit_store_dst(jd, iptr, d);
1205                         break;
1206
1207                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1208                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1209                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1210                         disp = dseg_add_unique_float(cd, 0.0);
1211                         
1212                         /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5)  */
1213                         M_FCMP(s1, s1);
1214                         M_FBU(5);
1215                         M_MOV(REG_ZERO, d); /* delay slot */
1216                         
1217                         M_CVTFI(s1, REG_FTMP2);
1218                         M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
1219                         M_ILD(d, REG_PV, disp);
1220                         emit_store_dst(jd, iptr, d);
1221                         break;
1222                         
1223                                
1224                 case ICMD_D2I:       /* ..., value  ==> ..., (int) value             */
1225                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1226                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1227                         disp = dseg_add_unique_float(cd, 0.0);
1228                         
1229                         /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5)  */
1230                         M_DCMP(s1, s1);
1231                         M_FBU(5);
1232                         M_MOV(REG_ZERO, d); /* delay slot */
1233                         
1234                         M_CVTDI(s1, REG_FTMP2);
1235                         M_FST(REG_FTMP2, REG_PV, disp);
1236                         M_ILD(d, REG_PV, disp);
1237                         emit_store_dst(jd, iptr, d);
1238                         break;
1239
1240                 case ICMD_F2L:       /* ..., value  ==> ..., (long) value             */
1241                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1242                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1243                         disp = dseg_add_unique_double(cd, 0.0);
1244                         
1245                         /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5)  */
1246                         M_FCMP(s1, s1);
1247                         M_FBU(5);
1248                         M_MOV(REG_ZERO, d); /* delay slot */
1249                         
1250                         M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1251                         M_DST(REG_FTMP2, REG_PV, disp);
1252                         M_LDX(d, REG_PV, disp);
1253                         emit_store_dst(jd, iptr, d);
1254                         break;
1255                         
1256                 case ICMD_D2L:       /* ..., value  ==> ..., (long) value             */
1257                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1258                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1259                         disp = dseg_add_unique_double(cd, 0.0);
1260                         
1261                         /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5)  */
1262                         M_DCMP(s1, s1);
1263                         M_FBU(5);
1264                         M_MOV(REG_ZERO, d); /* delay slot */
1265                         
1266                         M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1267                         M_DST(REG_FTMP2, REG_PV, disp);
1268                         M_LDX(d, REG_PV, disp);
1269                         emit_store_dst(jd, iptr, d);
1270                         break;
1271
1272                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1273
1274                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1275                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1276                         M_CVTFD(s1, d);
1277                         emit_store_dst(jd, iptr, d);
1278                         break;
1279                                         
1280                 case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
1281
1282                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1283                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1284                         M_CVTDF(s1, d);
1285                         emit_store_dst(jd, iptr, d);
1286                         break;
1287         
1288         /* XXX merge F/D versions? only compare instr. is different */
1289                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1290
1291                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1292                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1293                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1294                         M_FCMP(s1,s2);
1295                         M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1296                         M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1297                         M_CMOVFGT_IMM(1, d); /* 1 if greater */
1298                         emit_store_dst(jd, iptr, d);
1299                         break;
1300                         
1301                 case ICMD_DCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1302
1303                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1304                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1305                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1306                         M_DCMP(s1,s2);
1307                         M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1308                         M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1309                         M_CMOVFGT_IMM(1, d); /* 1 if greater */
1310                         emit_store_dst(jd, iptr, d);
1311                         break;
1312                         
1313                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1314
1315                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1316                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1317                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);    
1318                         M_FCMP(s1,s2);
1319                         M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1320                         M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1321                         M_CMOVFLT_IMM(-1, d); /* -1 if less */
1322                         emit_store_dst(jd, iptr, d);
1323                         break;
1324                         
1325                 case ICMD_DCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1326
1327                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1328                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1329                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);    
1330                         M_DCMP(s1,s2);
1331                         M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1332                         M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1333                         M_CMOVFLT_IMM(-1, d); /* -1 if less */
1334                         emit_store_dst(jd, iptr, d);
1335                         break;
1336                         
1337
1338                 /* memory operations **************************************************/
1339
1340                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
1341
1342                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1343                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1344                         emit_nullpointer_check(cd, iptr, s1);
1345                         M_ILD(d, s1, OFFSET(java_arrayheader, size));
1346                         emit_store_dst(jd, iptr, d);
1347                         break;
1348
1349                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1350
1351                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1352                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1353                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1354                         /* implicit null-pointer check */
1355                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1356                         M_AADD(s2, s1, REG_ITMP3);
1357                         M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
1358                         emit_store_dst(jd, iptr, d);
1359                         break;
1360
1361                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1362
1363                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1364                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1365                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1366                         /* implicit null-pointer check */
1367                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1368                         M_AADD(s2, s1, REG_ITMP3);
1369                         M_AADD(s2, REG_ITMP3, REG_ITMP3);
1370                         M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1371                         emit_store_dst(jd, iptr, d);
1372                         break;                  
1373
1374                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1375
1376                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1377                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1378                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1379                         /* implicit null-pointer check */
1380                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1381                         M_AADD(s2, s1, REG_ITMP3);
1382                         M_AADD(s2, REG_ITMP3, REG_ITMP3);
1383                         M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
1384                         emit_store_dst(jd, iptr, d);
1385                         break;
1386
1387                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1388
1389                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1390                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1391                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1392                         /* implicit null-pointer check */
1393                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1394                         M_ASLL_IMM(s2, 2, REG_ITMP3);
1395                         M_AADD(REG_ITMP3, s1, REG_ITMP3);
1396                         M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
1397                         emit_store_dst(jd, iptr, d);
1398                         break;
1399
1400                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1401
1402                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1403                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1404                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1405                         /* implicit null-pointer check */
1406                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1407                         M_ASLL_IMM(s2, 3, REG_ITMP3);
1408                         M_AADD(REG_ITMP3, s1, REG_ITMP3);
1409                         M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
1410                         emit_store_dst(jd, iptr, d);
1411                         break;
1412
1413                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1414
1415                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1416                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1417                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1418                         /* implicit null-pointer check */
1419                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1420                         M_ASLL_IMM(s2, 2, REG_ITMP3);
1421                         M_AADD(REG_ITMP3, s1, REG_ITMP3);
1422                         M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
1423                         emit_store_dst(jd, iptr, d);
1424                         break;
1425
1426                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1427
1428                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1429                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1430                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1431                         /* implicit null-pointer check */
1432                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1433                         M_ASLL_IMM(s2, 3, REG_ITMP3);
1434                         M_AADD(REG_ITMP3, s1, REG_ITMP3);
1435                         M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
1436                         emit_store_dst(jd, iptr, d);
1437                         break;
1438
1439                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1440
1441                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1442                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1443                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1444                         /* implicit null-pointer check */
1445                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1446                         M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1447                         M_AADD(REG_ITMP3, s1, REG_ITMP3);
1448                         M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
1449                         emit_store_dst(jd, iptr, d);
1450                         break;
1451
1452         
1453                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1454
1455                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1456                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1457                         /* implicit null-pointer check */
1458                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1459                         M_AADD(s2, s1, REG_ITMP1);
1460                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1461                         M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1462                         break;
1463
1464                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1465                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1466
1467                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1468                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1469                         /* implicit null-pointer check */
1470                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1471                         M_AADD(s2, s1, REG_ITMP1);
1472                         M_AADD(s2, REG_ITMP1, REG_ITMP1);
1473                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1474                         M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1475                         break;
1476
1477                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1478
1479                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1480                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1481                         /* implicit null-pointer check */
1482                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1483                         M_ASLL_IMM(s2, 2, REG_ITMP2);
1484                         M_AADD(REG_ITMP2, s1, REG_ITMP1);
1485                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1486                         M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1487                         break;
1488
1489                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1490
1491                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1492                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1493                         /* implicit null-pointer check */
1494                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1495                         M_ASLL_IMM(s2, 3, REG_ITMP2);
1496                         M_AADD(REG_ITMP2, s1, REG_ITMP1);
1497                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1498                         M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1499                         break;
1500
1501                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1502
1503                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1504                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1505                         /* implicit null-pointer check */
1506                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1507                         M_ASLL_IMM(s2, 2, REG_ITMP2);
1508                         M_AADD(REG_ITMP2, s1, REG_ITMP1);
1509                         s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1510                         M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1511                         break;
1512
1513                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1514
1515                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1516                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1517                         /* implicit null-pointer check */
1518                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1519                         M_ASLL_IMM(s2, 3, REG_ITMP2);
1520                         M_AADD(REG_ITMP2, s1, REG_ITMP1);
1521                         s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1522                         M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1523                         break;
1524
1525
1526                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1527
1528                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1529                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1530                         /* implicit null-pointer check */
1531                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1532                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1533
1534                         M_MOV(s1, REG_OUT0);
1535                         M_MOV(s3, REG_OUT1);
1536                         disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1537                         M_ALD(REG_ITMP3, REG_PV, disp);
1538                         M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
1539                         M_NOP;
1540                         emit_exception_check(cd, iptr);
1541
1542                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1543                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1544                         M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1545                         M_AADD(REG_ITMP2, s1, REG_ITMP1);
1546                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1547                         /* implicit null-pointer check */
1548                         M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1549                         break;
1550
1551
1552                 case ICMD_BASTORECONST:   /* ..., arrayref, index  ==> ...            */
1553
1554                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1555                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1556                         /* implicit null-pointer check */
1557                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1558                         M_AADD(s2, s1, REG_ITMP1);
1559                         M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1560                         break;
1561
1562                 case ICMD_CASTORECONST:   /* ..., arrayref, index  ==> ...            */
1563                 case ICMD_SASTORECONST:   /* ..., arrayref, index  ==> ...            */
1564
1565                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1566                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1567                         /* implicit null-pointer check */
1568                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1569                         M_AADD(s2, s1, REG_ITMP1);
1570                         M_AADD(s2, REG_ITMP1, REG_ITMP1);
1571                         M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1572                         break;
1573
1574                 case ICMD_IASTORECONST:   /* ..., arrayref, index  ==> ...            */
1575
1576                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1577                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1578                         /* implicit null-pointer check */
1579                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1580                         M_ASLL_IMM(s2, 2, REG_ITMP2);
1581                         M_AADD(REG_ITMP2, s1, REG_ITMP1);
1582                         M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1583                         break;
1584
1585                 case ICMD_LASTORECONST:   /* ..., arrayref, index  ==> ...            */
1586
1587                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1588                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1589                         /* implicit null-pointer check */
1590                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1591                         M_ASLL_IMM(s2, 3, REG_ITMP2);
1592                         M_AADD(REG_ITMP2, s1, REG_ITMP1);
1593                         M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1594                         break;
1595
1596                 case ICMD_AASTORECONST:   /* ..., arrayref, index  ==> ...            */
1597
1598                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1599                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1600                         /* implicit null-pointer check */
1601                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1602                         M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1603                         M_AADD(REG_ITMP2, s1, REG_ITMP1);
1604                         M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1605                         break;
1606                 
1607
1608                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
1609
1610                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1611                                 uf = iptr->sx.s23.s3.uf;
1612                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1613                                 disp      = dseg_add_unique_address(cd, uf);
1614
1615                                 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1616                         } 
1617                         else {
1618                                 fi = iptr->sx.s23.s3.fmiref->p.field;
1619                                 fieldtype = fi->type;
1620                                 disp = dseg_add_address(cd, &(fi->value));
1621
1622                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1623                                         codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1624                         }
1625
1626                         M_ALD(REG_ITMP1, REG_PV, disp);
1627
1628                         switch (fieldtype) {
1629                         case TYPE_INT:
1630                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1631                                 M_ILD_INTERN(d, REG_ITMP1, 0);
1632                                 break;
1633                         case TYPE_LNG:
1634                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1635                                 M_LDX_INTERN(d, REG_ITMP1, 0);
1636                                 break;
1637                         case TYPE_ADR:
1638                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1639                                 M_ALD_INTERN(d, REG_ITMP1, 0);
1640                                 break;
1641                         case TYPE_FLT:
1642                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1643                                 M_FLD_INTERN(d, REG_ITMP1, 0);
1644                                 break;
1645                         case TYPE_DBL:                          
1646                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1647                                 M_DLD_INTERN(d, REG_ITMP1, 0);
1648                                 break;
1649                         }
1650                         emit_store_dst(jd, iptr, d);
1651                         break;
1652
1653                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
1654
1655                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1656                                 uf = iptr->sx.s23.s3.uf;
1657                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1658                                 disp      = dseg_add_unique_address(cd, uf);
1659
1660                                 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1661                         } 
1662                         else {
1663                                 fi = iptr->sx.s23.s3.fmiref->p.field;
1664                                 fieldtype = fi->type;
1665                                 disp = dseg_add_address(cd, &(fi->value));
1666
1667                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1668                                         codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1669                         }
1670
1671                         M_ALD(REG_ITMP1, REG_PV, disp);
1672
1673                         switch (fieldtype) {
1674                         case TYPE_INT:
1675                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1676                                 M_IST_INTERN(s1, REG_ITMP1, 0);
1677                                 break;
1678                         case TYPE_LNG:
1679                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1680                                 M_STX_INTERN(s1, REG_ITMP1, 0);
1681                                 break;
1682                         case TYPE_ADR:
1683                                 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1684                                 M_AST_INTERN(s1, REG_ITMP1, 0);
1685                                 break;
1686                         case TYPE_FLT:
1687                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1688                                 M_FST_INTERN(s1, REG_ITMP1, 0);
1689                                 break;
1690                         case TYPE_DBL:
1691                                 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1692                                 M_DST_INTERN(s1, REG_ITMP1, 0);
1693                                 break;
1694                         }
1695                         break;
1696
1697                 case ICMD_PUTSTATICCONST: /* ...  ==> ...                             */
1698                                           /* val = value (in current instruction)     */
1699                                           /* following NOP)                           */
1700
1701                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1702                                 uf        = iptr->sx.s23.s3.uf;
1703                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1704                                 disp = dseg_add_unique_address(cd, uf);
1705
1706                                 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1707                         } 
1708                         else {
1709                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1710                                 fieldtype = fi->type;
1711                                 disp      = dseg_add_address(cd, &(fi->value));
1712
1713                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1714                                         codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1715                         }
1716
1717                         M_ALD(REG_ITMP1, REG_PV, disp);
1718
1719                         switch (fieldtype) {
1720                         case TYPE_INT:
1721                                 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1722                                 break;
1723                         case TYPE_LNG:
1724                                 M_STX_INTERN(REG_ZERO, REG_ITMP1, 0);
1725                                 break;
1726                         case TYPE_ADR:
1727                                 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1728                                 break;
1729                         case TYPE_FLT:
1730                                 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1731                                 break;
1732                         case TYPE_DBL:
1733                                 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1734                                 break;
1735                         }
1736                         break;
1737
1738
1739                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
1740
1741                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1742                         emit_nullpointer_check(cd, iptr, s1);
1743
1744                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1745                                 uf = iptr->sx.s23.s3.uf;
1746
1747                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1748                                 disp      = 0;
1749
1750                                 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1751                         } 
1752                         else {
1753                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1754                                 fieldtype = fi->type;
1755                                 disp      = fi->offset;
1756                         }
1757
1758                         switch (fieldtype) {
1759                         case TYPE_INT:
1760                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1761                                 M_ILD(d, s1, disp);
1762                                 break;
1763                         case TYPE_LNG:
1764                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1765                                 M_LDX(d, s1, disp);
1766                                 break;
1767                         case TYPE_ADR:
1768                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1769                                 M_ALD(d, s1, disp);
1770                                 break;
1771                         case TYPE_FLT:
1772                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1773                                 M_FLD(d, s1, disp);
1774                                 break;
1775                         case TYPE_DBL:                          
1776                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1777                                 M_DLD(d, s1, disp);
1778                                 break;
1779                         default:
1780                                 assert(0);
1781                                 break;
1782                         }
1783                         emit_store_dst(jd, iptr, d);
1784                         break;
1785
1786                 case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
1787
1788                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1789                         emit_nullpointer_check(cd, iptr, s1);
1790
1791                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1792                                 uf = iptr->sx.s23.s3.uf;
1793                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1794                                 disp      = 0;
1795                         }
1796                         else {
1797                                 uf        = NULL;
1798                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1799                                 fieldtype = fi->type;
1800                                 disp      = fi->offset;
1801                                 }
1802
1803                         if (IS_INT_LNG_TYPE(fieldtype))
1804                                 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1805                         else
1806                                 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1807
1808                         if (INSTRUCTION_IS_UNRESOLVED(iptr))
1809                                 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1810
1811                         switch (fieldtype) {
1812                         case TYPE_INT:
1813                                 M_IST(s2, s1, disp);
1814                                 break;
1815                         case TYPE_LNG:
1816                                 M_STX(s2, s1, disp);
1817                                 break;
1818                         case TYPE_ADR:
1819                                 M_AST(s2, s1, disp);
1820                                 break;
1821                         case TYPE_FLT:
1822                                 M_FST(s2, s1, disp);
1823                                 break;
1824                         case TYPE_DBL:
1825                                 M_DST(s2, s1, disp);
1826                                 break;
1827                         default:
1828                                 assert(0);
1829                                 break;
1830                         }
1831                         break;
1832
1833                 case ICMD_PUTFIELDCONST:  /* ..., objectref  ==> ...                  */
1834                                           /* val = value (in current instruction)     */
1835                                           /* following NOP)                           */
1836
1837                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1838                         emit_nullpointer_check(cd, iptr, s1);
1839
1840                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1841                                 unresolved_field *uf = iptr->sx.s23.s3.uf;
1842
1843                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1844
1845                                 codegen_addpatchref(cd, PATCHER_get_putfield,
1846                                                                         uf, 0);
1847
1848                                 if (opt_showdisassemble) {
1849                                         M_NOP; M_NOP;
1850                                 }
1851
1852                                 disp = 0;
1853
1854                         } else {
1855                         {
1856                                 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1857
1858                                 fieldtype = fi->type;
1859                                 disp = fi->offset;
1860                         }
1861
1862                         }
1863
1864                         switch (fieldtype) {
1865                         case TYPE_INT:
1866                                 M_IST(REG_ZERO, s1, disp);
1867                                 break;
1868                         case TYPE_LNG:
1869                                 M_STX(REG_ZERO, s1, disp);
1870                                 break;
1871                         case TYPE_ADR:
1872                                 M_AST(REG_ZERO, s1, disp);
1873                                 break;
1874                         case TYPE_FLT:
1875                                 M_FST(REG_ZERO, s1, disp);
1876                                 break;
1877                         case TYPE_DBL:
1878                                 M_DST(REG_ZERO, s1, disp);
1879                                 break;
1880                         }
1881                         break;
1882
1883
1884                 /* branch operations **************************************************/
1885
1886                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
1887
1888                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1889                         M_INTMOVE(s1, REG_ITMP2_XPTR);
1890
1891 #ifdef ENABLE_VERIFIER
1892                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1893                                 unresolved_class *uc = iptr->sx.s23.s2.uc;
1894
1895                                 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
1896                         }
1897 #endif /* ENABLE_VERIFIER */
1898
1899                         disp = dseg_add_functionptr(cd, asm_handle_exception);
1900                         M_ALD(REG_ITMP1, REG_PV, disp);
1901                         M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
1902                         M_NOP;
1903                         M_NOP;              /* nop ensures that XPC is less than the end */
1904                                             /* of basic block                            */
1905                         ALIGNCODENOP;
1906                         break;
1907
1908                 case ICMD_GOTO:         /* ... ==> ...                                */
1909                 case ICMD_RET:          /* ... ==> ...                                */
1910
1911                         emit_br(cd, iptr->dst.block);
1912                         ALIGNCODENOP;
1913                         break;
1914
1915                 case ICMD_JSR:          /* ... ==> ...                                */
1916
1917                         emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1918                         ALIGNCODENOP;
1919                         break;
1920
1921                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
1922                 case ICMD_IFNONNULL:
1923
1924                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1925                         emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
1926                         break;
1927                         
1928                 /* Note: int compares must not branch on the register directly.       */
1929                 /* Reason is, that register content is not 32-bit clean.              */
1930
1931                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
1932
1933                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1934                         
1935                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1936                                 M_CMP_IMM(s1, iptr->sx.val.i);
1937                         }
1938                         else {
1939                                 ICONST(REG_ITMP2, iptr->sx.val.i);
1940                                 M_CMP(s1, REG_ITMP2);
1941                         }
1942                         emit_beq(cd, iptr->dst.block);
1943                         break;
1944
1945                 case ICMD_IFLT:         /* ..., value ==> ...                         */
1946
1947                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1948                         
1949                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1950                                 M_CMP_IMM(s1, iptr->sx.val.i);
1951                         } 
1952                         else {
1953                                 ICONST(REG_ITMP2, iptr->sx.val.i);
1954                                 M_CMP(s1, REG_ITMP2);
1955                         }
1956                         emit_blt(cd, iptr->dst.block);
1957                         break;
1958
1959                 case ICMD_IFLE:         /* ..., value ==> ...                         */
1960
1961                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1962
1963                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1964                                 M_CMP_IMM(s1, iptr->sx.val.i);
1965                         }
1966                         else {
1967                                 ICONST(REG_ITMP2, iptr->sx.val.i);
1968                                 M_CMP(s1, REG_ITMP2);
1969                         }
1970                         emit_ble(cd, iptr->dst.block);
1971                         break;
1972
1973                 case ICMD_IFNE:         /* ..., value ==> ...                         */
1974
1975                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1976                 
1977                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1978                                 M_CMP_IMM(s1, iptr->sx.val.i);
1979                         }
1980                         else {
1981                                 ICONST(REG_ITMP2, iptr->sx.val.i);
1982                                 M_CMP(s1, REG_ITMP2);
1983                         }
1984                         emit_bne(cd, iptr->dst.block);
1985                         break;
1986                                                 
1987                 case ICMD_IFGT:         /* ..., value ==> ...                         */
1988
1989                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1990                 
1991                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1992                                 M_CMP_IMM(s1, iptr->sx.val.i);
1993                         } 
1994                         else {
1995                                 ICONST(REG_ITMP2, iptr->sx.val.i);
1996                                 M_CMP(s1, REG_ITMP2);
1997                         }
1998                         emit_bgt(cd, iptr->dst.block);          
1999                         break;
2000
2001                 case ICMD_IFGE:         /* ..., value ==> ...                         */
2002
2003                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2004
2005                         if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2006                                 M_CMP_IMM(s1, iptr->sx.val.i);
2007                         }
2008                         else {
2009                                 ICONST(REG_ITMP2, iptr->sx.val.i);
2010                                 M_CMP(s1, REG_ITMP2);
2011                         }
2012                         emit_bge(cd, iptr->dst.block);
2013                         break;
2014                         
2015                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
2016
2017                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2018                         if (iptr->sx.val.l == 0)
2019                                 emit_beqz(cd, iptr->dst.block, s1);
2020                         else {
2021                                 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2022                                         M_CMP_IMM(s1, iptr->sx.val.l);
2023                                 }
2024                                 else {
2025                                         LCONST(REG_ITMP2, iptr->sx.val.l);
2026                                         M_CMP(s1, REG_ITMP2);
2027                                 }
2028                                 emit_beq_xcc(cd, iptr->dst.block);
2029                         }
2030                         break;
2031                         
2032                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
2033
2034                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2035                         if (iptr->sx.val.l == 0)
2036                                 emit_bltz(cd, iptr->dst.block, s1);
2037                         else {
2038                                 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2039                                         M_CMP_IMM(s1, iptr->sx.val.l);
2040                                 } 
2041                                 else {
2042                                         LCONST(REG_ITMP2, iptr->sx.val.l);
2043                                         M_CMP(s1, REG_ITMP2);
2044                                 }
2045                                 emit_blt_xcc(cd, iptr->dst.block);
2046                         }
2047                         break;
2048
2049                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
2050
2051                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2052                         if (iptr->sx.val.l == 0)
2053                                 emit_blez(cd, iptr->dst.block, s1);
2054                         else {
2055                                 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2056                                         M_CMP_IMM(s1, iptr->sx.val.l);
2057                                 }
2058                                 else {
2059                                         LCONST(REG_ITMP2, iptr->sx.val.l);
2060                                         M_CMP(s1, REG_ITMP2);
2061                                 }
2062                                 emit_ble_xcc(cd, iptr->dst.block);
2063                         }
2064                         break;
2065                         
2066                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
2067
2068                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2069                         if (iptr->sx.val.l == 0)
2070                                 emit_bnez(cd, iptr->dst.block, s1);
2071                         else {
2072                                 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2073                                         M_CMP_IMM(s1, iptr->sx.val.l);
2074                                 }
2075                                 else {
2076                                         LCONST(REG_ITMP2, iptr->sx.val.l);
2077                                         M_CMP(s1, REG_ITMP2);
2078                                 }
2079                                 emit_bne_xcc(cd, iptr->dst.block);
2080                         }
2081                         break;
2082                                                 
2083                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
2084
2085                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2086                         if (iptr->sx.val.l == 0)
2087                                 emit_bgtz(cd, iptr->dst.block, s1);
2088                         else {
2089                                 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2090                                         M_CMP_IMM(s1, iptr->sx.val.l);
2091                                 } 
2092                                 else {
2093                                         LCONST(REG_ITMP2, iptr->sx.val.l);
2094                                         M_CMP(s1, REG_ITMP2);
2095                                 }
2096                                 emit_bgt_xcc(cd, iptr->dst.block);
2097                         }
2098                         break;
2099
2100                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
2101
2102                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2103                         if (iptr->sx.val.l == 0)
2104                                 emit_bgez(cd, iptr->dst.block, s1);
2105                         else {
2106                                 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2107                                         M_CMP_IMM(s1, iptr->sx.val.l);
2108                                 }
2109                                 else {
2110                                         LCONST(REG_ITMP2, iptr->sx.val.l);
2111                                         M_CMP(s1, REG_ITMP2);
2112                                 }
2113                                 emit_bge_xcc(cd, iptr->dst.block);
2114                         }
2115                         break;                  
2116                         
2117
2118                 case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
2119                 case ICMD_IF_LCMPEQ:    /* op1 = target JavaVM pc                     */
2120
2121                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2122                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2123                         M_CMP(s1, s2);
2124                         emit_beq_xcc(cd, iptr->dst.block);
2125                         break;
2126
2127                 case ICMD_IF_ICMPEQ:    /* 32-bit compare                             */
2128
2129                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2130                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2131                         M_CMP(s1, s2);
2132                         emit_beq(cd, iptr->dst.block);
2133                         break;
2134
2135                 case ICMD_IF_ACMPNE:    /* ..., value, value ==> ...                  */
2136                 case ICMD_IF_LCMPNE:    /* op1 = target JavaVM pc                     */
2137
2138                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2139                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2140                         M_CMP(s1, s2);
2141                         emit_bne_xcc(cd, iptr->dst.block);
2142                         break;
2143                         
2144                 case ICMD_IF_ICMPNE:    /* 32-bit compare                             */
2145
2146                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2147                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2148                         M_CMP(s1, s2);
2149                         emit_bne(cd, iptr->dst.block);
2150                         break;
2151
2152                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
2153
2154                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2155                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2156                         M_CMP(s1, s2);
2157                         emit_blt_xcc(cd, iptr->dst.block);
2158                         break;
2159                         
2160                 case ICMD_IF_ICMPLT:    /* 32-bit compare                             */
2161
2162                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2163                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2164                         M_CMP(s1, s2);
2165                         emit_blt(cd, iptr->dst.block);
2166                         break;
2167
2168                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
2169
2170                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2171                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2172                         M_CMP(s1, s2);
2173                         emit_bgt_xcc(cd, iptr->dst.block);
2174                         break;
2175                         
2176                 case ICMD_IF_ICMPGT:    /* 32-bit compare                             */
2177
2178                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2179                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2180                         M_CMP(s1, s2);
2181                         emit_bgt(cd, iptr->dst.block);
2182                         break;
2183
2184                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
2185
2186                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2187                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2188                         M_CMP(s1, s2);
2189                         emit_ble_xcc(cd, iptr->dst.block);
2190                         break;
2191                         
2192                 case ICMD_IF_ICMPLE:    /* 32-bit compare                             */
2193
2194                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2195                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2196                         M_CMP(s1, s2);
2197                         emit_ble(cd, iptr->dst.block);
2198                         break;                  
2199         
2200
2201                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
2202
2203                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2204                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2205                         M_CMP(s1, s2);
2206                         emit_bge_xcc(cd, iptr->dst.block);
2207                         break;
2208                         
2209                 case ICMD_IF_ICMPGE:    /* 32-bit compare                             */
2210
2211                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2212                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2213                         M_CMP(s1, s2);
2214                         emit_bge(cd, iptr->dst.block);
2215                         break;
2216
2217
2218                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
2219                 case ICMD_LRETURN:
2220
2221                         s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2222                         M_INTMOVE(s1, REG_RESULT_CALLEE);
2223                         goto nowperformreturn;
2224
2225                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
2226
2227                         s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2228                         M_INTMOVE(s1, REG_RESULT_CALLEE);
2229
2230 #ifdef ENABLE_VERIFIER
2231                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2232                                 unresolved_class *uc = iptr->sx.s23.s2.uc;
2233
2234                                 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2235                         }
2236 #endif /* ENABLE_VERIFIER */
2237                         goto nowperformreturn;
2238
2239                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
2240                 case ICMD_DRETURN:
2241
2242                         s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2243                         M_DBLMOVE(s1, REG_FRESULT);
2244                         goto nowperformreturn;
2245
2246                 case ICMD_RETURN:       /* ...  ==> ...                               */
2247
2248 nowperformreturn:
2249                         {
2250                         s4 i, p;
2251                         
2252                         p = cd->stackframesize;
2253
2254 #if !defined(NDEBUG)
2255                         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2256                                 emit_verbosecall_exit(jd);
2257 #endif
2258
2259 #if defined(ENABLE_THREADS)
2260                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2261                                 /* XXX jit-c-call */
2262                                 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2263                                 M_ALD(REG_ITMP3, REG_PV, disp);
2264
2265                                 /* we need to save fp return value (int saved by window) */
2266
2267                                 switch (iptr->opc) {
2268                                 case ICMD_FRETURN:
2269                                 case ICMD_DRETURN:
2270                                         M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
2271                                         M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2272                                         M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2273
2274                                         /* restore the fp return value */
2275
2276                                         M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
2277                                         break;
2278                                 case ICMD_IRETURN:
2279                                 case ICMD_LRETURN:
2280                                 case ICMD_ARETURN:
2281                                 case ICMD_RETURN:
2282                                         M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2283                                         M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2284                                         break;
2285                                 default:
2286                                         assert(false);
2287                                         break;
2288                                 }
2289                         }
2290 #endif
2291
2292
2293
2294                         M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
2295                         M_NOP;
2296                         ALIGNCODENOP;
2297                         }
2298                         break;
2299
2300                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2301                         {
2302                         s4 i, l;
2303                         branch_target_t *table;
2304
2305                         table = iptr->dst.table;
2306
2307                         l = iptr->sx.s23.s2.tablelow;
2308                         i = iptr->sx.s23.s3.tablehigh;
2309                         
2310                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2311                         if (l == 0) {
2312                                 M_INTMOVE(s1, REG_ITMP1);
2313                         }
2314                         else if (l <= 4095) {
2315                                 M_ADD_IMM(s1, -l, REG_ITMP1);
2316                         }
2317                         else {
2318                                 ICONST(REG_ITMP2, l);
2319                                 /* XXX: do I need to truncate s1 to 32-bit ? */
2320                                 M_SUB(s1, REG_ITMP2, REG_ITMP1);
2321                         }
2322                         i = i - l + 1;
2323
2324
2325                         /* range check */
2326                                         
2327                         if (i <= 4095) {
2328                                 M_CMP_IMM(REG_ITMP1, i - 1);
2329                         }
2330                         else {
2331                                 ICONST(REG_ITMP2, i - 1);
2332                                 M_CMP(REG_ITMP1, REG_ITMP2);
2333                         }               
2334                         emit_bugt(cd, table[0].block); /* default target */
2335
2336                         /* build jump table top down and use address of lowest entry */
2337
2338                         table += i;
2339
2340                         while (--i >= 0) {
2341                                 dseg_add_target(cd, table->block); 
2342                                 --table;
2343                                 }
2344                         }
2345
2346                         /* length of dataseg after last dseg_addtarget is used by load */
2347
2348                         M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
2349                         M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2350                         M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2351                         M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
2352                         M_NOP;
2353                         ALIGNCODENOP;
2354                         break;
2355                         
2356                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
2357                         {
2358                         s4 i;
2359                         lookup_target_t *lookup;
2360
2361                         lookup = iptr->dst.lookup;
2362
2363                         i = iptr->sx.s23.s2.lookupcount;
2364                         
2365                         MCODECHECK((i<<2)+8);
2366                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2367
2368                         while (--i >= 0) {
2369                                 if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
2370                                         M_CMP_IMM(s1, lookup->value);
2371                                 } else {                                        
2372                                         ICONST(REG_ITMP2, lookup->value);
2373                                         M_CMP(s1, REG_ITMP2);
2374                                 }
2375                                 emit_beq(cd, lookup->target.block);
2376                                 ++lookup;
2377                         }
2378
2379                         emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2380                         ALIGNCODENOP;
2381                         break;
2382                         }
2383
2384
2385                 case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
2386
2387                         bte = iptr->sx.s23.s3.bte;
2388                         md = bte->md;
2389                         
2390                         /* XXX: builtin calling with stack arguments not implemented */
2391                         assert(md->paramcount <= 5 && md->argfltreguse <= 16);
2392                         
2393                         s3 = md->paramcount;
2394
2395                         MCODECHECK((s3 << 1) + 64);
2396
2397 #ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
2398
2399                         /* copy float arguments according to ABI convention */
2400
2401                         int num_fltregargs = 0;
2402                         int fltregarg_inswap[16];
2403
2404                         for (s3 = s3 - 1; s3 >= 0; s3--) {
2405                                 var = VAR(iptr->sx.s23.s2.args[s3]);
2406
2407                                 if (IS_FLT_DBL_TYPE(var->type)) {
2408                                         if (!md->params[s3].inmemory) {
2409                                                 s1 = s3; /*native flt args use argument index directly*/
2410                                                 d = emit_load(jd, iptr, var, REG_FTMP1);
2411                                                 
2412                                                 M_DMOV(d, s1 + 16);
2413                                                 fltregarg_inswap[num_fltregargs] = s1;
2414                                                 num_fltregargs++;
2415                                                 /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
2416                                         }
2417                                         else {
2418                                                 assert(0);
2419                                         }
2420                                 }
2421                         }
2422                         
2423                         int i;
2424                         /* move swapped float args to target regs */
2425                         for (i = 0; i < num_fltregargs; i++) {
2426                                 s1 = fltregarg_inswap[i];
2427                                 M_DMOV(s1 + 16, s1);
2428                                 /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
2429                         }
2430                         
2431 #else
2432                         assert(md->argfltreguse == 0);
2433 #endif
2434                         
2435                         goto gen_method;
2436
2437                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2438
2439                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2440                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
2441                 case ICMD_INVOKEINTERFACE:
2442
2443                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2444                                 lm = NULL;
2445                                 um = iptr->sx.s23.s3.um;
2446                                 md = um->methodref->parseddesc.md;
2447                         }
2448                         else {
2449                                 lm = iptr->sx.s23.s3.fmiref->p.method;
2450                                 um = NULL;
2451                                 md = lm->parseddesc;
2452                         }
2453
2454 gen_method:
2455                         s3 = md->paramcount;
2456
2457                         MCODECHECK((s3 << 1) + 64);
2458
2459                         /* copy arguments to registers or stack location                  */
2460
2461                         for (s3 = s3 - 1; s3 >= 0; s3--) {
2462                                 var = VAR(iptr->sx.s23.s2.args[s3]);
2463                                 d  = md->params[s3].regoff;
2464
2465                                 if (var->flags & PREALLOC)
2466                                         continue;
2467
2468                                 if (IS_INT_LNG_TYPE(var->type)) {
2469                                         if (!md->params[s3].inmemory) {
2470                                                 s1 = emit_load(jd, iptr, var, d);
2471                                                 M_INTMOVE(s1, d);
2472                                         } 
2473                                         else {
2474                                                 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2475                                                 M_STX(s1, REG_SP, JITSTACK + d);
2476                                         }
2477                                 }
2478                                 else {
2479 #ifdef BUILTIN_FLOAT_ARGS
2480                                         if (iptr->opc == ICMD_BUILTIN)
2481                                                 continue;
2482 #endif
2483                                                 
2484                                         if (!md->params[s3].inmemory) {
2485                                                 s1 = emit_load(jd, iptr, var, d);
2486                                                 if (IS_2_WORD_TYPE(var->type))
2487                                                         M_DMOV(s1, d);
2488                                                 else
2489                                                         M_FMOV(s1, d);
2490                                         }
2491                                         else {
2492                                                 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2493                                                 M_DST(s1, REG_SP, JITSTACK + d);
2494                                         }
2495                                 }
2496                         }
2497
2498                         switch (iptr->opc) {
2499                         case ICMD_BUILTIN:
2500                                 disp = dseg_add_functionptr(cd, bte->fp);
2501
2502                                 M_ALD(REG_PV_CALLER, REG_PV, disp);  /* built-in-function pointer */
2503
2504                                 /* XXX jit-c-call */
2505                                 /* generate the actual call */
2506     
2507                             M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2508                             M_NOP;
2509                             disp = (s4) (cd->mcodeptr - cd->mcodebase);
2510                             /* REG_RA holds the value of the jmp instruction, therefore +8 */
2511                             M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
2512
2513                                 emit_exception_check(cd, iptr);
2514                                 if (md->returntype.type == TYPE_FLT) {
2515                                         /* special handling for float return value in %f0 */
2516                                         M_FMOV_INTERN(0,1);
2517                                 }
2518                                 break;
2519
2520                         case ICMD_INVOKESPECIAL:
2521                                 emit_nullpointer_check(cd, iptr, REG_OUT0);
2522                                 /* fall-through */
2523
2524                         case ICMD_INVOKESTATIC:
2525                                 if (lm == NULL) {
2526                                         disp = dseg_add_unique_address(cd, NULL);
2527
2528                                         codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
2529                                                                                 um, disp);
2530                                 }
2531                                 else
2532                                         disp = dseg_add_address(cd, lm->stubroutine);
2533
2534                                 M_ALD(REG_PV_CALLER, REG_PV, disp);          /* method pointer in pv */
2535                                 
2536                                 /* generate the actual call */
2537     
2538                             M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2539                             M_NOP;
2540                             disp = (s4) (cd->mcodeptr - cd->mcodebase);
2541                             /* REG_RA holds the value of the jmp instruction, therefore +8 */
2542                             M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
2543                                 break;
2544
2545                         case ICMD_INVOKEVIRTUAL:
2546                                 emit_nullpointer_check(cd, iptr, REG_OUT0);
2547
2548                                 if (lm == NULL) {
2549                                         codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
2550
2551                                         s1 = 0;
2552                                 }
2553                                 else
2554                                         s1 = OFFSET(vftbl_t, table[0]) +
2555                                                 sizeof(methodptr) * lm->vftblindex;
2556
2557                                 /* implicit null-pointer check */
2558                                 M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_objectheader, vftbl));
2559                                 M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
2560                                 
2561                                 /* generate the actual call */
2562     
2563                             M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2564                             M_NOP;
2565                             disp = (s4) (cd->mcodeptr - cd->mcodebase);
2566                             /* REG_RA holds the value of the jmp instruction, therefore +8 */
2567                             M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8); 
2568                                 break;
2569
2570                         case ICMD_INVOKEINTERFACE:
2571                                 emit_nullpointer_check(cd, iptr, REG_OUT0);
2572
2573                                 if (lm == NULL) {
2574                                         codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
2575
2576                                         s1 = 0;
2577                                         s2 = 0;
2578                                 } 
2579                                 else {
2580                                         s1 = OFFSET(vftbl_t, interfacetable[0]) -
2581                                                 sizeof(methodptr*) * lm->class->index;
2582
2583                                         s2 = sizeof(methodptr) * (lm - lm->class->methods);
2584                                 }
2585
2586                                 /* implicit null-pointer check */
2587                                 M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_objectheader, vftbl));
2588                                 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2589                                 M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
2590
2591                             /* generate the actual call */
2592     
2593                             M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2594                             M_NOP;
2595                             disp = (s4) (cd->mcodeptr - cd->mcodebase);
2596                             /* REG_RA holds the value of the jmp instruction, therefore +8 */
2597                             M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2598                                 break;
2599                         }
2600
2601                         /* store return value */
2602
2603                         d = md->returntype.type;
2604
2605                         if (d != TYPE_VOID) {
2606                                 if (IS_INT_LNG_TYPE(d)) {
2607                                         s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2608                                         M_INTMOVE(REG_RESULT_CALLER, s1);
2609                                 } 
2610                                 else {
2611                                         s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2612                                         if (IS_2_WORD_TYPE(d)) {
2613                                                 M_DBLMOVE(REG_FRESULT, s1);
2614                                         } else {
2615                                                 M_FLTMOVE(REG_FRESULT, s1);
2616                                         }
2617                                 }
2618                                 emit_store_dst(jd, iptr, s1);
2619                         }
2620                         break;
2621
2622
2623                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
2624                                       /* val.a: (classinfo*) superclass               */
2625
2626                         /*  superclass is an interface:
2627                          *
2628                          *  OK if ((sub == NULL) ||
2629                          *         (sub->vftbl->interfacetablelength > super->index) &&
2630                          *         (sub->vftbl->interfacetable[-super->index] != NULL));
2631                          *
2632                          *  superclass is a class:
2633                          *
2634                          *  OK if ((sub == NULL) || (0
2635                          *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2636                          *         super->vftbl->diffvall));
2637                          */
2638
2639                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2640                                 classinfo *super;
2641                                 s4         superindex;
2642
2643                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2644                                         super      = NULL;
2645                                         superindex = 0;
2646                                 }
2647                                 else {
2648                                         super = iptr->sx.s23.s3.c.cls;
2649                                         superindex = super->index;
2650                                 }
2651
2652                                 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2653                                         CODEGEN_CRITICAL_SECTION_NEW;
2654
2655                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2656
2657                                 /* if class is not resolved, check which code to call */
2658
2659                                 if (super == NULL) {
2660                                         emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2661
2662                                         cr   = iptr->sx.s23.s3.c.ref;
2663                                         disp = dseg_add_unique_s4(cd, 0);         /* super->flags */
2664
2665                                         codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2666                                                                                   cr, disp);
2667
2668                                         M_ILD(REG_ITMP2, REG_PV, disp);
2669                                         M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2670                                         emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
2671                                 }
2672
2673                                 /* interface checkcast code */
2674
2675                                 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2676                                         if (super == NULL) {
2677                                                 cr = iptr->sx.s23.s3.c.ref;
2678
2679                                                 codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
2680                                                                                           cr, 0);
2681                                         }
2682                                         else {
2683                                                 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2684                                         }
2685
2686                                         M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2687                                         M_ILD(REG_ITMP3, REG_ITMP2,
2688                                                         OFFSET(vftbl_t, interfacetablelength));
2689                                         M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
2690                                         emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
2691
2692                                         M_ALD(REG_ITMP3, REG_ITMP2,
2693                                                   OFFSET(vftbl_t, interfacetable[0]) -
2694                                                   superindex * sizeof(methodptr*));
2695                                         emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
2696
2697                                         if (super == NULL)
2698                                                 emit_label_br(cd, BRANCH_LABEL_4);
2699                                         else
2700                                                 emit_label(cd, BRANCH_LABEL_3);
2701                                 }
2702
2703                                 /* class checkcast code */
2704
2705                                 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2706                                         if (super == NULL) {
2707                                                 emit_label(cd, BRANCH_LABEL_2);
2708
2709                                                 cr   = iptr->sx.s23.s3.c.ref;
2710                                                 disp = dseg_add_unique_address(cd, NULL);
2711
2712                                                 codegen_add_patch_ref(cd,
2713                                                                                         PATCHER_checkcast_instanceof_class,
2714                                                                                           cr, disp);
2715                                         }
2716                                         else {
2717                                                 disp = dseg_add_address(cd, super->vftbl);
2718
2719                                                 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2720                                         }
2721
2722                                         M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2723                                         M_ALD(REG_ITMP3, REG_PV, disp);
2724                                         
2725                                         CODEGEN_CRITICAL_SECTION_START;
2726
2727                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2728                                         M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2729                                         M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2730                                         M_ALD(REG_ITMP3, REG_PV, disp);
2731                                         M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2732
2733                                         CODEGEN_CRITICAL_SECTION_END;
2734
2735                                         /*                              } */
2736                                         M_CMP(REG_ITMP3, REG_ITMP2);
2737                                         emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
2738
2739                                         if (super != NULL)
2740                                                 emit_label(cd, BRANCH_LABEL_5);
2741                                 }
2742
2743                                 if (super == NULL) {
2744                                         emit_label(cd, BRANCH_LABEL_1);
2745                                         emit_label(cd, BRANCH_LABEL_4);
2746                                 }
2747
2748                                 d = codegen_reg_of_dst(jd, iptr, s1);
2749                         }
2750                         else {
2751                                 /* array type cast-check */
2752
2753                                 s1 = emit_load_s1(jd, iptr, REG_OUT0);
2754                                 M_INTMOVE(s1, REG_OUT0);
2755
2756                                 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2757
2758                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2759                                         cr   = iptr->sx.s23.s3.c.ref;
2760                                         disp = dseg_add_unique_address(cd, NULL);
2761
2762                                         codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
2763                                                                                   cr, disp);
2764                                 }
2765                                 else
2766                                         disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2767
2768                                 M_ALD(REG_OUT1, REG_PV, disp);
2769                                 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2770                                 M_ALD(REG_ITMP3, REG_PV, disp);
2771                                 /* XXX jit-c-call */
2772                                 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2773                                 M_NOP;
2774
2775                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2776                                 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
2777
2778                                 d = codegen_reg_of_dst(jd, iptr, s1);
2779                         }
2780
2781                         M_INTMOVE(s1, d);
2782                         emit_store_dst(jd, iptr, d);
2783                         break;
2784
2785                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
2786                                       /* val.a: (classinfo*) superclass               */
2787
2788                         /*  superclass is an interface:
2789                          *      
2790                          *  return (sub != NULL) &&
2791                          *         (sub->vftbl->interfacetablelength > super->index) &&
2792                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
2793                          *      
2794                          *  superclass is a class:
2795                          *      
2796                          *  return ((sub != NULL) && (0
2797                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2798                          *          super->vftbl->diffvall));
2799                          */
2800
2801                         {
2802                         classinfo *super;
2803                         vftbl_t   *supervftbl;
2804                         s4         superindex;
2805
2806                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2807                                 super = NULL;
2808                                 superindex = 0;
2809                                 supervftbl = NULL;
2810
2811                         } else {
2812                                 super = iptr->sx.s23.s3.c.cls;
2813                                 superindex = super->index;
2814                                 supervftbl = super->vftbl;
2815                         }
2816
2817                         if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2818                                 CODEGEN_CRITICAL_SECTION_NEW;
2819
2820                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2821                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2822                         if (s1 == d) {
2823                                 M_MOV(s1, REG_ITMP1);
2824                                 s1 = REG_ITMP1;
2825                         }
2826
2827                         M_CLR(d);
2828
2829                         /* if class is not resolved, check which code to call */
2830
2831                         if (super == NULL) {
2832                                 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2833
2834                                 cr   = iptr->sx.s23.s3.c.ref;
2835                                 disp = dseg_add_unique_s4(cd, 0);             /* super->flags */
2836
2837                                 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2838                                                                           cr, disp);
2839
2840                                 M_ILD(REG_ITMP3, REG_PV, disp);
2841                                 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2842                                 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
2843                         }
2844
2845                         /* interface instanceof code */
2846
2847                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2848                                 if (super == NULL) {
2849                                         cr = iptr->sx.s23.s3.c.ref;
2850
2851                                         codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
2852                                                                                   cr, 0);
2853                                 }
2854                                 else {
2855                                         emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2856                                 }
2857
2858                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2859                                 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2860                                 M_CMP_IMM(REG_ITMP3, superindex);
2861                                 M_BLE(4);
2862                                 M_NOP;
2863                                 M_ALD(REG_ITMP1, REG_ITMP1,
2864                                           (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2865                                                         superindex * sizeof(methodptr*)));
2866                                 M_CMOVRNE_IMM(REG_ITMP1, 1, d);      /* REG_ITMP1 != 0  */
2867
2868                                 if (super == NULL)
2869                                         emit_label_br(cd, BRANCH_LABEL_4);
2870                                 else
2871                                         emit_label(cd, BRANCH_LABEL_3);
2872                         }
2873
2874                         /* class instanceof code */
2875
2876                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2877                                 if (super == NULL) {
2878                                         emit_label(cd, BRANCH_LABEL_2);
2879
2880                                         cr   = iptr->sx.s23.s3.c.ref;
2881                                         disp = dseg_add_unique_address(cd, NULL);
2882
2883                                         codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
2884                                                                                   cr, disp);
2885                                 }
2886                                 else {
2887                                         disp = dseg_add_address(cd, supervftbl);
2888
2889                                         emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2890                                 }
2891
2892                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2893                                 M_ALD(REG_ITMP2, REG_PV, disp);
2894
2895                                 CODEGEN_CRITICAL_SECTION_START;
2896
2897                                 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2898                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2899                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2900
2901                                 CODEGEN_CRITICAL_SECTION_END;
2902
2903                                 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2904                                 M_CMP(REG_ITMP1, REG_ITMP2);
2905                                 M_XCMOVULE_IMM(1, d);
2906
2907                                 if (super != NULL)
2908                                         emit_label(cd, BRANCH_LABEL_5);
2909                         }
2910
2911                         if (super == NULL) {
2912                                 emit_label(cd, BRANCH_LABEL_1);
2913                                 emit_label(cd, BRANCH_LABEL_4);
2914                         }
2915
2916                         emit_store_dst(jd, iptr, d);
2917                         }
2918                         break;
2919
2920                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
2921
2922                         /* check for negative sizes and copy sizes to stack if necessary  */
2923
2924                         MCODECHECK((iptr->s1.argcount << 1) + 64);
2925
2926                         for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2927
2928                                 var = VAR(iptr->sx.s23.s2.args[s1]);
2929         
2930                                 /* copy SAVEDVAR sizes to stack */
2931
2932                                 /* Already Preallocated? */
2933
2934                                 if (!(var->flags & PREALLOC)) {
2935                                         s2 = emit_load(jd, iptr, var, REG_ITMP1);
2936                                         M_STX(s2, REG_SP, CSTACK + (s1 * 8));
2937                                 }
2938                         }
2939
2940                         /* arg 0 = dimension count */
2941
2942                         ICONST(REG_OUT0, iptr->s1.argcount);
2943
2944                         /* is patcher function set? */
2945
2946                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2947                                 disp = dseg_add_unique_address(cd, 0);
2948
2949                                 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
2950                                                                           iptr->sx.s23.s3.c.ref,
2951                                                                           disp);
2952                         }
2953                         else
2954                                 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2955
2956                         /* arg 1 = arraydescriptor */
2957
2958                         M_ALD(REG_OUT1, REG_PV, disp);
2959
2960                         /* arg 2 = pointer to dimensions = stack pointer (absolute) */
2961
2962                         M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
2963
2964                         /* XXX c abi call */
2965                         disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2966                         M_ALD(REG_ITMP3, REG_PV, disp);
2967                         M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2968                         M_NOP;
2969
2970                         /* check for exception before result assignment */
2971
2972                         emit_exception_check(cd, iptr);
2973
2974                         d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2975                         M_INTMOVE(REG_RESULT_CALLER, d);
2976                         emit_store_dst(jd, iptr, d);
2977                         break;
2978
2979                 default:
2980                         exceptions_throw_internalerror("Unknown ICMD %d during code generation",
2981                                                                                    iptr->opc);
2982                         return false;
2983                         
2984         } /* switch */
2985                 
2986         } /* for instruction */
2987
2988         MCODECHECK(64);
2989         
2990         /* At the end of a basic block we may have to append some nops,
2991            because the patcher stub calling code might be longer than the
2992            actual instruction. So codepatching does not change the
2993            following block unintentionally. */
2994
2995         if (cd->mcodeptr < cd->lastmcodeptr) {
2996                 while (cd->mcodeptr < cd->lastmcodeptr) {
2997                         M_NOP;
2998                 }
2999         }
3000                 
3001         } /* if (bptr -> flags >= BBREACHED) */
3002         } /* for basic block */
3003         
3004         dseg_createlinenumbertable(cd);
3005
3006         /* generate stubs */
3007
3008         emit_patcher_stubs(jd);
3009         REPLACEMENT_EMIT_STUBS(jd);
3010         
3011         /* everything's ok */
3012
3013         return true;    
3014 }
3015
3016
3017 /* codegen_emit_stub_compiler **************************************************
3018
3019    Emits a stub routine which calls the compiler.
3020         
3021 *******************************************************************************/
3022
3023 void codegen_emit_stub_compiler(jitdata *jd)
3024 {
3025         methodinfo  *m;
3026         codegendata *cd;
3027
3028         /* get required compiler data */
3029
3030         m  = jd->m;
3031         cd = jd->cd;
3032
3033         /* code for the stub */
3034
3035         /* no window save yet, user caller's PV */
3036         M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P);  /* codeinfo pointer */
3037         M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P);  /* pointer to compiler */
3038         M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO);  /* jump to the compiler, RA is wasted */
3039         M_NOP;
3040 }
3041
3042
3043 /* codegen_emit_stub_native ****************************************************
3044
3045    Emits a stub routine which calls a native method.
3046
3047 *******************************************************************************/
3048
3049 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3050 {
3051         methodinfo   *m;
3052         codeinfo     *code;
3053         codegendata  *cd;
3054         methoddesc   *md;
3055         s4            nativeparams;
3056         s4            i, j;                 /* count variables                    */
3057         s4            t;
3058         s4            s1, s2, disp;
3059         s4            funcdisp;             /* displacement of the function       */
3060         s4            fltregarg_offset[FLT_ARG_CNT];
3061
3062         /* get required compiler data */
3063
3064         m    = jd->m;
3065         code = jd->code;
3066         cd   = jd->cd;
3067
3068         /* initialize variables */
3069
3070         md = m->parseddesc;
3071         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3072
3073         /* calculate stack frame size */
3074
3075         cd->stackframesize =
3076                 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3077                 sizeof(localref_table) / SIZEOF_VOID_P +
3078                 md->paramcount +                /* for saving arguments over calls    */
3079                 nmd->memuse +  /* nmd knows about the native stackframe layout */
3080                 WINSAVE_CNT;
3081
3082
3083         /* keep stack 16-byte aligned (ABI requirement) */
3084
3085         if (cd->stackframesize & 1)
3086                 cd->stackframesize++;
3087
3088         /* create method header */
3089
3090         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
3091         (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize       */
3092         (void) dseg_add_unique_s4(cd, 0);                      /* IsSync          */
3093         (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
3094         (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
3095         (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
3096         (void) dseg_addlinenumbertablesize(cd);
3097         (void) dseg_add_unique_s4(cd, 0);                      /* ExTableSize     */
3098
3099         /* generate stub code */
3100
3101         M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe    */
3102
3103 #if !defined(NDEBUG)
3104         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3105                 emit_verbosecall_enter(jd);
3106 #endif
3107
3108         /* get function address (this must happen before the stackframeinfo) */
3109
3110         funcdisp = dseg_add_functionptr(cd, f);
3111
3112 #if !defined(WITH_STATIC_CLASSPATH)
3113         if (f == NULL) {
3114                 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
3115         }
3116 #endif
3117
3118         /* save float argument registers (into abi parameter slots) */
3119
3120         assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
3121
3122         for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3123                 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3124                         s1 = WINSAVE_CNT + nmd->memuse + j;
3125                         M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
3126                         fltregarg_offset[i] = s1; /* remember stack offset */
3127                         j++;
3128                 }
3129         }
3130
3131         /* prepare data structures for native function call */
3132
3133         M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */
3134         M_MOV(REG_PV_CALLEE, REG_OUT1);
3135         M_MOV(REG_FP, REG_OUT2); /* java sp */
3136         M_MOV(REG_RA_CALLEE, REG_OUT3);
3137         disp = dseg_add_functionptr(cd, codegen_start_native_call);
3138         M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3139         M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3140         M_NOP; /* XXX fill me! */
3141
3142         /* keep float arguments on stack */
3143 #if 0
3144         for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3145                 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3146                         M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
3147                         j++;
3148                 }
3149         }
3150 #endif
3151
3152         /* copy or spill arguments to new locations */
3153
3154         for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3155                 t = md->paramtypes[i].type;
3156
3157                 if (IS_INT_LNG_TYPE(t)) {
3158
3159                         /* integral types */
3160
3161                         if (!md->params[i].inmemory) {
3162                                 s1 = md->params[i].regoff;
3163                                 /* s1 refers to the old window, transpose */
3164                                 s1 = REG_WINDOW_TRANSPOSE(s1);
3165
3166                                 if (!nmd->params[j].inmemory) {
3167                                         s2 = nat_argintregs[nmd->params[j].regoff];
3168                                         M_INTMOVE(s1, s2);
3169                                 } else {
3170                                         s2 = nmd->params[j].regoff - 6 * 8;
3171                                         M_AST(s1, REG_SP, CSTACK + s2);
3172                                 }
3173
3174                         } else {
3175                                 if (!nmd->params[j].inmemory) {
3176                                         /* JIT stack arg -> NAT reg arg */
3177
3178                                         /* Due to the Env pointer that is always passed, the 6th JIT arg   */
3179                                         /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */
3180
3181                                         assert(false); /* path never taken */
3182                                 }
3183
3184                                 s1 = md->params[i].regoff + cd->stackframesize * 8;
3185                                 s2 = nmd->params[j].regoff - 6 * 8;
3186                                 M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
3187                                 M_AST(REG_ITMP1, REG_SP, CSTACK + s2);
3188                         }
3189
3190                 } else {
3191
3192                         /* floating point types */
3193
3194                         if (!md->params[i].inmemory) {
3195                                 s1 = md->params[i].regoff;
3196
3197                                 if (!nmd->params[j].inmemory) {
3198
3199                                         /* no mapping to regs needed, native flt args use regoff */
3200                                         s2 = nmd->params[j].regoff;
3201
3202                                         /* JIT float regs are still on the stack */
3203                                         M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8));
3204                                 } 
3205                                 else {
3206                                         /* not supposed to happen with 16 NAT flt args */
3207                                         assert(false); 
3208                                         /*
3209                                         s2 = nmd->params[j].regoff;
3210                                         if (IS_2_WORD_TYPE(t))
3211                                                 M_DST(s1, REG_SP, CSTACK + (s2 * 8));
3212                                         else
3213                                                 M_FST(s1, REG_SP, CSTACK + (s2 * 8));
3214                                         */
3215                                 }
3216
3217                         } 
3218                         else {
3219                                 s1 = md->params[i].regoff + cd->stackframesize * 8;
3220
3221                                 if (!nmd->params[j].inmemory) {
3222
3223                                         /* JIT stack -> NAT reg */
3224
3225                                         s2 = nmd->params[j].regoff; 
3226                                         M_DLD(s2, REG_SP, CSTACK + s1);
3227                                 }
3228                                 else {
3229
3230                                         /* JIT stack -> NAT stack */
3231
3232                                         s2 = nmd->params[j].regoff - 6 * 8;
3233
3234                                         /* The FTMP register may already be loaded with args */
3235                                         /* we know $f0 is unused because of the env pointer  */
3236                                         M_DLD(REG_F0, REG_SP, CSTACK + s1);
3237                                         M_DST(REG_F0, REG_SP, CSTACK + s2);
3238                                 }
3239                         }
3240                 }
3241         }
3242         
3243
3244         /* put class into second argument register */
3245
3246         if (m->flags & ACC_STATIC) {
3247                 disp = dseg_add_address(cd, m->class);
3248                 M_ALD(REG_OUT1, REG_PV_CALLEE, disp);
3249         }
3250
3251         /* put env into first argument register */
3252
3253         disp = dseg_add_address(cd, _Jv_env);
3254         M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
3255
3256         /* do the native function call */
3257
3258         M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method       */
3259         M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method                 */
3260         M_NOP;                              /* delay slot                         */
3261
3262         /* save return value */
3263
3264         if (md->returntype.type != TYPE_VOID) {
3265                 if (IS_INT_LNG_TYPE(md->returntype.type))
3266                         M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3267                 else
3268                         M_DST(REG_FRESULT, REG_SP, CSTACK);
3269         }
3270         
3271         /* Note: native functions return float values in %f0 (see ABI) */
3272         /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
3273
3274 #if !defined(NDEBUG)
3275         /* But for the trace function we need to put a flt result into %f1 */
3276         if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3277                 if (!IS_2_WORD_TYPE(md->returntype.type))
3278                         M_FLD(REG_FRESULT, REG_SP, CSTACK);
3279                 emit_verbosecall_exit(jd);
3280         }
3281 #endif
3282
3283         /* remove native stackframe info */
3284
3285         M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3286         disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3287         M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3288         M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3289         M_NOP; /* XXX fill me! */
3290         M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
3291
3292         /* restore float return value, int return value already in our return reg */
3293
3294         if (md->returntype.type != TYPE_VOID) {
3295                 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3296                         if (IS_2_WORD_TYPE(md->returntype.type))
3297                                 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3298                         else
3299                                 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3300                 }
3301         }
3302
3303         /* check for exception */
3304         M_BNEZ(REG_ITMP2_XPTR, 4);          /* if no exception then return        */
3305         M_NOP;
3306
3307         M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3308         M_NOP;
3309
3310         /* handle exception */
3311         
3312         disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3313         M_ALD(REG_ITMP1, REG_PV, disp);     /* load asm exception handler address */
3314         M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address             */
3315         M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler     */
3316         M_RESTORE(REG_ZERO, 0, REG_ZERO);   /* restore callers window (DELAY)     */
3317         
3318         /* generate patcher stubs */
3319
3320         emit_patcher_stubs(jd);
3321 }
3322
3323 /*
3324  * These are local overrides for various environment variables in Emacs.
3325  * Please do not remove this and leave it at the end of the file, where
3326  * Emacs will automagically detect them.
3327  * ---------------------------------------------------------------------
3328  * Local variables:
3329  * mode: c
3330  * indent-tabs-mode: t
3331  * c-basic-offset: 4
3332  * tab-width: 4
3333  * End:
3334  * vim:noexpandtab:sw=4:ts=4:
3335  */