CACAO
emit.cpp
Go to the documentation of this file.
1 /* src/vm/jit/s390/emit.cpp - s390 code emitter functions
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 #include "config.h"
26 
27 #include <assert.h>
28 #include <stdint.h>
29 
30 #include "vm/jit/s390/codegen.hpp"
31 #include "vm/jit/s390/emit.hpp"
32 #include "vm/jit/s390/md-abi.hpp"
33 
34 #include "mm/memory.hpp"
35 
36 #include "threads/lock.hpp"
37 
38 #include "vm/jit/builtin.hpp"
39 #include "vm/global.hpp"
40 #include "vm/types.hpp"
41 
42 #include "vm/descriptor.hpp"
43 #include "vm/options.hpp"
44 
45 #include "vm/jit/abi.hpp"
46 #include "vm/jit/abi-asm.hpp"
47 #include "vm/jit/asmpart.hpp"
48 #include "vm/jit/code.hpp"
50 #include "vm/jit/dseg.hpp"
51 #include "vm/jit/emit-common.hpp"
52 #include "vm/jit/jit.hpp"
54 #include "vm/jit/replace.hpp"
55 #include "vm/jit/trace.hpp"
56 #include "vm/jit/trap.hpp"
57 
58 
59 /* emit_load *******************************************************************
60 
61  Emits a possible load of an operand.
62 
63 *******************************************************************************/
64 
65 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
66 {
67  codegendata *cd;
68  s4 disp;
69  s4 reg;
70 
71  /* get required compiler data */
72 
73  cd = jd->cd;
74 
75  if (IS_INMEMORY(src->flags)) {
77 
78  disp = src->vv.regoff;
79 
80  if (IS_FLT_DBL_TYPE(src->type)) {
81  if (IS_2_WORD_TYPE(src->type))
82  M_DLD(tempreg, REG_SP, disp);
83  else
84  M_FLD(tempreg, REG_SP, disp);
85  }
86  else {
87  if (IS_2_WORD_TYPE(src->type))
88  M_LLD(tempreg, REG_SP, disp);
89  else
90  M_ILD(tempreg, REG_SP, disp);
91  }
92 
93  reg = tempreg;
94  }
95  else
96  reg = src->vv.regoff;
97 
98  return reg;
99 }
100 
101 
102 /* emit_store ******************************************************************
103 
104  This function generates the code to store the result of an
105  operation back into a spilled pseudo-variable. If the
106  pseudo-variable has not been spilled in the first place, this
107  function will generate nothing.
108 
109 *******************************************************************************/
110 
111 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
112 {
113  codegendata *cd;
114 
115  /* get required compiler data */
116 
117  cd = jd->cd;
118 
119  if (IS_INMEMORY(dst->flags)) {
120  COUNT_SPILLS;
121 
122  if (IS_FLT_DBL_TYPE(dst->type)) {
123  if (IS_2_WORD_TYPE(dst->type))
124  M_DST(d, REG_SP, dst->vv.regoff);
125  else
126  M_FST(d, REG_SP, dst->vv.regoff);
127  }
128  else {
129  if (IS_2_WORD_TYPE(dst->type))
130  M_LST(d, REG_SP, dst->vv.regoff);
131  else
132  M_IST(d, REG_SP, dst->vv.regoff);
133  }
134  }
135 }
136 
137 
138 /* emit_copy *******************************************************************
139 
140  Generates a register/memory to register/memory copy.
141 
142 *******************************************************************************/
143 
144 void emit_copy(jitdata *jd, instruction *iptr)
145 {
146  codegendata *cd;
147  varinfo *src;
148  varinfo *dst;
149  s4 s1, d;
150 
151  /* get required compiler data */
152 
153  cd = jd->cd;
154 
155  /* get source and destination variables */
156 
157  src = VAROP(iptr->s1);
158  dst = VAROP(iptr->dst);
159 
160  if ((src->vv.regoff != dst->vv.regoff) ||
161  ((src->flags ^ dst->flags) & INMEMORY)) {
162 
163  if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
164  /* emit nothing, as the value won't be used anyway */
165  return;
166  }
167 
168  if (IS_INMEMORY(src->flags) && IS_INMEMORY(dst->flags)) {
169  if (IS_2_WORD_TYPE(src->type)) {
170  N_MVC(dst->vv.regoff, 8, REG_SP, src->vv.regoff, REG_SP);
171  } else {
172  N_MVC(dst->vv.regoff, 4, REG_SP, src->vv.regoff, REG_SP);
173  }
174  } else {
175 
176  /* If one of the variables resides in memory, we can eliminate
177  the register move from/to the temporary register with the
178  order of getting the destination register and the load. */
179 
180  if (IS_INMEMORY(src->flags)) {
181  if (IS_FLT_DBL_TYPE(dst->type)) {
182  d = codegen_reg_of_var(iptr->opc, dst, REG_FTMP1);
183  } else {
184  if (IS_2_WORD_TYPE(dst->type)) {
185  d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
186  } else {
187  d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1);
188  }
189  }
190  s1 = emit_load(jd, iptr, src, d);
191  }
192  else {
193  if (IS_FLT_DBL_TYPE(src->type)) {
194  s1 = emit_load(jd, iptr, src, REG_FTMP1);
195  } else {
196  if (IS_2_WORD_TYPE(src->type)) {
197  s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
198  } else {
199  s1 = emit_load(jd, iptr, src, REG_ITMP1);
200  }
201  }
202  d = codegen_reg_of_var(iptr->opc, dst, s1);
203  }
204 
205  if (s1 != d) {
206  if (IS_FLT_DBL_TYPE(src->type)) {
207  M_FMOV(s1, d);
208  } else {
209  if (IS_2_WORD_TYPE(src->type)) {
210  M_LNGMOVE(s1, d);
211  } else {
212  M_MOV(s1, d);
213  }
214  }
215  }
216 
217  emit_store(jd, iptr, dst, d);
218  }
219  }
220 }
221 
222 
223 /**
224  * Emits code updating the condition register by comparing one integer
225  * register to an immediate integer value.
226  */
227 void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
228 {
229  int32_t disp;
230 
231  if (N_VALID_IMM(value)) {
232  M_ICMP_IMM(reg, value);
233  } else {
234  disp = dseg_add_s4(cd, value);
235  if (N_VALID_DSEG_DISP(disp)) {
236  N_C(reg, N_DSEG_DISP(disp), RN, REG_PV);
237  } else {
238  assert(reg != REG_ITMP2);
239  ICONST(REG_ITMP2, disp);
240  N_C(reg, -N_PV_OFFSET, REG_ITMP2, REG_PV);
241  }
242  }
243 }
244 
245 
246 /* emit_trap *******************************************************************
247 
248  Emit a trap instruction and return the original machine code.
249 
250 *******************************************************************************/
251 
252 uint32_t emit_trap(codegendata *cd)
253 {
254  uint32_t mcode;
255 
256  /* Get machine code which is patched back in later. The
257  trap is 2 bytes long. */
258 
259  mcode = *((u2 *) cd->mcodeptr);
260 
262 
263  return mcode;
264 }
265 
266 
267 /**
268  * Generates synchronization code to enter a monitor.
269  */
270 #if defined(ENABLE_THREADS)
271 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
272 {
273  int32_t p;
274  int32_t disp;
275 
276  // Get required compiler data.
277  methodinfo* m = jd->m;
278  codegendata* cd = jd->cd;
279 
280 #if !defined(NDEBUG)
283 
284  for (p = 0; p < INT_ARG_CNT; p++)
286 
287  for (p = 0; p < FLT_ARG_CNT; p++)
288  M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
289 
290  syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
291  }
292 #endif
293 
294  /* decide which monitor enter function to call */
295 
296  if (m->flags & ACC_STATIC) {
297  disp = dseg_add_address(cd, &m->clazz->object.header);
298  M_ALD_DSEG(REG_A0, disp);
299  }
300  else {
301  M_TEST(REG_A0);
302  M_BNE(SZ_BRC + SZ_ILL);
304  }
305 
307  M_ALD_DSEG(REG_ITMP2, disp);
308 
309  M_AST(REG_A0, REG_SP, syncslot_offset);
310 
311  M_ASUB_IMM(96, REG_SP);
312  M_CALL(REG_ITMP2);
313  M_AADD_IMM(96, REG_SP);
314 
315 #if !defined(NDEBUG)
317  for (p = 0; p < INT_ARG_CNT; p++)
319 
320  for (p = 0; p < FLT_ARG_CNT; p++)
321  M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
322 
323  M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
324  }
325 #endif
326 }
327 #endif
328 
329 
330 /**
331  * Generates synchronization code to leave a monitor.
332  */
333 #if defined(ENABLE_THREADS)
334 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
335 {
336  int32_t disp;
337 
338  // Get required compiler data.
339  methodinfo* m = jd->m;
340  codegendata* cd = jd->cd;
341 
342  /* we need to save the proper return value */
343 
344  methoddesc* md = m->parseddesc;
345 
346  switch (md->returntype.type) {
347  case TYPE_LNG:
348  M_IST(REG_RESULT2, REG_SP, syncslot_offset + 8 + 4);
349  /* fall through */
350  case TYPE_INT:
351  case TYPE_ADR:
352  M_IST(REG_RESULT , REG_SP, syncslot_offset + 8);
353  break;
354  case TYPE_FLT:
355  M_FST(REG_FRESULT, REG_SP, syncslot_offset + 8);
356  break;
357  case TYPE_DBL:
358  M_DST(REG_FRESULT, REG_SP, syncslot_offset + 8);
359  break;
360  }
361 
362  M_ALD(REG_A0, REG_SP, syncslot_offset);
363 
365  M_ALD_DSEG(REG_ITMP2, disp);
366 
367  M_ASUB_IMM(96, REG_SP);
368  M_CALL(REG_ITMP2);
369  M_AADD_IMM(96, REG_SP);
370 
371  /* and now restore the proper return value */
372 
373  switch (md->returntype.type) {
374  case TYPE_LNG:
375  M_ILD(REG_RESULT2, REG_SP, syncslot_offset + 8 + 4);
376  /* fall through */
377  case TYPE_INT:
378  case TYPE_ADR:
379  M_ILD(REG_RESULT , REG_SP, syncslot_offset + 8);
380  break;
381  case TYPE_FLT:
382  M_FLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
383  break;
384  case TYPE_DBL:
385  M_DLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
386  break;
387  }
388 }
389 #endif
390 
391 
392 /**
393  * Emit profiling code for method frequency counting.
394  */
395 #if defined(ENABLE_PROFILING)
396 void emit_profile_method(codegendata* cd, codeinfo* code)
397 {
399  ICONST(REG_ITMP2, 1);
400  N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
401  M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
402 }
403 #endif
404 
405 
406 /**
407  * Emit profiling code for basicblock frequency counting.
408  */
409 #if defined(ENABLE_PROFILING)
410 void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
411 {
413  M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
414  ICONST(REG_ITMP2, 1);
415  N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
416  M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
417 }
418 #endif
419 
420 
421 /**
422  * Emit profiling code to start CPU cycle counting.
423  */
424 #if defined(ENABLE_PROFILING)
425 void emit_profile_cycle_start(codegendata* cd, codeinfo* code)
426 {
427  // XXX Not implemented yet!
428 }
429 #endif
430 
431 
432 /**
433  * Emit profiling code to stop CPU cycle counting.
434  */
435 #if defined(ENABLE_PROFILING)
436 void emit_profile_cycle_stop(codegendata* cd, codeinfo* code)
437 {
438  // XXX Not implemented yet!
439 }
440 #endif
441 
442 
443 /* emit_verbosecall_enter ******************************************************
444 
445  Generates the code for the call trace.
446 
447 *******************************************************************************/
448 
449 #if !defined(NDEBUG)
451 {
452  methodinfo *m;
453  codeinfo *code;
454  codegendata *cd;
455  methoddesc *md;
456  s4 stackframesize;
457  s4 i, off, disp, s;
458 
459  m = jd->m;
460  code = jd->code;
461  cd = jd->cd;
462 
463  md = m->parseddesc;
464 
465  /* mark trace code */
466 
467  M_NOP;
468 
469  /* allocate stack frame */
470 
471  stackframesize = 96 + (md->paramcount * 8);
472 
473  /* for leaf methods we need to store unused argument and temporary registers */
474 
475  if (code_is_leafmethod(code)) {
476  stackframesize += (ARG_CNT + TMP_CNT) * 8;
477  }
478 
479  /* allocate stack frame */
480 
481  M_ASUB_IMM(stackframesize, REG_SP);
482 
483  /* store argument registers in array */
484 
485  off = 96;
486 
487  for (i = 0; i < md->paramcount; i++) {
488  if (! md->params[i].inmemory) {
489  s = md->params[i].regoff;
490  switch (md->paramtypes[i].type) {
491  case TYPE_INT:
492  case TYPE_ADR:
493  M_IST(s, REG_SP, off);
494  break;
495  case TYPE_LNG:
496  M_LST(s, REG_SP, off);
497  break;
498  case TYPE_FLT:
499  M_FST(s, REG_SP, off);
500  break;
501  case TYPE_DBL:
502  M_DST(s, REG_SP, off);
503  break;
504  }
505  }
506  off += 8;
507  }
508 
509  /* save unused (currently all) argument registers for leaf methods */
510  /* save temporary registers for leaf methods */
511 
512  if (code_is_leafmethod(code)) {
513 
514  for (i = 0; i < INT_ARG_CNT; ++i, off += 8) {
516  }
517 
518  for (i = 0; i < FLT_ARG_CNT; ++i, off += 8) {
520  }
521 
522  for (i = 0; i < INT_TMP_CNT; ++i, off += 8) {
524  }
525 
526  for (i = 0; i < FLT_TMP_CNT; ++i, off += 8) {
528  }
529  }
530 
531  /* load arguments for trace_java_call_enter */
532 
533  /* methodinfo */
534 
535  disp = dseg_add_address(cd, m);
536  M_ALD_DSEG(REG_A0, disp);
537  /* pointer to argument registers array */
538  M_LDA(REG_A1, REG_SP, 96);
539  /* pointer to on stack arguments */
540  M_LDA(REG_A2, REG_SP, stackframesize + (cd->stackframesize * 8));
541 
542  /* call trace_java_call_enter */
543 
545  M_ALD_DSEG(REG_ITMP2, disp);
546  M_CALL(REG_ITMP2);
547 
548  /* restore used argument registers */
549  /* for leaf methods restore all argument and temporary registers */
550 
551  if (code_is_leafmethod(code)) {
552  off = 96 + (8 * md->paramcount);
553 
554  for (i = 0; i < INT_ARG_CNT; ++i, off += 8) {
556  }
557 
558  for (i = 0; i < FLT_ARG_CNT; ++i, off += 8) {
560  }
561 
562  for (i = 0; i < INT_TMP_CNT; ++i, off += 8) {
564  }
565 
566  for (i = 0; i < FLT_TMP_CNT; ++i, off += 8) {
568  }
569  } else {
570  off = 96;
571 
572  for (i = 0; i < md->paramcount; i++) {
573  if (! md->params[i].inmemory) {
574  s = md->params[i].regoff;
575  switch (md->paramtypes[i].type) {
576  case TYPE_INT:
577  case TYPE_ADR:
578  M_ILD(s, REG_SP, off);
579  break;
580  case TYPE_LNG:
581  M_LLD(s, REG_SP, off);
582  break;
583  case TYPE_FLT:
584  M_FLD(s, REG_SP, off);
585  break;
586  case TYPE_DBL:
587  M_DLD(s, REG_SP, off);
588  break;
589  }
590  }
591  off += 8;
592  }
593  }
594 
595  /* remove stack frame */
596 
597  M_AADD_IMM(stackframesize, REG_SP);
598 
599  /* mark trace code */
600 
601  M_NOP;
602 
603 }
604 #endif /* !defined(NDEBUG) */
605 
606 
607 /* emit_verbosecall_exit *******************************************************
608 
609  Generates the code for the call trace.
610 
611 *******************************************************************************/
612 
613 #if !defined(NDEBUG)
615 {
616  methodinfo *m;
617  codegendata *cd;
618  s4 disp;
619  s4 stackframesize;
620  s4 off;
621  s4 t;
622 
623  m = jd->m;
624  cd = jd->cd;
625  t = m->parseddesc->returntype.type;
626 
627  /* mark trace code */
628 
629  M_NOP;
630 
631  /* allocate stackframe */
632 
633  stackframesize = 96 + (1 * 8);
634  M_ASUB_IMM(stackframesize, REG_SP);
635 
636  off = 96;
637 
638  /* store return values in array */
639 
640  if (IS_INT_LNG_TYPE(t)) {
641  if (IS_2_WORD_TYPE(t)) {
643  } else {
644  M_IST(REG_RESULT, REG_SP, off);
645  }
646  } else {
647  M_DST(REG_FRESULT, REG_SP, off);
648  }
649 
650  /* call trace_java_call_exit */
651 
652  disp = dseg_add_address(cd, m);
653  M_ALD_DSEG(REG_A0, disp);
654  M_LDA(REG_A1, REG_SP, off);
656  M_ALD_DSEG(REG_ITMP2, disp);
657  M_CALL(REG_ITMP2);
658 
659  /* restore return value */
660 
661  if (IS_INT_LNG_TYPE(t)) {
662  if (IS_2_WORD_TYPE(t)) {
664  } else {
665  M_ILD(REG_RESULT, REG_SP, off);
666  }
667  } else {
668  M_DLD(REG_FRESULT, REG_SP, off);
669  }
670 
671  /* remove stackframe */
672 
673  M_AADD_IMM(stackframesize, REG_SP);
674 
675  /* mark trace code */
676 
677  M_NOP;
678 }
679 #endif /* !defined(NDEBUG) */
680 
681 
682 /* emit_load_high **************************************************************
683 
684  Emits a possible load of the high 32-bits of an operand.
685 
686 *******************************************************************************/
687 
688 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
689 {
690  codegendata *cd;
691  s4 disp;
692  s4 reg;
693 
694  assert(src->type == TYPE_LNG);
695 
696  /* get required compiler data */
697 
698  cd = jd->cd;
699 
700  if (IS_INMEMORY(src->flags)) {
701  COUNT_SPILLS;
702 
703  disp = src->vv.regoff;
704 
705  M_ILD(tempreg, REG_SP, disp);
706 
707  reg = tempreg;
708  }
709  else
710  reg = GET_HIGH_REG(src->vv.regoff);
711 
712  return reg;
713 }
714 
715 /* emit_load_low ***************************************************************
716 
717  Emits a possible load of the low 32-bits of an operand.
718 
719 *******************************************************************************/
720 
721 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
722 {
723  codegendata *cd;
724  s4 disp;
725  s4 reg;
726 
727  assert(src->type == TYPE_LNG);
728 
729  /* get required compiler data */
730 
731  cd = jd->cd;
732 
733  if (IS_INMEMORY(src->flags)) {
734  COUNT_SPILLS;
735 
736  disp = src->vv.regoff;
737 
738  M_ILD(tempreg, REG_SP, disp + 4);
739 
740  reg = tempreg;
741  }
742  else
743  reg = GET_LOW_REG(src->vv.regoff);
744 
745  return reg;
746 }
747 
748 s4 emit_load_s1_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
749  codegendata *cd = jd->cd;
750  s4 reg = emit_load_s1(jd, iptr, tempreg);
751  if (reg == notreg) {
752  if (IS_FLT_DBL_TYPE(VAROP(iptr->s1)->type)) {
753  M_FMOV(reg, tempreg);
754  } else {
755  M_MOV(reg, tempreg);
756  }
757  return tempreg;
758  } else {
759  return reg;
760  }
761 }
762 
763 s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
764  codegendata *cd = jd->cd;
765  s4 reg = emit_load_s2(jd, iptr, tempreg);
766  if (reg == notreg) {
767  if (IS_FLT_DBL_TYPE(VAROP(iptr->sx.s23.s2)->type)) {
768  M_FMOV(reg, tempreg);
769  } else {
770  M_MOV(reg, tempreg);
771  }
772  return tempreg;
773  } else {
774  return reg;
775  }
776 }
777 
778 void emit_copy_dst(jitdata *jd, instruction *iptr, s4 dtmpreg) {
779  codegendata *cd;
780  varinfo *dst;
781  cd = jd->cd;
782  dst = VAROP(iptr->dst);
783  if (! IS_INMEMORY(dst->flags)) {
784  if (dst->vv.regoff != dtmpreg) {
785  if (IS_FLT_DBL_TYPE(dst->type)) {
786  M_FLTMOVE(dtmpreg, dst->vv.regoff);
787  } else if (IS_2_WORD_TYPE(dst->type)) {
788  M_LNGMOVE(dtmpreg, dst->vv.regoff);
789  } else {
790  M_INTMOVE(dtmpreg, dst->vv.regoff);
791  }
792  }
793  }
794 }
795 
796 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt) {
797 
798  s4 branchdisp = disp;
799  s4 branchmpc;
800  u1 *ref;
801 
802  if (N_VALID_BRANCH(branchdisp)) {
803 
804  /* valid displacement */
805 
806  switch (condition) {
807  case BRANCH_EQ:
808  M_BEQ(branchdisp);
809  break;
810  case BRANCH_NE:
811  M_BNE(branchdisp);
812  break;
813  case BRANCH_LT:
814  M_BLT(branchdisp);
815  break;
816  case BRANCH_GE:
817  M_BGE(branchdisp);
818  break;
819  case BRANCH_GT:
820  M_BGT(branchdisp);
821  break;
822  case BRANCH_LE:
823  M_BLE(branchdisp);
824  break;
826  M_BR(branchdisp);
827  break;
828  default:
829  vm_abort("emit_branch: unknown condition %d", condition);
830  }
831  } else {
832 
833  /* If LONGBRANCHES is not set, the flag and the error flag */
834 
836  cd->flags |= (CODEGENDATA_FLAG_ERROR |
838  }
839 
840  /* If error flag is set, do nothing. The method has to be recompiled. */
841 
843  return;
844  }
845 
846  /* Patch the displacement to branch over the actual branch manually
847  * to not get yet more nops.
848  */
849 
850  branchmpc = cd->mcodeptr - cd->mcodebase;
851  ref = cd->mcodeptr;
852 
853  switch (condition) {
854  case BRANCH_EQ:
855  M_BNE(0);
856  break;
857  case BRANCH_NE:
858  M_BEQ(0);
859  break;
860  case BRANCH_LT:
861  M_BGE(0);
862  break;
863  case BRANCH_GE:
864  M_BLT(0);
865  break;
866  case BRANCH_GT:
867  M_BLE(0);
868  break;
869  case BRANCH_LE:
870  M_BGT(0);
871  break;
873  /* fall through, no displacement to patch */
874  ref = NULL;
875  break;
876  default:
877  vm_abort("emit_branch: unknown condition %d", condition);
878  }
879 
880  /* The actual long branch */
881 
882  disp = dseg_add_s4(cd, branchmpc + disp - N_PV_OFFSET);
883  M_ILD_DSEG(REG_ITMP2, disp);
885  M_JMP(RN, REG_ITMP2);
886 
887  /* Patch back the displacement */
888 
889  N_BRC_BACK_PATCH(ref);
890  }
891 }
892 
894 {
895  if (INSTRUCTION_MUST_CHECK(iptr)) {
896  M_TEST(reg);
897  M_BNE(SZ_BRC + SZ_ILL);
899  }
900 }
901 
902 /* emit_arrayindexoutofbounds_check ********************************************
903 
904  Emit a ArrayIndexOutOfBoundsException check.
905 
906 *******************************************************************************/
907 
909 {
910  if (INSTRUCTION_MUST_CHECK(iptr)) {
911  /* Size is s4, >= 0
912  * Do unsigned comparison to catch negative indexes.
913  */
914  N_CL(s2, OFFSET(java_array_t, size), RN, s1);
915  M_BLT(SZ_BRC + SZ_ILL);
917  }
918 }
919 
920 
921 /* emit_arraystore_check *******************************************************
922 
923  Emit an ArrayStoreException check.
924 
925 *******************************************************************************/
926 
928 {
929  if (INSTRUCTION_MUST_CHECK(iptr)) {
931  M_BNE(SZ_BRC + SZ_ILL);
933  }
934 }
935 
936 
937 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1) {
938  if (INSTRUCTION_MUST_CHECK(iptr)) {
939  if (reg != RN) {
940  M_TEST(reg);
941  }
942  switch (condition) {
943  case BRANCH_LE:
944  M_BGT(SZ_BRC + SZ_ILL);
945  break;
946  case BRANCH_EQ:
947  M_BNE(SZ_BRC + SZ_ILL);
948  break;
949  case BRANCH_GT:
950  M_BLE(SZ_BRC + SZ_ILL);
951  break;
952  default:
953  vm_abort("emit_classcast_check: unknown condition %d", condition);
954  }
956  }
957 }
958 
960 {
961  if (INSTRUCTION_MUST_CHECK(iptr)) {
962  M_TEST(reg);
963  M_BNE(SZ_BRC + SZ_ILL);
965  }
966 }
967 
969 {
970  if (INSTRUCTION_MUST_CHECK(iptr)) {
972  M_BNE(SZ_BRC + SZ_ILL);
974  }
975 }
976 
978  s4 offset, offset_imm;
979 
980  /*
981  N_BASR(REG_PV, RN);
982  disp = (s4) (cd->mcodeptr - cd->mcodebase);
983  M_ASUB_IMM32(disp, REG_ITMP1, REG_PV);
984  */
985 
986  /* If the offset from the method start does not fit into an immediate
987  * value, we can't put it into the data segment!
988  */
989 
990  /* Displacement from start of method to here */
991 
992  offset = (s4) (cd->mcodeptr - cd->mcodebase);
993  offset_imm = -offset - SZ_BASR + N_PV_OFFSET;
994 
995  if (N_VALID_IMM(offset_imm)) {
996  /* Get program counter */
997  N_BASR(REG_PV, RN);
998  /* Substract displacement */
999  M_AADD_IMM(offset_imm, REG_PV);
1000  } else {
1001  /* Save program counter and jump over displacement in instruction flow */
1003  /* Place displacement here */
1004  /* REG_PV points now exactly to this position */
1005  N_LONG(-offset - SZ_BRAS + N_PV_OFFSET);
1006  /* Substract *(REG_PV) from REG_PV */
1007  N_A(REG_PV, 0, RN, REG_PV);
1008  }
1009 }
1010 
1011 /* emit_trap_compiler **********************************************************
1012 
1013  Emit a trap instruction which calls the JIT compiler.
1014 
1015 *******************************************************************************/
1016 
1018 {
1020 }
1021 
1022 /*
1023  * These are local overrides for various environment variables in Emacs.
1024  * Please do not remove this and leave it at the end of the file, where
1025  * Emacs will automagically detect them.
1026  * ---------------------------------------------------------------------
1027  * Local variables:
1028  * mode: c++
1029  * indent-tabs-mode: t
1030  * c-basic-offset: 4
1031  * tab-width: 4
1032  * End:
1033  * vim:noexpandtab:sw=4:ts=4:
1034  */
const s4 abi_registers_float_argument[]
Definition: md-abi.cpp:107
#define REG_SP
Definition: md-abi.hpp:53
#define CODEGENDATA_FLAG_ERROR
java_object_t header
Definition: class.hpp:73
#define N_BRC_BACK_PATCH(brc_pos)
Definition: codegen.hpp:437
#define GET_HIGH_REG(a)
#define SZ_LONG
Definition: codegen.hpp:399
union varinfo::@19 vv
#define REG_PV
Definition: md-abi.hpp:42
#define N_VALID_BRANCH(x)
Definition: codegen.hpp:345
#define M_ILL(data)
Definition: codegen.hpp:628
dummy_java_lang_Class object
Definition: class.hpp:88
s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
Definition: emit-common.cpp:63
#define N_CL(r1, d2, x2, b2)
Definition: codegen.hpp:454
#define M_ALD(a, b, disp)
Definition: codegen.hpp:345
#define REG_A1
Definition: md-abi.hpp:36
Definition: jit.hpp:126
void emit_monitor_exit(jitdata *jd, int32_t syncslot_offset)
Generates synchronization code to leave a monitor.
Definition: emit.cpp:565
#define M_LST(a, b, disp)
Definition: codegen.hpp:349
#define REG_A0
Definition: md-abi.hpp:35
paramdesc * params
Definition: descriptor.hpp:164
s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg)
Definition: emit.cpp:763
#define BRANCH_LE
#define JITDATA_HAS_FLAG_VERBOSECALL(jd)
Definition: jit.hpp:227
#define N_BASR(r1, r2)
Definition: codegen.hpp:417
#define M_BEQ(off)
Definition: codegen.hpp:482
#define M_ILD(a, b, disp)
Definition: codegen.hpp:347
#define IS_INT_LNG_TYPE(a)
Definition: global.hpp:130
#define BRANCH_NE
#define N_PV_OFFSET
Definition: codegen.hpp:339
#define M_IST(a, b, disp)
Definition: codegen.hpp:351
#define M_BNE(off)
Definition: codegen.hpp:483
#define ICONST(d, c)
Definition: codegen.hpp:53
#define M_LDA(a, b, disp)
Definition: codegen.hpp:163
#define BRANCH_GT
void emit_monitor_enter(jitdata *jd, int32_t syncslot_offset)
Generates synchronization code to enter a monitor.
Definition: emit.cpp:507
#define BRANCH_EQ
const s4 abi_registers_integer_argument[]
Definition: md-abi.cpp:64
#define M_AADD_IMM(a, b, c)
Definition: codegen.hpp:277
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
s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
#define BRANCH_UNCONDITIONAL
#define dseg_add_functionptr(cd, value)
Definition: dseg.hpp:39
codegendata * cd
Definition: jit.hpp:129
#define N_C(r1, d2, x2, b2)
Definition: codegen.hpp:447
#define REG_A2
Definition: md-abi.hpp:37
void emit_arraystore_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:380
#define M_FST(a, b, disp)
Definition: codegen.hpp:357
#define M_FLD(a, b, disp)
Definition: codegen.hpp:354
uint8_t u1
Definition: types.hpp:40
#define RN
Definition: codegen.hpp:106
#define COUNT_SPILLS
Definition: jit.hpp:108
#define N_DSEG_DISP(x)
Definition: codegen.hpp:340
void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
Definition: trace.cpp:240
Type type
Definition: reg.hpp:44
#define M_TEST(a)
Definition: codegen.hpp:359
#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)
#define CODEGENDATA_FLAG_LONGBRANCHES
const s4 abi_registers_float_temporary[]
Definition: md-abi.cpp:129
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
Definition: reg.hpp:43
void emit_recompute_pv(codegendata *cd)
Emit code to recompute the procedure vector.
Definition: emit.cpp:495
#define M_FLTMOVE(a, b)
static int code_is_leafmethod(codeinfo *code)
Definition: code.hpp:151
#define M_FMOV(b, c)
Definition: codegen.hpp:341
s4 dseg_add_s4(codegendata *cd, s4 value)
Definition: dseg.cpp:246
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
#define N_BRAS(r1, i2)
Definition: codegen.hpp:431
s4 regoff
Definition: reg.hpp:47
void emit_verbosecall_enter(jitdata *jd)
Definition: emit.cpp:625
typedesc paramtypes[1]
Definition: descriptor.hpp:167
#define IS_2_WORD_TYPE(a)
Definition: global.hpp:132
#define CODEGENDATA_HAS_FLAG_ERROR(cd)
void emit_exception_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:447
#define GET_LOW_REG(a)
void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
Definition: trace.cpp:149
s4 emit_load_s1_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg)
Definition: emit.cpp:748
#define FLT_TMP_CNT
Definition: md-abi.hpp:82
s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:174
dst_operand_t dst
#define SZ_BASR
Definition: codegen.hpp:418
uint16_t u2
Definition: types.hpp:43
#define N_VALID_IMM(x)
Definition: codegen.hpp:331
#define LOCK_monitor_enter
Definition: builtin.hpp:124
classinfo * clazz
Definition: method.hpp:80
#define M_JMP(a, b)
Definition: codegen.hpp:259
#define ARG_CNT
Definition: abi-asm.hpp:41
s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
Definition: emit-common.cpp:82
#define M_LNGMOVE(a, b)
#define BRANCH_GE
#define IS_FLT_DBL_TYPE(a)
Definition: global.hpp:131
#define INT_ARG_CNT
Definition: md-abi.hpp:74
void emit_trap_compiler(codegendata *cd)
Definition: emit.cpp:463
#define M_ICMP_IMM(a, b)
Definition: codegen.hpp:297
const s4 abi_registers_integer_temporary[]
Definition: md-abi.cpp:88
#define M_ASUB_IMM(a, b, c)
Definition: codegen.hpp:278
void emit_trap(codegendata *cd, u1 Xd, int type)
Definition: emit-asm.hpp:563
MIIterator i
#define CodeinfoPointer
s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:66
#define SZ_ILL
Definition: codegen.hpp:388
typedesc returntype
Definition: descriptor.hpp:166
#define M_BGE(off)
Definition: codegen.hpp:484
int32_t s4
Definition: types.hpp:45
void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
Definition: emit.cpp:113
#define M_AST(a, b, disp)
Definition: codegen.hpp:350
union instruction::@12 sx
void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:346
#define LOCK_monitor_exit
Definition: builtin.hpp:132
#define M_MOV(a, b)
Definition: codegen.hpp:340
#define N_AL(r1, d2, x2, b2)
Definition: codegen.hpp:409
bool inmemory
Definition: descriptor.hpp:151
#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
void emit_copy(jitdata *jd, instruction *iptr)
Definition: emit.cpp:153
s1_operand_t s1
#define TMP_CNT
Definition: abi-asm.hpp:42
void emit_copy_dst(jitdata *jd, instruction *iptr, s4 dtmpreg)
Definition: emit.cpp:778
uint32_t u4
Definition: types.hpp:46
#define BRANCH_LT
#define INT_TMP_CNT
Definition: md-abi.hpp:75
#define M_BGT(off)
Definition: codegen.hpp:485
methoddesc * parseddesc
Definition: method.hpp:78
#define REG_FTMP1
Definition: md-abi.hpp:65
#define VAROP(v)
Definition: jit.hpp:251
#define N_VALID_DSEG_DISP(x)
Definition: codegen.hpp:341
methodinfo * m
Definition: jit.hpp:127
static bool IS_INMEMORY(s4 flags)
Definition: stack.hpp:51
s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:136
#define N_A(r1, d2, x2, b2)
Definition: codegen.hpp:404
#define FLT_ARG_CNT
Definition: md-abi.hpp:81
#define M_ILL2(data1, data2)
Definition: codegen.hpp:629
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
void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
Definition: emit.cpp:263
s4 nr
Definition: jit.hpp:312
#define SZ_BRC
Definition: codegen.hpp:435
int8_t s1
Definition: types.hpp:39
int16_t s2
Definition: types.hpp:42
#define M_DST(a, b, disp)
Definition: codegen.hpp:356
struct instruction::@12::@13 s23
#define REG_RESULT2
Definition: md-abi.hpp:37
#define M_LLD(a, b, disp)
Definition: codegen.hpp:344
#define SZ_BRAS
Definition: codegen.hpp:432
#define M_BLE(off)
Definition: codegen.hpp:487
s4 flags
Definition: method.hpp:70
#define N_LONG(l)
Definition: codegen.hpp:398
#define N_MVC(d1, l, b1, d2, b2)
Definition: codegen.hpp:498
#define M_NOP
Definition: codegen.hpp:338
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_CALL(a)
Definition: codegen.hpp:290
void emit_verbosecall_exit(jitdata *jd)
Definition: emit.cpp:766
uint32_t regoff
Definition: descriptor.hpp:153
#define M_AADD(a, b, c)
Definition: codegen.hpp:578
#define OFFSET(s, el)
Definition: memory.hpp:90
#define INSTRUCTION_MUST_CHECK(iptr)
#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
#define REG_RESULT_PACKED
Definition: md-abi.hpp:133