* src/vm/jit/arm/codegen.c: Remove hack for return value in float registers.
[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                         break;
1712
1713                 case ICMD_INVOKESPECIAL:
1714                         emit_nullpointer_check(cd, iptr, REG_A0);
1715                         /* fall through */
1716
1717                 case ICMD_INVOKESTATIC:
1718                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1719                                 um = iptr->sx.s23.s3.um;
1720                                 disp = dseg_add_unique_address(cd, NULL);
1721
1722                                 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
1723                                                                         um, disp);
1724                         }
1725                         else {
1726                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1727                                 disp = dseg_add_address(cd, lm->stubroutine);
1728                         }
1729
1730                         M_DSEG_LOAD(REG_PV, disp);            /* Pointer to method */
1731
1732                         /* generate the actual call */
1733
1734                         M_MOV(REG_LR, REG_PC);
1735                         M_MOV(REG_PC, REG_PV);
1736                         break;
1737
1738                 case ICMD_INVOKEVIRTUAL:
1739                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1740                                 um = iptr->sx.s23.s3.um;
1741                                 int32_t disp = dseg_add_unique_s4(cd, 0);
1742                                 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, disp);
1743
1744                                 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1745                                 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1746
1747                                 // Sanity check.
1748                                 assert(REG_ITMP1 != REG_METHODPTR);
1749                                 assert(REG_ITMP2 == REG_METHODPTR);
1750
1751                                 M_DSEG_LOAD(REG_ITMP1, disp);
1752                                 M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
1753
1754                                 // This must be a load with displacement,
1755                                 // otherwise the JIT method address patching does
1756                                 // not work anymore (see md_jit_method_patch_address).
1757                                 M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
1758                         }
1759                         else {
1760                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1761                                 s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
1762
1763                                 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1764                                 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1765                                 M_LDR(REG_PV, REG_METHODPTR, s1);
1766                         }
1767
1768                         // Generate the actual call.
1769                         M_MOV(REG_LR, REG_PC);
1770                         M_MOV(REG_PC, REG_PV);
1771                         break;
1772
1773                 case ICMD_INVOKEINTERFACE:
1774                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1775                                 um = iptr->sx.s23.s3.um;
1776                                 int32_t disp  = dseg_add_unique_s4(cd, 0);
1777                                 int32_t disp2 = dseg_add_unique_s4(cd, 0);
1778
1779                                 // XXX We need two displacements.
1780                                 assert(disp2 == disp - 4);
1781                                 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, disp);
1782
1783                                 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1784                                 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1785
1786                                 // Sanity check.
1787                                 assert(REG_ITMP1 != REG_METHODPTR);
1788                                 assert(REG_ITMP2 == REG_METHODPTR);
1789                                 assert(REG_ITMP3 != REG_METHODPTR);
1790
1791                                 M_DSEG_LOAD(REG_ITMP1, disp);
1792                                 M_LDR_REG(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
1793
1794                                 M_DSEG_LOAD(REG_ITMP3, disp2);
1795                                 M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP3);
1796
1797                                 // This must be a load with displacement,
1798                                 // otherwise the JIT method address patching does
1799                                 // not work anymore (see md_jit_method_patch_address).
1800                                 M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
1801                         }
1802                         else {
1803                                 lm = iptr->sx.s23.s3.fmiref->p.method;
1804                                 s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->clazz->index;
1805                                 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1806
1807                                 // The following instruction MUST NOT change a0 because of the implicit NPE check.
1808                                 M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1809                                 M_LDR(REG_METHODPTR, REG_METHODPTR, s1);
1810                                 M_LDR(REG_PV, REG_METHODPTR, s2);
1811                         }
1812
1813                         // Generate the actual call.
1814                         M_MOV(REG_LR, REG_PC);
1815                         M_MOV(REG_PC, REG_PV);
1816                         break;
1817
1818                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
1819
1820                         if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1821                                 /* object type cast-check */
1822
1823                         classinfo *super;
1824                         s4         superindex;
1825
1826                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1827                                 super      = NULL;
1828                                 superindex = 0;
1829                         }
1830                         else {
1831                                 super      = iptr->sx.s23.s3.c.cls;
1832                                 superindex = super->index;
1833                         }
1834
1835                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1836
1837                         /* if class is not resolved, check which code to call */
1838
1839                         if (super == NULL) {
1840                                 M_TST(s1, s1);
1841                                 emit_label_beq(cd, BRANCH_LABEL_1);
1842
1843                                 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
1844                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
1845                                                     iptr->sx.s23.s3.c.ref, disp);
1846
1847                                 M_DSEG_LOAD(REG_ITMP2, disp);
1848                                 disp = dseg_add_s4(cd, ACC_INTERFACE);
1849                                 M_DSEG_LOAD(REG_ITMP3, disp);
1850                                 M_TST(REG_ITMP2, REG_ITMP3);
1851                                 emit_label_beq(cd, BRANCH_LABEL_2);
1852                         }
1853
1854                         /* interface checkcast code */
1855
1856                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
1857                                 if ((super == NULL) || !IS_IMM(superindex)) {
1858                                         disp = dseg_add_unique_s4(cd, superindex);
1859                                 }
1860                                 if (super == NULL) {
1861                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
1862                                                             iptr->sx.s23.s3.c.ref, disp);
1863                                 }
1864                                 else {
1865                                         M_TST(s1, s1);
1866                                         emit_label_beq(cd, BRANCH_LABEL_3);
1867                                 }
1868
1869                                 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1870                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
1871
1872                                 /* we put unresolved or non-immediate superindices onto dseg */
1873                                 if ((super == NULL) || !IS_IMM(superindex)) {
1874                                         /* disp was computed before we added the patcher */
1875                                         M_DSEG_LOAD(REG_ITMP2, disp);
1876                                         M_CMP(REG_ITMP3, REG_ITMP2);
1877                                 } else {
1878                                         assert(IS_IMM(superindex));
1879                                         M_CMP_IMM(REG_ITMP3, superindex);
1880                                 }
1881
1882                                 emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
1883
1884                                 /* if we loaded the superindex out of the dseg above, we do
1885                                    things differently here! */
1886                                 if ((super == NULL) || !IS_IMM(superindex)) {
1887
1888                                         M_LDR_INTERN(REG_ITMP3, s1, OFFSET(java_object_t, vftbl));
1889
1890                                         /* this assumes something */
1891                                         assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
1892
1893                                         /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
1894                                         assert(sizeof(methodptr*) == 4);
1895                                         M_SUB(REG_ITMP2, REG_ITMP3, REG_LSL(REG_ITMP2, 2));
1896
1897                                         s2 = 0;
1898
1899                                 } else {
1900
1901                                         s2 = OFFSET(vftbl_t, interfacetable[0]) -
1902                                                                 superindex * sizeof(methodptr*);
1903
1904                                 }
1905
1906                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP2, s2);
1907                                 M_TST(REG_ITMP3, REG_ITMP3);
1908                                 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
1909
1910                                 if (super == NULL)
1911                                         emit_label_br(cd, BRANCH_LABEL_4);
1912                                 else
1913                                         emit_label(cd, BRANCH_LABEL_3);
1914                         }
1915
1916                         /* class checkcast code */
1917
1918                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
1919                                 if (super == NULL) {
1920                                         emit_label(cd, BRANCH_LABEL_2);
1921
1922                                         disp = dseg_add_unique_address(cd, NULL);
1923
1924                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
1925                                                             iptr->sx.s23.s3.c.ref,
1926                                                                                 disp);
1927                                 }
1928                                 else {
1929                                         disp = dseg_add_address(cd, super->vftbl);
1930
1931                                         M_TST(s1, s1);
1932                                         emit_label_beq(cd, BRANCH_LABEL_5);
1933                                 }
1934
1935                                 // The following code checks whether object s is a subtype of class t.
1936                                 // Represents the following semantic:
1937                                 //    if (!fast_subtype_check(s->vftbl, t->vftbl)) throw;
1938
1939                                 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1940                                 M_DSEG_LOAD(REG_ITMP3, disp);
1941
1942                                 if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
1943                                         // Represents the following semantic:
1944                                         //    if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) good;
1945                                         // Preconditions:
1946                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
1947                                         M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
1948                                         M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
1949                                         M_CMP(REG_ITMP1, REG_ITMP3);
1950                                         emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
1951                                         emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
1952
1953                                         // Represents the following semantic:
1954                                         //    if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) throw;
1955                                         // Preconditions:
1956                                         //    REG_ITMP3==t->vftbl;
1957                                         if (super == NULL) {
1958                                                 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
1959                                                 M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
1960                                                 emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
1961                                                 emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);  /* throw */
1962                                         }
1963
1964                                         // Represents the following semantic:
1965                                         //    if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) throw;
1966                                         // Preconditions:
1967                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
1968                                         M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
1969                                         M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
1970                                         M_CMP(REG_ITMP1, REG_ITMP3);
1971                                         emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
1972                                         emit_classcast_check(cd, iptr, BRANCH_LT, 0, s1);  /* throw */
1973
1974                                         // Represents the following semantic:
1975                                         //    if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) throw;
1976                                         // Preconditions:
1977                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
1978                                         M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
1979                                         M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2));  /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
1980                                         M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
1981                                         M_DSEG_LOAD(REG_ITMP3, disp);  /* reload REG_ITMP3, was destroyed */
1982                                         M_CMP(REG_ITMP2, REG_ITMP3);
1983                                         emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);  /* throw */
1984
1985                                         emit_label(cd, BRANCH_LABEL_6);
1986                                 }
1987                                 else {
1988                                         // Represents the following semantic:
1989                                         //    if (*(s->vftbl + t->vftbl->subtype_offset) != t->vftbl) throw;
1990                                         // Preconditions:
1991                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
1992                                         M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
1993                                         M_CMP(REG_ITMP2, REG_ITMP3);
1994                                         emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);
1995                                 }
1996
1997                                 if (super != NULL)
1998                                         emit_label(cd, BRANCH_LABEL_5);
1999                         }
2000
2001                         if (super == NULL) {
2002                                 emit_label(cd, BRANCH_LABEL_1);
2003                                 emit_label(cd, BRANCH_LABEL_4);
2004                         }
2005
2006                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2007                         }
2008                         else {
2009                                 /* array type cast-check */
2010
2011                                 s1 = emit_load_s1(jd, iptr, REG_A0);
2012                                 M_INTMOVE(s1, REG_A0);
2013
2014                                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2015                                         disp = dseg_add_unique_address(cd, NULL);
2016
2017                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2018                                                                                 iptr->sx.s23.s3.c.ref,
2019                                                                                 disp);
2020                                 }
2021                                 else
2022                                         disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2023
2024                                 M_DSEG_LOAD(REG_A1, disp);
2025                                 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2026                                 M_DSEG_BRANCH(disp);
2027
2028                                 emit_recompute_pv(cd);
2029
2030                                 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2031                                 M_TST(REG_RESULT, REG_RESULT);
2032                                 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2033
2034                                 d = codegen_reg_of_dst(jd, iptr, s1);
2035                         }
2036
2037                         M_INTMOVE(s1, d);
2038                         emit_store_dst(jd, iptr, d);
2039                         break;
2040
2041                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
2042
2043                         {
2044                         classinfo *super;
2045                         s4         superindex;
2046
2047                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2048                                 super      = NULL;
2049                                 superindex = 0;
2050                         }
2051                         else {
2052                                 super      = iptr->sx.s23.s3.c.cls;
2053                                 superindex = super->index;
2054                         }
2055
2056                         s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2057                         d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2058
2059                         if (s1 == d) {
2060                                 M_MOV(REG_ITMP1, s1);
2061                                 s1 = REG_ITMP1;
2062                         }
2063
2064                         /* if class is not resolved, check which code to call */
2065
2066                         if (super == NULL) {
2067                                 M_EOR(d, d, d);
2068
2069                                 M_TST(s1, s1);
2070                                 emit_label_beq(cd, BRANCH_LABEL_1);
2071
2072                                 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2073                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2074                                                     iptr->sx.s23.s3.c.ref, disp);
2075
2076                                 M_DSEG_LOAD(REG_ITMP2, disp);
2077                                 disp = dseg_add_s4(cd, ACC_INTERFACE);
2078                                 M_DSEG_LOAD(REG_ITMP3, disp);
2079                                 M_TST(REG_ITMP2, REG_ITMP3);
2080                                 emit_label_beq(cd, BRANCH_LABEL_2);
2081                         }
2082
2083                         /* interface checkcast code */
2084
2085                         if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2086                                 if ((super == NULL) || !IS_IMM(superindex)) {
2087                                         disp = dseg_add_unique_s4(cd, superindex);
2088                                 }
2089                                 if (super == NULL) {
2090                                         /* If d == REG_ITMP2, then it's destroyed in check
2091                                            code above.  */
2092                                         if (d == REG_ITMP2)
2093                                                 M_EOR(d, d, d);
2094
2095                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_index,
2096                                                             iptr->sx.s23.s3.c.ref, disp);
2097                                 }
2098                                 else {
2099                                         M_EOR(d, d, d);
2100                                         M_TST(s1, s1);
2101                                         emit_label_beq(cd, BRANCH_LABEL_3);
2102                                 }
2103
2104                                 M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2105                                 M_LDR_INTERN(REG_ITMP3,
2106                                                          REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2107
2108                                 /* we put unresolved or non-immediate superindices onto dseg
2109                                    and do things slightly different */
2110                                 if ((super == NULL) || !IS_IMM(superindex)) {
2111                                         /* disp was computed before we added the patcher */
2112                                         M_DSEG_LOAD(REG_ITMP2, disp);
2113                                         M_CMP(REG_ITMP3, REG_ITMP2);
2114
2115                                         if (d == REG_ITMP2) {
2116                                                 M_EORLE(d, d, d);
2117                                                 M_BLE(4);
2118                                         } else {
2119                                                 M_BLE(3);
2120                                         }
2121
2122                                         /* this assumes something */
2123                                         assert(OFFSET(vftbl_t, interfacetable[0]) == 0);
2124
2125                                         /* this does: REG_ITMP3 - superindex * sizeof(methodptr*) */
2126                                         assert(sizeof(methodptr*) == 4);
2127                                         M_SUB(REG_ITMP1, REG_ITMP1, REG_LSL(REG_ITMP2, 2));
2128
2129                                         if (d == REG_ITMP2) {
2130                                                 M_EOR(d, d, d);
2131                                         }
2132
2133                                         s2 = 0;
2134
2135                                 } else {
2136                                         assert(IS_IMM(superindex));
2137                                         M_CMP_IMM(REG_ITMP3, superindex);
2138
2139                                         M_BLE(2);
2140
2141                                         s2 = OFFSET(vftbl_t, interfacetable[0]) -
2142                                                 superindex * sizeof(methodptr*);
2143
2144                                 }
2145
2146                                 M_LDR_INTERN(REG_ITMP3, REG_ITMP1, s2);
2147                                 M_TST(REG_ITMP3, REG_ITMP3);
2148                                 M_MOVNE_IMM(1, d);
2149
2150                                 if (super == NULL)
2151                                         emit_label_br(cd, BRANCH_LABEL_4);
2152                                 else
2153                                         emit_label(cd, BRANCH_LABEL_3);
2154                         }
2155
2156                         /* class checkcast code */
2157
2158                         if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2159                                 if (super == NULL) {
2160                                         emit_label(cd, BRANCH_LABEL_2);
2161
2162                                         disp = dseg_add_unique_address(cd, NULL);
2163
2164                                         patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
2165                                                             iptr->sx.s23.s3.c.ref, disp);
2166                                 }
2167                                 else {
2168                                         disp = dseg_add_address(cd, super->vftbl);
2169
2170                                         M_EOR(d, d, d);
2171                                         M_TST(s1, s1);
2172                                         emit_label_beq(cd, BRANCH_LABEL_5);
2173                                 }
2174
2175                                 // The following code checks whether object s is a subtype of class t.
2176                                 // Represents the following semantic:
2177                                 //    fast_subtype_check(s->vftbl, t->vftbl));
2178
2179                                 M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2180                                 M_DSEG_LOAD(REG_ITMP3, disp);
2181
2182                                 if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
2183                                         // Represents the following semantic:
2184                                         //    if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) true;
2185                                         // Preconditions:
2186                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2187                                         M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2188                                         M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
2189                                         M_CMP(REG_ITMP1, REG_ITMP3);
2190                                         emit_label_beq(cd, BRANCH_LABEL_6);  /* true */
2191
2192                                         // Represents the following semantic:
2193                                         //    if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) false;
2194                                         // Preconditions:
2195                                         //    REG_ITMP3==t->vftbl;
2196                                         if (super == NULL) {
2197                                                 M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2198                                                 M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
2199                                                 emit_label_bne(cd, BRANCH_LABEL_7);  /* false */
2200                                         }
2201
2202                                         // Represents the following semantic:
2203                                         //    if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) false;
2204                                         // Preconditions:
2205                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2206                                         M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
2207                                         M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
2208                                         M_CMP(REG_ITMP1, REG_ITMP3);
2209                                         emit_label_blt(cd, BRANCH_LABEL_8);  /* false */
2210
2211                                         // Represents the following semantic:
2212                                         //    if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) false;
2213                                         // Preconditions:
2214                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
2215                                         M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
2216                                         M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2));  /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
2217                                         M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
2218                                         M_DSEG_LOAD(REG_ITMP3, disp);  /* reload REG_ITMP3, was destroyed */
2219                                         M_CMP(REG_ITMP2, REG_ITMP3);
2220
2221                                         emit_label(cd, BRANCH_LABEL_6);
2222                                         if (super == NULL)
2223                                                 emit_label(cd, BRANCH_LABEL_7);
2224                                         emit_label(cd, BRANCH_LABEL_8);
2225
2226                                         /* If d == REG_ITMP2, then it's destroyed */
2227                                         if (d == REG_ITMP2)
2228                                                 M_EOR(d, d, d);
2229                                         M_MOVEQ_IMM(1, d);
2230                                 }
2231                                 else {
2232                                         // Represents the following semantic:
2233                                         //    *(s->vftbl + t->vftbl->subtype_offset) == t->vftbl;
2234                                         // Preconditions:
2235                                         //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
2236                                         M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
2237                                         M_CMP(REG_ITMP2, REG_ITMP3);
2238                                         /* If d == REG_ITMP2, then it's destroyed */
2239                                         if (d == REG_ITMP2)
2240                                                 M_EOR(d, d, d);
2241                                         M_MOVEQ_IMM(1, d);
2242                                 }
2243
2244                                 if (super != NULL)
2245                                         emit_label(cd, BRANCH_LABEL_5);
2246                         }
2247
2248                         if (super == NULL) {
2249                                 emit_label(cd, BRANCH_LABEL_1);
2250                                 emit_label(cd, BRANCH_LABEL_4);
2251                         }
2252
2253                         }
2254
2255                         emit_store_dst(jd, iptr, d);
2256                         break;
2257
2258                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
2259
2260                         /* copy sizes to stack if necessary  */
2261
2262                         MCODECHECK((iptr->s1.argcount << 1) + 64);
2263
2264                         for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2265
2266                                 var = VAR(iptr->sx.s23.s2.args[s1]);
2267         
2268                                 /* copy SAVEDVAR sizes to stack */
2269
2270                                 if (!(var->flags & PREALLOC)) {
2271                                         s2 = emit_load(jd, iptr, var, REG_ITMP1);
2272                                         M_STR(s2, REG_SP, s1 * 4);
2273                                 }
2274                         }
2275
2276                         /* a0 = dimension count */
2277
2278                         assert(IS_IMM(iptr->s1.argcount));
2279                         M_MOV_IMM(REG_A0, iptr->s1.argcount);
2280
2281                         /* is patcher function set? */
2282
2283                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2284                                 disp = dseg_add_unique_address(cd, NULL);
2285
2286                                 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2287                                                                         iptr->sx.s23.s3.c.ref, disp);
2288                         }
2289                         else
2290                                 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2291
2292                         /* a1 = arraydescriptor */
2293
2294                         M_DSEG_LOAD(REG_A1, disp);
2295
2296                         /* a2 = pointer to dimensions = stack pointer */
2297
2298                         M_INTMOVE(REG_SP, REG_A2);
2299
2300                         /* call builtin_multianewarray here */
2301
2302                         disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2303                         M_DSEG_BRANCH(disp);
2304
2305                         /* recompute pv */
2306
2307                         emit_recompute_pv(cd);
2308
2309                         /* check for exception before result assignment */
2310
2311                         emit_exception_check(cd, iptr);
2312
2313                         /* get arrayref */
2314
2315                         d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2316                         M_INTMOVE(REG_RESULT, d);
2317                         emit_store_dst(jd, iptr, d);
2318                         break;
2319
2320                 default:
2321                         vm_abort("Unknown ICMD %d during code generation", iptr->opc);
2322         } /* the big switch */
2323 }
2324
2325
2326 /* codegen_emit_stub_native ****************************************************
2327
2328    Emits a stub routine which calls a native method.
2329
2330 *******************************************************************************/
2331
2332 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2333 {
2334         methodinfo  *m;
2335         codeinfo    *code;
2336         codegendata *cd;
2337         methoddesc  *md;
2338         s4           i, j;
2339         s4           t;
2340         int          s1, s2;
2341         int          disp;
2342
2343         /* get required compiler data */
2344
2345         m    = jd->m;
2346         code = jd->code;
2347         cd   = jd->cd;
2348
2349         /* initialize variables */
2350
2351         md = m->parseddesc;
2352
2353         /* calculate stackframe size */
2354
2355         cd->stackframesize =
2356                 1 +                                                /* return address  */
2357                 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +         /* stackframeinfo  */
2358                 sizeof(localref_table) / SIZEOF_VOID_P +           /* localref_table  */
2359                 nmd->memuse;                                       /* stack arguments */
2360
2361         /* align stack to 8-byte */
2362
2363         cd->stackframesize = (cd->stackframesize + 1) & ~1;
2364
2365         /* create method header */
2366
2367         (void) dseg_add_unique_address(cd, code);              /* CodeinfoPointer */
2368         (void) dseg_add_unique_s4(cd, cd->stackframesize);     /* FrameSize       */
2369         (void) dseg_add_unique_s4(cd, 0);                      /* IsLeaf          */
2370         (void) dseg_add_unique_s4(cd, 0);                      /* IntSave         */
2371         (void) dseg_add_unique_s4(cd, 0);                      /* FltSave         */
2372
2373         /* generate stub code */
2374
2375         M_STMFD(1<<REG_LR, REG_SP);
2376         M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize * 2 - 1);
2377
2378 #if defined(ENABLE_GC_CACAO)
2379         /* Save callee saved integer registers in stackframeinfo (GC may
2380            need to recover them during a collection). */
2381
2382         disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
2383                 OFFSET(stackframeinfo_t, intregs);
2384
2385         for (i = 0; i < INT_SAV_CNT; i++)
2386                 M_STR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2387 #endif
2388
2389         /* Save integer and float argument registers (these are 4
2390            registers, stack is 8-byte aligned). */
2391
2392         M_STMFD(BITMASK_ARGS, REG_SP);
2393         /* TODO: floating point */
2394
2395         /* create native stackframe info */
2396
2397         M_ADD_IMM(REG_A0, REG_SP, 4*4);
2398         M_MOV(REG_A1, REG_PV);
2399         disp = dseg_add_functionptr(cd, codegen_start_native_call);
2400         M_DSEG_BRANCH(disp);
2401
2402         /* recompute pv */
2403
2404         emit_recompute_pv(cd);
2405
2406         /* remember class argument */
2407
2408         if (m->flags & ACC_STATIC)
2409                 M_MOV(REG_ITMP3, REG_RESULT);
2410
2411         /* Restore integer and float argument registers (these are 4
2412            registers, stack is 8-byte aligned). */
2413
2414         M_LDMFD(BITMASK_ARGS, REG_SP);
2415         /* TODO: floating point */
2416
2417         /* copy or spill arguments to new locations */
2418         /* ATTENTION: the ARM has only integer argument registers! */
2419
2420         for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2421                 t = md->paramtypes[i].type;
2422
2423                 if (!md->params[i].inmemory) {
2424                         s1 = md->params[i].regoff;
2425                         s2 = nmd->params[j].regoff;
2426
2427                         if (!nmd->params[j].inmemory) {
2428 #if !defined(__ARM_EABI__)
2429                                 SPLIT_OPEN(t, s2, REG_ITMP1);
2430 #endif
2431
2432                                 if (IS_2_WORD_TYPE(t))
2433                                         M_LNGMOVE(s1, s2);
2434                                 else
2435                                         M_INTMOVE(s1, s2);
2436
2437 #if !defined(__ARM_EABI__)
2438                                 SPLIT_STORE_AND_CLOSE(t, s2, 0);
2439 #endif
2440                         }
2441                         else {
2442                                 if (IS_2_WORD_TYPE(t))
2443                                         M_LST(s1, REG_SP, s2);
2444                                 else
2445                                         M_IST(s1, REG_SP, s2);
2446                         }
2447                 }
2448                 else {
2449                         s1 = md->params[i].regoff + cd->stackframesize * 8;
2450                         s2 = nmd->params[j].regoff;
2451
2452                         if (IS_2_WORD_TYPE(t)) {
2453                                 M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
2454                                 M_LST(REG_ITMP12_PACKED, REG_SP, s2);
2455                         }
2456                         else {
2457                                 M_ILD(REG_ITMP1, REG_SP, s1);
2458                                 M_IST(REG_ITMP1, REG_SP, s2);
2459                         }
2460                 }
2461         }
2462
2463         /* Handle native Java methods. */
2464
2465         if (m->flags & ACC_NATIVE) {
2466                 /* put class into second argument register */
2467
2468                 if (m->flags & ACC_STATIC)
2469                         M_MOV(REG_A1, REG_ITMP3);
2470
2471                 /* put env into first argument register */
2472
2473                 disp = dseg_add_address(cd, VM_get_jnienv());
2474                 M_DSEG_LOAD(REG_A0, disp);
2475         }
2476
2477         /* Call the native function. */
2478
2479         disp = dseg_add_functionptr(cd, f);
2480         M_DSEG_BRANCH(disp);
2481
2482         /* recompute pv */
2483         /* TODO: this is only needed because of the tracer ... do we
2484            really need it? */
2485
2486         emit_recompute_pv(cd);
2487
2488         /* remove native stackframe info */
2489         /* TODO: improve this store/load */
2490
2491         M_STMFD(BITMASK_RESULT, REG_SP);
2492
2493         M_ADD_IMM(REG_A0, REG_SP, 2*4);
2494         M_MOV(REG_A1, REG_PV);
2495         disp = dseg_add_functionptr(cd, codegen_finish_native_call);
2496         M_DSEG_BRANCH(disp);
2497         emit_recompute_pv(cd);
2498
2499         M_MOV(REG_ITMP1_XPTR, REG_RESULT);
2500         M_LDMFD(BITMASK_RESULT, REG_SP);
2501
2502 #if defined(ENABLE_GC_CACAO)
2503         /* restore callee saved int registers from stackframeinfo (GC might have  */
2504         /* modified them during a collection).                                    */
2505
2506         disp = cd->stackframesize - SIZEOF_VOID_P - sizeof(stackframeinfo_t) +
2507                 OFFSET(stackframeinfo_t, intregs);
2508
2509         for (i = 0; i < INT_SAV_CNT; i++)
2510                 M_LDR_INTERN(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2511 #endif
2512
2513         /* finish stub code, but do not yet return to caller */
2514
2515         M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize * 2 - 1);
2516         M_LDMFD(1<<REG_LR, REG_SP);
2517
2518         /* check for exception */
2519
2520         M_TST(REG_ITMP1_XPTR, REG_ITMP1_XPTR);
2521         M_MOVEQ(REG_LR, REG_PC);            /* if no exception, return to caller  */
2522
2523         /* handle exception here */
2524
2525         M_SUB_IMM(REG_ITMP2_XPC, REG_LR, 4);/* move fault address into xpc        */
2526
2527         disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
2528         M_DSEG_LOAD(REG_ITMP3, disp);       /* load asm exception handler address */
2529         M_MOV(REG_PC, REG_ITMP3);           /* jump to asm exception handler      */
2530 }
2531
2532
2533 /* asm_debug *******************************************************************
2534
2535    Lazy debugger!
2536
2537 *******************************************************************************/
2538
2539 void asm_debug(int a1, int a2, int a3, int a4)
2540 {
2541         printf("===> i am going to exit after this debugging message!\n");
2542         printf("got asm_debug(%p, %p, %p, %p)\n",(void*)a1,(void*)a2,(void*)a3,(void*)a4);
2543         vm_abort("leave you now");
2544 }
2545
2546
2547 /*
2548  * These are local overrides for various environment variables in Emacs.
2549  * Please do not remove this and leave it at the end of the file, where
2550  * Emacs will automagically detect them.
2551  * ---------------------------------------------------------------------
2552  * Local variables:
2553  * mode: c
2554  * indent-tabs-mode: t
2555  * c-basic-offset: 4
2556  * tab-width: 4
2557  * End:
2558  * vim:noexpandtab:sw=4:ts=4:
2559  */