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