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