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