CACAO
codegen.cpp
Go to the documentation of this file.
1 /* src/vm/jit/s390/codegen.cpp - machine code generator for s390
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 <assert.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 
32 #include "vm/jit/s390/arch.hpp"
33 #include "vm/jit/s390/codegen.hpp"
34 #include "vm/jit/s390/emit.hpp"
35 #include "vm/jit/s390/md-abi.hpp"
36 
37 #include "native/localref.hpp"
38 #include "native/native.hpp"
39 
40 #include "mm/memory.hpp"
41 
42 #include "threads/lock.hpp"
43 
44 #include "vm/jit/builtin.hpp"
45 #include "vm/exceptions.hpp"
46 #include "vm/field.hpp"
47 #include "vm/global.hpp"
48 #include "vm/loader.hpp"
49 #include "vm/options.hpp"
50 #include "vm/statistics.hpp"
51 #include "vm/types.hpp"
52 #include "vm/vm.hpp"
53 
54 #include "vm/jit/abi.hpp"
55 #include "vm/jit/asmpart.hpp"
57 #include "vm/jit/dseg.hpp"
58 #include "vm/jit/emit-common.hpp"
59 #include "vm/jit/jit.hpp"
61 #include "vm/jit/methodheader.hpp"
62 #include "vm/jit/parse.hpp"
64 #include "vm/jit/reg.hpp"
65 #include "vm/jit/stacktrace.hpp"
66 #include "vm/jit/trap.hpp"
67 
68 
69 /* DO__LOG generates a call to do__log. No registers are destroyed,
70  * so you may use it anywhere. regs is an array containing all general
71  * purpose registers.
72  */
73 
74 /*
75 static void do__log(u4 *regs) {
76 }
77 */
78 
79 #define DO__LOG \
80  N_AHI(REG_SP, -200); \
81  N_STM(R0, R15, 96, REG_SP); \
82  M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
83  N_LA(R2, 96, RN, REG_SP); \
84  N_BASR(R14, R14); \
85  N_LM(R0, R15, 96, REG_SP); \
86  N_AHI(REG_SP, 200);
87 
88 /* If the following macro is defined, workaround code for hercules quirks
89  * is generated
90  */
91 
92 /* #define SUPPORT_HERCULES 1 */
93 
94 /*
95 
96 Layout of stackframe:
97 
98 Meaning Offset
99 ===============================================================================
100 return_address (stackframesize - 1) * 8
101 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
102 ...
103 saved_int_reg[rd->savintreguse]
104 saved_flt_reg[FLT_SAV_CNT - 1]
105 ...
106 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
107 
108 return_value_tmp (rd->memuse + 1) * 8
109 monitorenter_argument (rd->memuse) * 8
110 ???
111 local[rd->memuse - 1] (rd->memuse - 1) * 8
112 ....
113 local[2] 2 * 8
114 local[1] 1 * 8
115 local[0] 0 * 8
116 
117 */
118 
119 
120 /**
121  * Generates machine code for the method prolog.
122  */
124 {
125  varinfo* var;
126  methoddesc* md;
127  int32_t s1, s2;
128  int32_t p, t, l;
129  int32_t varindex;
130  int i;
131 
132  // Get required compiler data.
133  methodinfo* m = jd->m;
134  codeinfo* code = jd->code;
135  codegendata* cd = jd->cd;
136  registerdata* rd = jd->rd;
137 
138  /* CAUTION:
139  * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
140  */
141 
142  /* Offset PV */
143 
145 
146  /* create stack frame (if necessary) */
147 
148  if (cd->stackframesize) {
149  M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
150  }
151 
152  /* store return address */
153 
154  M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
155 
156  /* save used callee saved registers and return address */
157 
158  p = cd->stackframesize - 1;
159 
160  for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
161  p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
162  }
163  for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
164  p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
165  }
166 
167  /* take arguments out of register or stack frame */
168 
169  md = m->parseddesc;
170 
171  for (p = 0, l = 0; p < md->paramcount; p++) {
172  t = md->paramtypes[p].type;
173  varindex = jd->local_map[l * 5 + t];
174 
175  l++;
176 
177  if (IS_2_WORD_TYPE(t))
178  l++;
179 
180  if (varindex == UNUSED)
181  continue;
182 
183  var = VAR(varindex);
184 
185  s1 = md->params[p].regoff;
186 
187  if (IS_INT_LNG_TYPE(t)) { /* integer args */
188  if (IS_2_WORD_TYPE(t)) {
189  s2 = PACK_REGS(
190  GET_LOW_REG(s1),
191  GET_HIGH_REG(s1)
192  );
193  } else {
194  s2 = s1;
195  }
196  if (!md->params[p].inmemory) { /* register arguments */
197  if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
198  if (IS_2_WORD_TYPE(t)) {
199  M_LNGMOVE(s2, var->vv.regoff);
200  } else {
201  M_INTMOVE(s2, var->vv.regoff);
202  }
203  } else { /* reg arg -> spilled */
204  if (IS_2_WORD_TYPE(t)) {
205  M_LST(s2, REG_SP, var->vv.regoff);
206  } else {
207  M_IST(s2, REG_SP, var->vv.regoff);
208  }
209  }
210 
211  } else { /* stack arguments */
212  if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
213  if (IS_2_WORD_TYPE(t)) {
214  M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
215  } else {
216  M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
217  }
218  } else { /* stack arg -> spilled */
219  N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
220  }
221  }
222 
223  } else { /* floating args */
224  if (!md->params[p].inmemory) { /* register arguments */
225  s2 = s1;
226  if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
227  emit_fmove(cd, s2, var->vv.regoff);
228 
229  } else { /* reg arg -> spilled */
230  if (IS_2_WORD_TYPE(t))
231  M_DST(s2, REG_SP, var->vv.regoff);
232  else
233  M_FST(s2, REG_SP, var->vv.regoff);
234  }
235 
236  } else { /* stack arguments */
237  if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
238  if (IS_2_WORD_TYPE(t))
239  M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
240 
241  else
242  M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
243 
244  } else { /* stack-arg -> spilled */
245  N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
246  var->vv.regoff = cd->stackframesize * 8 + s1;
247  }
248  }
249  }
250  } /* end for */
251 }
252 
253 
254 /**
255  * Generates machine code for the method epilog.
256  */
258 {
259  int32_t p;
260  int i;
261 
262  // Get required compiler data.
263  codegendata* cd = jd->cd;
264  registerdata* rd = jd->rd;
265 
266  p = cd->stackframesize;
267 
268  /* restore return address */
269 
270  p--; M_ALD(REG_RA, REG_SP, p * 8);
271 
272  /* restore saved registers */
273 
274  for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
275  p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
276  }
277  for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
278  p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
279  }
280 
281  /* deallocate stack */
282 
283  if (cd->stackframesize)
284  M_AADD_IMM(cd->stackframesize * 8, REG_SP);
285 
286  M_RET;
287 }
288 
289 
290 /**
291  * Generates machine code for one ICMD.
292  */
294 {
295  varinfo* var;
296  builtintable_entry* bte;
297  methodinfo* lm; // Local methodinfo for ICMD_INVOKE*.
298  unresolved_method* um;
299  fieldinfo* fi;
300  unresolved_field* uf;
301  int32_t fieldtype;
302  int32_t s1, s2, s3, d, dd;
303  int32_t disp;
304 
305  // Get required compiler data.
306  codeinfo* code = jd->code;
307  codegendata* cd = jd->cd;
308 
309  switch (iptr->opc) {
310 
311  /* constant operations ************************************************/
312 
313  case ICMD_FCONST: /* ... ==> ..., constant */
314  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
315  disp = dseg_add_float(cd, iptr->sx.val.f);
316  M_FLD_DSEG(d, disp, REG_ITMP1);
317  emit_store_dst(jd, iptr, d);
318  break;
319 
320  case ICMD_DCONST: /* ... ==> ..., constant */
321  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
322  disp = dseg_add_double(cd, iptr->sx.val.d);
323  M_DLD_DSEG(d, disp, REG_ITMP1);
324  emit_store_dst(jd, iptr, d);
325  break;
326 
327  case ICMD_ACONST: /* ... ==> ..., constant */
328  d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
329 
330  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
331  constant_classref *cr = iptr->sx.val.c.ref;
332  disp = dseg_add_unique_address(cd, cr);
333 
335  cr, disp);
336 
337  M_ALD_DSEG(d, disp);
338  } else {
339  if (iptr->sx.val.anyptr == 0) {
340  M_CLR(d);
341  } else {
342  disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
343  M_ALD_DSEG(d, disp);
344  /*
345  if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
346  N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
347  M_SLL_IMM(16, d);
348  N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
349  } else {
350  disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
351  M_ALD_DSEG(d, disp);
352  }
353  */
354  }
355  }
356  emit_store_dst(jd, iptr, d);
357  break;
358 
359 
360  /* integer operations *************************************************/
361 
362  case ICMD_INEG: /* ..., value ==> ..., - value */
363 
364  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
365  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
366  M_INEG(s1, d);
367  emit_store_dst(jd, iptr, d);
368 
369  break;
370 
371  case ICMD_LNEG: /* ..., value ==> ..., - value */
372 
373  s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
374  d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
376  M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
377  N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
378  N_AHI(GET_HIGH_REG(d), -1);
379  emit_store_dst(jd, iptr, d);
380  break;
381 
382  case ICMD_I2L: /* ..., value ==> ..., value */
383 
384  d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
385  if (! N_IS_EVEN_ODD(d)) {
386  d = REG_ITMP31_PACKED;
387  }
388  assert(N_IS_EVEN_ODD(d));
389 
390  s1 = emit_load_s1(jd, iptr, REG_ITMP2);
391 
392  M_INTMOVE(s1, GET_HIGH_REG(d));
393  M_SRDA_IMM(32, GET_HIGH_REG(d));
394 
395  emit_copy_dst(jd, iptr, d);
396  emit_store_dst(jd, iptr, d);
397  break;
398 
399  case ICMD_L2I: /* ..., value ==> ..., value */
400  s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
401  d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
402  M_INTMOVE(GET_LOW_REG(s1), d);
403  emit_store_dst(jd, iptr, d);
404  break;
405 
406  case ICMD_INT2BYTE: /* ..., value ==> ..., value */
407  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
408  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
409  M_INTMOVE(s1, d);
410  M_SLL_IMM(24, d);
411  M_SRA_IMM(24, d);
412  emit_store_dst(jd, iptr, d);
413  break;
414 
415  case ICMD_INT2CHAR: /* ..., value ==> ..., value */
416  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
417  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
418  M_INTMOVE(s1, d);
419  M_SLL_IMM(16, d);
420  M_SRL_IMM(16, d);
421  emit_store_dst(jd, iptr, d);
422  break;
423 
424  case ICMD_INT2SHORT: /* ..., value ==> ..., value */
425 
426  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
427  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
428  M_INTMOVE(s1, d);
429  M_SLL_IMM(16, d);
430  M_SRA_IMM(16, d);
431  emit_store_dst(jd, iptr, d);
432  break;
433 
434  case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
435 
436  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
437  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
438  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
439  if (s2 == d)
440  M_IADD(s1, d);
441  else {
442  M_INTMOVE(s1, d);
443  M_IADD(s2, d);
444  }
445  emit_store_dst(jd, iptr, d);
446 
447  break;
448 
449  case ICMD_IINC:
450  case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
451  /* sx.val.i = constant */
452  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
453  d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
454  M_INTMOVE(s1, d);
455 
456  if (N_VALID_IMM(iptr->sx.val.i)) {
457  M_IADD_IMM(iptr->sx.val.i, d);
458  } else {
459  ICONST(REG_ITMP2, iptr->sx.val.i);
460  M_IADD(REG_ITMP2, d);
461  }
462  emit_store_dst(jd, iptr, d);
463  break;
464 
465  case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
466 
467  /* M, (r, q) -> (r, q) */
468 
469  d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
470 
471  s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
472  s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
473  dd = GET_HIGH_REG(d);
474 
475  if (s2 == dd) {
476  M_IADD(s1, dd);
477  } else {
478  M_INTMOVE(s1, dd);
479  M_IADD(s2, dd);
480  }
481 
482  s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
483  s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
484  dd = GET_LOW_REG(d);
485 
486  if (s2 == dd) {
487  N_ALR(dd, s1);
488  } else {
489  M_INTMOVE(s1, dd);
490  N_ALR(dd, s2);
491  }
492 
493  N_BRC(8 | 4, SZ_BRC + SZ_AHI);
494  N_AHI(GET_HIGH_REG(d), 1);
495 
496  emit_store_dst(jd, iptr, d);
497  break;
498 
499  case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
500  /* sx.val.l = constant */
501 
502  d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
503  dd = GET_HIGH_REG(d);
504 
505  s1 = emit_load_s1_high(jd, iptr, dd);
506  s3 = iptr->sx.val.l >> 32;
507 
508  M_INTMOVE(s1, dd);
509 
510  if (N_VALID_IMM(s3)) {
511  M_IADD_IMM(s3, dd);
512  } else {
513  ICONST(REG_ITMP3, s3);
514  M_IADD(REG_ITMP3, dd);
515  }
516 
517  dd = GET_LOW_REG(d);
518  s1 = emit_load_s1_low(jd, iptr, dd);
519  s3 = iptr->sx.val.l & 0xffffffff;
520  ICONST(REG_ITMP3, s3);
521 
522  M_INTMOVE(s1, dd);
523  N_ALR(dd, REG_ITMP3);
524 
525  N_BRC(8 | 4, SZ_BRC + SZ_AHI);
526  N_AHI(GET_HIGH_REG(d), 1);
527 
528  emit_store_dst(jd, iptr, d);
529  break;
530 
531  case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
532 
533  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
534  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
535  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
536  if (s2 == d) {
537  M_INTMOVE(s1, REG_ITMP1);
538  M_ISUB(s2, REG_ITMP1);
539  M_INTMOVE(REG_ITMP1, d);
540  } else {
541  M_INTMOVE(s1, d);
542  M_ISUB(s2, d);
543  }
544  emit_store_dst(jd, iptr, d);
545 
546  break;
547 
548  case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
549  /* sx.val.i = constant */
550 
551  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
552  d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
553  M_INTMOVE(s1, d);
554 
555  if (N_VALID_IMM(-iptr->sx.val.i)) {
556  M_ISUB_IMM(iptr->sx.val.i, d);
557  } else {
558  ICONST(REG_ITMP2, iptr->sx.val.i);
559  M_ISUB(REG_ITMP2, d);
560  }
561  emit_store_dst(jd, iptr, d);
562 
563  break;
564 
565  case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
566 
567  d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
568 
569  s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
570  s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
571  dd = GET_HIGH_REG(d);
572 
573  if (s2 == dd) {
574  M_INTMOVE(s2, REG_ITMP3);
575  s2 = REG_ITMP3;
576  }
577 
578  M_INTMOVE(s1, dd);
579  M_ISUB(s2, dd);
580 
581  s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
582  s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
583  dd = GET_LOW_REG(d);
584 
585  if (s2 == dd) {
586  M_INTMOVE(s2, REG_ITMP3);
587  s2 = REG_ITMP3;
588  }
589 
590  M_INTMOVE(s1, dd);
591  N_SLR(dd, s2);
592 
593  N_BRC(1 | 2, SZ_BRC + SZ_AHI);
594  N_AHI(GET_HIGH_REG(d), -1);
595 
596  emit_store_dst(jd, iptr, d);
597  break;
598 
599  case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
600  /* sx.val.l = constant */
601 
602  d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
603 
604  dd = GET_HIGH_REG(d);
605  s1 = emit_load_s1_high(jd, iptr, dd);
606  s3 = iptr->sx.val.l >> 32;
607 
608  M_INTMOVE(s1, dd);
609 
610  if (N_VALID_IMM(-s3)) {
611  M_IADD_IMM(-s3, dd);
612  } else {
613  ICONST(REG_ITMP3, s3);
614  M_ISUB(REG_ITMP3, dd);
615  }
616 
617  dd = GET_LOW_REG(d);
618  s1 = emit_load_s1_low(jd, iptr, dd);
619  s3 = iptr->sx.val.l & 0xffffffff;
620  ICONST(REG_ITMP3, s3);
621 
622  M_INTMOVE(s1, dd);
623  N_SLR(dd, REG_ITMP3);
624 
625  N_BRC(1 | 2, SZ_BRC + SZ_AHI);
626  N_AHI(GET_HIGH_REG(d), -1);
627 
628  emit_store_dst(jd, iptr, d);
629  break;
630 
631  case ICMD_IMUL: /* ..., 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_ITMP2);
636  if (s2 == d)
637  M_IMUL(s1, d);
638  else {
639  M_INTMOVE(s1, d);
640  M_IMUL(s2, d);
641  }
642  emit_store_dst(jd, iptr, d);
643 
644  break;
645 
646  case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
647  /* sx.val.i = constant */
648  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
649  d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
650  M_INTMOVE(s1, d);
651  if (iptr->sx.val.i == 2) {
652  M_SLL_IMM(1, d);
653  } else if (N_VALID_IMM(iptr->sx.val.i)) {
654  M_IMUL_IMM(iptr->sx.val.i, d);
655  } else {
656  disp = dseg_add_s4(cd, iptr->sx.val.i);
657  M_ILD_DSEG(REG_ITMP2, disp);
658  M_IMUL(REG_ITMP2, d);
659  }
660  emit_store_dst(jd, iptr, d);
661  break;
662 
663  case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
664  case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
665 
666  /* load s1 into r0 */
667 
671 
672  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
673 
674  /* extend s1 to long */
675 
677 
678  /* divide */
679 
681 
682  /* take result */
683 
684  switch (iptr->opc) {
685  case ICMD_IREM:
688  break;
689  case ICMD_IDIV:
692  break;
693  }
694 
695  emit_store_dst(jd, iptr, d);
696 
697  break;
698 
699  case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
700  case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
701 
702  bte = iptr->sx.s23.s3.bte;
703 
704  /* test s2 for zero */
705 
706  s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
709  emit_arithmetic_check(cd, iptr, REG_ITMP3);
710 
711  /* TODO SIGFPE? */
712 
713  disp = dseg_add_functionptr(cd, bte->fp);
714 
715  /* load arguments */
716 
718 
719  s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
721 
722  /* call builtin */
723 
724  M_ASUB_IMM(96, REG_SP);
725  M_ALD_DSEG(REG_ITMP2, disp);
727  M_AADD_IMM(96, REG_SP);
728 
729  /* store result */
730 
731  d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
733  emit_store_dst(jd, iptr, d);
734 
735  break;
736 
737  case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
738  case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
739  case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
740 
741  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
742  d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
743  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
744 
745  /* Use only 5 bits of sencond operand. */
746 
747  M_INTMOVE(s2, REG_ITMP2);
748  s2 = REG_ITMP2;
749  ICONST(REG_ITMP3, 0x1F);
750  M_IAND(REG_ITMP3, s2);
751 
752  M_INTMOVE(s1, d);
753 
754  switch (iptr->opc) {
755  case ICMD_ISHL:
756  M_SLL(s2, d);
757  break;
758  case ICMD_ISHR:
759  M_SRA(s2, d);
760  break;
761  case ICMD_IUSHR:
762  M_SRL(s2, d);
763  break;
764  default:
765  assert(0);
766  }
767  emit_store_dst(jd, iptr, d);
768  break;
769 
770  case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
771  /* sx.val.i = constant */
772  {
773  u1 *ref;
774 
775  assert(iptr->sx.val.i <= 32);
776 
777  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
778  d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
779 
780  M_INTMOVE(s1, d);
781  M_TEST(d);
782  ref = cd->mcodeptr;
783  M_BGE(0);
784 
785  s3 = (1 << iptr->sx.val.i) - 1;
786 
787  if (N_VALID_IMM(s3)) {
788  M_IADD_IMM(s3, d);
789  } else {
790  ICONST(REG_ITMP1, -1);
791  M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
792  M_IADD(REG_ITMP1, d);
793  }
794 
795  N_BRC_BACK_PATCH(ref);
796 
797  M_SRA_IMM(iptr->sx.val.i, d);
798 
799  emit_store_dst(jd, iptr, d);
800  }
801 
802  break;
803 
804  case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
805  /* sx.val.i = constant */
806 
807  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
808  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
809 
810  if (s1 == d) {
811  M_MOV(s1, REG_ITMP1);
812  s1 = REG_ITMP1;
813  }
814 
815  ICONST(REG_ITMP3, iptr->sx.val.i);
816 
817  M_INTMOVE(s1, d);
818  M_IAND(REG_ITMP3, d);
819 
820  M_TEST(s1);
821  M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
822 
823  N_LCR(d, s1);
824  N_NR(d, REG_ITMP3);
825  N_LCR(d, d);
826 
827  emit_store_dst(jd, iptr, d);
828 
829  break;
830 
831  case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
832  /* sx.val.i = constant */
833  case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
834  /* sx.val.i = constant */
835  case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
836  /* sx.val.i = constant */
837  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
838  d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
839 
840  M_INTMOVE(s1, d);
841 
842  disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
843 
844  switch (iptr->opc) {
845  case ICMD_ISHLCONST:
846  N_SLL(d, disp, RN);
847  break;
848  case ICMD_ISHRCONST:
849  N_SRA(d, disp, RN);
850  break;
851  case ICMD_IUSHRCONST:
852  N_SRL(d, disp, RN);
853  break;
854  default:
855  assert(0);
856  }
857 
858  emit_store_dst(jd, iptr, d);
859  break;
860 
861  case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
862 
863  case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
864 
865  case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
866 
867  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
868 
869  /* Use only 6 bits of second operand */
870 
871  M_INTMOVE(s2, REG_ITMP2);
872  s2 = REG_ITMP2;
873  ICONST(REG_ITMP1, 0x3F);
874  M_IAND(REG_ITMP1, s2);
875 
876  s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
877  d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
878 
879  /* Destination must be even-odd pair */
880 
881  if (! N_IS_EVEN_ODD(d)) {
882  d = REG_ITMP31_PACKED;
883  }
884 
885  assert(N_IS_EVEN_ODD(d));
886 
887  M_LNGMOVE(s1, d);
888 
889  switch (iptr->opc) {
890  case ICMD_LSHL:
891  M_SLDL(s2, GET_HIGH_REG(d));
892  break;
893  case ICMD_LSHR:
894  M_SRDA(s2, GET_HIGH_REG(d));
895  break;
896  case ICMD_LUSHR:
897  M_SRDL(s2, GET_HIGH_REG(d));
898  break;
899  default:
900  assert(0);
901  }
902 
903  emit_copy_dst(jd, iptr, d);
904  emit_store_dst(jd, iptr, d);
905 
906  break;
907 
908  case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
909  /* sx.val.i = constant */
910  case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
911  /* sx.val.i = constant */
912  case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
913  /* sx.val.l = constant */
914  case ICMD_LMULPOW2:
915 
916  d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
917  if (! N_IS_EVEN_ODD(d)) {
918  d = REG_ITMP31_PACKED;
919  }
920  assert(N_IS_EVEN_ODD(d));
921 
922  s1 = emit_load_s1(jd, iptr, d);
923 
924  M_LNGMOVE(s1, d);
925 
926  disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
927 
928  switch (iptr->opc) {
929  case ICMD_LSHLCONST:
930  N_SLDL(GET_HIGH_REG(d), disp, RN);
931  break;
932  case ICMD_LSHRCONST:
933  N_SRDA(GET_HIGH_REG(d), disp, RN);
934  break;
935  case ICMD_LUSHRCONST:
936  N_SRDL(GET_HIGH_REG(d), disp, RN);
937  break;
938  case ICMD_LMULPOW2:
939  N_SLDL(GET_HIGH_REG(d), disp, RN);
940  break;
941  default:
942  assert(0);
943  }
944 
945  emit_copy_dst(jd, iptr, d);
946  emit_store_dst(jd, iptr, d);
947  break;
948 
949  case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
950 
951  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
952  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
953  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
954  if (s2 == d)
955  M_IAND(s1, d);
956  else {
957  M_INTMOVE(s1, d);
958  M_IAND(s2, d);
959  }
960  emit_store_dst(jd, iptr, d);
961 
962  break;
963 
964  case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
965 
966  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
967  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
968  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
969  if (s2 == d)
970  M_IOR(s1, d);
971  else {
972  M_INTMOVE(s1, d);
973  M_IOR(s2, d);
974  }
975  emit_store_dst(jd, iptr, d);
976 
977  break;
978 
979  case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
980 
981  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
982  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
983  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
984  if (s2 == d)
985  M_IXOR(s1, d);
986  else {
987  M_INTMOVE(s1, d);
988  M_IXOR(s2, d);
989  }
990  emit_store_dst(jd, iptr, d);
991 
992  break;
993 
994 
995 
996  case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
997  /* sx.val.i = constant */
998  case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
999  /* sx.val.i = constant */
1000  case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1001  /* sx.val.i = constant */
1002 
1003  d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1004  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1005 
1006  M_INTMOVE(s1, d);
1007  ICONST(REG_ITMP2, iptr->sx.val.i);
1008 
1009  switch (iptr->opc) {
1010  case ICMD_IANDCONST:
1011  M_IAND(REG_ITMP2, d);
1012  break;
1013  case ICMD_IXORCONST:
1014  M_IXOR(REG_ITMP2, d);
1015  break;
1016  case ICMD_IORCONST:
1017  M_IOR(REG_ITMP2, d);
1018  break;
1019  default:
1020  assert(0);
1021  }
1022 
1023  emit_store_dst(jd, iptr, d);
1024 
1025  break;
1026 
1027  case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1028  case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1029  case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1030 
1031  d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1032 
1033  s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1034  s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1035  dd = GET_LOW_REG(d);
1036 
1037  switch (iptr->opc) {
1038  case ICMD_LAND:
1039  if (s2 == dd) {
1040  M_IAND(s1, dd);
1041  } else {
1042  M_INTMOVE(s1, dd);
1043  M_IAND(s2, dd);
1044  }
1045  break;
1046  case ICMD_LXOR:
1047  if (s2 == dd) {
1048  M_IXOR(s1, dd);
1049  } else {
1050  M_INTMOVE(s1, dd);
1051  M_IXOR(s2, dd);
1052  }
1053  break;
1054  case ICMD_LOR:
1055  if (s2 == dd) {
1056  M_IOR(s1, dd);
1057  } else {
1058  M_INTMOVE(s1, dd);
1059  M_IOR(s2, dd);
1060  }
1061  break;
1062  default:
1063  assert(0);
1064  }
1065 
1066  s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1067  s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1068  dd = GET_HIGH_REG(d);
1069 
1070  switch (iptr->opc) {
1071  case ICMD_LAND:
1072  if (s2 == dd) {
1073  M_IAND(s1, dd);
1074  } else {
1075  M_INTMOVE(s1, dd);
1076  M_IAND(s2, dd);
1077  }
1078  break;
1079  case ICMD_LXOR:
1080  if (s2 == dd) {
1081  M_IXOR(s1, dd);
1082  } else {
1083  M_INTMOVE(s1, dd);
1084  M_IXOR(s2, dd);
1085  }
1086  break;
1087  case ICMD_LOR:
1088  if (s2 == dd) {
1089  M_IOR(s1, dd);
1090  } else {
1091  M_INTMOVE(s1, dd);
1092  M_IOR(s2, dd);
1093  }
1094  break;
1095  default:
1096  assert(0);
1097  }
1098 
1099  emit_store_dst(jd, iptr, d);
1100  break;
1101 
1102  case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1103  /* sx.val.l = constant */
1104  case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1105  /* sx.val.l = constant */
1106  case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1107  /* sx.val.l = constant */
1108 
1109  /* TODO should use memory operand to access data segment, not load */
1110 
1111  d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1112 
1113  s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1114  s3 = iptr->sx.val.l & 0xffffffff;
1115 
1116  M_INTMOVE(s1, GET_LOW_REG(d));
1117 
1118  ICONST(REG_ITMP3, s3);
1119 
1120  switch (iptr->opc) {
1121  case ICMD_LANDCONST:
1123  break;
1124  case ICMD_LXORCONST:
1126  break;
1127  case ICMD_LORCONST:
1129  break;
1130  default:
1131  assert(0);
1132  }
1133 
1134  s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1135  s3 = iptr->sx.val.l >> 32;
1136 
1137  M_INTMOVE(s1, GET_HIGH_REG(d));
1138 
1139  ICONST(REG_ITMP3, s3);
1140 
1141  switch (iptr->opc) {
1142  case ICMD_LANDCONST:
1144  break;
1145  case ICMD_LXORCONST:
1147  break;
1148  case ICMD_LORCONST:
1150  break;
1151  default:
1152  assert(0);
1153  }
1154 
1155  emit_store_dst(jd, iptr, d);
1156 
1157  break;
1158 
1159  /* floating operations ************************************************/
1160 
1161  case ICMD_FNEG: /* ..., value ==> ..., - value */
1162  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1163  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1164  M_FMOVN(s1, d);
1165  emit_store_dst(jd, iptr, d);
1166  break;
1167 
1168  case ICMD_DNEG: /* ..., value ==> ..., - value */
1169  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1170  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1171  M_DMOVN(s1, d);
1172  emit_store_dst(jd, iptr, d);
1173  break;
1174 
1175  case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1176  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1177  s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1178  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1179  if (s2 == d)
1180  M_FADD(s1, d);
1181  else {
1182  emit_fmove(cd, s1, d);
1183  M_FADD(s2, d);
1184  }
1185  emit_store_dst(jd, iptr, d);
1186  break;
1187 
1188  case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1189  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1190  s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1191  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1192  if (s2 == d)
1193  M_DADD(s1, d);
1194  else {
1195  emit_fmove(cd, s1, d);
1196  M_DADD(s2, d);
1197  }
1198  emit_store_dst(jd, iptr, d);
1199  break;
1200 
1201  case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1202  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1203  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1204  s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1205 
1206  emit_fmove(cd, s1, d);
1207  M_FSUB(s2, d);
1208  emit_store_dst(jd, iptr, d);
1209  break;
1210 
1211  case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1212  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1213  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1214  s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1215 
1216  emit_fmove(cd, s1, d);
1217  M_DSUB(s2, d);
1218  emit_store_dst(jd, iptr, d);
1219  break;
1220 
1221  case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1222  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1223  s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1224  d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1225  if (s2 == d)
1226  M_FMUL(s1, d);
1227  else {
1228  emit_fmove(cd, s1, d);
1229  M_FMUL(s2, d);
1230  }
1231  emit_store_dst(jd, iptr, d);
1232  break;
1233 
1234  case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1235  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1236  s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1237  d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1238  if (s2 == d)
1239  M_DMUL(s1, d);
1240  else {
1241  emit_fmove(cd, s1, d);
1242  M_DMUL(s2, d);
1243  }
1244  emit_store_dst(jd, iptr, d);
1245  break;
1246 
1247  case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1248  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1249  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1250  s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1251 
1252  emit_fmove(cd, s1, d);
1253  M_FDIV(s2, d);
1254  emit_store_dst(jd, iptr, d);
1255  break;
1256 
1257  case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1258  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1259  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1260  s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1261 
1262  emit_fmove(cd, s1, d);
1263  M_DDIV(s2, d);
1264  emit_store_dst(jd, iptr, d);
1265  break;
1266 
1267  case ICMD_I2F: /* ..., value ==> ..., (float) value */
1268  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1269  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1270  M_CVTIF(s1, d);
1271  emit_store_dst(jd, iptr, d);
1272  break;
1273 
1274  case ICMD_I2D: /* ..., value ==> ..., (double) value */
1275  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1276  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1277  M_CVTID(s1, d);
1278  emit_store_dst(jd, iptr, d);
1279  break;
1280 
1281  case ICMD_F2I: /* ..., value ==> ..., (int) value */
1282  case ICMD_D2I:
1283  {
1284  u1 *ref1;
1285 #ifdef SUPPORT_HERCULES
1286  u1 *ref2, *ref3;
1287 #endif
1288 
1289  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1290  d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1291 
1292  /* Test if NAN */
1293 
1294  switch (iptr->opc) {
1295  case ICMD_F2I:
1296  N_LTEBR(s1, s1);
1297  break;
1298  case ICMD_D2I:
1299  N_LTDBR(s1, s1);
1300  break;
1301  }
1302 
1303  N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1304  N_LHI(d, 0); /* Load 0 */
1305  ref1 = cd->mcodeptr;
1306  N_BRC(DD_ANY, 0); /* Exit */
1307 
1308  /* Convert */
1309 
1310  switch (iptr->opc) {
1311  case ICMD_F2I:
1312  M_CVTFI(s1, d);
1313  break;
1314  case ICMD_D2I:
1315  M_CVTDI(s1, d);
1316  break;
1317  }
1318 
1319 #ifdef SUPPORT_HERCULES
1320  /* Hercules does the conversion using a plain C conversion.
1321  * According to manual, real hardware should *NOT* require this.
1322  *
1323  * Corner case: Positive float leads to INT_MIN (overflow).
1324  */
1325 
1326  switch (iptr->opc) {
1327  case ICMD_F2I:
1328  N_LTEBR(s1, s1);
1329  break;
1330  case ICMD_D2I:
1331  N_LTDBR(s1, s1);
1332  break;
1333  }
1334 
1335  ref2 = cd->mcodeptr;
1336  N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1337 
1338  M_TEST(d);
1339 
1340  ref3 = cd->mcodeptr;
1341  M_BGE(0); /* If integer result is negative, continue */
1342 
1343  disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1344  M_ILD_DSEG(d, disp);
1345 #endif
1346  N_BRC_BACK_PATCH(ref1);
1347 #ifdef SUPPORT_HERCULES
1348  N_BRC_BACK_PATCH(ref2);
1349  N_BRC_BACK_PATCH(ref3);
1350 #endif
1351  emit_store_dst(jd, iptr, d);
1352  }
1353  break;
1354 
1355  case ICMD_F2D: /* ..., value ==> ..., (double) value */
1356  {
1357 #ifdef SUPPORT_HERCULES
1358  u1 *ref;
1359 #endif
1360  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1361  d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1362 #ifdef SUPPORT_HERCULES
1363  N_LTEBR(s1, s1);
1364  ref = cd->mcodeptr;
1365  N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1366  disp = dseg_add_double(cd, 0.0 / 0.0);
1367  M_DLD_DSEG(d, disp, REG_ITMP1);
1369  N_BRC_BACK_PATCH(ref);
1370 #endif
1371  M_CVTFD(s1, d);
1372 #ifdef SUPPORT_HERCULES
1374 #endif
1375  emit_store_dst(jd, iptr, d);
1376  }
1377  break;
1378 
1379  case ICMD_D2F: /* ..., value ==> ..., (float) value */
1380  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1381  d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1382  M_CVTDF(s1, d);
1383  emit_store_dst(jd, iptr, d);
1384  break;
1385 
1386  case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1387  /* == => 0, < => 1, > => -1 */
1388  case ICMD_DCMPL:
1389 
1390 
1391  case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1392  /* == => 0, < => 1, > => -1 */
1393  case ICMD_DCMPG:
1394 
1395  s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1396  s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1397  d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1398 
1399  switch (iptr->opc) {
1400  case ICMD_FCMPG:
1401  case ICMD_FCMPL:
1402  M_FCMP(s1, s2);
1403  break;
1404  case ICMD_DCMPG:
1405  case ICMD_DCMPL:
1406  M_DCMP(s1, s2);
1407  break;
1408  }
1409 
1410  N_BRC( /* load 1 */
1411  DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1412  SZ_BRC + SZ_BRC + SZ_BRC
1413  );
1414 
1415  N_BRC( /* load -1 */
1416  DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1417  SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1418  );
1419 
1420  N_BRC( /* load 0 */
1421  DD_E,
1422  SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1423  );
1424 
1425  N_LHI(d, 1); /* GT */
1426  M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1427  N_LHI(d, -1); /* LT */
1428  M_BR(SZ_BRC + SZ_LHI);
1429  N_LHI(d, 0); /* EQ */
1430 
1431  emit_store_dst(jd, iptr, d);
1432 
1433  break;
1434 
1435 
1436  /* memory operations **************************************************/
1437 
1438  case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1439  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1440  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1441  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1442 
1443  /* implicit null-pointer check */
1444  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1445 
1446  N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1447 
1448  M_SLL_IMM(24, d);
1449  M_SRA_IMM(24, d);
1450 
1451  emit_store_dst(jd, iptr, d);
1452  break;
1453 
1454  case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1455 
1456  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1457  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1458  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1459 
1460  /* implicit null-pointer check */
1461  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1462 
1463  M_INTMOVE(s2, REG_ITMP2);
1464  M_SLL_IMM(1, REG_ITMP2);
1465 
1466  N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1467 
1468  /* N_LH does sign extends, undo ! */
1469 
1470  M_SLL_IMM(16, d);
1471  M_SRL_IMM(16, d);
1472 
1473  emit_store_dst(jd, iptr, d);
1474  break;
1475 
1476  case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1477  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1478  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1479  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1480 
1481  /* implicit null-pointer check */
1482  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1483 
1484  M_INTMOVE(s2, REG_ITMP2);
1485  M_SLL_IMM(1, REG_ITMP2);
1486 
1487  N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1488  emit_store_dst(jd, iptr, d);
1489  break;
1490 
1491  case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1492  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1493  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1494  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1495 
1496  /* implicit null-pointer check */
1497  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1498 
1499  M_INTMOVE(s2, REG_ITMP2);
1500  M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1501  N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1502  emit_store_dst(jd, iptr, d);
1503  break;
1504 
1505  case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1506 
1507  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1508  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1509 
1510  d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1511 
1512  /* implicit null-pointer check */
1513  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1514 
1515  M_INTMOVE(s2, REG_ITMP2);
1516  M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1517 
1518  N_L(
1519  GET_LOW_REG(d) /* maybe itmp3 */,
1520  OFFSET(java_longarray_t, data[0]) + 4,
1521  REG_ITMP2, s1 /* maybe itmp1 */
1522  );
1523 
1524  N_L(
1525  GET_HIGH_REG(d) /* maybe itmp1 */,
1526  OFFSET(java_longarray_t, data[0]),
1527  REG_ITMP2, s1 /* maybe itmp1 */
1528  );
1529 
1530  emit_store_dst(jd, iptr, d);
1531 
1532  break;
1533 
1534  case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1535 
1536  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1537  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1538  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1539 
1540  /* implicit null-pointer check */
1541  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1542 
1543  M_INTMOVE(s2, REG_ITMP2);
1544  M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1545 
1546  N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1547 
1548  emit_store_dst(jd, iptr, d);
1549  break;
1550 
1551  case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1552  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1553  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1554  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1555 
1556  /* implicit null-pointer check */
1557  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1558 
1559  M_INTMOVE(s2, REG_ITMP2);
1560  M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1561 
1562  N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1563 
1564  emit_store_dst(jd, iptr, d);
1565  break;
1566 
1567  case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1568  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1569  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1570  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1571 
1572  /* implicit null-pointer check */
1573  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1574 
1575  M_INTMOVE(s2, REG_ITMP2);
1576  M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1577  N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1578  emit_store_dst(jd, iptr, d);
1579  break;
1580 
1581  case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1582  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1583  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1584  /* implicit null-pointer check */
1585  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1586  s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1587 
1588  N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1589  break;
1590 
1591  case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1592 
1593  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1594  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1595  /* implicit null-pointer check */
1596  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1597  s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1598 
1599  M_INTMOVE(s2, REG_ITMP2);
1600  M_SLL_IMM(1, REG_ITMP2);
1601 
1602  N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1603 
1604  break;
1605 
1606  case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1607  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1608  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1609  /* implicit null-pointer check */
1610  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1611  s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1612 
1613  M_INTMOVE(s2, REG_ITMP2);
1614  M_SLL_IMM(1, REG_ITMP2);
1615 
1616  N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1617  break;
1618 
1619  case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1620 
1621  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1622  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1623  /* implicit null-pointer check */
1624  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1625 
1626  s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1627 
1628  M_INTMOVE(s2, REG_ITMP2);
1629  M_SLL_IMM(2, REG_ITMP2);
1630 
1631  N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1632  break;
1633 
1634  case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1635 
1636  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1637  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1638  /* implicit null-pointer check */
1639  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1640 
1641  M_INTMOVE(s2, REG_ITMP2);
1642  M_SLL_IMM(3, REG_ITMP2);
1643 
1644  s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1645  N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1);
1646  s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1647  N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1);
1648  break;
1649 
1650  case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1651  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1652  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1653  /* implicit null-pointer check */
1654  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1655  s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1656 
1657  M_INTMOVE(s2, REG_ITMP2);
1658  M_SLL_IMM(2, REG_ITMP2);
1659 
1660  N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1661  break;
1662 
1663  case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1664  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1665  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1666  /* implicit null-pointer check */
1667  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1668  s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1669 
1670  M_INTMOVE(s2, REG_ITMP2);
1671  M_SLL_IMM(3, REG_ITMP2);
1672 
1673  N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1674  break;
1675 
1676  case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1677 
1678  s1 = emit_load_s1(jd, iptr, REG_A0);
1679  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1680  /* implicit null-pointer check */
1681  emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1682  s3 = emit_load_s3(jd, iptr, REG_A1);
1683 
1684  M_INTMOVE(s1, REG_A0);
1685  M_INTMOVE(s3, REG_A1);
1686 
1688  M_ALD_DSEG(REG_ITMP2, disp);
1689  M_ASUB_IMM(96, REG_SP);
1691  M_AADD_IMM(96, REG_SP);
1692 
1693  emit_arraystore_check(cd, iptr);
1694 
1695  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1696  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1697  s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1698 
1699  M_INTMOVE(s2, REG_ITMP2);
1700  M_SLL_IMM(2, REG_ITMP2);
1701  N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1702 
1703  /*
1704  M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1705  M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1706  */
1707  break;
1708 
1709  case ICMD_GETFIELD: /* ... ==> ..., value */
1710 
1711  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1712  emit_nullpointer_check(cd, iptr, s1);
1713 
1714  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1715  uf = iptr->sx.s23.s3.uf;
1716  fieldtype = uf->fieldref->parseddesc.fd->type;
1717  disp = 0;
1718 
1720  }
1721  else {
1722  fi = iptr->sx.s23.s3.fmiref->p.field;
1723  fieldtype = fi->type;
1724  disp = fi->offset;
1725  }
1726 
1727  switch (fieldtype) {
1728  case TYPE_INT:
1729  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1730  M_ILD(d, s1, disp);
1731  break;
1732  case TYPE_LNG:
1733  d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1734  if (GET_HIGH_REG(d) == s1) {
1735  M_ILD(GET_LOW_REG(d), s1, disp + 4);
1736  M_ILD(GET_HIGH_REG(d), s1, disp);
1737  }
1738  else {
1739  M_ILD(GET_LOW_REG(d), s1, disp + 4);
1740  M_ILD(GET_HIGH_REG(d), s1, disp);
1741  }
1742  break;
1743  case TYPE_ADR:
1744  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1745  M_ALD(d, s1, disp);
1746  break;
1747  case TYPE_FLT:
1748  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1749  M_FLD(d, s1, disp);
1750  break;
1751  case TYPE_DBL:
1752  d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1753  M_DLD(d, s1, disp);
1754  break;
1755  }
1756  emit_store_dst(jd, iptr, d);
1757  break;
1758 
1759  case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1760  {
1761  u1 *ref;
1762  patchref_t *pr;
1763 
1764  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1765  emit_nullpointer_check(cd, iptr, s1);
1766 
1767  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1768  uf = iptr->sx.s23.s3.uf;
1769  fieldtype = uf->fieldref->parseddesc.fd->type;
1770  disp = 0;
1771  }
1772  else {
1773  fi = iptr->sx.s23.s3.fmiref->p.field;
1774  fieldtype = fi->type;
1775  disp = fi->offset;
1776  }
1777 
1778  /* We can't add a patcher ref behind this load,
1779  * because the patcher would destroy REG_ITMP3.
1780  *
1781  * We pass in the disp parameter, how many bytes
1782  * to skip to the to the actual store.
1783  *
1784  * XXX this relies on patcher_add_patch_ref internals
1785  */
1786 
1787  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1789  ref = cd->mcodeptr;
1790  }
1791 
1792 
1793  if (IS_INT_LNG_TYPE(fieldtype)) {
1794  if (IS_2_WORD_TYPE(fieldtype))
1795  s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1796  else
1797  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1798  } else {
1799  s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1800  }
1801 
1802  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1803  pr->disp = (cd->mcodeptr - ref);
1804  }
1805 
1806  switch (fieldtype) {
1807  case TYPE_INT:
1808  M_IST(s2, s1, disp);
1809  break;
1810  case TYPE_LNG:
1811  M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
1812  M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
1813  break;
1814  case TYPE_ADR:
1815  M_AST(s2, s1, disp);
1816  break;
1817  case TYPE_FLT:
1818  M_FST(s2, s1, disp);
1819  break;
1820  case TYPE_DBL:
1821  M_DST(s2, s1, disp);
1822  break;
1823  }
1824 
1825  }
1826  break;
1827 
1828  /* branch operations **************************************************/
1829 
1830  case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1831 
1833  M_ALD_DSEG(REG_ITMP1, disp);
1835  M_NOP;
1836 
1837  break;
1838 
1839  case ICMD_IF_LLT: /* ..., value ==> ... */
1840  case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
1841  case ICMD_IF_LGT:
1842  case ICMD_IF_LGE:
1843  case ICMD_IF_LEQ:
1844  case ICMD_IF_LNE:
1845 
1846  /* ATTENTION: compare high words signed and low words unsigned */
1847 
1848 # define LABEL_OUT BRANCH_LABEL_1
1849 
1850  s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1851 
1852  if (N_VALID_IMM(iptr->sx.val.l >> 32))
1853  M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
1854  else {
1855  disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
1856  if (N_VALID_DSEG_DISP(disp)) {
1857  N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
1858  } else {
1859  ICONST(REG_ITMP2, disp);
1860  N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
1861  }
1862  }
1863 
1864  switch(iptr->opc) {
1865  case ICMD_IF_LLT:
1866  case ICMD_IF_LLE:
1867  emit_blt(cd, iptr->dst.block);
1868  /* EQ ... fall through */
1869  emit_label_bgt(cd, LABEL_OUT);
1870  break;
1871  case ICMD_IF_LGT:
1872  case ICMD_IF_LGE:
1873  emit_bgt(cd, iptr->dst.block);
1874  /* EQ ... fall through */
1875  emit_label_blt(cd, LABEL_OUT);
1876  break;
1877  case ICMD_IF_LEQ:
1878  /* EQ ... fall through */
1879  emit_label_bne(cd, LABEL_OUT);
1880  break;
1881  case ICMD_IF_LNE:
1882  /* EQ ... fall through */
1883  emit_bne(cd, iptr->dst.block);
1884  break;
1885  default:
1886  assert(0);
1887  }
1888 
1889  s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1890 
1891  disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
1892  if (N_VALID_DSEG_DISP(disp)) {
1893  N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
1894  } else {
1895  ICONST(REG_ITMP2, disp);
1896  N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
1897  }
1898 
1899  switch(iptr->opc) {
1900  case ICMD_IF_LLT:
1901  emit_blt(cd, iptr->dst.block);
1902  emit_label(cd, LABEL_OUT);
1903  break;
1904  case ICMD_IF_LLE:
1905  emit_ble(cd, iptr->dst.block);
1906  emit_label(cd, LABEL_OUT);
1907  break;
1908  case ICMD_IF_LGT:
1909  emit_bgt(cd, iptr->dst.block);
1910  emit_label(cd, LABEL_OUT);
1911  break;
1912  case ICMD_IF_LGE:
1913  emit_bge(cd, iptr->dst.block);
1914  emit_label(cd, LABEL_OUT);
1915  break;
1916  case ICMD_IF_LEQ:
1917  emit_beq(cd, iptr->dst.block);
1918  emit_label(cd, LABEL_OUT);
1919  break;
1920  case ICMD_IF_LNE:
1921  emit_bne(cd, iptr->dst.block);
1922  break;
1923  default:
1924  assert(0);
1925  }
1926 
1927 # undef LABEL_OUT
1928  break;
1929 
1930  case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1931  case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
1932 
1933  /* Compare addresses as 31 bit unsigned integers */
1934 
1935  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1936  M_LDA(REG_ITMP1, s1, 0);
1937 
1938  s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1939  M_LDA(REG_ITMP2, s2, 0);
1940 
1942 
1943  switch (iptr->opc) {
1944  case ICMD_IF_ACMPEQ:
1945  emit_beq(cd, iptr->dst.block);
1946  break;
1947  case ICMD_IF_ACMPNE:
1948  emit_bne(cd, iptr->dst.block);
1949  break;
1950  }
1951 
1952  break;
1953 
1954  case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1955  case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1956  case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1957  case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1958  case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1959  case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1960  {
1961 
1962  u1 *out_ref = NULL;
1963 
1964  /* ATTENTION: compare high words signed and low words unsigned */
1965 
1966  s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1967  s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
1968 
1969  M_ICMP(s1, s2);
1970 
1971  switch(iptr->opc) {
1972  case ICMD_IF_LCMPLT:
1973  case ICMD_IF_LCMPLE:
1974  emit_blt(cd, iptr->dst.block);
1975  /* EQ ... fall through */
1976  out_ref = cd->mcodeptr;
1977  M_BGT(0);
1978  break;
1979  case ICMD_IF_LCMPGT:
1980  case ICMD_IF_LCMPGE:
1981  emit_bgt(cd, iptr->dst.block);
1982  /* EQ ... fall through */
1983  out_ref = cd->mcodeptr;
1984  M_BLT(0);
1985  break;
1986  case ICMD_IF_LCMPEQ:
1987  /* EQ ... fall through */
1988  out_ref = cd->mcodeptr;
1989  M_BNE(0);
1990  break;
1991  case ICMD_IF_LCMPNE:
1992  /* EQ ... fall through */
1993  emit_bne(cd, iptr->dst.block);
1994  break;
1995  default:
1996  assert(0);
1997  }
1998 
1999  s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2000  s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2001 
2002  M_ICMPU(s1, s2);
2003 
2004  switch(iptr->opc) {
2005  case ICMD_IF_LCMPLT:
2006  emit_blt(cd, iptr->dst.block);
2007  break;
2008  case ICMD_IF_LCMPLE:
2009  emit_ble(cd, iptr->dst.block);
2010  break;
2011  case ICMD_IF_LCMPGT:
2012  emit_bgt(cd, iptr->dst.block);
2013  break;
2014  case ICMD_IF_LCMPGE:
2015  emit_bge(cd, iptr->dst.block);
2016  break;
2017  case ICMD_IF_LCMPEQ:
2018  emit_beq(cd, iptr->dst.block);
2019  break;
2020  case ICMD_IF_LCMPNE:
2021  emit_bne(cd, iptr->dst.block);
2022  break;
2023  default:
2024  assert(0);
2025  }
2026 
2027  if (out_ref != NULL) {
2028  N_BRC_BACK_PATCH(out_ref);
2029  }
2030 
2031  }
2032  break;
2033 
2034  case ICMD_TABLESWITCH: /* ..., index ==> ... */
2035  {
2036  s4 i, l;
2037  branch_target_t *table;
2038 
2039  table = iptr->dst.table;
2040 
2041  l = iptr->sx.s23.s2.tablelow;
2042  i = iptr->sx.s23.s3.tablehigh;
2043 
2044  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2045  M_INTMOVE(s1, REG_ITMP1);
2046 
2047  if (l == 0) {
2048  /* do nothing */
2049  } else if (N_VALID_IMM(-l)) {
2050  M_ISUB_IMM(l, REG_ITMP1);
2051  } else {
2052  ICONST(REG_ITMP2, l);
2054  }
2055 
2056  /* number of targets */
2057 
2058  i = i - l + 1;
2059 
2060  /* range check */
2061 
2062  ICONST(REG_ITMP2, i);
2064  emit_bge(cd, table[0].block);
2065 
2066  /* build jump table top down and use address of lowest entry */
2067 
2068  table += i;
2069 
2070  while (--i >= 0) {
2071  dseg_add_target(cd, table->block);
2072  --table;
2073  }
2074  }
2075 
2076  /* length of dataseg after last dseg_add_target is used by load */
2077 
2078  M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2081  M_JMP(RN, REG_ITMP1);
2082 
2083  break;
2084 
2085 
2086  case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2087  bte = iptr->sx.s23.s3.bte;
2088  if (bte->stub == NULL) {
2089  disp = dseg_add_functionptr(cd, bte->fp);
2090  M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2091  } else {
2092  disp = dseg_add_functionptr(cd, bte->stub);
2093  }
2094 
2095  if (N_VALID_DSEG_DISP(disp)) {
2096  N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2097  } else {
2098  N_LHI(REG_ITMP1, disp);
2100  }
2101 
2102  /* generate the actual call */
2103  M_CALL(REG_PV);
2104 
2105  /* post call finalization */
2106  if (bte->stub == NULL) {
2107  M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2108  }
2109  break;
2110 
2111  case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2112  /* TODO softnull */
2113  /* Implicit NULL pointer check */
2114  M_ILD(REG_ITMP1, REG_A0, 0);
2115  /* fall through */
2116 
2117  case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2118  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2119  um = iptr->sx.s23.s3.um;
2120  disp = dseg_add_unique_address(cd, um);
2121 
2123  um, disp);
2124  }
2125  else {
2126  lm = iptr->sx.s23.s3.fmiref->p.method;
2127  disp = dseg_add_address(cd, lm->stubroutine);
2128  }
2129 
2130  if (N_VALID_DSEG_DISP(disp)) {
2131  N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2132  } else {
2133  N_LHI(REG_ITMP1, disp);
2135  }
2136 
2137  /* generate the actual call */
2138  M_CALL(REG_PV);
2139  break;
2140 
2141  case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2142  /* TODO softnull REG_A0 */
2143 
2144  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2145  um = iptr->sx.s23.s3.um;
2147 
2148  s1 = 0;
2149  }
2150  else {
2151  lm = iptr->sx.s23.s3.fmiref->p.method;
2152  s1 = OFFSET(vftbl_t, table[0]) +
2153  sizeof(methodptr) * lm->vftblindex;
2154  }
2155 
2156  /* implicit null-pointer check */
2157 
2159  M_ALD(REG_PV, REG_METHODPTR, s1);
2160 
2161  /* generate the actual call */
2162  M_CALL(REG_PV);
2163  break;
2164 
2165  case ICMD_INVOKEINTERFACE:
2166  /* TODO softnull REG_A0 */
2167 
2168  /* s1 will be negative here, so use (0xFFF + s1) as displacement
2169  * and -0xFFF in index register (itmp1)
2170  */
2171 
2172  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2173  um = iptr->sx.s23.s3.um;
2175 
2176  s1 = 0;
2177  s2 = 0;
2178  }
2179  else {
2180  lm = iptr->sx.s23.s3.fmiref->p.method;
2181  s1 = OFFSET(vftbl_t, interfacetable[0]) -
2182  sizeof(methodptr*) * lm->clazz->index;
2183 
2184  s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2185  }
2186 
2187  /* Implicit null-pointer check */
2189  N_LHI(REG_ITMP2, s1);
2191  M_ALD(REG_PV, REG_METHODPTR, s2);
2192 
2193  /* generate the actual call */
2194  M_CALL(REG_PV);
2195  break;
2196 
2197  case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2198 
2199  /* val.a: (classinfo*) superclass */
2200 
2201  /* superclass is an interface:
2202  *
2203  * OK if ((sub == NULL) ||
2204  * (sub->vftbl->interfacetablelength > super->index) &&
2205  * (sub->vftbl->interfacetable[-super->index] != NULL));
2206  *
2207  * superclass is a class:
2208  *
2209  * OK if ((sub == NULL) || (0
2210  * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2211  * super->vftbl->diffval));
2212  */
2213 
2214  if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2215  /* object type cast-check */
2216 
2217  classinfo *super;
2218  vftbl_t *supervftbl;
2219  s4 superindex;
2220 
2221 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2222 # define LABEL_CLASS BRANCH_LABEL_2
2223 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2224 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2225 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2226 
2227  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2228  super = NULL;
2229  superindex = 0;
2230  supervftbl = NULL;
2231  }
2232  else {
2233  super = iptr->sx.s23.s3.c.cls;
2234  superindex = super->index;
2235  supervftbl = super->vftbl;
2236  }
2237 
2238  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2239 
2240  /* if class is not resolved, check which code to call */
2241 
2242  if (super == NULL) {
2243  M_TEST(s1);
2244  emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2245 
2246  disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2247 
2249  iptr->sx.s23.s3.c.ref,
2250  disp);
2251 
2253 
2254  if (N_VALID_DSEG_DISP(disp)) {
2255  N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
2256  } else {
2257  ICONST(REG_ITMP2, disp);
2259  }
2260  emit_label_beq(cd, LABEL_CLASS);
2261  }
2262 
2263  /* interface checkcast code */
2264 
2265  if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2266  if (super == NULL) {
2268  PATCHER_checkcast_instanceof_interface,
2269  iptr->sx.s23.s3.c.ref,
2270  0);
2271  } else {
2272  M_TEST(s1);
2273  emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
2274  }
2275 
2276  M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2277  M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2278  M_ISUB_IMM(superindex, REG_ITMP3);
2279  emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
2280  N_AHI(
2281  REG_ITMP2,
2282  (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2283  superindex * sizeof(methodptr*))
2284  );
2285  M_ALD(REG_ITMP2, REG_ITMP2, 0);
2286  emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
2287 
2288  if (super == NULL) {
2290  }
2291  }
2292 
2293  /* class checkcast code */
2294 
2295  if (super == NULL) {
2296  emit_label(cd, LABEL_CLASS);
2297  }
2298 
2299  if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2300  if (super == NULL) {
2301  disp = dseg_add_unique_address(cd, NULL);
2302 
2305  iptr->sx.s23.s3.c.ref,
2306  disp);
2307  }
2308  else {
2309  disp = dseg_add_address(cd, supervftbl);
2310  M_TEST(s1);
2311  emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
2312  }
2313 
2314 #if 1
2315  /* REG_ITMP3 := baseval(s1) */
2316  M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2317  M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2318 
2319  /* REG_ITMP2 := baseval(class) */
2320  M_ALD_DSEG(REG_ITMP2, disp);
2321  M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2322 
2323  /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
2325 
2326  /* REG_ITMP2 := diffval(class) */
2327  M_ALD_DSEG(REG_ITMP2, disp);
2328  M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2329 
2330  M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
2331 
2332  /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
2333  /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
2334  /* Branch if greater then */
2335 #else
2336  M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2337  M_ALD_DSEG(REG_ITMP3, disp);
2338 
2339  M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2340  M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2342  M_ALD_DSEG(REG_ITMP3, disp);
2343  M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2344 
2345  M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
2346  /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
2347  /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
2348  /* Branch if greater then */
2349 #endif
2350  emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
2351  }
2352 
2353  if (super == NULL) {
2356  } else if (super->flags & ACC_INTERFACE) {
2358  } else {
2360  }
2361 
2362  d = codegen_reg_of_dst(jd, iptr, s1);
2363 
2364 # undef LABEL_EXIT_CHECK_NULL
2365 # undef LABEL_CLASS
2366 # undef LABEL_EXIT_INTERFACE_NULL
2367 # undef LABEL_EXIT_INTERFACE_DONE
2368 # undef LABEL_EXIT_CLASS_NULL
2369  }
2370  else {
2371  /* array type cast-check */
2372 
2373  s1 = emit_load_s1(jd, iptr, REG_A0);
2374  M_INTMOVE(s1, REG_A0);
2375 
2376  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2377  disp = dseg_add_unique_address(cd, NULL);
2378 
2381  iptr->sx.s23.s3.c.ref,
2382  disp);
2383  }
2384  else
2385  disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2386 
2387  M_ALD_DSEG(REG_A1, disp);
2389  M_ALD_DSEG(REG_ITMP1, disp);
2390  M_ASUB_IMM(96, REG_SP);
2392  M_AADD_IMM(96, REG_SP);
2393 
2394  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2395  emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2396 
2397  d = codegen_reg_of_dst(jd, iptr, s1);
2398  }
2399 
2400  M_INTMOVE(s1, d);
2401  emit_store_dst(jd, iptr, d);
2402  break;
2403 
2404  case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2405  /* val.a: (classinfo*) superclass */
2406 
2407  /* superclass is an interface:
2408  *
2409  * return (sub != NULL) &&
2410  * (sub->vftbl->interfacetablelength > super->index) &&
2411  * (sub->vftbl->interfacetable[-super->index] != NULL);
2412  *
2413  * superclass is a class:
2414  *
2415  * return ((sub != NULL) && (0
2416  * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2417  * super->vftbl->diffvall));
2418  *
2419  * If superclass is unresolved, we include both code snippets
2420  * above, a patcher resolves the class' flags and we select
2421  * the right code at runtime.
2422  */
2423 
2424  {
2425  classinfo *super;
2426  vftbl_t *supervftbl;
2427  s4 superindex;
2428 
2429  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2430  super = NULL;
2431  superindex = 0;
2432  supervftbl = NULL;
2433 
2434  } else {
2435  super = iptr->sx.s23.s3.c.cls;
2436  superindex = super->index;
2437  supervftbl = super->vftbl;
2438  }
2439 
2440 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2441 # define LABEL_CLASS BRANCH_LABEL_2
2442 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2443 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
2444 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
2445 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
2446 
2447  s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2448  d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2449  if (s1 == d) {
2450  M_MOV(s1, REG_ITMP1);
2451  s1 = REG_ITMP1;
2452  }
2453 
2454  /* if class is not resolved, check which code to call */
2455 
2456  if (super == NULL) {
2457  M_CLR(d);
2458 
2459  M_TEST(s1);
2460  emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2461 
2462  disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2463 
2465  iptr->sx.s23.s3.c.ref, disp);
2466 
2468 
2469  if (N_VALID_DSEG_DISP(disp)) {
2470  N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
2471  } else {
2472  ICONST(REG_ITMP2, disp);
2474  }
2475 
2476  emit_label_beq(cd, LABEL_CLASS);
2477  }
2478 
2479  /* interface instanceof code */
2480 
2481  if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2482  if (super == NULL) {
2483  /* If d == REG_ITMP2, then it's destroyed in check
2484  code above. */
2485  if (d == REG_ITMP2)
2486  M_CLR(d);
2487 
2489  PATCHER_checkcast_instanceof_interface,
2490  iptr->sx.s23.s3.c.ref, 0);
2491  }
2492  else {
2493  M_CLR(d);
2494  M_TEST(s1);
2495  emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
2496  }
2497 
2498  M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2499  M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2500  M_ISUB_IMM(superindex, REG_ITMP3);
2501 
2502  emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
2503 
2504  N_AHI(
2505  REG_ITMP1,
2506  (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2507  superindex * sizeof(methodptr*))
2508  );
2509  M_ALD(REG_ITMP1, REG_ITMP1, 0);
2510 
2511  /* d := (REG_ITMP1 != 0) */
2512 
2513  N_LTR(d, REG_ITMP1);
2514  M_BEQ(SZ_BRC + SZ_LHI);
2515  N_LHI(d, 1);
2516 
2517  if (super == NULL) {
2519  }
2520  }
2521 
2522  /* class instanceof code */
2523 
2524  if (super == NULL) {
2525  emit_label(cd, LABEL_CLASS);
2526  }
2527 
2528  if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2529  if (super == NULL) {
2530  disp = dseg_add_unique_address(cd, NULL);
2531 
2533  iptr->sx.s23.s3.c.ref,
2534  disp);
2535  }
2536  else {
2537  disp = dseg_add_address(cd, supervftbl);
2538 
2539  M_CLR(d);
2540 
2541  M_TEST(s1);
2542  emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
2543  }
2544 
2545  M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2546  M_ALD_DSEG(REG_ITMP2, disp);
2547 
2548  M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2549  M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2550  M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2551 
2552  M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
2553 
2554  M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
2555  N_LHI(d, 0);
2556  M_BGT(SZ_BRC + SZ_LHI);
2557  N_LHI(d, 1);
2558  }
2559 
2560  if (super == NULL) {
2564  } else if (super->flags & ACC_INTERFACE) {
2567  } else {
2569  }
2570 
2571 # undef LABEL_EXIT_CHECK_NULL
2572 # undef LABEL_CLASS
2573 # undef LABEL_EXIT_INTERFACE_NULL
2574 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
2575 # undef LABEL_EXIT_INTERFACE_DONE
2576 # undef LABEL_EXIT_CLASS_NULL
2577 
2578  emit_store_dst(jd, iptr, d);
2579 
2580  }
2581 
2582  break;
2583 
2584  case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2585 
2586  /* check for negative sizes and copy sizes to stack if necessary */
2587 
2588  /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
2589  MCODECHECK(512);
2590 
2591  for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2592 
2593  /* copy SAVEDVAR sizes to stack */
2594  var = VAR(iptr->sx.s23.s2.args[s1]);
2595 
2596  /* Already Preallocated? */
2597  if (!(var->flags & PREALLOC)) {
2598  s2 = emit_load(jd, iptr, var, REG_ITMP1);
2599  M_IST(s2, REG_SP, s1 * 4);
2600  }
2601  }
2602 
2603  /* is a patcher function set? */
2604 
2605  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2606  disp = dseg_add_unique_address(cd, 0);
2607 
2609  iptr->sx.s23.s3.c.ref,
2610  disp);
2611  }
2612  else
2613  disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2614 
2615  /* a0 = dimension count */
2616 
2617  ICONST(REG_A0, iptr->s1.argcount);
2618 
2619  /* a1 = classinfo */
2620 
2621  M_ALD_DSEG(REG_A1, disp);
2622 
2623  /* a2 = pointer to dimensions = stack pointer */
2624 
2625  M_MOV(REG_SP, REG_A2);
2626 
2628  M_ALD_DSEG(REG_ITMP1, disp);
2629  M_ASUB_IMM(96, REG_SP);
2631  M_AADD_IMM(96, REG_SP);
2632 
2633  /* check for exception before result assignment */
2634 
2635  emit_exception_check(cd, iptr);
2636 
2637  s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2638  M_INTMOVE(REG_RESULT, s1);
2639  emit_store_dst(jd, iptr, s1);
2640 
2641  break;
2642 
2643  default:
2644  vm_abort("Unknown ICMD %d during code generation", iptr->opc);
2645  } /* switch */
2646 }
2647 
2648 
2649 /* codegen_emit_stub_native ****************************************************
2650 
2651  Emits a stub routine which calls a native method.
2652 
2653 *******************************************************************************/
2654 
2655 /*
2656  arguments on stack \
2657 -------------------------------------------------| <- SP on nativestub entry
2658  return address |
2659  callee saved int regs (none) |
2660  callee saved float regs (none) | stack frame like in cacao
2661  local variable slots (none) |
2662  arguments for calling methods (none) /
2663 ------------------------------------------------------------------ <- datasp
2664  stackframe info
2665  locaref table
2666  integer arguments
2667  float arguments
2668 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
2669 0 - 96 register save area for callee /
2670 -------------------------------------------------------- <- SP native method
2671  ==
2672  SP after method entry
2673 */
2674 
2675 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2676 {
2677  methodinfo *m;
2678  codeinfo *code;
2679  codegendata *cd;
2680  methoddesc *md;
2681  int i, j;
2682  int t;
2683  int s1, s2;
2684  int disp;
2685 
2686  /* get required compiler data */
2687 
2688  m = jd->m;
2689  code = jd->code;
2690  cd = jd->cd;
2691 
2692  /* set some variables */
2693 
2694  md = m->parseddesc;
2695 
2696  /* calculate stackframe size */
2697 
2698  cd->stackframesize =
2699  1 + /* return address */
2700  sizeof(stackframeinfo_t) / 8 +
2701  sizeof(localref_table) / 8 +
2702  nmd->paramcount +
2703  nmd->memuse +
2704  (96 / 8); /* linkage area */
2705 
2706  /* keep stack 8-byte aligned */
2707 
2708  /*ALIGN_2(cd->stackframesize);*/
2709 
2710  /* create method header */
2711 
2712  (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2713  (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
2714  (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2715  (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2716  (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2717 
2718  /* generate code */
2719 
2720  M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
2722 
2723  /* store return address */
2724 
2725  M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
2726 
2727 #if defined(ENABLE_GC_CACAO)
2728  /* Save callee saved integer registers in stackframeinfo (GC may
2729  need to recover them during a collection). */
2730 
2731  disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2732  OFFSET(stackframeinfo_t, intregs);
2733 
2734  for (i = 0; i < INT_SAV_CNT; i++)
2735  M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2736 #endif
2737 
2738  /* save integer and float argument registers */
2739 
2740  for (i = 0; i < md->paramcount; i++) {
2741  if (!md->params[i].inmemory) {
2742  s1 = md->params[i].regoff;
2743 
2744  switch (md->paramtypes[i].type) {
2745  case TYPE_INT:
2746  case TYPE_ADR:
2747  M_IST(s1, REG_SP, 96 + i * 8);
2748  break;
2749  case TYPE_LNG:
2750  M_LST(s1, REG_SP, 96 + i * 8);
2751  break;
2752  case TYPE_FLT:
2753  case TYPE_DBL:
2754  M_DST(s1, REG_SP, 96 + i * 8);
2755  break;
2756  }
2757  }
2758  }
2759 
2760  /* create native stack info */
2761 
2762  M_MOV(REG_SP, REG_A0);
2765  M_ALD_DSEG(REG_ITMP2, disp);
2766  M_CALL(REG_ITMP2);
2767 
2768  /* remember class argument */
2769 
2770  if (m->flags & ACC_STATIC)
2772 
2773  /* restore integer and float argument registers */
2774 
2775  for (i = 0; i < md->paramcount; i++) {
2776  if (!md->params[i].inmemory) {
2777  s1 = md->params[i].regoff;
2778 
2779  switch (md->paramtypes[i].type) {
2780  case TYPE_INT:
2781  case TYPE_ADR:
2782  M_ILD(s1, REG_SP, 96 + i * 8);
2783  break;
2784  case TYPE_LNG:
2785  M_LLD(s1, REG_SP, 96 + i * 8);
2786  break;
2787  case TYPE_FLT:
2788  case TYPE_DBL:
2789  M_DLD(s1, REG_SP, 96 + i * 8);
2790  break;
2791  }
2792  }
2793  }
2794 
2795  /* copy or spill arguments to new locations */
2796 
2797  for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2798  t = md->paramtypes[i].type;
2799 
2800  if (IS_INT_LNG_TYPE(t)) {
2801  if (!md->params[i].inmemory) {
2802  s1 = md->params[i].regoff;
2803  s2 = nmd->params[j].regoff;
2804 
2805  if (!nmd->params[j].inmemory) {
2806  if (IS_2_WORD_TYPE(t))
2807  M_LNGMOVE(s1, s2);
2808  else
2809  M_INTMOVE(s1, s2);
2810  }
2811  else {
2812  if (IS_2_WORD_TYPE(t))
2813  M_LST(s1, REG_SP, s2);
2814  else
2815  M_IST(s1, REG_SP, s2);
2816  }
2817  }
2818  else {
2819  s1 = md->params[i].regoff + cd->stackframesize * 8;
2820  s2 = nmd->params[j].regoff;
2821 
2822  if (IS_2_WORD_TYPE(t)) {
2823  N_MVC(s2, 8, REG_SP, s1, REG_SP);
2824  } else {
2825  N_MVC(s2, 4, REG_SP, s1, REG_SP);
2826  }
2827  }
2828  }
2829  else {
2830  /* We only copy spilled float arguments, as the float
2831  argument registers keep unchanged. */
2832 
2833  if (md->params[i].inmemory) {
2834  s1 = md->params[i].regoff + cd->stackframesize * 8;
2835  s2 = nmd->params[j].regoff;
2836 
2837  if (IS_2_WORD_TYPE(t)) {
2838  N_MVC(s2, 8, REG_SP, s1, REG_SP);
2839  } else {
2840  N_MVC(s2, 4, REG_SP, s1, REG_SP);
2841  }
2842  }
2843  }
2844  }
2845 
2846  /* Handle native Java methods. */
2847 
2848  if (m->flags & ACC_NATIVE) {
2849  /* put class into second argument register */
2850 
2851  if (m->flags & ACC_STATIC)
2853 
2854  /* put env into first argument register */
2855 
2856  disp = dseg_add_address(cd, VM::get_current()->get_jnienv());
2857  M_ALD_DSEG(REG_A0, disp);
2858  }
2859 
2860  /* Call native function. */
2861 
2862  disp = dseg_add_functionptr(cd, f);
2863  M_ALD_DSEG(REG_ITMP2, disp);
2864  M_CALL(REG_ITMP2);
2865 
2866  /* save return value */
2867 
2868  switch (md->returntype.type) {
2869  case TYPE_INT:
2870  case TYPE_ADR:
2871  M_IST(REG_RESULT, REG_SP, 96);
2872  break;
2873  case TYPE_LNG:
2875  break;
2876  case TYPE_FLT:
2877  case TYPE_DBL:
2878  M_DST(REG_FRESULT, REG_SP, 96);
2879  break;
2880  case TYPE_VOID:
2881  break;
2882  }
2883 
2884  /* remove native stackframe info */
2885 
2886  M_MOV(REG_SP, REG_A0);
2889  M_ALD_DSEG(REG_ITMP1, disp);
2890  M_CALL(REG_ITMP1);
2891 
2893 
2894  /* restore return value */
2895 
2896  switch (md->returntype.type) {
2897  case TYPE_INT:
2898  case TYPE_ADR:
2899  M_ILD(REG_RESULT, REG_SP, 96);
2900  break;
2901  case TYPE_LNG:
2903  break;
2904  case TYPE_FLT:
2905  case TYPE_DBL:
2906  M_DLD(REG_FRESULT, REG_SP, 96);
2907  break;
2908  case TYPE_VOID:
2909  break;
2910  }
2911 
2912 #if defined(ENABLE_GC_CACAO)
2913  /* Restore callee saved integer registers from stackframeinfo (GC
2914  might have modified them during a collection). */
2915 
2916  disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2917  OFFSET(stackframeinfo_t, intregs);
2918 
2919  for (i = 0; i < INT_SAV_CNT; i++)
2920  M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
2921 #endif
2922 
2923  /* load return address */
2924 
2925  M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
2926 
2927  /* remove stackframe */
2928 
2929  M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2930 
2931  /* check for exception */
2932 
2934  M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
2935 
2936  M_RET;
2937 
2938  /* handle exception */
2939 
2942 
2944  M_ALD_DSEG(REG_ITMP2, disp);
2945  M_JMP(RN, REG_ITMP2);
2946 }
2947 
2948 /*
2949  * These are local overrides for various environment variables in Emacs.
2950  * Please do not remove this and leave it at the end of the file, where
2951  * Emacs will automagically detect them.
2952  * ---------------------------------------------------------------------
2953  * Local variables:
2954  * mode: c
2955  * indent-tabs-mode: t
2956  * c-basic-offset: 4
2957  * tab-width: 4
2958  * End:
2959  * vim:noexpandtab:sw=4:ts=4:
2960  */
void codegen_emit_instruction(jitdata *jd, instruction *iptr)
Generates machine code for one ICMD.
Definition: codegen.cpp:217
s4 dseg_add_double(codegendata *cd, double value)
Definition: dseg.cpp:465
#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 N_SLDL(r1, d2, b2)
Definition: codegen.hpp:523
#define N_BRC_BACK_PATCH(brc_pos)
Definition: codegen.hpp:437
#define GET_HIGH_REG(a)
s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
#define M_CMPU(a, b)
Definition: codegen.hpp:209
#define M_SRA(a, b, c)
Definition: codegen.hpp:307
basicblock * block
union varinfo::@19 vv
#define REG_PV
Definition: md-abi.hpp:42
#define LABEL_EXIT_CHECK_NULL
#define M_JSR(a, b)
Definition: codegen.hpp:260
s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
Definition: emit-common.cpp:63
#define LABEL_EXIT_CLASS_NULL
#define N_CL(r1, d2, x2, b2)
Definition: codegen.hpp:454
#define M_ALD(a, b, disp)
Definition: codegen.hpp:345
#define M_CVTDI(a, d)
Definition: codegen.hpp:725
#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_LST(a, b, disp)
Definition: codegen.hpp:349
#define REG_A0
Definition: md-abi.hpp:35
paramdesc * params
Definition: descriptor.hpp:164
#define M_SLL(a, b, c)
Definition: codegen.hpp:306
s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg)
Definition: emit.cpp:763
#define BRANCH_LE
#define SZ_LCR
Definition: codegen.hpp:489
#define M_CVTFD(a, b)
Definition: codegen.hpp:721
#define M_BEQ(off)
Definition: codegen.hpp:482
#define M_ILD(a, b, disp)
Definition: codegen.hpp:347
s4 dseg_add_unique_address(codegendata *cd, void *value)
Definition: dseg.cpp:525
int * savintregs
Definition: reg.hpp:71
methodinfo * methods
Definition: class.hpp:113
#define PATCHER_resolve_classref_to_vftbl
#define N_IS_EVEN_ODD(x)
Definition: codegen.hpp:348
#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 N_PV_OFFSET
Definition: codegen.hpp:339
#define M_IST(a, b, disp)
Definition: codegen.hpp:351
#define DD_0
Definition: codegen.hpp:369
#define M_BNE(off)
Definition: codegen.hpp:483
#define LABEL_CLASS
#define M_FCMP(a, b)
Definition: codegen.hpp:717
#define ICONST(d, c)
Definition: codegen.hpp:53
#define M_LDA(a, b, disp)
Definition: codegen.hpp:163
#define BRANCH_GT
#define M_SRL(a, b, c)
Definition: codegen.hpp:308
#define PATCHER_get_putfield
#define BRANCH_EQ
#define M_AADD_IMM(a, b, c)
Definition: codegen.hpp:277
#define M_IOR(a, b, d)
Definition: codegen.hpp:177
s4 dseg_add_address(codegendata *cd, void *value)
Definition: dseg.cpp:542
codeinfo * code
Definition: jit.hpp:128
#define REG_ITMP12_PACKED
Definition: md-abi.hpp:131
#define REG_FRESULT
Definition: md-abi.hpp:59
int32_t argcount
Definition: instruction.hpp:64
#define N_ST(r1, d2, x2, b2)
Definition: codegen.hpp:530
#define dseg_add_functionptr(cd, value)
Definition: dseg.hpp:39
#define N_NR(r1, r2)
Definition: codegen.hpp:410
#define N_AHI(r1, i2)
Definition: codegen.hpp:406
codegendata * cd
Definition: jit.hpp:129
#define N_C(r1, d2, x2, b2)
Definition: codegen.hpp:447
void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
Definition: codegen.cpp:2010
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
#define REG_ITMP1_XPTR
Definition: md-abi.hpp:50
#define REG_A2
Definition: md-abi.hpp:37
#define N_LTEBR(r1, r2)
Definition: codegen.hpp:609
void emit_arraystore_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:380
int savintreguse
Definition: reg.hpp:88
#define N_LE(r1, d2, x2, b2)
Definition: codegen.hpp:560
#define M_FST(a, b, disp)
Definition: codegen.hpp:357
#define M_ISUB(a, b, c)
Definition: codegen.hpp:265
patchref_t * patcher_add_patch_ref(jitdata *jd, functionptr patcher, void *ref, s4 disp)
constant_classref * ref
Definition: references.hpp:62
#define M_DMOVN(r, dst)
Definition: codegen.hpp:800
#define M_FLD(a, b, disp)
Definition: codegen.hpp:354
uint8_t u1
Definition: types.hpp:40
void dseg_add_target(codegendata *cd, basicblock *target)
Definition: dseg.cpp:565
#define RN
Definition: codegen.hpp:106
u1 * methodptr
Definition: global.hpp:40
#define N_STH(r1, d2, x2, b2)
Definition: codegen.hpp:537
#define N_DSEG_DISP(x)
Definition: codegen.hpp:340
#define M_TEST(a)
Definition: codegen.hpp:359
#define DD_2
Definition: codegen.hpp:371
java_object_t * codegen_finish_native_call(u1 *sp, u1 *pv)
u1 * stub
Definition: builtin.hpp:64
#define M_IAND(a, b, d)
Definition: codegen.hpp:174
const s4 abi_registers_integer_saved[]
Definition: md-abi.cpp:75
#define SZ_AHI
Definition: codegen.hpp:407
#define VAR(i)
Definition: jit.hpp:252
Definition: reg.hpp:43
#define N_SRDA(r1, d2, b2)
Definition: codegen.hpp:526
#define REG_ITMP13_PACKED
Definition: md-abi.hpp:80
#define BUILTIN_arraycheckcast
Definition: builtin.hpp:148
#define REG_ITMP2_XPC
Definition: md-abi.hpp:51
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
java_handle_t * codegen_start_native_call(u1 *sp, u1 *pv)
#define IS_2_WORD_TYPE(a)
Definition: global.hpp:132
void emit_exception_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:447
#define GET_LOW_REG(a)
s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
#define N_SRL(r1, d2, b2)
Definition: codegen.hpp:529
BeginInst *& block
#define N_N(r1, d2, x2, b2)
Definition: codegen.hpp:412
#define N_LD(r1, d2, x2, b2)
Definition: codegen.hpp:561
#define LABEL_EXIT_INTERFACE_DONE
#define M_FSUB(a, b, c)
Definition: codegen.hpp:375
#define M_CVTID(a, d)
Definition: codegen.hpp:723
#define N_DR(r1, r2)
Definition: codegen.hpp:468
classref_or_classinfo c
#define M_ICMPU(a, b)
Definition: codegen.hpp:742
u1 * stubroutine
Definition: method.hpp:102
s4 vftblindex
Definition: method.hpp:81
#define M_ISUB_IMM(a, b, c)
Definition: codegen.hpp:272
#define REG_A3
Definition: md-abi.hpp:38
dst_operand_t dst
#define M_CVTFI(a, d)
Definition: codegen.hpp:724
flags_operand_t flags
#define DD_L
Definition: codegen.hpp:356
#define N_VALID_IMM(x)
Definition: codegen.hpp:331
#define N_SRA(r1, d2, b2)
Definition: codegen.hpp:528
constant_FMIref * fieldref
Definition: resolve.hpp:88
#define N_STE(r1, d2, x2, b2)
Definition: codegen.hpp:565
int32_t offset
Definition: field.hpp:66
classinfo * clazz
Definition: method.hpp:80
#define M_JMP(a, b)
Definition: codegen.hpp:259
void emit_label_br(codegendata *cd, s4 label)
This file contains the statistics framework.
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 N_SLL(r1, d2, b2)
Definition: codegen.hpp:525
#define M_DCMP(a, b)
Definition: codegen.hpp:718
#define M_ICMP_IMM(a, b)
Definition: codegen.hpp:297
#define M_FADD(a, b, c)
Definition: codegen.hpp:373
s4 flags
Definition: class.hpp:90
#define M_IMUL(a, b, c)
Definition: codegen.hpp:267
#define M_ASUB_IMM(a, b, c)
Definition: codegen.hpp:278
typedesc * fd
Definition: references.hpp:74
s4 * local_map
Definition: jit.hpp:153
#define SZ_NR
Definition: codegen.hpp:411
#define M_SRL_IMM(a, b, c)
Definition: codegen.hpp:312
#define REG_FTMP2
Definition: md-abi.hpp:66
#define DD_1
Definition: codegen.hpp:370
#define M_SLDL(op, dst)
Definition: codegen.hpp:782
MIIterator i
#define N_LHI(r1, i2)
Definition: codegen.hpp:491
#define N_STC(r1, d2, x2, b2)
Definition: codegen.hpp:533
s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:66
typedesc returntype
Definition: descriptor.hpp:166
#define M_SRDL(op, dst)
Definition: codegen.hpp:788
#define REG_ITMP31_PACKED
Definition: md-abi.hpp:82
#define M_BGE(off)
Definition: codegen.hpp:484
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
registerdata * rd
Definition: jit.hpp:130
#define M_AST(a, b, disp)
Definition: codegen.hpp:350
s4 index
Definition: class.hpp:116
#define M_CVTIF(a, d)
Definition: codegen.hpp:722
union instruction::@12 sx
#define REG_RA
Definition: md-abi.hpp:41
void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:346
#define N_LCR(r1, r2)
Definition: codegen.hpp:488
void asm_handle_exception(void)
#define PACK_REGS(low, high)
#define M_SRDA_IMM(imm, reg)
Definition: codegen.hpp:777
int savfltreguse
Definition: reg.hpp:91
#define M_MOV(a, b)
Definition: codegen.hpp:340
bool inmemory
Definition: descriptor.hpp:151
#define REG_ITMP2
Definition: md-abi.hpp:47
#define DD_ANY
Definition: codegen.hpp:367
void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
s1_operand_t s1
void emit_copy_dst(jitdata *jd, instruction *iptr, s4 dtmpreg)
Definition: emit.cpp:778
#define N_STD(r1, d2, x2, b2)
Definition: codegen.hpp:566
basicblock * block
Definition: instruction.hpp:50
#define PATCHER_invokestatic_special
#define FLT_SAV_CNT
Definition: md-abi.hpp:80
#define M_ICMP(a, b)
Definition: codegen.hpp:361
#define BRANCH_LABEL_1
Definition: emit-common.hpp:47
#define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
#define N_L(r1, d2, x2, b2)
Definition: codegen.hpp:481
#define M_BGT(off)
Definition: codegen.hpp:485
#define M_INEG(a, dest)
Definition: codegen.hpp:794
vftbl_t * vftbl
Definition: class.hpp:121
#define DD_O
Definition: codegen.hpp:353
#define DD_E
Definition: codegen.hpp:360
methoddesc * parseddesc
Definition: method.hpp:78
#define M_SRA_IMM(a, b, c)
Definition: codegen.hpp:311
#define M_FMOVN(fa, fb)
Definition: codegen.hpp:412
#define M_FDIV(a, b, c)
Definition: codegen.hpp:379
#define REG_FTMP1
Definition: md-abi.hpp:65
#define PATCHER_invokevirtual
Definition: builtin.hpp:60
#define N_VALID_DSEG_DISP(x)
Definition: codegen.hpp:341
#define M_SLL_IMM(a, b, c)
Definition: codegen.hpp:310
#define M_IMUL_IMM(a, b, c)
Definition: codegen.hpp:274
#define M_DSUB(a, b, c)
Definition: codegen.hpp:376
methodinfo * m
Definition: jit.hpp:127
#define N_SRDL(r1, d2, b2)
Definition: codegen.hpp:527
static bool IS_INMEMORY(s4 flags)
Definition: stack.hpp:51
#define SZ_BCR
Definition: codegen.hpp:423
s4 type
Definition: field.hpp:60
void codegen_emit_epilog(jitdata *jd)
Generates machine code for the method epilog.
Definition: codegen.cpp:174
#define N_LH(r1, d2, x2, b2)
Definition: codegen.hpp:490
#define s3
Definition: md-asm.hpp:71
#define M_SRDA(op, dst)
Definition: codegen.hpp:789
s4 flags
Definition: reg.hpp:45
#define M_BLT(off)
Definition: codegen.hpp:486
#define M_ALD_DSEG(a, disp)
Definition: codegen.hpp:346
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 N_LTDBR(r1, r2)
Definition: codegen.hpp:610
void asm_handle_nat_exception(void)
#define SZ_LHI
Definition: codegen.hpp:492
#define M_FLD_DSEG(r, d, t)
Definition: codegen.hpp:680
#define SZ_BRC
Definition: codegen.hpp:435
int8_t s1
Definition: types.hpp:39
#define N_IC(r1, d2, x2, b2)
Definition: codegen.hpp:477
int16_t s2
Definition: types.hpp:42
#define M_IADD(a, b, c)
Definition: codegen.hpp:263
#define M_DST(a, b, disp)
Definition: codegen.hpp:356
#define INSTRUCTION_IS_UNRESOLVED(iptr)
#define N_ALR(r1, r2)
Definition: codegen.hpp:408
struct instruction::@12::@13 s23
#define LABEL_OUT
void codegen_emit_prolog(jitdata *jd)
Generates machine code for the method prolog.
Definition: codegen.cpp:73
#define N_LTR(r1, r2)
Definition: codegen.hpp:487
#define M_RET(a, b)
Definition: codegen.hpp:261
#define M_LLD(a, b, disp)
Definition: codegen.hpp:344
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 MCODECHECK(icnt)
Definition: codegen.hpp:40
functionptr fp
Definition: builtin.hpp:63
void emit_label(codegendata *cd, s4 label)
#define DD_3
Definition: codegen.hpp:372
#define N_SLR(r1, r2)
Definition: codegen.hpp:542
#define DD_H
Definition: codegen.hpp:354
#define M_CLR(c)
Definition: codegen.hpp:303
s4 flags
Definition: method.hpp:70
#define M_IADD_IMM(a, b, c)
Definition: codegen.hpp:270
#define N_MVC(d1, l, b1, d2, b2)
Definition: codegen.hpp:498
#define M_NOP
Definition: codegen.hpp:338
#define M_CVTDF(b, c)
Definition: codegen.hpp:391
void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
Definition: emit.cpp:362
#define M_ILD_DSEG(r, d)
Definition: codegen.hpp:653
#define M_DLD(a, b, disp)
Definition: codegen.hpp:353
#define M_DDIV(a, b, c)
Definition: codegen.hpp:380
#define M_CALL(a)
Definition: codegen.hpp:290
#define M_DLD_DSEG(r, d, t)
Definition: codegen.hpp:688
#define M_IXOR(a, dest)
Definition: codegen.hpp:763
uint32_t regoff
Definition: descriptor.hpp:153
s4 dseg_add_float(codegendata *cd, float value)
Definition: dseg.cpp:392
#define OFFSET(s, el)
Definition: memory.hpp:90
branch_target_t * table
#define M_BR(disp)
Definition: codegen.hpp:250
#define REG_RESULT
Definition: md-abi.hpp:33
#define M_INTMOVE(a, b)
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:431
#define REG_ITMP1
Definition: md-abi.hpp:46
static VM * get_current()
Definition: vm.hpp:99
#define REG_RESULT_PACKED
Definition: md-abi.hpp:133
#define N_BRC(m1, i2)
Definition: codegen.hpp:433
#define M_DADD(a, b, c)
Definition: codegen.hpp:374
#define LABEL_EXIT_INTERFACE_NULL