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