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