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