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