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