* merged with tip (040f180a056b)
[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.h"
41 #include "native/native.h"
42
43 #include "threads/lock-common.h"
44
45 #include "vm/builtin.h"
46 #include "vm/exceptions.hpp"
47 #include "vm/global.h"
48 #include "vm/loader.h"
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.h"
55 #include "vm/jit/dseg.h"
56 #include "vm/jit/emit-common.h"
57 #include "vm/jit/jit.h"
58 #include "vm/jit/jitcache.h"
59 #include "vm/jit/linenumbertable.h"
60 #include "vm/jit/methodheader.h"
61 #include "vm/jit/parse.h"
62 #include "vm/jit/patcher-common.h"
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                         M_CVTIF(s1, d);
1055                         emit_store_dst(jd, iptr, d);
1056                         break;
1057
1058                 case ICMD_I2D:       /* ..., value  ==> ..., (double) value           */
1059
1060                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1061                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1062                         M_CVTID(s1, d);
1063                         emit_store_dst(jd, iptr, d);
1064                         break;
1065
1066                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1067
1068                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1069                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1070                         /* this uses round towards zero, as Java likes it */
1071                         M_CVTFI(s1, d);
1072 #if !defined(__VFP_FP__)
1073                         /* this checks for NaN; to return zero as Java likes it */
1074                         M_FCMP(s1, 0x8);
1075                         M_MOVVS_IMM(0, d);
1076 #endif
1077                         emit_store_dst(jd, iptr, d);
1078                         break;
1079
1080                 case ICMD_D2I:       /* ..., value  ==> ..., (int) value              */
1081
1082                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1083                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1084                         /* this uses round towards zero, as Java likes it */
1085                         M_CVTDI(s1, d);
1086 #if !defined(__VFP_FP__)
1087                         /* this checks for NaN; to return zero as Java likes it */
1088                         M_DCMP(s1, 0x8);
1089                         M_MOVVS_IMM(0, d);
1090 #endif
1091                         emit_store_dst(jd, iptr, d);
1092                         break;
1093
1094                 case ICMD_D2F:       /* ..., value  ==> ..., (float) value            */
1095
1096                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1097                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1098                         M_CVTDF(s1, d);
1099                         emit_store_dst(jd, iptr, d);
1100                         break;
1101
1102                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1103
1104                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1105                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1106                         M_CVTFD(s1, d);
1107                         emit_store_dst(jd, iptr, d);
1108                         break;
1109
1110                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1111
1112                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1113                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1114                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1115                         M_FCMP(s2, s1);
1116                         M_MOV_IMM(d, 0);
1117 #if defined(__VFP_FP__)
1118                         M_FMSTAT; /* on VFP we need to transfer the flags */
1119 #endif
1120                         M_SUBGT_IMM(d, d, 1);
1121                         M_ADDLT_IMM(d, d, 1);
1122                         emit_store_dst(jd, iptr, d);
1123                         break;
1124
1125                 case ICMD_DCMPG:      /* ..., val1, val2  ==> ..., val1 dcmpg val2    */
1126
1127                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1128                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1129                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1130                         M_DCMP(s2, s1);
1131                         M_MOV_IMM(d, 0);
1132 #if defined(__VFP_FP__)
1133                         M_FMSTAT; /* on VFP we need to transfer the flags */
1134 #endif
1135                         M_SUBGT_IMM(d, d, 1);
1136                         M_ADDLT_IMM(d, d, 1);
1137                         emit_store_dst(jd, iptr, d);
1138                         break;
1139
1140                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1141
1142                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1143                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1144                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1145                         M_FCMP(s1, s2);
1146                         M_MOV_IMM(d, 0);
1147 #if defined(__VFP_FP__)
1148                         M_FMSTAT; /* on VFP we need to transfer the flags */
1149 #endif
1150                         M_SUBLT_IMM(d, d, 1);
1151                         M_ADDGT_IMM(d, d, 1);
1152                         emit_store_dst(jd, iptr, d);
1153                         break;
1154
1155                 case ICMD_DCMPL:      /* ..., val1, val2  ==> ..., val1 dcmpl val2    */
1156
1157                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1158                         s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1159                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1160                         M_DCMP(s1, s2);
1161                         M_MOV_IMM(d, 0);
1162 #if defined(__VFP_FP__)
1163                         M_FMSTAT; /* on VFP we need to transfer the flags */
1164 #endif
1165                         M_SUBLT_IMM(d, d, 1);
1166                         M_ADDGT_IMM(d, d, 1);
1167                         emit_store_dst(jd, iptr, d);
1168                         break;
1169
1170 #endif /* !defined(ENABLE_SOFTFLOAT) */
1171
1172
1173                 /* memory operations **************************************************/
1174
1175                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
1176
1177                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1178                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1179                         /* implicit null-pointer check */
1180                         M_ILD_INTERN(d, s1, OFFSET(java_array_t, size));
1181                         emit_store_dst(jd, iptr, d);
1182                         break;
1183
1184                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1185
1186                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1187                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1188                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1189                         /* implicit null-pointer check */
1190                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1191                         M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
1192                         M_LDRSB(d, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1193                         emit_store_dst(jd, iptr, d);
1194                         break;
1195
1196                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1197
1198                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1199                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1200                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1201                         /* implicit null-pointer check */
1202                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1203                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1204                         M_LDRH(d, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1205                         emit_store_dst(jd, iptr, d);
1206                         break;
1207
1208                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1209
1210                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1211                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1212                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1213                         /* implicit null-pointer check */
1214                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1215                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1216                         M_LDRSH(d, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
1217                         emit_store_dst(jd, iptr, d);
1218                         break;
1219
1220                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1221
1222                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1223                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1224                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1225                         /* implicit null-pointer check */
1226                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1227                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1228                         M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1229                         emit_store_dst(jd, iptr, d);
1230                         break;
1231
1232                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1233
1234                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1235                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1236                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1237                         /* implicit null-pointer check */
1238                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1239                         M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1240                         M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1241                         emit_store_dst(jd, iptr, d);
1242                         break;
1243
1244                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1245
1246                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1247                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1248                         /* implicit null-pointer check */
1249                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1250                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1251 #if !defined(ENABLE_SOFTFLOAT)
1252                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1253                         M_FLD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1254 #else
1255                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1256                         M_ILD_INTERN(d, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1257 #endif
1258                         emit_store_dst(jd, iptr, d);
1259                         break;
1260
1261                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1262
1263                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1264                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1265                         /* implicit null-pointer check */
1266                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1267                         M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1268 #if !defined(ENABLE_SOFTFLOAT)
1269                         d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1270                         M_DLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1271 #else
1272                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1273                         M_LLD_INTERN(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1274 #endif
1275                         emit_store_dst(jd, iptr, d);
1276                         break;
1277
1278                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1279
1280                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1281                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1282                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1283                         /* implicit null-pointer check */
1284                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1285                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1286                         M_LDR_INTERN(d, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1287                         emit_store_dst(jd, iptr, d);
1288                         break;
1289
1290                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1291
1292                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1293                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1294                         /* implicit null-pointer check */
1295                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1296                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1297                         M_ADD(REG_ITMP1, s1, s2); /* REG_ITMP1 = s1 + 1 * s2 */
1298                         M_STRB(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1299                         break;
1300
1301                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1302
1303                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1304                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1305                         /* implicit null-pointer check */
1306                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1307                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1308                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1309                         M_STRH(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1310                         break;
1311
1312                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1313
1314                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1315                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1316                         /* implicit null-pointer check */
1317                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1318                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1319                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 1)); /* REG_ITMP1 = s1 + 2 * s2 */
1320                         M_STRH(s3, REG_ITMP1, OFFSET(java_shortarray_t, data[0]));
1321                         break;
1322
1323                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1324
1325                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1326                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1327                         /* implicit null-pointer check */
1328                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1329                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1330                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1331                         M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1332                         break;
1333
1334                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1335
1336                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1337                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1338                         /* implicit null-pointer check */
1339                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1340                         M_ADD(REG_ITMP3, s1, REG_LSL(s2, 3)); /* REG_ITMP3 = s1 + 8 * s2 */
1341                         s3 = emit_load_s3(jd, iptr, REG_ITMP12_PACKED);
1342                         M_LST_INTERN(s3, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1343                         break;
1344
1345                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1346
1347                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1348                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1349                         /* implicit null-pointer check */
1350                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1351                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1352 #if !defined(ENABLE_SOFTFLOAT)
1353                         s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1354                         M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1355 #else
1356                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1357                         M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1358 #endif
1359                         break;
1360
1361                 case ICMD_DASTORE:    /* ..., 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, 3)); /* REG_ITMP1 = s1 + 8 * s2 */
1368 #if !defined(ENABLE_SOFTFLOAT)
1369                         s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1370                         M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1371 #else
1372                         s3 = emit_load_s3(jd, iptr, REG_ITMP23_PACKED);
1373                         M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1374 #endif
1375                         break;
1376
1377                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1378
1379                         s1 = emit_load_s1(jd, iptr, REG_A0);
1380                         s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1381                         s3 = emit_load_s3(jd, iptr, REG_A1);
1382
1383                         /* implicit null-pointer check */
1384                         emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1385
1386                         /* move arguments to argument registers */
1387                         M_INTMOVE(s1, REG_A0);
1388                         M_INTMOVE(s3, REG_A1);
1389
1390                         /* call builtin function */
1391                         disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1392                         JITCACHE_ADD_CACHED_REF(
1393                                 code, CRT_BUILTIN_FP,
1394                                 builtintable_get_internal(BUILTIN_FAST_canstore), disp);
1395
1396                         M_DSEG_BRANCH(disp);
1397
1398                         /* recompute pv */
1399                         s1 = (s4) (cd->mcodeptr - cd->mcodebase);
1400                         M_RECOMPUTE_PV(s1);
1401
1402                         /* check resturn value of builtin */
1403                         emit_arraystore_check(cd, iptr);
1404
1405                         /* finally store address into array */
1406                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1407                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1408                         s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1409                         M_ADD(REG_ITMP1, s1, REG_LSL(s2, 2)); /* REG_ITMP1 = s1 + 4 * s2 */
1410                         M_STR_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1411                         break;
1412
1413                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
1414
1415                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1416                                 uf        = iptr->sx.s23.s3.uf;
1417                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1418                                 disp      = dseg_add_unique_address(cd, NULL);
1419
1420                                 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1421                         }
1422                         else {
1423                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1424                                 fieldtype = fi->type;
1425                                 disp      = dseg_add_address(cd, fi->value);
1426                                 JITCACHE_ADD_CACHED_REF(code, CRT_FIELDINFO_VALUE, fi, disp);
1427                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
1428                                         patcher_add_patch_ref(jd, PATCHER_initialize_class,
1429                                                             fi->clazz, 0);
1430                                 }
1431                         }
1432
1433                         M_DSEG_LOAD(REG_ITMP3, disp);
1434                         switch (fieldtype) {
1435                         case TYPE_INT:
1436 #if defined(ENABLE_SOFTFLOAT)
1437                         case TYPE_FLT:
1438 #endif
1439                         case TYPE_ADR:
1440                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1441                                 M_ILD_INTERN(d, REG_ITMP3, 0);
1442                                 break;
1443                         case TYPE_LNG:
1444 #if defined(ENABLE_SOFTFLOAT)
1445                         case TYPE_DBL:
1446 #endif
1447                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1448                                 M_LLD_INTERN(d, REG_ITMP3, 0);
1449                                 break;
1450 #if !defined(ENABLE_SOFTFLOAT)
1451                         case TYPE_FLT:
1452                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1453                                 M_FLD_INTERN(d, REG_ITMP3, 0);
1454                                 break;
1455                         case TYPE_DBL:
1456                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1457                                 M_DLD_INTERN(d, REG_ITMP3, 0);
1458                                 break;
1459 #endif
1460                         default:
1461                                 assert(0);
1462                         }
1463                         emit_store_dst(jd, iptr, d);
1464                         break;
1465
1466                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
1467
1468                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1469                                 uf        = iptr->sx.s23.s3.uf;
1470                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1471                                 disp      = dseg_add_unique_address(cd, NULL);
1472
1473                                 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1474                         }
1475                         else {
1476                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1477                                 fieldtype = fi->type;
1478                                 disp      = dseg_add_address(cd, fi->value);
1479                                 JITCACHE_ADD_CACHED_REF(code, CRT_FIELDINFO_VALUE, fi, disp);
1480                                 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
1481                                         patcher_add_patch_ref(jd, PATCHER_initialize_class,
1482                                                             fi->clazz, 0);
1483                                 }
1484                         }
1485
1486                         M_DSEG_LOAD(REG_ITMP3, disp);
1487                         switch (fieldtype) {
1488                         case TYPE_INT:
1489 #if defined(ENABLE_SOFTFLOAT)
1490                         case TYPE_FLT:
1491 #endif
1492                         case TYPE_ADR:
1493                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1494                                 M_IST_INTERN(s1, REG_ITMP3, 0);
1495                                 break;
1496                         case TYPE_LNG:
1497 #if defined(ENABLE_SOFTFLOAT)
1498                         case TYPE_DBL:
1499 #endif
1500                                 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
1501                                 M_LST_INTERN(s1, REG_ITMP3, 0);
1502                                 break;
1503 #if !defined(ENABLE_SOFTFLOAT)
1504                         case TYPE_FLT:
1505                                 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1506                                 M_FST_INTERN(s1, REG_ITMP3, 0);
1507                                 break;
1508                         case TYPE_DBL:
1509                                 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1510                                 M_DST_INTERN(s1, REG_ITMP3, 0);
1511                                 break;
1512 #endif
1513                         default:
1514                                 assert(0);
1515                         }
1516                         break;
1517
1518                 case ICMD_GETFIELD:   /* ..., objectref, value  ==> ...               */
1519
1520                         s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1521                         emit_nullpointer_check(cd, iptr, s1);
1522
1523
1524                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1525                                 uf        = iptr->sx.s23.s3.uf;
1526                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1527                                 disp      = 0;
1528                         }
1529                         else {
1530                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1531                                 fieldtype = fi->type;
1532                                 disp      = fi->offset;
1533                         }
1534
1535 #if !defined(ENABLE_SOFTFLOAT)
1536                         /* HACK: softnull checks on floats */
1537                         if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1538                                 emit_nullpointer_check_force(cd, iptr, s1);
1539 #endif
1540
1541                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1542                                 /* XXX REMOVE ME */
1543                                 uf = iptr->sx.s23.s3.uf;
1544
1545                                 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1546                         }
1547
1548                         switch (fieldtype) {
1549                         case TYPE_INT:
1550 #if defined(ENABLE_SOFTFLOAT)
1551                         case TYPE_FLT:
1552 #endif
1553                         case TYPE_ADR:
1554                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1555                                 M_ILD(d, s1, disp);
1556                                 break;
1557                         case TYPE_LNG:
1558 #if defined(ENABLE_SOFTFLOAT)
1559                         case TYPE_DBL:
1560 #endif
1561                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1562                                 M_LLD(d, s1, disp);
1563                                 break;
1564 #if !defined(ENABLE_SOFTFLOAT)
1565                         case TYPE_FLT:
1566                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1567                                 M_FLD(d, s1, disp);
1568                                 break;
1569                         case TYPE_DBL:
1570                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1571                                 M_DLD(d, s1, disp);
1572                                 break;
1573 #endif
1574                         default:
1575                                 assert(0);
1576                         }
1577                         emit_store_dst(jd, iptr, d);
1578                         break;
1579
1580                 case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
1581
1582                         s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1583                         emit_nullpointer_check(cd, iptr, s1);
1584
1585                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1586                                 uf        = iptr->sx.s23.s3.uf;
1587                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1588                                 disp      = 0;
1589                         }
1590                         else {
1591                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1592                                 fieldtype = fi->type;
1593                                 disp      = fi->offset;
1594                         }
1595
1596 #if !defined(ENABLE_SOFTFLOAT)
1597                         /* HACK: softnull checks on floats */
1598                         if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1599                                 emit_nullpointer_check_force(cd, iptr, s1);
1600 #endif
1601
1602                         switch (fieldtype) {
1603                         case TYPE_INT:
1604 #if defined(ENABLE_SOFTFLOAT)
1605                         case TYPE_FLT:
1606 #endif
1607                         case TYPE_ADR:
1608                                 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1609                                 break;
1610 #if defined(ENABLE_SOFTFLOAT)
1611                         case TYPE_DBL: /* fall through */
1612 #endif
1613                         case TYPE_LNG:
1614                                 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
1615                                 break;
1616 #if !defined(ENABLE_SOFTFLOAT)
1617                         case TYPE_FLT:
1618                         case TYPE_DBL:
1619                                 s2 = emit_load_s2(jd, iptr, REG_FTMP1);
1620                                 break;
1621 #endif
1622                         default:
1623                                 assert(0);
1624                         }
1625
1626                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1627                                 /* XXX REMOVE ME */
1628                                 uf = iptr->sx.s23.s3.uf;
1629
1630                                 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1631                         }
1632
1633                         switch (fieldtype) {
1634                         case TYPE_INT:
1635 #if defined(ENABLE_SOFTFLOAT)
1636                         case TYPE_FLT:
1637 #endif
1638                         case TYPE_ADR:
1639                                 M_IST(s2, s1, disp);
1640                                 break;
1641                         case TYPE_LNG:
1642 #if defined(ENABLE_SOFTFLOAT)
1643                         case TYPE_DBL:
1644 #endif
1645                                 M_LST(s2, s1, disp);
1646                                 break;
1647 #if !defined(ENABLE_SOFTFLOAT)
1648                         case TYPE_FLT:
1649                                 M_FST(s2, s1, disp);
1650                                 break;
1651                         case TYPE_DBL:
1652                                 M_DST(s2, s1, disp);
1653                                 break;
1654 #endif
1655                         default:
1656                                 assert(0);
1657                         }
1658                         break;
1659
1660
1661                 /* branch operations **************************************************/
1662
1663                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
1664
1665                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1666                         M_INTMOVE(s1, REG_ITMP1_XPTR);
1667                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1668                                 patcher_add_patch_ref(jd, PATCHER_resolve_class,
1669                                                                         iptr->sx.s23.s2.uc, 0);
1670                         }
1671                         disp = dseg_add_functionptr(cd, asm_handle_exception);
1672                         JITCACHE_ADD_CACHED_REF(code, CRT_ASM_HANDLE_EXCEPTION, NULL, disp);
1673                         M_DSEG_LOAD(REG_ITMP3, disp);
1674                         M_MOV(REG_ITMP2_XPC, REG_PC);
1675                         M_MOV(REG_PC, REG_ITMP3);
1676                         M_NOP;              /* nop ensures that XPC is less than the end  */
1677                                             /* of basic block                             */
1678                         break;
1679
1680                 case ICMD_GOTO:         /* ... ==> ...                                */
1681                 case ICMD_RET:
1682
1683                         emit_br(cd, iptr->dst.block);
1684                         break;
1685
1686                 case ICMD_JSR:          /* ... ==> ...                                */
1687
1688                         emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1689                         break;
1690                 
1691                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
1692                 case ICMD_IFNONNULL:
1693
1694                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1695                         M_TEQ_IMM(s1, 0);
1696                         emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE);
1697                         break;
1698
1699                 case ICMD_IFLT:         /* ..., value ==> ...                         */
1700                 case ICMD_IFLE:         /* op1 = target JavaVM pc, val.i = constant   */
1701                 case ICMD_IFGT:
1702                 case ICMD_IFGE:
1703                 case ICMD_IFEQ:
1704                 case ICMD_IFNE:
1705
1706                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1707                         M_COMPARE(s1, iptr->sx.val.i);
1708                         emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE);
1709                         break;
1710
1711                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
1712
1713                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1714                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1715                         if (iptr->sx.val.l == 0) {
1716                                 M_ORR_S(s1, s2, REG_ITMP3);
1717                         }
1718                         else {
1719                                 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1720                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1721                                 M_CMP(s1, REG_ITMP3);*/
1722                                 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1723                                 M_CMPEQ(s2, REG_ITMP3);
1724                         }
1725                         emit_beq(cd, iptr->dst.block);
1726                         break;
1727
1728                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
1729
1730                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1731                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1732                         if (iptr->sx.val.l == 0) {
1733                                 /* if high word is less than zero, the whole long is too */
1734                                 M_CMP_IMM(s1, 0);
1735                                 emit_blt(cd, iptr->dst.block);
1736                         }
1737                         else {
1738                                 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1739                                 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1740                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1741                                 M_CMP(s1, REG_ITMP3);*/
1742                                 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1743                                 M_MOVGT_IMM(2, REG_ITMP1);
1744                                 M_MOVEQ_IMM(1, REG_ITMP1);
1745
1746                                 /* low compare: x=x-1(ifLO) */
1747                                 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1748                                 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1749                                 M_CMP(s2, REG_ITMP3);*/
1750                                 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1751
1752                                 /* branch if (x LT 1) */
1753                                 M_CMP_IMM(REG_ITMP1, 1);
1754                                 emit_blt(cd, iptr->dst.block);
1755                         }
1756                         break;
1757
1758                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
1759
1760                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1761                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1762                         if (iptr->sx.val.l == 0) {
1763                                 /* if high word is less than zero, the whole long is too  */
1764                                 M_CMP_IMM(s1, 0);
1765                                 emit_blt(cd, iptr->dst.block);
1766
1767                                 /* ... otherwise the low word has to be zero (tricky!) */
1768                                 M_CMPEQ_IMM(s2, 0);
1769                                 emit_beq(cd, iptr->dst.block);
1770                         }
1771                         else {
1772                                 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1773                                 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1774                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1775                                 M_CMP(s1, REG_ITMP3);*/
1776                                 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1777                                 M_MOVGT_IMM(2, REG_ITMP1);
1778                                 M_MOVEQ_IMM(1, REG_ITMP1);
1779
1780                                 /* low compare: x=x+1(ifHI) */
1781                                 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1782                                 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1783                                 M_CMP(s2, REG_ITMP3);*/
1784                                 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1785
1786                                 /* branch if (x LE 1) */
1787                                 M_CMP_IMM(REG_ITMP1, 1);
1788                                 emit_ble(cd, iptr->dst.block);
1789                         }
1790                         break;
1791
1792                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
1793
1794                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1795                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1796                         if (iptr->sx.val.l == 0) {
1797                                 /* if high word is greater or equal zero, the whole long is too */
1798                                 M_CMP_IMM(s1, 0);
1799                                 emit_bge(cd, iptr->dst.block);
1800                         }
1801                         else {
1802                                 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1803                                 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1804                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1805                                 M_CMP(s1, REG_ITMP3);*/
1806                                 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1807                                 M_MOVGT_IMM(2, REG_ITMP1);
1808                                 M_MOVEQ_IMM(1, REG_ITMP1);
1809
1810                                 /* low compare: x=x-1(ifLO) */
1811                                 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1812                                 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1813                                 M_CMP(s2, REG_ITMP3);*/
1814                                 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1815
1816                                 /* branch if (x GE 1) */
1817                                 M_CMP_IMM(REG_ITMP1, 1);
1818                                 emit_bge(cd, iptr->dst.block);
1819                         }
1820                         break;
1821
1822                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
1823
1824                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1825                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1826 #if 0
1827                         if (iptr->sx.val.l == 0) {
1828                                 /* if high word is greater than zero, the whole long is too */
1829                                 M_CMP_IMM(s1, 0);
1830                                 M_BGT(0);
1831                                 codegen_add_branch_ref(cd, iptr->dst.block);
1832
1833                                 /* ... or high was zero and low is non zero (tricky!) */
1834                                 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1835                                 M_MOVLT_IMM(1, REG_ITMP3);
1836                                 M_ORR_S(REG_ITMP3, s2, REG_ITMP3);
1837                                 M_BNE(0);
1838                                 codegen_add_branch_ref(cd, iptr->dst.block);
1839                         }
1840                         else {
1841 #endif
1842                                 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1843                                 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1844                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1845                                 M_CMP(s1, REG_ITMP3);*/
1846                                 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1847                                 M_MOVGT_IMM(2, REG_ITMP1);
1848                                 M_MOVEQ_IMM(1, REG_ITMP1);
1849
1850                                 /* low compare: x=x+1(ifHI) */
1851                                 M_COMPARE(s2, (iptr->sx.val.l & 0xffffffff));
1852                                 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1853                                 M_CMP(s2, REG_ITMP3);*/
1854                                 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1855
1856                                 /* branch if (x GT 1) */
1857                                 M_CMP_IMM(REG_ITMP1, 1);
1858                                 emit_bgt(cd, iptr->dst.block);
1859 #if 0
1860                         }
1861 #endif
1862                         break;
1863
1864                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
1865
1866                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1867                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1868                         if (iptr->sx.val.l == 0) {
1869                                 M_ORR_S(s1, s2, REG_ITMP3);
1870                         }
1871                         else {
1872                                 M_COMPARE(s1, (iptr->sx.val.l >> 32));
1873                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1874                                 M_CMP(s1, REG_ITMP3);*/
1875                                 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1876                                 M_CMPEQ(s2, REG_ITMP3);
1877                         }
1878                         emit_bne(cd, iptr->dst.block);
1879                         break;
1880                         
1881                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
1882                 case ICMD_IF_ICMPNE:
1883                 case ICMD_IF_ICMPLT:
1884                 case ICMD_IF_ICMPLE:
1885                 case ICMD_IF_ICMPGT:
1886                 case ICMD_IF_ICMPGE:
1887
1888                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1889                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1890                         M_CMP(s1, s2);
1891                         emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE);
1892                         break;
1893
1894                 case ICMD_IF_ACMPEQ:    /* ..., value, value ==> ...                  */
1895                 case ICMD_IF_ACMPNE:
1896
1897                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1898                         s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1899                         M_CMP(s1, s2);
1900                         emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE);
1901                         break;
1902
1903                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
1904                                         /* op1 = target JavaVM pc                     */
1905
1906                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1907                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1908                         M_CMP(s1, s2);
1909
1910                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1911                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1912                         M_CMPEQ(s1, s2);
1913
1914                         emit_beq(cd, iptr->dst.block);
1915                         break;
1916
1917                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
1918                                         /* op1 = target JavaVM pc                     */
1919
1920                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1921                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1922                         M_CMP(s1, s2);
1923
1924                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1925                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1926                         M_CMPEQ(s1, s2);
1927
1928                         emit_bne(cd, iptr->dst.block);
1929                         break;
1930
1931                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
1932                                         /* op1 = target JavaVM pc                     */
1933
1934                         /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1935                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1936                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1937                         M_CMP(s1, s2);
1938                         M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1939                         M_MOVGT_IMM(2, REG_ITMP3);
1940                         M_MOVEQ_IMM(1, REG_ITMP3);
1941
1942                         /* low compare: x=x-1(ifLO) */
1943                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1944                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1945                         M_CMP(s1, s2);
1946                         M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1947
1948                         /* branch if (x LT 1) */
1949                         M_CMP_IMM(REG_ITMP3, 1);
1950                         emit_blt(cd, iptr->dst.block);
1951                         break;
1952
1953                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
1954                                         /* op1 = target JavaVM pc                     */
1955
1956                         /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1957                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1958                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1959                         M_CMP(s1, s2);
1960                         M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1961                         M_MOVGT_IMM(2, REG_ITMP3);
1962                         M_MOVEQ_IMM(1, REG_ITMP3);
1963
1964                         /* low compare: x=x-1(ifLO) */
1965                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1966                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1967                         M_CMP(s1, s2);
1968                         M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1969
1970                         /* branch if (x LE 1) */
1971                         M_CMP_IMM(REG_ITMP3, 1);
1972                         emit_ble(cd, iptr->dst.block);
1973                         break;
1974
1975                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
1976                                         /* op1 = target JavaVM pc                     */
1977
1978                         /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1979                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1980                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1981                         M_CMP(s1, s2);
1982                         M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1983                         M_MOVGT_IMM(2, REG_ITMP3);
1984                         M_MOVEQ_IMM(1, REG_ITMP3);
1985
1986                         /* low compare: x=x-1(ifLO) */
1987                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1988                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1989                         M_CMP(s1, s2);
1990                         M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1991
1992                         /* branch if (x GT 1) */
1993                         M_CMP_IMM(REG_ITMP3, 1);
1994                         emit_bgt(cd, iptr->dst.block);
1995                         break;
1996
1997                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
1998                                         /* op1 = target JavaVM pc                     */
1999
2000                         /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
2001                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2002                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2003                         M_CMP(s1, s2);
2004                         M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
2005                         M_MOVGT_IMM(2, REG_ITMP3);
2006                         M_MOVEQ_IMM(1, REG_ITMP3);
2007
2008                         /* low compare: x=x-1(ifLO) */
2009                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2010                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2011                         M_CMP(s1, s2);
2012                         M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
2013
2014                         /* branch if (x GE 1) */
2015                         M_CMP_IMM(REG_ITMP3, 1);
2016                         emit_bge(cd, iptr->dst.block);
2017                         break;
2018
2019                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2020                         {
2021                         s4 i, l;
2022                         branch_target_t *table;
2023
2024                         table = iptr->dst.table;
2025
2026                         l = iptr->sx.s23.s2.tablelow;
2027                         i = iptr->sx.s23.s3.tablehigh;
2028
2029                         /* calculate new index (index - low) */
2030                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2031                         if (l  == 0) {
2032                                 M_INTMOVE(s1, REG_ITMP1);
2033                         } else if (IS_IMM(l)) {
2034                                 M_SUB_IMM(REG_ITMP1, s1, l);
2035                         } else {
2036                                 ICONST(REG_ITMP2, l);
2037                                 M_SUB(REG_ITMP1, s1, REG_ITMP2);
2038                         }
2039
2040                         /* range check (index <= high-low) */
2041                         i = i - l + 1;
2042                         M_COMPARE(REG_ITMP1, i-1);
2043                         emit_bugt(cd, table[0].block);
2044
2045                         /* build jump table top down and use address of lowest entry */
2046
2047                         table += i;
2048
2049                         while (--i >= 0) {
2050                                 dseg_add_target(cd, table->block);
2051                                 --table;
2052                         }
2053                         }
2054
2055                         /* length of dataseg after last dseg_add_target is used by load */
2056                         /* TODO: this loads from data-segment */
2057                         M_ADD(REG_ITMP2, REG_PV, REG_LSL(REG_ITMP1, 2));
2058                         M_LDR(REG_PC, REG_ITMP2, -(cd->dseglen));
2059                         break;
2060
2061                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
2062                         {
2063                         s4 i;
2064                         lookup_target_t *lookup;
2065
2066                         lookup = iptr->dst.lookup;
2067
2068                         i = iptr->sx.s23.s2.lookupcount;
2069                         
2070                         /* compare keys */
2071                         MCODECHECK((i<<2)+8);
2072                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2073
2074                         while (--i >= 0) {
2075                                 M_COMPARE(s1, lookup->value);
2076                                 emit_beq(cd, lookup->target.block);
2077                                 lookup++;
2078                         }
2079
2080                         /* default branch */
2081                         emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2082                         }
2083                         break;
2084
2085                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
2086
2087 #if !defined(ENABLE_SOFTFLOAT)
2088                         REPLACEMENT_POINT_RETURN(cd, iptr);
2089                         s1 = emit_load_s1(jd, iptr, REG_FTMP1);
2090                         M_CAST_F2I(s1, REG_RESULT);
2091                         goto ICMD_RETURN_do;
2092 #endif
2093
2094                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
2095
2096                         REPLACEMENT_POINT_RETURN(cd, iptr);
2097                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
2098                         M_INTMOVE(s1, REG_RESULT);
2099                         goto ICMD_RETURN_do;
2100
2101                 case ICMD_DRETURN:      /* ..., 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_D2L(s1, REG_RESULT_PACKED);
2107                         goto ICMD_RETURN_do;
2108 #endif
2109
2110                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
2111
2112                         REPLACEMENT_POINT_RETURN(cd, iptr);
2113                         s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2114                         M_LNGMOVE(s1, REG_RESULT_PACKED);
2115                         goto ICMD_RETURN_do;
2116
2117                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
2118
2119                         REPLACEMENT_POINT_RETURN(cd, iptr);
2120                         s1 = emit_load_s1(jd, iptr, REG_RESULT);
2121                         M_INTMOVE(s1, REG_RESULT);
2122                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2123                                 patcher_add_patch_ref(jd, PATCHER_resolve_class,
2124                                                                         iptr->sx.s23.s2.uc, 0);
2125                         }
2126                         goto ICMD_RETURN_do;
2127
2128                 case ICMD_RETURN:       /* ...  ==> ...                               */
2129
2130                         REPLACEMENT_POINT_RETURN(cd, iptr);
2131                         ICMD_RETURN_do:
2132
2133 #if !defined(NDEBUG)
2134                         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2135                                 emit_verbosecall_exit(jd);
2136 #endif
2137
2138 #if defined(ENABLE_THREADS)
2139                         /* call monitorexit function */
2140
2141                         if (checksync && code_is_synchronized(code)) {
2142                                 /* stack offset for monitor argument */
2143
2144                                 s1 = rd->memuse * 8;
2145
2146                                 /* we need to save the proper return value */
2147
2148                                 switch (iptr->opc) {
2149                                 case ICMD_IRETURN:
2150                                 case ICMD_ARETURN:
2151                                 case ICMD_LRETURN:
2152                                 case ICMD_FRETURN: /* XXX TWISTI: is that correct? */
2153                                 case ICMD_DRETURN:
2154                                         M_STMFD(BITMASK_RESULT, REG_SP);
2155                                         s1 += 2 * 4;
2156                                         break;
2157                                 }
2158
2159                                 M_LDR(REG_A0, REG_SP, s1);
2160                                 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2161                                 JITCACHE_ADD_CACHED_REF(code,
2162                                         CRT_BUILTIN_FP, builtintable_get_internal(LOCK_monitor_exit),
2163                                         disp);
2164
2165                                 M_DSEG_BRANCH(disp);
2166
2167                                 /* we no longer need PV here, no more loading */
2168                                 /*s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2169                                 M_RECOMPUTE_PV(s1);*/
2170
2171                                 switch (iptr->opc) {
2172                                 case ICMD_IRETURN:
2173                                 case ICMD_ARETURN:
2174                                 case ICMD_LRETURN:
2175                                 case ICMD_FRETURN: /* XXX TWISTI: is that correct? */
2176                                 case ICMD_DRETURN:
2177                                         M_LDMFD(BITMASK_RESULT, REG_SP);
2178                                         break;
2179                                 }
2180                         }
2181 #endif
2182
2183                         /* deallocate stackframe for spilled variables */
2184
2185                         if ((cd->stackframesize / 4 - savedregs_num) > 0)
2186                                 M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - savedregs_num);
2187
2188                         /* restore callee saved registers + do return */
2189
2190                         if (savedregs_bitmask) {
2191                                 if (!code_is_leafmethod(code)) {
2192                                         savedregs_bitmask &= ~(1<<REG_LR);
2193                                         savedregs_bitmask |= (1<<REG_PC);
2194                                 }
2195                                 M_LDMFD(savedregs_bitmask, REG_SP);
2196                         }
2197
2198                         /* if LR was not on stack, we need to return manually */
2199
2200                         if (code_is_leafmethod(code))
2201                                 M_MOV(REG_PC, REG_LR);
2202                         break;
2203
2204                 case ICMD_BUILTIN:      /* ..., arg1, arg2, arg3 ==> ...              */
2205
2206                         bte = iptr->sx.s23.s3.bte;
2207                         md  = bte->md;
2208                         goto ICMD_INVOKE_do;
2209
2210                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2211                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2212                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
2213                 case ICMD_INVOKEINTERFACE:
2214
2215                         REPLACEMENT_POINT_INVOKE(cd, iptr);
2216
2217                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2218                                 lm = NULL;
2219                                 um = iptr->sx.s23.s3.um;
2220                                 md = um->methodref->parseddesc.md;
2221                         }
2222                         else {
2223                                 lm = iptr->sx.s23.s3.fmiref->p.method;
2224                                 um = NULL;
2225                                 md = lm->parseddesc;
2226                         }
2227
2228                 ICMD_INVOKE_do:
2229                         /* copy arguments to registers or stack location */
2230
2231                         s3 = md->paramcount;
2232
2233                         MCODECHECK((s3 << 1) + 64);
2234
2235                         for (s3 = s3 - 1; s3 >= 0; s3--) {
2236                                 var = VAR(iptr->sx.s23.s2.args[s3]);
2237                                 d   = md->params[s3].regoff;
2238
2239                                 if (var->flags & PREALLOC) /* argument was precolored? */
2240                                         continue;
2241
2242                                 /* TODO: document me */
2243 #if !defined(ENABLE_SOFTFLOAT)
2244                                 if (IS_INT_LNG_TYPE(var->type)) {
2245 #endif /* !defined(ENABLE_SOFTFLOAT) */
2246                                         if (!md->params[s3].inmemory) {
2247                                                 s1 = emit_load(jd, iptr, var, d);
2248
2249                                                 if (IS_2_WORD_TYPE(var->type))
2250                                                         M_LNGMOVE(s1, d);
2251                                                 else
2252                                                         M_INTMOVE(s1, d);
2253                                         }
2254                                         else {
2255                                                 if (IS_2_WORD_TYPE(var->type)) {
2256                                                         s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2257                                                         M_LST(s1, REG_SP, d);
2258                                                 }
2259                                                 else {
2260                                                         s1 = emit_load(jd, iptr, var, REG_ITMP1);
2261                                                         M_IST(s1, REG_SP, d);
2262                                                 }
2263                                         }
2264 #if !defined(ENABLE_SOFTFLOAT)
2265                                 }
2266                                 else {
2267                                         if (!md->params[s3].inmemory) {
2268                                                 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2269                                                 if (IS_2_WORD_TYPE(var->type))
2270                                                         M_CAST_D2L(s1, d);
2271                                                 else
2272                                                         M_CAST_F2I(s1, d);
2273                                         }
2274                                         else {
2275                                                 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2276                                                 if (IS_2_WORD_TYPE(var->type))
2277                                                         M_DST(s1, REG_SP, d);
2278                                                 else
2279                                                         M_FST(s1, REG_SP, d);
2280                                         }
2281                                 }
2282 #endif /* !defined(ENABLE_SOFTFLOAT) */
2283                         }
2284
2285                         switch (iptr->opc) {
2286                         case ICMD_BUILTIN:
2287
2288                                 if (bte->stub == NULL) {
2289                                         disp = dseg_add_functionptr(cd, bte->fp);
2290                                 } else {
2291                                         disp = dseg_add_functionptr(cd, bte->stub);
2292                                 }
2293
2294                                 JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN, bte, disp);
2295
2296                                 M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
2297
2298                                 /* generate the actual call */
2299
2300                                 M_MOV(REG_LR, REG_PC);
2301                                 M_MOV(REG_PC, REG_PV);
2302                                 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2303                                 M_RECOMPUTE_PV(s1);
2304                                 break;
2305
2306                         case ICMD_INVOKESPECIAL:
2307                                 emit_nullpointer_check(cd, iptr, REG_A0);
2308                                 /* fall through */
2309
2310                         case ICMD_INVOKESTATIC:
2311                                 if (lm == NULL) {
2312                                         disp = dseg_add_unique_address(cd, NULL);
2313
2314                                         patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2315                                                                                 um, disp);
2316                                 }
2317                                 else
2318                                 {
2319                                         disp = dseg_add_address(cd, lm->stubroutine);
2320                                         JITCACHE_ADD_CACHED_REF(code, CRT_METHODINFO_STUBROUTINE, lm, disp);
2321                                 }
2322
2323                                 M_DSEG_LOAD(REG_PV, disp);            /* Pointer to method */
2324
2325                                 /* generate the actual call */
2326
2327                                 M_MOV(REG_LR, REG_PC);
2328                                 M_MOV(REG_PC, REG_PV);
2329                                 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2330                                 M_RECOMPUTE_PV(s1);
2331                                 break;
2332
2333                         case ICMD_INVOKEVIRTUAL:
2334                                 if (lm == NULL) {
2335
2336                                         patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2337
2338                                         s1 = 0;
2339                                 }
2340                                 else
2341                                         s1 = OFFSET(vftbl_t, table[0]) +
2342                                                 sizeof(methodptr) * lm->vftblindex;
2343                                 
2344
2345                                 /* implicit null-pointer check */
2346                                 M_LDR_INTERN(REG_METHODPTR, REG_A0,
2347                                                          OFFSET(java_object_t, vftbl));
2348                                 M_LDR_INTERN(REG_PV, REG_METHODPTR, s1);
2349                                 /* generate the actual call */
2350
2351                                 M_MOV(REG_LR, REG_PC);
2352                                 M_MOV(REG_PC, REG_PV);
2353                                 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2354                                 M_RECOMPUTE_PV(s1);
2355                                 break;
2356
2357                         case ICMD_INVOKEINTERFACE:
2358                                 if (lm == NULL) {
2359                                         patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2360
2361                                         s1 = 0;
2362                                         s2 = 0;
2363                                 }
2364                                 else {
2365                                         s1 = OFFSET(vftbl_t, interfacetable[0]) -
2366                                                 sizeof(methodptr*) * lm->clazz->index;
2367                                         s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2368                                 }
2369
2370                                 /* implicit null-pointer check */
2371                                 M_LDR_INTERN(REG_METHODPTR, REG_A0,
2372                                                          OFFSET(java_object_t, vftbl));
2373                                 M_LDR_INTERN(REG_METHODPTR, REG_METHODPTR, s1);
2374
2375                                 M_LDR_INTERN(REG_PV, REG_METHODPTR, s2);
2376                                 JITCACHE_ADD_CACHED_REF_MD_JD(jd, CRT_METHODINFO_METHODOFFSET, 1, lm);
2377
2378                                 /* generate the actual call */
2379
2380                                 M_MOV(REG_LR, REG_PC);
2381                                 M_MOV(REG_PC, REG_PV);
2382                                 s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2383                                 M_RECOMPUTE_PV(s1);
2384                                 break;
2385                         }
2386
2387                         /* store size of call code in replacement point */
2388                         REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2389
2390                         /* store return value */
2391
2392                         d = md->returntype.type;
2393
2394 #if !defined(__SOFTFP__)
2395                         /* TODO: this is only a hack, since we use R0/R1 for float
2396                            return!  this depends on gcc; it is independent from
2397                            our ENABLE_SOFTFLOAT define */
2398                         if (iptr->opc == ICMD_BUILTIN && d != TYPE_VOID && IS_FLT_DBL_TYPE(d)) {
2399 #if 0 && !defined(NDEBUG)
2400                                 dolog("BUILTIN that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
2401 #endif
2402                                 /* we cannot use this macro, since it is not defined
2403                                    in ENABLE_SOFTFLOAT M_CAST_FLT_TO_INT_TYPED(d,
2404                                    REG_FRESULT, REG_RESULT_TYPED(d)); */
2405                                 if (IS_2_WORD_TYPE(d)) {
2406                                         DCD(0xed2d8102); /* stfd    f0, [sp, #-8]! */
2407                                         M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
2408                                 } else {
2409                                         DCD(0xed2d0101); /* stfs    f0, [sp, #-4]!*/
2410                                         M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
2411                                 }
2412                         }
2413 #endif
2414
2415                         if (d != TYPE_VOID) {
2416 #if !defined(ENABLE_SOFTFLOAT)
2417                                 if (IS_INT_LNG_TYPE(d)) {
2418 #endif /* !defined(ENABLE_SOFTFLOAT) */
2419                                         if (IS_2_WORD_TYPE(d)) {
2420                                                 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2421                                                 M_LNGMOVE(REG_RESULT_PACKED, s1);
2422                                         }
2423                                         else {
2424                                                 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2425                                                 M_INTMOVE(REG_RESULT, s1);
2426                                         }
2427
2428 #if !defined(ENABLE_SOFTFLOAT)
2429                                 } else {
2430                                         s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2431                                         if (IS_2_WORD_TYPE(d))
2432                                                 M_CAST_L2D(REG_RESULT_PACKED, s1);
2433                                         else
2434                                                 M_CAST_I2F(REG_RESULT, s1);
2435                                 }
2436 #endif /* !defined(ENABLE_SOFTFLOAT) */
2437
2438                                 emit_store_dst(jd, iptr, s1);
2439                         }
2440                         break;
2441
2442                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
2443
2444                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2445                                 /* object type cast-check */
2446
2447                         classinfo *super;
2448                         s4         superindex;
2449
2450                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2451                                 super      = NULL;
2452                                 superindex = 0;
2453                         }
2454                         else {
2455                                 super      = iptr->sx.s23.s3.c.cls;
2456                                 superindex = super->index;
2457                         }
2458
2459                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2460
2461                         /* if class is not resolved, check which code to call */
2462
2463                         if (super == NULL) {
2464                                 M_TST(s1, s1);
2465                                 emit_label_beq(cd, BRANCH_LABEL_1);
2466
2467                                 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2468                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2469                                                     iptr->sx.s23.s3.c.ref, disp);
2470
2471                                 M_DSEG_LOAD(REG_ITMP2, disp);
2472                                 disp = dseg_add_s4(cd, ACC_INTERFACE);
2473                                 M_DSEG_LOAD(REG_ITMP3, disp);
2474                                 M_TST(REG_ITMP2, REG_ITMP3);
2475                                 emit_label_beq(cd, BRANCH_LABEL_2);
2476                         }
2477
2478                         /* interface checkcast code */
2479
2480                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2481                                 if ((super == NULL) || !IS_IMM(superindex)) {
2482                                         disp = dseg_add_unique_s4(cd, superindex);
2483                                 }
2484                                 if (super == NULL) {
2485                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2486                                                             iptr->sx.s23.s3.c.ref, disp);
2487                                 }
2488                                 else {
2489 /*
2490                                         JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INDEX, super, disp);
2491 */
2492                                         M_TST(s1, s1);
2493                                         emit_label_beq(cd, BRANCH_LABEL_3);
2494                                 }
2495
2496                                 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2497                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2498
2499                                 /* we put unresolved or non-immediate superindices onto dseg */
2500                                 if ((super == NULL) || !IS_IMM(superindex)) {
2501                                         /* disp was computed before we added the patcher */
2502                                         M_DSEG_LOAD(REG_ITMP2, disp);
2503                                         M_CMP(REG_ITMP3, REG_ITMP2);
2504                                 } else {
2505                                         assert(IS_IMM(superindex));
2506                                         M_CMP_IMM(REG_ITMP3, superindex);
2507                                 }
2508
2509                                 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
2510
2511                                 /* if we loaded the superindex out of the dseg above, we do
2512                                    things differently here! */
2513                                 if ((super == NULL) || !IS_IMM(superindex)) {
2514
2515                                         M_LDR_INTERN(REG_ITMP3, s1, OFFSET(java_object_t, vftbl));
2516
2517                                         /* this assumes something */
2518                                         assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2519
2520                                         /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2521                                         assert(sizeof(methodptr*) == 4);
2522                                         M_SUB(REG_ITMP2, REG_ITMP3, REG_LSL(REG_ITMP2, 2));
2523
2524                                         s2 = 0;
2525
2526                                 } else {
2527
2528                                         s2 = OFFSET(vftbl_t, interfacetable[0]) -
2529                                                                 superindex * sizeof(methodptr*);
2530
2531                                 }
2532
2533                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, s2);
2534                                 M_TST(REG_ITMP3, REG_ITMP3);
2535                                 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
2536
2537                                 if (super == NULL)
2538                                         emit_label_br(cd, BRANCH_LABEL_4);
2539                                 else
2540                                         emit_label(cd, BRANCH_LABEL_3);
2541                         }
2542
2543                         /* class checkcast code */
2544
2545                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2546                                 if (super == NULL) {
2547                                         emit_label(cd, BRANCH_LABEL_2);
2548
2549                                         disp = dseg_add_unique_address(cd, NULL);
2550
2551                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2552                                                             iptr->sx.s23.s3.c.ref,
2553                                                                                 disp);
2554                                 }
2555                                 else {
2556                                         disp = dseg_add_address(cd, super->vftbl);
2557                                         JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO_VFTBL, super, disp);
2558                                         M_TST(s1, s1);
2559                                         emit_label_beq(cd, BRANCH_LABEL_5);
2560                                 }
2561
2562                                 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2563                                 M_DSEG_LOAD(REG_ITMP3, disp);
2564
2565                                 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2566                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2567                                 M_SUB(REG_ITMP2, REG_ITMP2, REG_ITMP3);
2568                                 M_DSEG_LOAD(REG_ITMP3, disp);
2569                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2570
2571                                 M_CMP(REG_ITMP2, REG_ITMP3);
2572                                 emit_classcast_check(cd, iptr, BRANCH_UGT, 0, s1);
2573
2574                                 if (super != NULL)
2575                                         emit_label(cd, BRANCH_LABEL_5);
2576                         }
2577
2578                         if (super == NULL) {
2579                                 emit_label(cd, BRANCH_LABEL_1);
2580                                 emit_label(cd, BRANCH_LABEL_4);
2581                         }
2582
2583                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2584                         }
2585                         else {
2586                                 /* array type cast-check */
2587
2588                                 s1 = emit_load_s1(jd, iptr, REG_A0);
2589                                 M_INTMOVE(s1, REG_A0);
2590
2591                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2592                                         disp = dseg_add_unique_address(cd, NULL);
2593
2594                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2595                                                                                 iptr->sx.s23.s3.c.ref,
2596                                                                                 disp);
2597                                 }
2598                                 else
2599                                 {
2600                                         disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2601                                         JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO, iptr->sx.s23.s3.c.cls, disp);
2602                                 }
2603
2604                                 M_DSEG_LOAD(REG_A1, disp);
2605                                 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2606                                 JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN, builtintable_get_internal(BUILTIN_arraycheckcast), disp);
2607                                 M_DSEG_BRANCH(disp);
2608
2609                                 /* recompute pv */
2610                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2611                                 M_RECOMPUTE_PV(disp);
2612
2613                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2614                                 M_TST(REG_RESULT, REG_RESULT);
2615                                 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2616
2617                                 d = codegen_reg_of_dst(jd, iptr, s1);
2618                         }
2619
2620                         M_INTMOVE(s1, d);
2621                         emit_store_dst(jd, iptr, d);
2622                         break;
2623
2624                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
2625
2626                         {
2627                         classinfo *super;
2628                         s4         superindex;
2629
2630                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2631                                 super      = NULL;
2632                                 superindex = 0;
2633                         }
2634                         else {
2635                                 super      = iptr->sx.s23.s3.c.cls;
2636                                 superindex = super->index;
2637                         }
2638
2639                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2640                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2641
2642                         if (s1 == d) {
2643                                 M_MOV(REG_ITMP1, s1);
2644                                 s1 = REG_ITMP1;
2645                         }
2646
2647                         /* if class is not resolved, check which code to call */
2648
2649                         if (super == NULL) {
2650                                 M_EOR(d, d, d);
2651
2652                                 M_TST(s1, s1);
2653                                 emit_label_beq(cd, BRANCH_LABEL_1);
2654
2655                                 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2656                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2657                                                     iptr->sx.s23.s3.c.ref, disp);
2658
2659                                 M_DSEG_LOAD(REG_ITMP2, disp);
2660                                 disp = dseg_add_s4(cd, ACC_INTERFACE);
2661                                 M_DSEG_LOAD(REG_ITMP3, disp);
2662                                 M_TST(REG_ITMP2, REG_ITMP3);
2663                                 emit_label_beq(cd, BRANCH_LABEL_2);
2664                         }
2665
2666                         /* interface checkcast code */
2667
2668                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2669                                 if ((super == NULL) || !IS_IMM(superindex)) {
2670                                         disp = dseg_add_unique_s4(cd, superindex);
2671                                 }
2672                                 if (super == NULL) {
2673                                         /* If d == REG_ITMP2, then it's destroyed in check
2674                                            code above.  */
2675                                         if (d == REG_ITMP2)
2676                                                 M_EOR(d, d, d);
2677
2678                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2679                                                             iptr->sx.s23.s3.c.ref, disp);
2680                                 }
2681                                 else {
2682 /* TODO: Not needed?
2683                                         JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO_INDEX, super, disp);
2684 */
2685                                         M_EOR(d, d, d);
2686                                         M_TST(s1, s1);
2687                                         emit_label_beq(cd, BRANCH_LABEL_3);
2688                                 }
2689
2690                                 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2691                                 M_LDR_INTERN(REG_ITMP3,
2692                                                          REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2693
2694                                 /* we put unresolved or non-immediate superindices onto dseg
2695                                    and do things slightly different */
2696                                 if ((super == NULL) || !IS_IMM(superindex)) {
2697                                         /* disp was computed before we added the patcher */
2698                                         M_DSEG_LOAD(REG_ITMP2, disp);
2699                                         M_CMP(REG_ITMP3, REG_ITMP2);
2700
2701                                         if (d == REG_ITMP2) {
2702                                                 M_EORLE(d, d, d);
2703                                                 M_BLE(4);
2704                                         } else {
2705                                                 M_BLE(3);
2706                                         }
2707
2708                                         /* this assumes something */
2709                                         assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2710
2711                                         /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2712                                         assert(sizeof(methodptr*) == 4);
2713                                         M_SUB(REG_ITMP1, REG_ITMP1, REG_LSL(REG_ITMP2, 2));
2714
2715                                         if (d == REG_ITMP2) {
2716                                                 M_EOR(d, d, d);
2717                                         }
2718
2719                                         s2 = 0;
2720
2721                                 } else {
2722                                         assert(IS_IMM(superindex));
2723                                         M_CMP_IMM(REG_ITMP3, superindex);
2724
2725                                         M_BLE(2);
2726
2727                                         s2 = OFFSET(vftbl_t, interfacetable[0]) -
2728                                                 superindex * sizeof(methodptr*);
2729
2730                                 }
2731
2732                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP1, s2);
2733                                 M_TST(REG_ITMP3, REG_ITMP3);
2734                                 M_MOVNE_IMM(1, d);
2735
2736                                 if (super == NULL)
2737                                         emit_label_br(cd, BRANCH_LABEL_4);
2738                                 else
2739                                         emit_label(cd, BRANCH_LABEL_3);
2740                         }
2741
2742                         /* class checkcast code */
2743
2744                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2745                                 if (super == NULL) {
2746                                         emit_label(cd, BRANCH_LABEL_2);
2747
2748                                         disp = dseg_add_unique_address(cd, NULL);
2749
2750                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2751                                                             iptr->sx.s23.s3.c.ref, disp);
2752                                 }
2753                                 else {
2754                                         disp = dseg_add_address(cd, super->vftbl);
2755                                         JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO_VFTBL, super, disp);
2756
2757                                         M_EOR(d, d, d);
2758                                         M_TST(s1, s1);
2759                                         emit_label_beq(cd, BRANCH_LABEL_5);
2760                                 }
2761
2762                                 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2763                                 M_DSEG_LOAD(REG_ITMP2, disp);
2764
2765                                 M_LDR_INTERN(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2766                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2767                                 M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2768
2769                                 M_SUB(REG_ITMP1, REG_ITMP1, REG_ITMP3);
2770                                 M_CMP(REG_ITMP1, REG_ITMP2);
2771                                 /* If d == REG_ITMP2, then it's destroyed */
2772                                 if (d == REG_ITMP2)
2773                                         M_EOR(d, d, d);
2774                                 M_MOVLS_IMM(1, d);
2775
2776                                 if (super != NULL)
2777                                         emit_label(cd, BRANCH_LABEL_5);
2778                         }
2779
2780                         if (super == NULL) {
2781                                 emit_label(cd, BRANCH_LABEL_1);
2782                                 emit_label(cd, BRANCH_LABEL_4);
2783                         }
2784
2785                         }
2786
2787                         emit_store_dst(jd, iptr, d);
2788                         break;
2789
2790                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
2791
2792                         /* copy sizes to stack if necessary  */
2793
2794                         MCODECHECK((iptr->s1.argcount << 1) + 64);
2795
2796                         for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2797
2798                                 var = VAR(iptr->sx.s23.s2.args[s1]);
2799         
2800                                 /* copy SAVEDVAR sizes to stack */
2801
2802                                 if (!(var->flags & PREALLOC)) {
2803                                         s2 = emit_load(jd, iptr, var, REG_ITMP1);
2804                                         M_STR(s2, REG_SP, s1 * 4);
2805                                 }
2806                         }
2807
2808                         /* a0 = dimension count */
2809
2810                         assert(IS_IMM(iptr->s1.argcount));
2811                         M_MOV_IMM(REG_A0, iptr->s1.argcount);
2812
2813                         /* is patcher function set? */
2814
2815                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2816                                 disp = dseg_add_unique_address(cd, NULL);
2817
2818                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2819                                                                         iptr->sx.s23.s3.c.ref, disp);
2820                         }
2821                         else
2822                         {
2823                                 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2824                                 JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO, iptr->sx.s23.s3.c.cls, disp);
2825                         }
2826
2827                         /* a1 = arraydescriptor */
2828
2829                         M_DSEG_LOAD(REG_A1, disp);
2830
2831                         /* a2 = pointer to dimensions = stack pointer */
2832
2833                         M_INTMOVE(REG_SP, REG_A2);
2834
2835                         /* call builtin_multianewarray here */
2836
2837                         disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2838                         /*
2839                         * For some unknown reason this causes an illegal instruction.
2840                         * JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN, builtintable_get_internal(BUILTIN_multianewarray), disp);
2841                         */
2842
2843                         M_DSEG_BRANCH(disp);
2844
2845                         /* recompute pv */
2846
2847                         s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2848                         M_RECOMPUTE_PV(s1);
2849
2850                         /* check for exception before result assignment */
2851
2852                         emit_exception_check(cd, iptr);
2853
2854                         /* get arrayref */
2855
2856                         d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2857                         M_INTMOVE(REG_RESULT, d);
2858                         emit_store_dst(jd, iptr, d);
2859                         break;
2860
2861                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
2862
2863                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2864                         emit_nullpointer_check(cd, iptr, s1);
2865                         break;
2866
2867                 default:
2868                         exceptions_throw_internalerror("Unknown ICMD %d during code generation",
2869                                                                                    iptr->opc);
2870                         return false;
2871                 } /* the big switch */
2872
2873                 } /* for all instructions */
2874
2875         } /* for all basic blocks */
2876
2877         /* generate traps */
2878
2879         emit_patcher_traps(jd);
2880
2881         /* everything's ok */
2882
2883         return true;
2884 }
2885
2886
2887 /* codegen_emit_stub_compiler **************************************************
2888
2889    Emits a stub routine which calls the compiler.
2890         
2891 *******************************************************************************/
2892
2893 void codegen_emit_stub_compiler(jitdata *jd)
2894 {
2895         methodinfo  *m;
2896         codegendata *cd;
2897
2898         /* get required compiler data */
2899
2900         m  = jd->m;
2901         cd = jd->cd;
2902
2903         /* code for the stub */
2904
2905         M_LDR_INTERN(REG_ITMP1, REG_PC, -(2 * 4 + 2 * SIZEOF_VOID_P));
2906         M_LDR_INTERN(REG_PC, REG_PC, -(3 * 4 + 3 * SIZEOF_VOID_P));
2907 }
2908
2909
2910 /* codegen_emit_stub_native ****************************************************
2911
2912    Emits a stub routine which calls a native method.
2913
2914 *******************************************************************************/
2915
2916 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2917 {
2918         methodinfo  *m;
2919         codeinfo    *code;
2920         codegendata *cd;
2921         methoddesc  *md;
2922         s4           i, j;
2923         s4           t;
2924         int          s1, s2;
2925         int          disp;
2926
2927         /* get required compiler data */
2928
2929         m    = jd->m;
2930         code = jd->code;
2931         cd   = jd->cd;
2932
2933         /* initialize variables */
2934
2935         md = m->parseddesc;
2936
2937         /* calculate stackframe size */
2938
2939         cd->stackframesize =
2940                 4 +                                                /* return address  */
2941                 sizeof(stackframeinfo_t) +                         /* stackframeinfo  */
2942                 sizeof(localref_table) +                           /* localref_table  */
2943                 nmd->memuse * 4;                                   /* stack arguments */
2944
2945         /* align stack to 8-byte */
2946
2947         cd->stackframesize = (cd->stackframesize + 4) & ~4;
2948
2949         /* create method header */
2950
2951         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
2952         (void) dseg_add_unique_s4(cd, cd->stackframesize);     /* FrameSize       */
2953         (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
2954         (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
2955         (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
2956
2957         /* generate stub code */
2958
2959         M_STMFD(1<<REG_LR, REG_SP);
2960         M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
2961
2962 #if !defined(NDEBUG)
2963         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2964                 emit_verbosecall_enter(jd);
2965 #endif
2966
2967 #if defined(ENABLE_GC_CACAO)
2968         /* Save callee saved integer registers in stackframeinfo (GC may
2969            need to recover them during a collection). */
2970
2971         disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
2972                 OFFSET(stackframeinfo_t, intregs);
2973
2974         for (i = 0; i < INT_SAV_CNT; i++)
2975                 M_STR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2976 #endif
2977
2978         /* Save integer and float argument registers (these are 4
2979            registers, stack is 8-byte aligned). */
2980
2981         M_STMFD(BITMASK_ARGS, REG_SP);
2982         /* TODO: floating point */
2983
2984         /* create native stackframe info */
2985
2986         M_ADD_IMM(REG_A0, REG_SP, 4*4);
2987         M_MOV(REG_A1, REG_PV);
2988         disp = dseg_add_functionptr(cd, codegen_start_native_call);
2989         M_DSEG_BRANCH(disp);
2990
2991         /* recompute pv */
2992
2993         s1 = (s4) (cd->mcodeptr - cd->mcodebase);
2994         M_RECOMPUTE_PV(s1);
2995
2996         /* remember class argument */
2997
2998         if (m->flags & ACC_STATIC)
2999                 M_MOV(REG_ITMP3, REG_RESULT);
3000
3001         /* Restore integer and float argument registers (these are 4
3002            registers, stack is 8-byte aligned). */
3003
3004         M_LDMFD(BITMASK_ARGS, REG_SP);
3005         /* TODO: floating point */
3006
3007         /* copy or spill arguments to new locations */
3008         /* ATTENTION: the ARM has only integer argument registers! */
3009
3010         for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3011                 t = md->paramtypes[i].type;
3012
3013                 if (!md->params[i].inmemory) {
3014                         s1 = md->params[i].regoff;
3015                         s2 = nmd->params[j].regoff;
3016
3017                         if (!nmd->params[j].inmemory) {
3018 #if !defined(__ARM_EABI__)
3019                                 SPLIT_OPEN(t, s2, REG_ITMP1);
3020 #endif
3021
3022                                 if (IS_2_WORD_TYPE(t))
3023                                         M_LNGMOVE(s1, s2);
3024                                 else
3025                                         M_INTMOVE(s1, s2);
3026
3027 #if !defined(__ARM_EABI__)
3028                                 SPLIT_STORE_AND_CLOSE(t, s2, 0);
3029 #endif
3030                         }
3031                         else {
3032                                 if (IS_2_WORD_TYPE(t))
3033                                         M_LST(s1, REG_SP, s2);
3034                                 else
3035                                         M_IST(s1, REG_SP, s2);
3036                         }
3037                 }
3038                 else {
3039                         s1 = md->params[i].regoff + cd->stackframesize;
3040                         s2 = nmd->params[j].regoff;
3041
3042                         if (IS_2_WORD_TYPE(t)) {
3043                                 M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
3044                                 M_LST(REG_ITMP12_PACKED, REG_SP, s2);
3045                         }
3046                         else {
3047                                 M_ILD(REG_ITMP1, REG_SP, s1);
3048                                 M_IST(REG_ITMP1, REG_SP, s2);
3049                         }
3050                 }
3051         }
3052
3053         /* Handle native Java methods. */
3054
3055         if (m->flags & ACC_NATIVE) {
3056                 /* put class into second argument register */
3057
3058                 if (m->flags & ACC_STATIC)
3059                         M_MOV(REG_A1, REG_ITMP3);
3060
3061                 /* put env into first argument register */
3062
3063                 disp = dseg_add_address(cd, VM_get_jnienv());
3064                 M_DSEG_LOAD(REG_A0, disp);
3065         }
3066
3067         /* Call the native function. */
3068
3069         disp = dseg_add_functionptr(cd, f);
3070         M_DSEG_BRANCH(disp);
3071
3072         /* recompute pv */
3073         /* TODO: this is only needed because of the tracer ... do we
3074            really need it? */
3075
3076         s1 = (s4) (cd->mcodeptr - cd->mcodebase);
3077         M_RECOMPUTE_PV(s1);
3078
3079 #if !defined(__SOFTFP__)
3080         /* TODO: this is only a hack, since we use R0/R1 for float return! */
3081         /* this depends on gcc; it is independent from our ENABLE_SOFTFLOAT define */
3082         if (md->returntype.type != TYPE_VOID && IS_FLT_DBL_TYPE(md->returntype.type)) {
3083 #if 0 && !defined(NDEBUG)
3084                 dolog("NATIVESTUB that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
3085 #endif
3086                 /* we cannot use this macro, since it is not defined in ENABLE_SOFTFLOAT */
3087                 /* M_CAST_FLT_TO_INT_TYPED(md->returntype.type, REG_FRESULT, REG_RESULT_TYPED(md->returntype.type)); */
3088                 if (IS_2_WORD_TYPE(md->returntype.type)) {
3089                         DCD(0xed2d8102); /* stfd    f0, [sp, #-8]! */
3090                         M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
3091                 } else {
3092                         DCD(0xed2d0101); /* stfs    f0, [sp, #-4]!*/
3093                         M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
3094                 }
3095         }
3096 #endif
3097
3098 #if !defined(NDEBUG)
3099         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3100                 emit_verbosecall_exit(jd);
3101 #endif
3102
3103         /* remove native stackframe info */
3104         /* TODO: improve this store/load */
3105
3106         M_STMFD(BITMASK_RESULT, REG_SP);
3107
3108         M_ADD_IMM(REG_A0, REG_SP, 2*4);
3109         M_MOV(REG_A1, REG_PV);
3110         disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3111         M_DSEG_BRANCH(disp);
3112         s1 = (s4) (cd->mcodeptr - cd->mcodebase);
3113         M_RECOMPUTE_PV(s1);
3114
3115         M_MOV(REG_ITMP1_XPTR, REG_RESULT);
3116         M_LDMFD(BITMASK_RESULT, REG_SP);
3117
3118 #if defined(ENABLE_GC_CACAO)
3119         /* restore callee saved int registers from stackframeinfo (GC might have  */
3120         /* modified them during a collection).                                    */
3121
3122         disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
3123                 OFFSET(stackframeinfo_t, intregs);
3124
3125         for (i = 0; i < INT_SAV_CNT; i++)
3126                 M_LDR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3127 #endif
3128
3129         /* finish stub code, but do not yet return to caller */
3130
3131         M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
3132         M_LDMFD(1<<REG_LR, REG_SP);
3133
3134         /* check for exception */
3135
3136         M_TST(REG_ITMP1_XPTR, REG_ITMP1_XPTR);
3137         M_MOVEQ(REG_LR, REG_PC);            /* if no exception, return to caller  */
3138
3139         /* handle exception here */
3140
3141         M_SUB_IMM(REG_ITMP2_XPC, REG_LR, 4);/* move fault address into xpc        */
3142
3143         disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3144         M_DSEG_LOAD(REG_ITMP3, disp);       /* load asm exception handler address */
3145         M_MOV(REG_PC, REG_ITMP3);           /* jump to asm exception handler      */
3146 }
3147
3148
3149 /* asm_debug *******************************************************************
3150
3151    Lazy debugger!
3152
3153 *******************************************************************************/
3154
3155 void asm_debug(int a1, int a2, int a3, int a4)
3156 {
3157         printf("===> i am going to exit after this debugging message!\n");
3158         printf("got asm_debug(%p, %p, %p, %p)\n",(void*)a1,(void*)a2,(void*)a3,(void*)a4);
3159         vm_abort("leave you now");
3160 }
3161
3162
3163 /*
3164  * These are local overrides for various environment variables in Emacs.
3165  * Please do not remove this and leave it at the end of the file, where
3166  * Emacs will automagically detect them.
3167  * ---------------------------------------------------------------------
3168  * Local variables:
3169  * mode: c
3170  * indent-tabs-mode: t
3171  * c-basic-offset: 4
3172  * tab-width: 4
3173  * End:
3174  * vim:noexpandtab:sw=4:ts=4:
3175  */