CACAO
emit.cpp
Go to the documentation of this file.
1 /* src/vm/jit/arm/emit.cpp - Arm code emitter functions
2 
3  Copyright (C) 1996-2014
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 "vm/jit/arm/emit.hpp"
26 
27 #include "config.h"
28 
29 #include <cassert>
30 #include <stdint.h>
31 
32 #include "vm/types.hpp"
33 
34 #include "md-abi.hpp"
35 
36 #include "vm/jit/arm/codegen.hpp"
37 
38 #include "mm/memory.hpp"
39 
40 #include "threads/lock.hpp"
41 
42 #include "vm/descriptor.hpp" // for typedesc, methoddesc, etc
43 #include "vm/global.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/builtin.hpp"
49 #include "vm/jit/code.hpp"
51 #include "vm/jit/dseg.hpp"
52 #include "vm/jit/emit-common.hpp"
53 #include "vm/jit/jit.hpp"
55 #include "vm/jit/replace.hpp"
56 #include "vm/jit/trace.hpp"
57 #include "vm/jit/trap.hpp"
58 
60 
61 #include "toolbox/logging.hpp" /* XXX for debugging only */
62 
63 
64 /* emit_load *******************************************************************
65 
66  Emits a possible load of an operand.
67 
68 *******************************************************************************/
69 
70 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
71 {
72  codegendata *cd;
73  s4 disp;
74  s4 reg;
75 
76  /* get required compiler data */
77 
78  cd = jd->cd;
79 
80  if (src->flags & INMEMORY) {
82 
83  disp = src->vv.regoff;
84 
85 #if defined(ENABLE_SOFTFLOAT)
86  switch (src->type) {
87  case TYPE_INT:
88  case TYPE_FLT:
89  case TYPE_ADR:
90  M_ILD(tempreg, REG_SP, disp);
91  break;
92  case TYPE_LNG:
93  case TYPE_DBL:
94  M_LLD(tempreg, REG_SP, disp);
95  break;
96  default:
97  vm_abort("emit_load: unknown type %d", src->type);
98  break;
99  }
100 #else
101  switch (src->type) {
102  case TYPE_INT:
103  case TYPE_ADR:
104  M_ILD(tempreg, REG_SP, disp);
105  break;
106  case TYPE_LNG:
107  M_LLD(tempreg, REG_SP, disp);
108  break;
109  case TYPE_FLT:
110  M_FLD(tempreg, REG_SP, disp);
111  break;
112  case TYPE_DBL:
113  M_DLD(tempreg, REG_SP, disp);
114  break;
115  default:
116  vm_abort("emit_load: unknown type %d", src->type);
117  break;
118  }
119 #endif
120 
121  reg = tempreg;
122  }
123  else
124  reg = src->vv.regoff;
125 
126  return reg;
127 }
128 
129 
130 /* emit_load_low ***************************************************************
131 
132  Emits a possible load of the low 32-bits of a long source operand.
133 
134 *******************************************************************************/
135 
136 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
137 {
138  codegendata *cd;
139  s4 disp;
140  s4 reg;
141 
142  assert(src->type == TYPE_LNG);
143 
144  /* get required compiler data */
145 
146  cd = jd->cd;
147 
148  if (src->flags & INMEMORY) {
149  COUNT_SPILLS;
150 
151  disp = src->vv.regoff;
152 
153 #if defined(__ARMEL__)
154  M_ILD(tempreg, REG_SP, disp);
155 #else
156  M_ILD(tempreg, REG_SP, disp + 4);
157 #endif
158 
159  reg = tempreg;
160  }
161  else
162  reg = GET_LOW_REG(src->vv.regoff);
163 
164  return reg;
165 }
166 
167 
168 /* emit_load_high **************************************************************
169 
170  Emits a possible load of the high 32-bits of a long source operand.
171 
172 *******************************************************************************/
173 
174 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
175 {
176  codegendata *cd;
177  s4 disp;
178  s4 reg;
179 
180  assert(src->type == TYPE_LNG);
181 
182  /* get required compiler data */
183 
184  cd = jd->cd;
185 
186  if (src->flags & INMEMORY) {
187  COUNT_SPILLS;
188 
189  disp = src->vv.regoff;
190 
191 #if defined(__ARMEL__)
192  M_ILD(tempreg, REG_SP, disp + 4);
193 #else
194  M_ILD(tempreg, REG_SP, disp);
195 #endif
196 
197  reg = tempreg;
198  }
199  else
200  reg = GET_HIGH_REG(src->vv.regoff);
201 
202  return reg;
203 }
204 
205 
206 /* emit_store ******************************************************************
207 
208  Emits a possible store to a variable.
209 
210 *******************************************************************************/
211 
212 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
213 {
214  codegendata *cd;
215  s4 disp;
216 
217  /* get required compiler data */
218 
219  cd = jd->cd;
220 
221  if (dst->flags & INMEMORY) {
222  COUNT_SPILLS;
223 
224  disp = dst->vv.regoff;
225 
226 #if defined(ENABLE_SOFTFLOAT)
227  switch (dst->type) {
228  case TYPE_INT:
229  case TYPE_FLT:
230  case TYPE_ADR:
231  M_IST(d, REG_SP, disp);
232  break;
233  case TYPE_LNG:
234  case TYPE_DBL:
235  M_LST(d, REG_SP, disp);
236  break;
237  default:
238  vm_abort("emit_store: unknown type %d", dst->type);
239  break;
240  }
241 #else
242  switch (dst->type) {
243  case TYPE_INT:
244  case TYPE_ADR:
245  M_IST(d, REG_SP, disp);
246  break;
247  case TYPE_LNG:
248  M_LST(d, REG_SP, disp);
249  break;
250  case TYPE_FLT:
251  M_FST(d, REG_SP, disp);
252  break;
253  case TYPE_DBL:
254  M_DST(d, REG_SP, disp);
255  break;
256  default:
257  vm_abort("emit_store: unknown type %d", dst->type);
258  break;
259  }
260 #endif
261  }
262 }
263 
264 
265 /* emit_copy *******************************************************************
266 
267  Generates a register/memory to register/memory copy.
268 
269 *******************************************************************************/
270 
271 void emit_copy(jitdata *jd, instruction *iptr)
272 {
273  codegendata *cd;
274  varinfo *src;
275  varinfo *dst;
276  s4 s1, d;
277 
278  /* get required compiler data */
279 
280  cd = jd->cd;
281 
282  /* get source and destination variables */
283 
284  src = VAROP(iptr->s1);
285  dst = VAROP(iptr->dst);
286 
287  /* XXX dummy call, removed me!!! */
288  d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1);
289 
290  if ((src->vv.regoff != dst->vv.regoff) ||
291  ((src->flags ^ dst->flags) & INMEMORY)) {
292 
293  if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
294  /* emit nothing, as the value won't be used anyway */
295  return;
296  }
297 
298  /* If one of the variables resides in memory, we can eliminate
299  the register move from/to the temporary register with the
300  order of getting the destination register and the load. */
301 
302  if (IS_INMEMORY(src->flags)) {
303 #if !defined(ENABLE_SOFTFLOAT)
304  if (IS_FLT_DBL_TYPE(src->type))
305  d = codegen_reg_of_var(iptr->opc, dst, REG_FTMP1);
306  else
307 #endif
308  {
309  if (IS_2_WORD_TYPE(src->type))
310  d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
311  else
312  d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1);
313  }
314 
315  s1 = emit_load(jd, iptr, src, d);
316  }
317  else {
318 #if !defined(ENABLE_SOFTFLOAT)
319  if (IS_FLT_DBL_TYPE(src->type))
320  s1 = emit_load(jd, iptr, src, REG_FTMP1);
321  else
322 #endif
323  {
324  if (IS_2_WORD_TYPE(src->type))
325  s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
326  else
327  s1 = emit_load(jd, iptr, src, REG_ITMP1);
328  }
329 
330  d = codegen_reg_of_var(iptr->opc, dst, s1);
331  }
332 
333  if (s1 != d) {
334 #if defined(ENABLE_SOFTFLOAT)
335  switch (src->type) {
336  case TYPE_INT:
337  case TYPE_FLT:
338  case TYPE_ADR:
339  /* XXX grrrr, wrong direction! */
340  M_MOV(d, s1);
341  break;
342  case TYPE_LNG:
343  case TYPE_DBL:
344  /* XXX grrrr, wrong direction! */
345  M_MOV(GET_LOW_REG(d), GET_LOW_REG(s1));
347  break;
348  default:
349  vm_abort("emit_copy: unknown type %d", src->type);
350  break;
351  }
352 #else
353  switch (src->type) {
354  case TYPE_INT:
355  case TYPE_ADR:
356  /* XXX grrrr, wrong direction! */
357  M_MOV(d, s1);
358  break;
359  case TYPE_LNG:
360  /* XXX grrrr, wrong direction! */
361  M_MOV(GET_LOW_REG(d), GET_LOW_REG(s1));
363  break;
364  case TYPE_FLT:
365  M_FMOV(s1, d);
366  break;
367  case TYPE_DBL:
368  M_DMOV(s1, d);
369  break;
370  default:
371  vm_abort("emit_copy: unknown type %d", src->type);
372  break;
373  }
374 #endif
375  }
376 
377  emit_store(jd, iptr, dst, d);
378  }
379 }
380 
381 
382 /* emit_iconst *****************************************************************
383 
384  XXX
385 
386 *******************************************************************************/
387 
388 void emit_iconst(codegendata *cd, s4 d, s4 value)
389 {
390  s4 disp;
391 
392  if (IS_IMM(value))
393  M_MOV_IMM(d, value);
394  else {
395  disp = dseg_add_s4(cd, value);
396  M_DSEG_LOAD(d, disp);
397  }
398 }
399 
400 
401 /**
402  * Emits code updating the condition register by comparing one integer
403  * register to an immediate integer value.
404  */
405 void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
406 {
407  int32_t disp;
408 
409  if (IS_IMM(value)) {
410  M_CMP_IMM(reg, value);
411  } else if (IS_IMM(-value)) {
412  M_CMN_IMM(reg, -value);
413  } else {
414  assert(reg != REG_ITMP3);
415  disp = dseg_add_s4(cd, value);
416  M_DSEG_LOAD(REG_ITMP3, disp);
417  M_CMP(reg, REG_ITMP3);
418  }
419 }
420 
421 
422 /* emit_branch *****************************************************************
423 
424  Emits the code for conditional and unconditional branchs.
425 
426 *******************************************************************************/
427 
428 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
429 {
430  s4 checkdisp;
431  s4 branchdisp;
432 
433  /* calculate the different displacements */
434 
435  checkdisp = (disp - 8);
436  branchdisp = (disp - 8) >> 2;
437 
438  /* check which branch to generate */
439 
440  if (condition == BRANCH_UNCONDITIONAL) {
441  /* check displacement for overflow */
442 
443  if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) {
444  /* if the long-branches flag isn't set yet, do it */
445 
447  cd->flags |= (CODEGENDATA_FLAG_ERROR |
449  }
450 
451  vm_abort("emit_branch: emit unconditional long-branch code");
452  }
453  else {
454  M_B(branchdisp);
455  }
456  }
457  else {
458  /* and displacement for overflow */
459 
460  if ((checkdisp < (s4) 0xff000000) || (checkdisp > (s4) 0x00ffffff)) {
461  /* if the long-branches flag isn't set yet, do it */
462 
464  cd->flags |= (CODEGENDATA_FLAG_ERROR |
466  }
467 
468  vm_abort("emit_branch: emit conditional long-branch code");
469  }
470  else {
471  switch (condition) {
472  case BRANCH_EQ:
473  M_BEQ(branchdisp);
474  break;
475  case BRANCH_NE:
476  M_BNE(branchdisp);
477  break;
478  case BRANCH_LT:
479  M_BLT(branchdisp);
480  break;
481  case BRANCH_GE:
482  M_BGE(branchdisp);
483  break;
484  case BRANCH_GT:
485  M_BGT(branchdisp);
486  break;
487  case BRANCH_LE:
488  M_BLE(branchdisp);
489  break;
490  case BRANCH_UGT:
491  M_BHI(branchdisp);
492  break;
493  default:
494  vm_abort("emit_branch: unknown condition %d", condition);
495  break;
496  }
497  }
498  }
499 }
500 
501 
502 /* emit_arithmetic_check *******************************************************
503 
504  Emit an ArithmeticException check.
505 
506 *******************************************************************************/
507 
509 {
510  if (INSTRUCTION_MUST_CHECK(iptr)) {
511  CHECK_INT_REG(reg);
512  M_TEQ_IMM(reg, 0);
514  }
515 }
516 
517 
518 /* emit_nullpointer_check ******************************************************
519 
520  Emit a NullPointerException check.
521 
522 *******************************************************************************/
523 
525 {
526  if (INSTRUCTION_MUST_CHECK(iptr)) {
527  M_TST(reg, reg);
529  }
530 }
531 
533 {
534  M_TST(reg, reg);
536 }
537 
538 
539 /* emit_arrayindexoutofbounds_check ********************************************
540 
541  Emit a ArrayIndexOutOfBoundsException check.
542 
543 *******************************************************************************/
544 
546 {
547  if (INSTRUCTION_MUST_CHECK(iptr)) {
549  M_CMP(s2, REG_ITMP3);
551  }
552 }
553 
554 
555 /* emit_arraystore_check *******************************************************
556 
557  Emit an ArrayStoreException check.
558 
559 *******************************************************************************/
560 
562 {
563  if (INSTRUCTION_MUST_CHECK(iptr)) {
566  }
567 }
568 
569 
570 /* emit_classcast_check ********************************************************
571 
572  Emit a ClassCastException check.
573 
574 *******************************************************************************/
575 
576 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
577 {
578  if (INSTRUCTION_MUST_CHECK(iptr)) {
579  switch (condition) {
580  case BRANCH_EQ:
582  break;
583 
584  case BRANCH_NE:
586  break;
587 
588  case BRANCH_LT:
590  break;
591 
592  case BRANCH_LE:
594  break;
595 
596  case BRANCH_UGT:
598  break;
599 
600  default:
601  vm_abort("emit_classcast_check: unknown condition %d", condition);
602  break;
603  }
604  }
605 }
606 
607 /* emit_exception_check ********************************************************
608 
609  Emit an Exception check.
610 
611 *******************************************************************************/
612 
614 {
615  if (INSTRUCTION_MUST_CHECK(iptr)) {
618  }
619 }
620 
621 
622 /* emit_trap_compiler **********************************************************
623 
624  Emit a trap instruction which calls the JIT compiler.
625 
626 *******************************************************************************/
627 
629 {
631 }
632 
634 {
636 }
637 
638 
639 /* emit_trap *******************************************************************
640 
641  Emit a trap instruction and return the original machine code.
642 
643 *******************************************************************************/
644 
645 uint32_t emit_trap(codegendata *cd)
646 {
647  uint32_t mcode;
648 
649  /* Get machine code which is patched back in later. The
650  trap is 1 instruction word long. */
651 
652  mcode = *((uint32_t *) cd->mcodeptr);
653 
654  M_TRAP(0, TRAP_PATCHER);
655 
656  return mcode;
657 }
658 
659 
660 /**
661  * Emit code to recompute the procedure vector.
662  */
664 {
665  // This is used to recompute our PV (we use the IP for this) out
666  // of the current PC.
667  int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
668 
669  // We use PC relative addressing.
670  disp += 8;
671 
672  // Sanity checks.
673  assert((disp & 0x03) == 0);
674  assert(disp >= 0 && disp <= 0x03ffffff);
675 
676  // ATTENTION: If you change this, you have to look at other functions
677  // as well! Following things depend on it: md_codegen_get_pv_from_pc();
678  if (disp > 0x0003ffff) {
679  M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 18, 9));
680  M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 10, 5));
681  M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1));
682  } else if (disp > 0x000003ff) {
683  M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 10, 5));
684  M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1));
685  } else {
686  M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 2, 1));
687  }
688 }
689 
690 
691 /**
692  * Generates synchronization code to enter a monitor.
693  */
694 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
695 {
696  int32_t disp, p;
697 
698  // Get required compiler data.
699  methodinfo* m = jd->m;
700  codegendata* cd = jd->cd;
701 
702 # if !defined(NDEBUG)
705  syncslot_offset += 4 * 4;
706 
707 #if defined(__ARMHF__)
709 
710  for (p = 0; p < FLT_ARG_CNT; p++)
712 
713  syncslot_offset += FLT_ARG_CNT * 8;
714 #endif
715  }
716 # endif
717 
718  /* get the correct lock object */
719 
720  if (m->flags & ACC_STATIC) {
721  disp = dseg_add_address(cd, &m->clazz->object.header);
722  M_DSEG_LOAD(REG_A0, disp);
723  }
724  else {
726  }
727 
728  M_STR(REG_A0, REG_SP, syncslot_offset);
730  M_DSEG_BRANCH(disp);
731  emit_recompute_pv(cd);
732 
733 # if !defined(NDEBUG)
735 #if defined(__ARMHF__)
736  for (p = 0; p < FLT_ARG_CNT; p++)
738 
739  M_ADD_IMM(REG_SP, REG_SP, FLT_ARG_CNT * 8);
740 #endif
741 
743  }
744 # endif
745 }
746 
747 
748 /**
749  * Generates synchronization code to leave a monitor.
750  */
751 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
752 {
753  int32_t disp;
754 
755  // Get required compiler data.
756  methodinfo* m = jd->m;
757  codegendata* cd = jd->cd;
758 
759  /* we need to save the proper return value */
760 
761  methoddesc* md = m->parseddesc;
762 
763  switch (md->returntype.type) {
764  case TYPE_INT:
765  case TYPE_ADR:
766  case TYPE_LNG:
767  case TYPE_FLT: /* XXX TWISTI: is that correct? */
768  case TYPE_DBL:
770  syncslot_offset += 2 * 4;
771  break;
772  case TYPE_VOID:
773  break;
774  default:
775  assert(false);
776  break;
777  }
778 
779  M_LDR(REG_A0, REG_SP, syncslot_offset);
781  M_DSEG_BRANCH(disp);
782 
783  /* we no longer need PV here, no more loading */
784  /*emit_recompute_pv(cd);*/
785 
786  switch (md->returntype.type) {
787  case TYPE_INT:
788  case TYPE_ADR:
789  case TYPE_LNG:
790  case TYPE_FLT: /* XXX TWISTI: is that correct? */
791  case TYPE_DBL:
793  break;
794  case TYPE_VOID:
795  break;
796  default:
797  assert(false);
798  break;
799  }
800 }
801 
802 
803 /* emit_verbosecall_enter ******************************************************
804 
805  Generates the code for the call trace.
806 
807 *******************************************************************************/
808 
809 #if !defined(NDEBUG)
811 {
812  methodinfo *m;
813  codeinfo *code;
814  codegendata *cd;
815  registerdata *rd;
816  methoddesc *md;
817  s4 disp;
818  s4 i, s;
819 
820  /* get required compiler data */
821 
822  m = jd->m;
823  code = jd->code;
824  cd = jd->cd;
825  rd = jd->rd;
826 
827  md = m->parseddesc;
828 
829  /* mark trace code */
830 
831  M_NOP;
832 
833  /* Keep stack 8-byte aligned. */
834 
835  M_STMFD((1<<REG_LR) | (1<<REG_PV), REG_SP);
837 
838  /* save argument registers */
839 
840  for (i = 0; i < md->paramcount; i++) {
841  if (!md->params[i].inmemory) {
842  s = md->params[i].regoff;
843 
844  switch (md->paramtypes[i].type) {
845  case TYPE_INT:
846  case TYPE_ADR:
847 #if !defined(__ARMHF__)
848  case TYPE_FLT:
849 #endif
850  M_IST(s, REG_SP, i * 8);
851  break;
852  case TYPE_LNG:
853 #if !defined(__ARMHF__)
854  case TYPE_DBL:
855 #endif
856  M_LST(s, REG_SP, i * 8);
857  break;
858 #if defined(__ARMHF__)
859  case TYPE_FLT:
860  case TYPE_DBL:
861  M_DST(s, REG_SP, i * 8);
862  break;
863 #endif
864  default:
865  assert(false);
866  break;
867  }
868  }
869  }
870 
871  /* save all argument and temporary registers for leaf methods */
872 
873  if (code_is_leafmethod(code)) {
874  for (i = 0; i < INT_ARG_CNT; i++)
876 
877 #if defined(__ARMHF__)
878  for (i = 0; i < FLT_ARG_CNT; i++)
879  M_DST(abi_registers_float_argument[i], REG_SP, (md->paramcount + INT_ARG_CNT + i) * 8);
880 #endif
881 
882  for (i = 0; i < INT_TMP_CNT; i++)
883  M_IST(rd->tmpintregs[i], REG_SP, (md->paramcount + ARG_CNT + i) * 8);
884 
885 #if defined(__ARMHF__)
886  for (i = 0; i < FLT_TMP_CNT; i++)
887  M_DST(rd->tmpfltregs[i], REG_SP, (md->paramcount + ARG_CNT + INT_TMP_CNT + i) * 8);
888 #endif
889  }
890 
891  disp = dseg_add_address(cd, m);
892  M_DSEG_LOAD(REG_A0, disp);
893  M_MOV(REG_A1, REG_SP);
894  M_ADD_IMM_EXT_MUL4(REG_A2, REG_SP, ((md->paramcount + ARG_CNT + TMP_CNT) * 8 + 2 * 4 + cd->stackframesize * 8) >> 2);
896 
897  /* restore argument registers */
898 
899  for (i = 0; i < md->paramcount; i++) {
900  if (!md->params[i].inmemory) {
901  s = md->params[i].regoff;
902 
903  switch (md->paramtypes[i].type) {
904  case TYPE_INT:
905  case TYPE_ADR:
906 #if !defined(__ARMHF__)
907  case TYPE_FLT:
908 #endif
909  M_ILD(s, REG_SP, i * 8);
910  break;
911  case TYPE_LNG:
912 #if !defined(__ARMHF__)
913  case TYPE_DBL:
914 #endif
915  M_LLD(s, REG_SP, i * 8);
916  break;
917 #if defined(__ARMHF__)
918  case TYPE_FLT:
919  case TYPE_DBL:
920  M_DLD(s, REG_SP, i * 8);
921  break;
922 #endif
923  default:
924  assert(false);
925  break;
926  }
927  }
928  }
929 
930  /* restore all argument and temporary registers for leaf methods */
931 
932  if (code_is_leafmethod(code)) {
933  for (i = 0; i < INT_ARG_CNT; i++)
935 
936 #if defined(__ARMHF__)
937  for (i = 0; i < FLT_ARG_CNT; i++)
938  M_DLD(abi_registers_float_argument[i], REG_SP, (md->paramcount + INT_ARG_CNT + i) * 8);
939 #endif
940 
941  for (i = 0; i < INT_TMP_CNT; i++)
942  M_ILD(rd->tmpintregs[i], REG_SP, (md->paramcount + ARG_CNT + i) * 8);
943 
944 #if defined(__ARMHF__)
945  for (i = 0; i < FLT_TMP_CNT; i++)
946  M_DLD(rd->tmpfltregs[i], REG_SP, (md->paramcount + ARG_CNT + INT_TMP_CNT + i) * 8);
947 #endif
948  }
949 
950  /* Keep stack 8-byte aligned. */
951 
953  M_LDMFD((1<<REG_LR) | (1<<REG_PV), REG_SP);
954 
955  /* mark trace code */
956 
957  M_NOP;
958 }
959 #endif /* !defined(NDEBUG) */
960 
961 
962 /* emit_verbosecall_exit *******************************************************
963 
964  Generates the code for the call trace.
965 
966 *******************************************************************************/
967 
968 #if !defined(NDEBUG)
970 {
971  methodinfo *m;
972  codegendata *cd;
973  methoddesc *md;
974  s4 disp;
975 
976  /* get required compiler data */
977 
978  m = jd->m;
979  cd = jd->cd;
980 
981  md = m->parseddesc;
982 
983  /* mark trace code */
984 
985  M_NOP;
986 
987  /* Keep stack 8-byte aligned. */
988 
989  M_STMFD((1<<REG_LR) | (1<<REG_PV), REG_SP);
990  M_SUB_IMM(REG_SP, REG_SP, 1 * 8);
991 
992  /* save return value */
993 
994  switch (md->returntype.type) {
995  case TYPE_ADR:
996  case TYPE_INT:
997 #if !defined(__ARMHF__)
998  case TYPE_FLT:
999 #endif
1000  M_IST(REG_RESULT, REG_SP, 0 * 8);
1001  break;
1002  case TYPE_LNG:
1003 #if !defined(__ARMHF__)
1004  case TYPE_DBL:
1005 #endif
1006  M_LST(REG_RESULT_PACKED, REG_SP, 0 * 8);
1007  break;
1008 #if defined(__ARMHF__)
1009  case TYPE_FLT:
1010  case TYPE_DBL:
1011  M_DST(REG_FRESULT, REG_SP, 0 * 8);
1012  break;
1013 #endif
1014  case TYPE_VOID:
1015  break;
1016  default:
1017  assert(false);
1018  break;
1019  }
1020 
1021  disp = dseg_add_address(cd, m);
1022  M_DSEG_LOAD(REG_A0, disp);
1023  M_MOV(REG_A1, REG_SP);
1025 
1026  /* restore return value */
1027 
1028  switch (md->returntype.type) {
1029  case TYPE_ADR:
1030  case TYPE_INT:
1031 #if !defined(__ARMHF__)
1032  case TYPE_FLT:
1033 #endif
1034  M_ILD(REG_RESULT, REG_SP, 0 * 8);
1035  break;
1036  case TYPE_LNG:
1037 #if !defined(__ARMHF__)
1038  case TYPE_DBL:
1039 #endif
1040  M_LLD(REG_RESULT_PACKED, REG_SP, 0 * 8);
1041  break;
1042 #if defined(__ARMHF__)
1043  case TYPE_FLT:
1044  case TYPE_DBL:
1045  M_DLD(REG_FRESULT, REG_SP, 0 * 8);
1046  break;
1047 #endif
1048  case TYPE_VOID:
1049  break;
1050  default:
1051  assert(false);
1052  break;
1053  }
1054 
1055  /* Keep stack 8-byte aligned. */
1056 
1057  M_ADD_IMM(REG_SP, REG_SP, 1 * 8);
1058  M_LDMFD((1<<REG_LR) | (1<<REG_PV), REG_SP);
1059 
1060  /* mark trace code */
1061 
1062  M_NOP;
1063 }
1064 #endif /* !defined(NDEBUG) */
1065 
1066 
1067 /**
1068  * Emit profiling code for method frequency counting.
1069  * Its slow but working, so be carefull, if you want to use it...
1070  */
1071 #if defined(ENABLE_PROFILING)
1072 void emit_profile_method(codegendata* cd, codeinfo* code)
1073 {
1074  ICONST(REG_ITMP3,code);
1075  M_LDR(REG_ITMP2,REG_ITMP3,OFFSET(codeinfo, frequency));
1077  M_STR(REG_ITMP2,REG_ITMP3,OFFSET(codeinfo, frequency));
1078 // M_TRAP(0, TRAP_DEBUG);
1079 }
1080 
1081 #endif
1082 
1083 /**
1084  * Emit profiling code for basicblock frequency counting.
1085  * Its slow but working, so be carefull, if you want to use it...
1086  */
1087 #if defined(ENABLE_PROFILING)
1088 void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
1089 {
1090  ICONST(REG_ITMP3,code);
1091  M_LDR(REG_ITMP2,REG_ITMP3,OFFSET(codeinfo, bbfrequency));
1093  M_STR(REG_ITMP2,REG_ITMP3,OFFSET(codeinfo, bbfrequency));
1094 }
1095 #endif
1096 
1097 
1098 /**
1099  * Emit profiling code to start CPU cycle counting.
1100  */
1101 #if defined(ENABLE_PROFILING)
1102 void emit_profile_cycle_start(codegendata* cd, codeinfo* code)
1103 {
1104  // XXX Not implemented yet!
1105 }
1106 #endif
1107 
1108 
1109 /**
1110  * Emit profiling code to stop CPU cycle counting.
1111  */
1112 #if defined(ENABLE_PROFILING)
1113 void emit_profile_cycle_stop(codegendata* cd, codeinfo* code)
1114 {
1115  // XXX Not implemented yet!
1116 }
1117 #endif
1118 
1119 /*
1120  * These are local overrides for various environment variables in Emacs.
1121  * Please do not remove this and leave it at the end of the file, where
1122  * Emacs will automagically detect them.
1123  * ---------------------------------------------------------------------
1124  * Local variables:
1125  * mode: c++
1126  * indent-tabs-mode: t
1127  * c-basic-offset: 4
1128  * tab-width: 4
1129  * End:
1130  * vim:noexpandtab:sw=4:ts=4:
1131  */
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 GET_HIGH_REG(a)
#define REG_LR
Definition: md-abi.hpp:40
union varinfo::@19 vv
#define REG_PV
Definition: md-abi.hpp:42
dummy_java_lang_Class object
Definition: class.hpp:88
#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
#define M_TRAPLT(a, i)
Definition: codegen.hpp:571
paramdesc * params
Definition: descriptor.hpp:164
#define BRANCH_LE
#define JITDATA_HAS_FLAG_VERBOSECALL(jd)
Definition: jit.hpp:227
#define M_BEQ(off)
Definition: codegen.hpp:482
#define M_ILD(a, b, disp)
Definition: codegen.hpp:347
#define M_CMP(a, b)
Definition: codegen.hpp:430
#define BRANCH_NE
#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 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_ADD_IMM(d, a, i)
Definition: codegen.hpp:437
#define CHECK_INT_REG(r)
Definition: codegen.hpp:87
s4 dseg_add_address(codegendata *cd, void *value)
Definition: dseg.cpp:542
codeinfo * code
Definition: jit.hpp:128
#define M_DSEG_BRANCH(offset)
Definition: codegen.hpp:1136
#define 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 M_STMFD(regs, base)
Definition: codegen.hpp:502
#define REG_PC
Definition: md-abi.hpp:42
#define M_B(off)
Definition: codegen.hpp:480
#define REG_A2
Definition: md-abi.hpp:37
#define M_DSEG_LOAD(reg, offset)
Definition: codegen.hpp:1133
int * tmpfltregs
Definition: reg.hpp:72
void emit_arraystore_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:380
#define M_FST(a, b, disp)
Definition: codegen.hpp:357
#define M_BHI(off)
Definition: codegen.hpp:488
#define M_FLD(a, b, disp)
Definition: codegen.hpp:354
#define COUNT_SPILLS
Definition: jit.hpp:108
void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
Definition: trace.cpp:240
Type type
Definition: reg.hpp:44
#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)
#define M_TST(a, b)
Definition: codegen.hpp:428
#define CODEGENDATA_FLAG_LONGBRANCHES
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
void emit_abstractmethoderror_trap(codegendata *cd)
Definition: emit.cpp:468
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
s4 regoff
Definition: reg.hpp:47
void emit_verbosecall_enter(jitdata *jd)
Definition: emit.cpp:625
typedesc paramtypes[1]
Definition: descriptor.hpp:167
#define M_TRAPEQ(a, i)
Definition: codegen.hpp:569
#define IS_2_WORD_TYPE(a)
Definition: global.hpp:132
#define M_CMP_IMM(a, i)
Definition: codegen.hpp:446
void emit_exception_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:447
#define M_MOV_IMM(d, i)
Definition: codegen.hpp:448
#define GET_LOW_REG(a)
void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
Definition: trace.cpp:149
#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 M_LDR(d, base, offset)
Definition: codegen.hpp:891
#define LOCK_monitor_enter
Definition: builtin.hpp:124
classinfo * clazz
Definition: method.hpp:80
#define ARG_CNT
Definition: abi-asm.hpp:41
#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
void emit_trap(codegendata *cd, u1 Xd, int type)
Definition: emit-asm.hpp:563
MIIterator i
s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:66
#define BRANCH_UGT
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
registerdata * rd
Definition: jit.hpp:130
void emit_nullpointer_check_force(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:532
void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:346
#define M_TEQ_IMM(a, i)
Definition: codegen.hpp:445
#define M_SUB_IMM(d, a, i)
Definition: codegen.hpp:439
#define LOCK_monitor_exit
Definition: builtin.hpp:132
#define M_TRAP(a, i)
Definition: codegen.hpp:568
#define M_MOV(a, b)
Definition: codegen.hpp:340
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
#define BITMASK_RESULT
Definition: md-abi.hpp:63
s1_operand_t s1
#define TMP_CNT
Definition: abi-asm.hpp:42
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 M_ADD_IMM_EXT_MUL4(d, n, imm)
Definition: codegen.hpp:1064
#define REG_FTMP1
Definition: md-abi.hpp:65
#define VAROP(v)
Definition: jit.hpp:251
int * tmpintregs
Definition: reg.hpp:70
methodinfo * m
Definition: jit.hpp:127
#define M_TRAPLE(a, i)
Definition: codegen.hpp:572
static bool IS_INMEMORY(s4 flags)
Definition: stack.hpp:51
#define M_LONGBRANCH(adr)
Definition: codegen.hpp:1123
s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:136
#define FLT_ARG_CNT
Definition: md-abi.hpp:81
s4 flags
Definition: reg.hpp:45
#define M_BLT(off)
Definition: codegen.hpp:486
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
#define M_TRAPHI(a, i)
Definition: codegen.hpp:573
int8_t s1
Definition: types.hpp:39
int16_t s2
Definition: types.hpp:42
#define M_DST(a, b, disp)
Definition: codegen.hpp:356
#define IS_IMM(val)
Definition: codegen.hpp:84
void emit_iconst(codegendata *cd, s4 d, s4 value)
Definition: emit.cpp:220
#define M_LDMFD(regs, base)
Definition: codegen.hpp:501
#define M_LLD(a, b, disp)
Definition: codegen.hpp:344
#define M_STR(d, base, offset)
Definition: codegen.hpp:980
#define REG_ITMP3
Definition: md-abi.hpp:48
#define BITMASK_ARGS
Definition: md-abi.hpp:62
#define M_BLE(off)
Definition: codegen.hpp:487
s4 flags
Definition: method.hpp:70
#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_DLD(a, b, disp)
Definition: codegen.hpp:353
#define M_CMN_IMM(a, i)
Definition: codegen.hpp:447
void emit_verbosecall_exit(jitdata *jd)
Definition: emit.cpp:766
uint32_t regoff
Definition: descriptor.hpp:153
#define OFFSET(s, el)
Definition: memory.hpp:90
#define INSTRUCTION_MUST_CHECK(iptr)
#define REG_RESULT
Definition: md-abi.hpp:33
#define IMM_ROTL(imm, rot)
Definition: codegen.hpp:414
#define M_TRAPHS(a, i)
Definition: codegen.hpp:574
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:431
#define M_SUB_IMM_EXT_MUL4(d, n, imm)
Definition: codegen.hpp:1073
#define REG_ITMP1
Definition: md-abi.hpp:46
#define M_DMOV(b, c)
Definition: codegen.hpp:342
#define REG_RESULT_PACKED
Definition: md-abi.hpp:133
#define M_ILD_INTERN(a, b, disp)
Definition: codegen.hpp:180
#define M_TRAPNE(a, i)
Definition: codegen.hpp:570