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