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