* src/vm/jit/arm/codegen.c: Fixed use of uninitialized variable.
[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-2011
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         methoddesc*         md;
252         methodinfo*         lm;             // Local methodinfo for ICMD_INVOKE*.
253         unresolved_method*  um;
254         fieldinfo*          fi;
255         unresolved_field*   uf;
256         int32_t             fieldtype;
257         int32_t             s1, s2, s3, d;
258         int32_t             disp;
259
260         // Get required compiler data.
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_GETFIELD:   /* ..., objectref, value  ==> ...               */
1213
1214                         s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1215                         emit_nullpointer_check(cd, iptr, s1);
1216
1217
1218                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1219                                 uf        = iptr->sx.s23.s3.uf;
1220                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1221                                 disp      = 0;
1222                         }
1223                         else {
1224                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1225                                 fieldtype = fi->type;
1226                                 disp      = fi->offset;
1227                         }
1228
1229 #if !defined(ENABLE_SOFTFLOAT)
1230                         /* HACK: softnull checks on floats */
1231                         if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1232                                 emit_nullpointer_check_force(cd, iptr, s1);
1233 #endif
1234
1235                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1236                                 /* XXX REMOVE ME */
1237                                 uf = iptr->sx.s23.s3.uf;
1238
1239                                 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1240                         }
1241
1242                         switch (fieldtype) {
1243                         case TYPE_INT:
1244 #if defined(ENABLE_SOFTFLOAT)
1245                         case TYPE_FLT:
1246 #endif
1247                         case TYPE_ADR:
1248                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1249                                 M_ILD(d, s1, disp);
1250                                 break;
1251                         case TYPE_LNG:
1252 #if defined(ENABLE_SOFTFLOAT)
1253                         case TYPE_DBL:
1254 #endif
1255                                 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1256                                 M_LLD(d, s1, disp);
1257                                 break;
1258 #if !defined(ENABLE_SOFTFLOAT)
1259                         case TYPE_FLT:
1260                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1261                                 M_FLD(d, s1, disp);
1262                                 break;
1263                         case TYPE_DBL:
1264                                 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1265                                 M_DLD(d, s1, disp);
1266                                 break;
1267 #endif
1268                         default:
1269                                 assert(0);
1270                         }
1271                         emit_store_dst(jd, iptr, d);
1272                         break;
1273
1274                 case ICMD_PUTFIELD:   /* ..., objectref, value  ==> ...               */
1275
1276                         s1 = emit_load_s1(jd, iptr, REG_ITMP3);
1277                         emit_nullpointer_check(cd, iptr, s1);
1278
1279                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1280                                 uf        = iptr->sx.s23.s3.uf;
1281                                 fieldtype = uf->fieldref->parseddesc.fd->type;
1282                                 disp      = 0;
1283                         }
1284                         else {
1285                                 fi        = iptr->sx.s23.s3.fmiref->p.field;
1286                                 fieldtype = fi->type;
1287                                 disp      = fi->offset;
1288                         }
1289
1290 #if !defined(ENABLE_SOFTFLOAT)
1291                         /* HACK: softnull checks on floats */
1292                         if (!INSTRUCTION_MUST_CHECK(iptr) && IS_FLT_DBL_TYPE(fieldtype))
1293                                 emit_nullpointer_check_force(cd, iptr, s1);
1294 #endif
1295
1296                         switch (fieldtype) {
1297                         case TYPE_INT:
1298 #if defined(ENABLE_SOFTFLOAT)
1299                         case TYPE_FLT:
1300 #endif
1301                         case TYPE_ADR:
1302                                 s2 = emit_load_s2(jd, iptr, REG_ITMP1);
1303                                 break;
1304 #if defined(ENABLE_SOFTFLOAT)
1305                         case TYPE_DBL: /* fall through */
1306 #endif
1307                         case TYPE_LNG:
1308                                 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
1309                                 break;
1310 #if !defined(ENABLE_SOFTFLOAT)
1311                         case TYPE_FLT:
1312                         case TYPE_DBL:
1313                                 s2 = emit_load_s2(jd, iptr, REG_FTMP1);
1314                                 break;
1315 #endif
1316                         default:
1317                                 assert(0);
1318                         }
1319
1320                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1321                                 /* XXX REMOVE ME */
1322                                 uf = iptr->sx.s23.s3.uf;
1323
1324                                 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1325                         }
1326
1327                         switch (fieldtype) {
1328                         case TYPE_INT:
1329 #if defined(ENABLE_SOFTFLOAT)
1330                         case TYPE_FLT:
1331 #endif
1332                         case TYPE_ADR:
1333                                 M_IST(s2, s1, disp);
1334                                 break;
1335                         case TYPE_LNG:
1336 #if defined(ENABLE_SOFTFLOAT)
1337                         case TYPE_DBL:
1338 #endif
1339                                 M_LST(s2, s1, disp);
1340                                 break;
1341 #if !defined(ENABLE_SOFTFLOAT)
1342                         case TYPE_FLT:
1343                                 M_FST(s2, s1, disp);
1344                                 break;
1345                         case TYPE_DBL:
1346                                 M_DST(s2, s1, disp);
1347                                 break;
1348 #endif
1349                         default:
1350                                 assert(0);
1351                         }
1352                         break;
1353
1354
1355                 /* branch operations **************************************************/
1356
1357                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
1358
1359                         disp = dseg_add_functionptr(cd, asm_handle_exception);
1360                         M_DSEG_LOAD(REG_ITMP3, disp);
1361                         M_MOV(REG_ITMP2_XPC, REG_PC);
1362                         M_MOV(REG_PC, REG_ITMP3);
1363                         M_NOP;              /* nop ensures that XPC is less than the end  */
1364                                             /* of basic block                             */
1365                         break;
1366
1367                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
1368
1369                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1370                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1371                         if (iptr->sx.val.l == 0) {
1372                                 M_ORR_S(s1, s2, REG_ITMP3);
1373                         }
1374                         else {
1375                                 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1376                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1377                                 M_CMP(s1, REG_ITMP3);*/
1378                                 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1379                                 M_CMPEQ(s2, REG_ITMP3);
1380                         }
1381                         emit_beq(cd, iptr->dst.block);
1382                         break;
1383
1384                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
1385
1386                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1387                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1388                         if (iptr->sx.val.l == 0) {
1389                                 /* if high word is less than zero, the whole long is too */
1390                                 M_CMP_IMM(s1, 0);
1391                                 emit_blt(cd, iptr->dst.block);
1392                         }
1393                         else {
1394                                 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1395                                 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1396                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1397                                 M_CMP(s1, REG_ITMP3);*/
1398                                 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1399                                 M_MOVGT_IMM(2, REG_ITMP1);
1400                                 M_MOVEQ_IMM(1, REG_ITMP1);
1401
1402                                 /* low compare: x=x-1(ifLO) */
1403                                 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1404                                 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1405                                 M_CMP(s2, REG_ITMP3);*/
1406                                 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1407
1408                                 /* branch if (x LT 1) */
1409                                 M_CMP_IMM(REG_ITMP1, 1);
1410                                 emit_blt(cd, iptr->dst.block);
1411                         }
1412                         break;
1413
1414                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
1415
1416                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1417                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1418                         if (iptr->sx.val.l == 0) {
1419                                 /* if high word is less than zero, the whole long is too  */
1420                                 M_CMP_IMM(s1, 0);
1421                                 emit_blt(cd, iptr->dst.block);
1422
1423                                 /* ... otherwise the low word has to be zero (tricky!) */
1424                                 M_CMPEQ_IMM(s2, 0);
1425                                 emit_beq(cd, iptr->dst.block);
1426                         }
1427                         else {
1428                                 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1429                                 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1430                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1431                                 M_CMP(s1, REG_ITMP3);*/
1432                                 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1433                                 M_MOVGT_IMM(2, REG_ITMP1);
1434                                 M_MOVEQ_IMM(1, REG_ITMP1);
1435
1436                                 /* low compare: x=x+1(ifHI) */
1437                                 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1438                                 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1439                                 M_CMP(s2, REG_ITMP3);*/
1440                                 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1441
1442                                 /* branch if (x LE 1) */
1443                                 M_CMP_IMM(REG_ITMP1, 1);
1444                                 emit_ble(cd, iptr->dst.block);
1445                         }
1446                         break;
1447
1448                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
1449
1450                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1451                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1452                         if (iptr->sx.val.l == 0) {
1453                                 /* if high word is greater or equal zero, the whole long is too */
1454                                 M_CMP_IMM(s1, 0);
1455                                 emit_bge(cd, iptr->dst.block);
1456                         }
1457                         else {
1458                                 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1459                                 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1460                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1461                                 M_CMP(s1, REG_ITMP3);*/
1462                                 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1463                                 M_MOVGT_IMM(2, REG_ITMP1);
1464                                 M_MOVEQ_IMM(1, REG_ITMP1);
1465
1466                                 /* low compare: x=x-1(ifLO) */
1467                                 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1468                                 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1469                                 M_CMP(s2, REG_ITMP3);*/
1470                                 M_SUBLO_IMM(REG_ITMP1, REG_ITMP1, 1);
1471
1472                                 /* branch if (x GE 1) */
1473                                 M_CMP_IMM(REG_ITMP1, 1);
1474                                 emit_bge(cd, iptr->dst.block);
1475                         }
1476                         break;
1477
1478                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
1479
1480                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1481                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1482 #if 0
1483                         if (iptr->sx.val.l == 0) {
1484                                 /* if high word is greater than zero, the whole long is too */
1485                                 M_CMP_IMM(s1, 0);
1486                                 M_BGT(0);
1487                                 codegen_add_branch_ref(cd, iptr->dst.block);
1488
1489                                 /* ... or high was zero and low is non zero (tricky!) */
1490                                 M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1491                                 M_MOVLT_IMM(1, REG_ITMP3);
1492                                 M_ORR_S(REG_ITMP3, s2, REG_ITMP3);
1493                                 M_BNE(0);
1494                                 codegen_add_branch_ref(cd, iptr->dst.block);
1495                         }
1496                         else {
1497 #endif
1498                                 /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1499                                 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1500                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1501                                 M_CMP(s1, REG_ITMP3);*/
1502                                 M_EOR(REG_ITMP1, REG_ITMP1, REG_ITMP1);
1503                                 M_MOVGT_IMM(2, REG_ITMP1);
1504                                 M_MOVEQ_IMM(1, REG_ITMP1);
1505
1506                                 /* low compare: x=x+1(ifHI) */
1507                                 emit_icmp_imm(cd, s2, (iptr->sx.val.l & 0xffffffff));
1508                                 /*ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1509                                 M_CMP(s2, REG_ITMP3);*/
1510                                 M_ADDHI_IMM(REG_ITMP1, REG_ITMP1, 1);
1511
1512                                 /* branch if (x GT 1) */
1513                                 M_CMP_IMM(REG_ITMP1, 1);
1514                                 emit_bgt(cd, iptr->dst.block);
1515 #if 0
1516                         }
1517 #endif
1518                         break;
1519
1520                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
1521
1522                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1523                         s2 = emit_load_s1_low(jd, iptr, REG_ITMP2);
1524                         if (iptr->sx.val.l == 0) {
1525                                 M_ORR_S(s1, s2, REG_ITMP3);
1526                         }
1527                         else {
1528                                 emit_icmp_imm(cd, s1, (iptr->sx.val.l >> 32));
1529                                 /*ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
1530                                 M_CMP(s1, REG_ITMP3);*/
1531                                 ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
1532                                 M_CMPEQ(s2, REG_ITMP3);
1533                         }
1534                         emit_bne(cd, iptr->dst.block);
1535                         break;
1536                         
1537                 case ICMD_IF_LCMPEQ:    /* ..., value, value ==> ...                  */
1538                                         /* op1 = target JavaVM pc                     */
1539
1540                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1541                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1542                         M_CMP(s1, s2);
1543
1544                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1545                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1546                         M_CMPEQ(s1, s2);
1547
1548                         emit_beq(cd, iptr->dst.block);
1549                         break;
1550
1551                 case ICMD_IF_LCMPNE:    /* ..., value, value ==> ...                  */
1552                                         /* op1 = target JavaVM pc                     */
1553
1554                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1555                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1556                         M_CMP(s1, s2);
1557
1558                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1559                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1560                         M_CMPEQ(s1, s2);
1561
1562                         emit_bne(cd, iptr->dst.block);
1563                         break;
1564
1565                 case ICMD_IF_LCMPLT:    /* ..., value, value ==> ...                  */
1566                                         /* op1 = target JavaVM pc                     */
1567
1568                         /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1569                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1570                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1571                         M_CMP(s1, s2);
1572                         M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1573                         M_MOVGT_IMM(2, REG_ITMP3);
1574                         M_MOVEQ_IMM(1, REG_ITMP3);
1575
1576                         /* low compare: x=x-1(ifLO) */
1577                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1578                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1579                         M_CMP(s1, s2);
1580                         M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1581
1582                         /* branch if (x LT 1) */
1583                         M_CMP_IMM(REG_ITMP3, 1);
1584                         emit_blt(cd, iptr->dst.block);
1585                         break;
1586
1587                 case ICMD_IF_LCMPLE:    /* ..., value, value ==> ...                  */
1588                                         /* op1 = target JavaVM pc                     */
1589
1590                         /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1591                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1592                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1593                         M_CMP(s1, s2);
1594                         M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1595                         M_MOVGT_IMM(2, REG_ITMP3);
1596                         M_MOVEQ_IMM(1, REG_ITMP3);
1597
1598                         /* low compare: x=x-1(ifLO) */
1599                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1600                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1601                         M_CMP(s1, s2);
1602                         M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1603
1604                         /* branch if (x LE 1) */
1605                         M_CMP_IMM(REG_ITMP3, 1);
1606                         emit_ble(cd, iptr->dst.block);
1607                         break;
1608
1609                 case ICMD_IF_LCMPGT:    /* ..., value, value ==> ...                  */
1610                                         /* op1 = target JavaVM pc                     */
1611
1612                         /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1613                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1614                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1615                         M_CMP(s1, s2);
1616                         M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1617                         M_MOVGT_IMM(2, REG_ITMP3);
1618                         M_MOVEQ_IMM(1, REG_ITMP3);
1619
1620                         /* low compare: x=x-1(ifLO) */
1621                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1622                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1623                         M_CMP(s1, s2);
1624                         M_ADDHI_IMM(REG_ITMP3, REG_ITMP3, 1);
1625
1626                         /* branch if (x GT 1) */
1627                         M_CMP_IMM(REG_ITMP3, 1);
1628                         emit_bgt(cd, iptr->dst.block);
1629                         break;
1630
1631                 case ICMD_IF_LCMPGE:    /* ..., value, value ==> ...                  */
1632                                         /* op1 = target JavaVM pc                     */
1633
1634                         /* high compare: x=0(ifLT) ; x=1(ifEQ) ; x=2(ifGT) */
1635                         s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1636                         s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1637                         M_CMP(s1, s2);
1638                         M_EOR(REG_ITMP3, REG_ITMP3, REG_ITMP3);
1639                         M_MOVGT_IMM(2, REG_ITMP3);
1640                         M_MOVEQ_IMM(1, REG_ITMP3);
1641
1642                         /* low compare: x=x-1(ifLO) */
1643                         s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1644                         s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
1645                         M_CMP(s1, s2);
1646                         M_SUBLO_IMM(REG_ITMP3, REG_ITMP3, 1);
1647
1648                         /* branch if (x GE 1) */
1649                         M_CMP_IMM(REG_ITMP3, 1);
1650                         emit_bge(cd, iptr->dst.block);
1651                         break;
1652
1653                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
1654                         {
1655                         s4 i, l;
1656                         branch_target_t *table;
1657
1658                         table = iptr->dst.table;
1659
1660                         l = iptr->sx.s23.s2.tablelow;
1661                         i = iptr->sx.s23.s3.tablehigh;
1662
1663                         /* calculate new index (index - low) */
1664                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1665                         if (l  == 0) {
1666                                 M_INTMOVE(s1, REG_ITMP1);
1667                         } else if (IS_IMM(l)) {
1668                                 M_SUB_IMM(REG_ITMP1, s1, l);
1669                         } else {
1670                                 ICONST(REG_ITMP2, l);
1671                                 M_SUB(REG_ITMP1, s1, REG_ITMP2);
1672                         }
1673
1674                         /* range check (index <= high-low) */
1675                         i = i - l + 1;
1676                         emit_icmp_imm(cd, REG_ITMP1, i-1);
1677                         emit_bugt(cd, table[0].block);
1678
1679                         /* build jump table top down and use address of lowest entry */
1680
1681                         table += i;
1682
1683                         while (--i >= 0) {
1684                                 dseg_add_target(cd, table->block);
1685                                 --table;
1686                         }
1687                         }
1688
1689                         /* length of dataseg after last dseg_add_target is used by load */
1690                         /* TODO: this loads from data-segment */
1691                         M_ADD(REG_ITMP2, REG_PV, REG_LSL(REG_ITMP1, 2));
1692                         M_LDR(REG_PC, REG_ITMP2, -(cd->dseglen));
1693                         break;
1694
1695                 case ICMD_BUILTIN:
1696                         bte = iptr->sx.s23.s3.bte;
1697                         md = bte->md;
1698                         if (bte->stub == NULL) {
1699                                 disp = dseg_add_functionptr(cd, bte->fp);
1700                         } else {
1701                                 disp = dseg_add_functionptr(cd, bte->stub);
1702                         }
1703
1704                         M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
1705
1706                         /* generate the actual call */
1707
1708                         M_MOV(REG_LR, REG_PC);
1709                         M_MOV(REG_PC, REG_PV);
1710
1711 #if !defined(__SOFTFP__)
1712                         d = md->returntype.type;
1713
1714                         /* TODO: this is only a hack, since we use R0/R1 for float
1715                            return!  this depends on gcc; it is independent from
1716                            our ENABLE_SOFTFLOAT define */
1717                         if (d != TYPE_VOID && IS_FLT_DBL_TYPE(d)) {
1718 #if 0 && !defined(NDEBUG)
1719                                 dolog("BUILTIN that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
1720 #endif
1721                                 /* we cannot use this macro, since it is not defined
1722                                    in ENABLE_SOFTFLOAT M_CAST_FLT_TO_INT_TYPED(d,
1723                                    REG_FRESULT, REG_RESULT_TYPED(d)); */
1724                                 if (IS_2_WORD_TYPE(d)) {
1725                                         DCD(0xed2d8102); /* stfd    f0, [sp, #-8]! */
1726                                         M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
1727                                 } else {
1728                                         DCD(0xed2d0101); /* stfs    f0, [sp, #-4]!*/
1729                                         M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
1730                                 }
1731                         }
1732 #endif
1733                         break;
1734
1735                 case ICMD_INVOKESPECIAL:
1736                         emit_nullpointer_check(cd, iptr, REG_A0);
1737                         /* fall through */
1738
1739                 case ICMD_INVOKESTATIC:
1740                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1741                                 um = iptr->sx.s23.s3.um;
1742                                 disp = dseg_add_unique_address(cd, NULL);
1743
1744                                 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
1745                                                                         um, disp);
1746                         }
1747                         else {
1748                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1749                                 disp = dseg_add_address(cd, lm->stubroutine);
1750                         }
1751
1752                         M_DSEG_LOAD(REG_PV, disp);            /* Pointer to method */
1753
1754                         /* generate the actual call */
1755
1756                         M_MOV(REG_LR, REG_PC);
1757                         M_MOV(REG_PC, REG_PV);
1758                         break;
1759
1760                 case ICMD_INVOKEVIRTUAL:
1761                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1762                                 um = iptr->sx.s23.s3.um;
1763                                 int32_t disp = dseg_add_unique_s4(cd, 0);
1764                                 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, disp);
1765
1766                                 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1767                                 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1768
1769                                 // Sanity check.
1770                                 assert(REG_ITMP1 != REG_METHODPTR);
1771                                 assert(REG_ITMP2 == REG_METHODPTR);
1772
1773                                 M_DSEG_LOAD(REG_ITMP1, disp);
1774                                 M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
1775
1776                                 // This must be a load with displacement,
1777                                 // otherwise the JIT method address patching does
1778                                 // not work anymore (see md_jit_method_patch_address).
1779                                 M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
1780                         }
1781                         else {
1782                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1783                                 s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
1784
1785                                 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1786                                 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1787                                 M_LDR(REG_PV, REG_METHODPTR, s1);
1788                         }
1789
1790                         // Generate the actual call.
1791                         M_MOV(REG_LR, REG_PC);
1792                         M_MOV(REG_PC, REG_PV);
1793                         break;
1794
1795                 case ICMD_INVOKEINTERFACE:
1796                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1797                                 um = iptr->sx.s23.s3.um;
1798                                 int32_t disp  = dseg_add_unique_s4(cd, 0);
1799                                 int32_t disp2 = dseg_add_unique_s4(cd, 0);
1800
1801                                 // XXX We need two displacements.
1802                                 assert(disp2 == disp - 4);
1803                                 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, disp);
1804
1805                                 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1806                                 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1807
1808                                 // Sanity check.
1809                                 assert(REG_ITMP1 != REG_METHODPTR);
1810                                 assert(REG_ITMP2 == REG_METHODPTR);
1811                                 assert(REG_ITMP3 != REG_METHODPTR);
1812
1813                                 M_DSEG_LOAD(REG_ITMP1, disp);
1814                                 M_LDR_REG(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
1815
1816                                 M_DSEG_LOAD(REG_ITMP3, disp2);
1817                                 M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP3);
1818
1819                                 // This must be a load with displacement,
1820                                 // otherwise the JIT method address patching does
1821                                 // not work anymore (see md_jit_method_patch_address).
1822                                 M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
1823                         }
1824                         else {
1825                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1826                                 s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->clazz->index;
1827                                 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1828
1829                                 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1830                                 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1831                                 M_LDR(REG_METHODPTR, REG_METHODPTR, s1);
1832                                 M_LDR(REG_PV, REG_METHODPTR, s2);
1833                         }
1834
1835                         // Generate the actual call.
1836                         M_MOV(REG_LR, REG_PC);
1837                         M_MOV(REG_PC, REG_PV);
1838                         break;
1839
1840                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
1841
1842                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1843                                 /* object type cast-check */
1844
1845                         classinfo *super;
1846                         s4         superindex;
1847
1848                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1849                                 super      = NULL;
1850                                 superindex = 0;
1851                         }
1852                         else {
1853                                 super      = iptr->sx.s23.s3.c.cls;
1854                                 superindex = super->index;
1855                         }
1856
1857                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1858
1859                         /* if class is not resolved, check which code to call */
1860
1861                         if (super == NULL) {
1862                                 M_TST(s1, s1);
1863                                 emit_label_beq(cd, BRANCH_LABEL_1);
1864
1865                                 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
1866                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
1867                                                     iptr->sx.s23.s3.c.ref, disp);
1868
1869                                 M_DSEG_LOAD(REG_ITMP2, disp);
1870                                 disp = dseg_add_s4(cd, ACC_INTERFACE);
1871                                 M_DSEG_LOAD(REG_ITMP3, disp);
1872                                 M_TST(REG_ITMP2, REG_ITMP3);
1873                                 emit_label_beq(cd, BRANCH_LABEL_2);
1874                         }
1875
1876                         /* interface checkcast code */
1877
1878                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
1879                                 if ((super == NULL) || !IS_IMM(superindex)) {
1880                                         disp = dseg_add_unique_s4(cd, superindex);
1881                                 }
1882                                 if (super == NULL) {
1883                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
1884                                                             iptr->sx.s23.s3.c.ref, disp);
1885                                 }
1886                                 else {
1887                                         M_TST(s1, s1);
1888                                         emit_label_beq(cd, BRANCH_LABEL_3);
1889                                 }
1890
1891                                 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1892                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
1893
1894                                 /* we put unresolved or non-immediate superindices onto dseg */
1895                                 if ((super == NULL) || !IS_IMM(superindex)) {
1896                                         /* disp was computed before we added the patcher */
1897                                         M_DSEG_LOAD(REG_ITMP2, disp);
1898                                         M_CMP(REG_ITMP3, REG_ITMP2);
1899                                 } else {
1900                                         assert(IS_IMM(superindex));
1901                                         M_CMP_IMM(REG_ITMP3, superindex);
1902                                 }
1903
1904                                 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
1905
1906                                 /* if we loaded the superindex out of the dseg above, we do
1907                                    things differently here! */
1908                                 if ((super == NULL) || !IS_IMM(superindex)) {
1909
1910                                         M_LDR_INTERN(REG_ITMP3, s1, OFFSET(java_object_t, vftbl));
1911
1912                                         /* this assumes something */
1913                                         assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
1914
1915                                         /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
1916                                         assert(sizeof(methodptr*) == 4);
1917                                         M_SUB(REG_ITMP2, REG_ITMP3, REG_LSL(REG_ITMP2, 2));
1918
1919                                         s2 = 0;
1920
1921                                 } else {
1922
1923                                         s2 = OFFSET(vftbl_t, interfacetable[0]) -
1924                                                                 superindex * sizeof(methodptr*);
1925
1926                                 }
1927
1928                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, s2);
1929                                 M_TST(REG_ITMP3, REG_ITMP3);
1930                                 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
1931
1932                                 if (super == NULL)
1933                                         emit_label_br(cd, BRANCH_LABEL_4);
1934                                 else
1935                                         emit_label(cd, BRANCH_LABEL_3);
1936                         }
1937
1938                         /* class checkcast code */
1939
1940                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
1941                                 if (super == NULL) {
1942                                         emit_label(cd, BRANCH_LABEL_2);
1943
1944                                         disp = dseg_add_unique_address(cd, NULL);
1945
1946                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
1947                                                             iptr->sx.s23.s3.c.ref,
1948                                                                                 disp);
1949                                 }
1950                                 else {
1951                                         disp = dseg_add_address(cd, super->vftbl);
1952
1953                                         M_TST(s1, s1);
1954                                         emit_label_beq(cd, BRANCH_LABEL_5);
1955                                 }
1956
1957                                 // The following code checks whether object s is a subtype of class t.
1958                                 // Represents the following semantic:
1959                                 //    if (!fast_subtype_check(s->vftbl, t->vftbl)) throw;
1960
1961                                 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1962                                 M_DSEG_LOAD(REG_ITMP3, disp);
1963
1964                                 if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
1965                                         // Represents the following semantic:
1966                                         //    if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) good;
1967                                         // Preconditions:
1968                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
1969                                         M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
1970                                         M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
1971                                         M_CMP(REG_ITMP1, REG_ITMP3);
1972                                         emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
1973                                         emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
1974
1975                                         // Represents the following semantic:
1976                                         //    if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) throw;
1977                                         // Preconditions:
1978                                         //    REG_ITMP3==t->vftbl;
1979                                         if (super == NULL) {
1980                                                 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
1981                                                 M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
1982                                                 emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
1983                                                 emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);  /* throw */
1984                                         }
1985
1986                                         // Represents the following semantic:
1987                                         //    if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) throw;
1988                                         // Preconditions:
1989                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
1990                                         M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
1991                                         M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
1992                                         M_CMP(REG_ITMP1, REG_ITMP3);
1993                                         emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
1994                                         emit_classcast_check(cd, iptr, BRANCH_LT, 0, s1);  /* throw */
1995
1996                                         // Represents the following semantic:
1997                                         //    if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) throw;
1998                                         // Preconditions:
1999                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
2000                                         M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
2001                                         M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2));  /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
2002                                         M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
2003                                         M_DSEG_LOAD(REG_ITMP3, disp);  /* reload REG_ITMP3, was destroyed */
2004                                         M_CMP(REG_ITMP2, REG_ITMP3);
2005                                         emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);  /* throw */
2006
2007                                         emit_label(cd, BRANCH_LABEL_6);
2008                                 }
2009                                 else {
2010                                         // Represents the following semantic:
2011                                         //    if (*(s->vftbl + t->vftbl->subtype_offset) != t->vftbl) throw;
2012                                         // Preconditions:
2013                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2014                                         M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
2015                                         M_CMP(REG_ITMP2, REG_ITMP3);
2016                                         emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);
2017                                 }
2018
2019                                 if (super != NULL)
2020                                         emit_label(cd, BRANCH_LABEL_5);
2021                         }
2022
2023                         if (super == NULL) {
2024                                 emit_label(cd, BRANCH_LABEL_1);
2025                                 emit_label(cd, BRANCH_LABEL_4);
2026                         }
2027
2028                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2029                         }
2030                         else {
2031                                 /* array type cast-check */
2032
2033                                 s1 = emit_load_s1(jd, iptr, REG_A0);
2034                                 M_INTMOVE(s1, REG_A0);
2035
2036                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2037                                         disp = dseg_add_unique_address(cd, NULL);
2038
2039                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2040                                                                                 iptr->sx.s23.s3.c.ref,
2041                                                                                 disp);
2042                                 }
2043                                 else
2044                                         disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2045
2046                                 M_DSEG_LOAD(REG_A1, disp);
2047                                 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2048                                 M_DSEG_BRANCH(disp);
2049
2050                                 emit_recompute_pv(cd);
2051
2052                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2053                                 M_TST(REG_RESULT, REG_RESULT);
2054                                 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2055
2056                                 d = codegen_reg_of_dst(jd, iptr, s1);
2057                         }
2058
2059                         M_INTMOVE(s1, d);
2060                         emit_store_dst(jd, iptr, d);
2061                         break;
2062
2063                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
2064
2065                         {
2066                         classinfo *super;
2067                         s4         superindex;
2068
2069                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2070                                 super      = NULL;
2071                                 superindex = 0;
2072                         }
2073                         else {
2074                                 super      = iptr->sx.s23.s3.c.cls;
2075                                 superindex = super->index;
2076                         }
2077
2078                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2079                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2080
2081                         if (s1 == d) {
2082                                 M_MOV(REG_ITMP1, s1);
2083                                 s1 = REG_ITMP1;
2084                         }
2085
2086                         /* if class is not resolved, check which code to call */
2087
2088                         if (super == NULL) {
2089                                 M_EOR(d, d, d);
2090
2091                                 M_TST(s1, s1);
2092                                 emit_label_beq(cd, BRANCH_LABEL_1);
2093
2094                                 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2095                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2096                                                     iptr->sx.s23.s3.c.ref, disp);
2097
2098                                 M_DSEG_LOAD(REG_ITMP2, disp);
2099                                 disp = dseg_add_s4(cd, ACC_INTERFACE);
2100                                 M_DSEG_LOAD(REG_ITMP3, disp);
2101                                 M_TST(REG_ITMP2, REG_ITMP3);
2102                                 emit_label_beq(cd, BRANCH_LABEL_2);
2103                         }
2104
2105                         /* interface checkcast code */
2106
2107                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2108                                 if ((super == NULL) || !IS_IMM(superindex)) {
2109                                         disp = dseg_add_unique_s4(cd, superindex);
2110                                 }
2111                                 if (super == NULL) {
2112                                         /* If d == REG_ITMP2, then it's destroyed in check
2113                                            code above.  */
2114                                         if (d == REG_ITMP2)
2115                                                 M_EOR(d, d, d);
2116
2117                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2118                                                             iptr->sx.s23.s3.c.ref, disp);
2119                                 }
2120                                 else {
2121                                         M_EOR(d, d, d);
2122                                         M_TST(s1, s1);
2123                                         emit_label_beq(cd, BRANCH_LABEL_3);
2124                                 }
2125
2126                                 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2127                                 M_LDR_INTERN(REG_ITMP3,
2128                                                          REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2129
2130                                 /* we put unresolved or non-immediate superindices onto dseg
2131                                    and do things slightly different */
2132                                 if ((super == NULL) || !IS_IMM(superindex)) {
2133                                         /* disp was computed before we added the patcher */
2134                                         M_DSEG_LOAD(REG_ITMP2, disp);
2135                                         M_CMP(REG_ITMP3, REG_ITMP2);
2136
2137                                         if (d == REG_ITMP2) {
2138                                                 M_EORLE(d, d, d);
2139                                                 M_BLE(4);
2140                                         } else {
2141                                                 M_BLE(3);
2142                                         }
2143
2144                                         /* this assumes something */
2145                                         assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2146
2147                                         /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2148                                         assert(sizeof(methodptr*) == 4);
2149                                         M_SUB(REG_ITMP1, REG_ITMP1, REG_LSL(REG_ITMP2, 2));
2150
2151                                         if (d == REG_ITMP2) {
2152                                                 M_EOR(d, d, d);
2153                                         }
2154
2155                                         s2 = 0;
2156
2157                                 } else {
2158                                         assert(IS_IMM(superindex));
2159                                         M_CMP_IMM(REG_ITMP3, superindex);
2160
2161                                         M_BLE(2);
2162
2163                                         s2 = OFFSET(vftbl_t, interfacetable[0]) -
2164                                                 superindex * sizeof(methodptr*);
2165
2166                                 }
2167
2168                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP1, s2);
2169                                 M_TST(REG_ITMP3, REG_ITMP3);
2170                                 M_MOVNE_IMM(1, d);
2171
2172                                 if (super == NULL)
2173                                         emit_label_br(cd, BRANCH_LABEL_4);
2174                                 else
2175                                         emit_label(cd, BRANCH_LABEL_3);
2176                         }
2177
2178                         /* class checkcast code */
2179
2180                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2181                                 if (super == NULL) {
2182                                         emit_label(cd, BRANCH_LABEL_2);
2183
2184                                         disp = dseg_add_unique_address(cd, NULL);
2185
2186                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2187                                                             iptr->sx.s23.s3.c.ref, disp);
2188                                 }
2189                                 else {
2190                                         disp = dseg_add_address(cd, super->vftbl);
2191
2192                                         M_EOR(d, d, d);
2193                                         M_TST(s1, s1);
2194                                         emit_label_beq(cd, BRANCH_LABEL_5);
2195                                 }
2196
2197                                 // The following code checks whether object s is a subtype of class t.
2198                                 // Represents the following semantic:
2199                                 //    fast_subtype_check(s->vftbl, t->vftbl));
2200
2201                                 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2202                                 M_DSEG_LOAD(REG_ITMP3, disp);
2203
2204                                 if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
2205                                         // Represents the following semantic:
2206                                         //    if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) true;
2207                                         // Preconditions:
2208                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2209                                         M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2210                                         M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
2211                                         M_CMP(REG_ITMP1, REG_ITMP3);
2212                                         emit_label_beq(cd, BRANCH_LABEL_6);  /* true */
2213
2214                                         // Represents the following semantic:
2215                                         //    if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) false;
2216                                         // Preconditions:
2217                                         //    REG_ITMP3==t->vftbl;
2218                                         if (super == NULL) {
2219                                                 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2220                                                 M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
2221                                                 emit_label_bne(cd, BRANCH_LABEL_7);  /* false */
2222                                         }
2223
2224                                         // Represents the following semantic:
2225                                         //    if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) false;
2226                                         // Preconditions:
2227                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2228                                         M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
2229                                         M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
2230                                         M_CMP(REG_ITMP1, REG_ITMP3);
2231                                         emit_label_blt(cd, BRANCH_LABEL_8);  /* false */
2232
2233                                         // Represents the following semantic:
2234                                         //    if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) false;
2235                                         // Preconditions:
2236                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
2237                                         M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
2238                                         M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2));  /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
2239                                         M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
2240                                         M_DSEG_LOAD(REG_ITMP3, disp);  /* reload REG_ITMP3, was destroyed */
2241                                         M_CMP(REG_ITMP2, REG_ITMP3);
2242
2243                                         emit_label(cd, BRANCH_LABEL_6);
2244                                         if (super == NULL)
2245                                                 emit_label(cd, BRANCH_LABEL_7);
2246                                         emit_label(cd, BRANCH_LABEL_8);
2247
2248                                         /* If d == REG_ITMP2, then it's destroyed */
2249                                         if (d == REG_ITMP2)
2250                                                 M_EOR(d, d, d);
2251                                         M_MOVEQ_IMM(1, d);
2252                                 }
2253                                 else {
2254                                         // Represents the following semantic:
2255                                         //    *(s->vftbl + t->vftbl->subtype_offset) == t->vftbl;
2256                                         // Preconditions:
2257                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2258                                         M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
2259                                         M_CMP(REG_ITMP2, REG_ITMP3);
2260                                         /* If d == REG_ITMP2, then it's destroyed */
2261                                         if (d == REG_ITMP2)
2262                                                 M_EOR(d, d, d);
2263                                         M_MOVEQ_IMM(1, d);
2264                                 }
2265
2266                                 if (super != NULL)
2267                                         emit_label(cd, BRANCH_LABEL_5);
2268                         }
2269
2270                         if (super == NULL) {
2271                                 emit_label(cd, BRANCH_LABEL_1);
2272                                 emit_label(cd, BRANCH_LABEL_4);
2273                         }
2274
2275                         }
2276
2277                         emit_store_dst(jd, iptr, d);
2278                         break;
2279
2280                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
2281
2282                         /* copy sizes to stack if necessary  */
2283
2284                         MCODECHECK((iptr->s1.argcount << 1) + 64);
2285
2286                         for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2287
2288                                 var = VAR(iptr->sx.s23.s2.args[s1]);
2289         
2290                                 /* copy SAVEDVAR sizes to stack */
2291
2292                                 if (!(var->flags & PREALLOC)) {
2293                                         s2 = emit_load(jd, iptr, var, REG_ITMP1);
2294                                         M_STR(s2, REG_SP, s1 * 4);
2295                                 }
2296                         }
2297
2298                         /* a0 = dimension count */
2299
2300                         assert(IS_IMM(iptr->s1.argcount));
2301                         M_MOV_IMM(REG_A0, iptr->s1.argcount);
2302
2303                         /* is patcher function set? */
2304
2305                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2306                                 disp = dseg_add_unique_address(cd, NULL);
2307
2308                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2309                                                                         iptr->sx.s23.s3.c.ref, disp);
2310                         }
2311                         else
2312                                 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2313
2314                         /* a1 = arraydescriptor */
2315
2316                         M_DSEG_LOAD(REG_A1, disp);
2317
2318                         /* a2 = pointer to dimensions = stack pointer */
2319
2320                         M_INTMOVE(REG_SP, REG_A2);
2321
2322                         /* call builtin_multianewarray here */
2323
2324                         disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2325                         M_DSEG_BRANCH(disp);
2326
2327                         /* recompute pv */
2328
2329                         emit_recompute_pv(cd);
2330
2331                         /* check for exception before result assignment */
2332
2333                         emit_exception_check(cd, iptr);
2334
2335                         /* get arrayref */
2336
2337                         d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2338                         M_INTMOVE(REG_RESULT, d);
2339                         emit_store_dst(jd, iptr, d);
2340                         break;
2341
2342                 default:
2343                         vm_abort("Unknown ICMD %d during code generation", iptr->opc);
2344         } /* the big switch */
2345 }
2346
2347
2348 /* codegen_emit_stub_native ****************************************************
2349
2350    Emits a stub routine which calls a native method.
2351
2352 *******************************************************************************/
2353
2354 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2355 {
2356         methodinfo  *m;
2357         codeinfo    *code;
2358         codegendata *cd;
2359         methoddesc  *md;
2360         s4           i, j;
2361         s4           t;
2362         int          s1, s2;
2363         int          disp;
2364
2365         /* get required compiler data */
2366
2367         m    = jd->m;
2368         code = jd->code;
2369         cd   = jd->cd;
2370
2371         /* initialize variables */
2372
2373         md = m->parseddesc;
2374
2375         /* calculate stackframe size */
2376
2377         cd->stackframesize =
2378                 1 +                                                /* return address  */
2379                 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +         /* stackframeinfo  */
2380                 sizeof(localref_table) / SIZEOF_VOID_P +           /* localref_table  */
2381                 nmd->memuse;                                       /* stack arguments */
2382
2383         /* align stack to 8-byte */
2384
2385         cd->stackframesize = (cd->stackframesize + 1) & ~1;
2386
2387         /* create method header */
2388
2389         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
2390         (void) dseg_add_unique_s4(cd, cd->stackframesize);     /* FrameSize       */
2391         (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
2392         (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
2393         (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
2394
2395         /* generate stub code */
2396
2397         M_STMFD(1<<REG_LR, REG_SP);
2398         M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize * 2 - 1);
2399
2400 #if defined(ENABLE_GC_CACAO)
2401         /* Save callee saved integer registers in stackframeinfo (GC may
2402            need to recover them during a collection). */
2403
2404         disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
2405                 OFFSET(stackframeinfo_t, intregs);
2406
2407         for (i = 0; i < INT_SAV_CNT; i++)
2408                 M_STR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2409 #endif
2410
2411         /* Save integer and float argument registers (these are 4
2412            registers, stack is 8-byte aligned). */
2413
2414         M_STMFD(BITMASK_ARGS, REG_SP);
2415         /* TODO: floating point */
2416
2417         /* create native stackframe info */
2418
2419         M_ADD_IMM(REG_A0, REG_SP, 4*4);
2420         M_MOV(REG_A1, REG_PV);
2421         disp = dseg_add_functionptr(cd, codegen_start_native_call);
2422         M_DSEG_BRANCH(disp);
2423
2424         /* recompute pv */
2425
2426         emit_recompute_pv(cd);
2427
2428         /* remember class argument */
2429
2430         if (m->flags & ACC_STATIC)
2431                 M_MOV(REG_ITMP3, REG_RESULT);
2432
2433         /* Restore integer and float argument registers (these are 4
2434            registers, stack is 8-byte aligned). */
2435
2436         M_LDMFD(BITMASK_ARGS, REG_SP);
2437         /* TODO: floating point */
2438
2439         /* copy or spill arguments to new locations */
2440         /* ATTENTION: the ARM has only integer argument registers! */
2441
2442         for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2443                 t = md->paramtypes[i].type;
2444
2445                 if (!md->params[i].inmemory) {
2446                         s1 = md->params[i].regoff;
2447                         s2 = nmd->params[j].regoff;
2448
2449                         if (!nmd->params[j].inmemory) {
2450 #if !defined(__ARM_EABI__)
2451                                 SPLIT_OPEN(t, s2, REG_ITMP1);
2452 #endif
2453
2454                                 if (IS_2_WORD_TYPE(t))
2455                                         M_LNGMOVE(s1, s2);
2456                                 else
2457                                         M_INTMOVE(s1, s2);
2458
2459 #if !defined(__ARM_EABI__)
2460                                 SPLIT_STORE_AND_CLOSE(t, s2, 0);
2461 #endif
2462                         }
2463                         else {
2464                                 if (IS_2_WORD_TYPE(t))
2465                                         M_LST(s1, REG_SP, s2);
2466                                 else
2467                                         M_IST(s1, REG_SP, s2);
2468                         }
2469                 }
2470                 else {
2471                         s1 = md->params[i].regoff + cd->stackframesize * 8;
2472                         s2 = nmd->params[j].regoff;
2473
2474                         if (IS_2_WORD_TYPE(t)) {
2475                                 M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
2476                                 M_LST(REG_ITMP12_PACKED, REG_SP, s2);
2477                         }
2478                         else {
2479                                 M_ILD(REG_ITMP1, REG_SP, s1);
2480                                 M_IST(REG_ITMP1, REG_SP, s2);
2481                         }
2482                 }
2483         }
2484
2485         /* Handle native Java methods. */
2486
2487         if (m->flags & ACC_NATIVE) {
2488                 /* put class into second argument register */
2489
2490                 if (m->flags & ACC_STATIC)
2491                         M_MOV(REG_A1, REG_ITMP3);
2492
2493                 /* put env into first argument register */
2494
2495                 disp = dseg_add_address(cd, VM_get_jnienv());
2496                 M_DSEG_LOAD(REG_A0, disp);
2497         }
2498
2499         /* Call the native function. */
2500
2501         disp = dseg_add_functionptr(cd, f);
2502         M_DSEG_BRANCH(disp);
2503
2504         /* recompute pv */
2505         /* TODO: this is only needed because of the tracer ... do we
2506            really need it? */
2507
2508         emit_recompute_pv(cd);
2509
2510 #if !defined(__SOFTFP__)
2511         /* TODO: this is only a hack, since we use R0/R1 for float return! */
2512         /* this depends on gcc; it is independent from our ENABLE_SOFTFLOAT define */
2513         if (md->returntype.type != TYPE_VOID && IS_FLT_DBL_TYPE(md->returntype.type)) {
2514 #if 0 && !defined(NDEBUG)
2515                 dolog("NATIVESTUB that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
2516 #endif
2517                 /* we cannot use this macro, since it is not defined in ENABLE_SOFTFLOAT */
2518                 /* M_CAST_FLT_TO_INT_TYPED(md->returntype.type, REG_FRESULT, REG_RESULT_TYPED(md->returntype.type)); */
2519                 if (IS_2_WORD_TYPE(md->returntype.type)) {
2520                         DCD(0xed2d8102); /* stfd    f0, [sp, #-8]! */
2521                         M_LDRD_UPDATE(REG_RESULT_PACKED, REG_SP, 8);
2522                 } else {
2523                         DCD(0xed2d0101); /* stfs    f0, [sp, #-4]!*/
2524                         M_LDR_UPDATE(REG_RESULT, REG_SP, 4);
2525                 }
2526         }
2527 #endif
2528
2529         /* remove native stackframe info */
2530         /* TODO: improve this store/load */
2531
2532         M_STMFD(BITMASK_RESULT, REG_SP);
2533
2534         M_ADD_IMM(REG_A0, REG_SP, 2*4);
2535         M_MOV(REG_A1, REG_PV);
2536         disp = dseg_add_functionptr(cd, codegen_finish_native_call);
2537         M_DSEG_BRANCH(disp);
2538         emit_recompute_pv(cd);
2539
2540         M_MOV(REG_ITMP1_XPTR, REG_RESULT);
2541         M_LDMFD(BITMASK_RESULT, REG_SP);
2542
2543 #if defined(ENABLE_GC_CACAO)
2544         /* restore callee saved int registers from stackframeinfo (GC might have  */
2545         /* modified them during a collection).                                    */
2546
2547         disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
2548                 OFFSET(stackframeinfo_t, intregs);
2549
2550         for (i = 0; i < INT_SAV_CNT; i++)
2551                 M_LDR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2552 #endif
2553
2554         /* finish stub code, but do not yet return to caller */
2555
2556         M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize * 2 - 1);
2557         M_LDMFD(1<<REG_LR, REG_SP);
2558
2559         /* check for exception */
2560
2561         M_TST(REG_ITMP1_XPTR, REG_ITMP1_XPTR);
2562         M_MOVEQ(REG_LR, REG_PC);            /* if no exception, return to caller  */
2563
2564         /* handle exception here */
2565
2566         M_SUB_IMM(REG_ITMP2_XPC, REG_LR, 4);/* move fault address into xpc        */
2567
2568         disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
2569         M_DSEG_LOAD(REG_ITMP3, disp);       /* load asm exception handler address */
2570         M_MOV(REG_PC, REG_ITMP3);           /* jump to asm exception handler      */
2571 }
2572
2573
2574 /* asm_debug *******************************************************************
2575
2576    Lazy debugger!
2577
2578 *******************************************************************************/
2579
2580 void asm_debug(int a1, int a2, int a3, int a4)
2581 {
2582         printf("===> i am going to exit after this debugging message!\n");
2583         printf("got asm_debug(%p, %p, %p, %p)\n",(void*)a1,(void*)a2,(void*)a3,(void*)a4);
2584         vm_abort("leave you now");
2585 }
2586
2587
2588 /*
2589  * These are local overrides for various environment variables in Emacs.
2590  * Please do not remove this and leave it at the end of the file, where
2591  * Emacs will automagically detect them.
2592  * ---------------------------------------------------------------------
2593  * Local variables:
2594  * mode: c
2595  * indent-tabs-mode: t
2596  * c-basic-offset: 4
2597  * tab-width: 4
2598  * End:
2599  * vim:noexpandtab:sw=4:ts=4:
2600  */