CACAO
emit.cpp
Go to the documentation of this file.
1 /* src/vm/jit/mips/emit.cpp - MIPS 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 
26 #include "config.h"
27 
28 #include <cassert>
29 
30 #include "vm/types.hpp"
31 
32 #include "vm/jit/mips/codegen.hpp"
33 #include "vm/jit/mips/md-abi.hpp"
34 
35 #include "mm/memory.hpp"
36 
37 #include "threads/lock.hpp"
38 
39 #include "vm/descriptor.hpp" // for typedesc, methoddesc, etc
40 #include "vm/options.hpp"
41 
42 #include "vm/jit/abi.hpp"
43 #include "vm/jit/abi-asm.hpp"
44 #include "vm/jit/asmpart.hpp"
45 #include "vm/jit/builtin.hpp"
46 #include "vm/jit/code.hpp"
48 #include "vm/jit/dseg.hpp"
49 #include "vm/jit/emit-common.hpp"
50 #include "vm/jit/jit.hpp"
52 #include "vm/jit/replace.hpp"
53 #include "vm/jit/trace.hpp"
54 #include "vm/jit/trap.hpp"
55 
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 (src->flags & INMEMORY) {
77 
78  disp = src->vv.regoff;
79 
80  switch (src->type) {
81 #if SIZEOF_VOID_P == 8
82  case TYPE_INT:
83  case TYPE_LNG:
84  case TYPE_ADR:
85  M_LLD(tempreg, REG_SP, disp);
86  break;
87 #else
88  case TYPE_INT:
89  case TYPE_ADR:
90  M_ILD(tempreg, REG_SP, disp);
91  break;
92  case TYPE_LNG:
93  M_LLD(tempreg, REG_SP, disp);
94  break;
95 #endif
96  case TYPE_FLT:
97  M_FLD(tempreg, REG_SP, disp);
98  break;
99  case TYPE_DBL:
100  M_DLD(tempreg, REG_SP, disp);
101  break;
102  default:
103  vm_abort("emit_load: unknown type %d", src->type);
104  break;
105  }
106 
107  reg = tempreg;
108  }
109  else
110  reg = src->vv.regoff;
111 
112  return reg;
113 }
114 
115 
116 /* emit_load_low ***************************************************************
117 
118  Emits a possible load of the low 32-bits of an operand.
119 
120 *******************************************************************************/
121 
122 #if SIZEOF_VOID_P == 4
123 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
124 {
125  codegendata *cd;
126  s4 disp;
127  s4 reg;
128 
129  assert(src->type == TYPE_LNG);
130 
131  /* get required compiler data */
132 
133  cd = jd->cd;
134 
135  if (src->flags & INMEMORY) {
136  COUNT_SPILLS;
137 
138  disp = src->vv.regoff;
139 
140 #if WORDS_BIGENDIAN == 1
141  M_ILD(tempreg, REG_SP, disp + 4);
142 #else
143  M_ILD(tempreg, REG_SP, disp);
144 #endif
145 
146  reg = tempreg;
147  }
148  else
149  reg = GET_LOW_REG(src->vv.regoff);
150 
151  return reg;
152 }
153 #endif /* SIZEOF_VOID_P == 4 */
154 
155 
156 /* emit_load_high **************************************************************
157 
158  Emits a possible load of the high 32-bits of an operand.
159 
160 *******************************************************************************/
161 
162 #if SIZEOF_VOID_P == 4
163 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
164 {
165  codegendata *cd;
166  s4 disp;
167  s4 reg;
168 
169  assert(src->type == TYPE_LNG);
170 
171  /* get required compiler data */
172 
173  cd = jd->cd;
174 
175  if (src->flags & INMEMORY) {
176  COUNT_SPILLS;
177 
178  disp = src->vv.regoff;
179 
180 #if WORDS_BIGENDIAN == 1
181  M_ILD(tempreg, REG_SP, disp);
182 #else
183  M_ILD(tempreg, REG_SP, disp + 4);
184 #endif
185 
186  reg = tempreg;
187  }
188  else
189  reg = GET_HIGH_REG(src->vv.regoff);
190 
191  return reg;
192 }
193 #endif /* SIZEOF_VOID_P == 4 */
194 
195 
196 /* emit_store ******************************************************************
197 
198  Emits a possible store to variable.
199 
200 *******************************************************************************/
201 
202 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
203 {
204  codegendata *cd;
205  s4 disp;
206 
207  /* get required compiler data */
208 
209  cd = jd->cd;
210 
211  if (dst->flags & INMEMORY) {
212  COUNT_SPILLS;
213 
214  disp = dst->vv.regoff;
215 
216  switch (dst->type) {
217 #if SIZEOF_VOID_P == 8
218  case TYPE_INT:
219  case TYPE_LNG:
220  case TYPE_ADR:
221  M_LST(d, REG_SP, disp);
222  break;
223 #else
224  case TYPE_INT:
225  case TYPE_ADR:
226  M_IST(d, REG_SP, disp);
227  break;
228  case TYPE_LNG:
229  M_LST(d, REG_SP, disp);
230  break;
231 #endif
232  case TYPE_FLT:
233  M_FST(d, REG_SP, disp);
234  break;
235  case TYPE_DBL:
236  M_DST(d, REG_SP, disp);
237  break;
238  default:
239  vm_abort("emit_store: unknown type %d", dst->type);
240  break;
241  }
242  }
243 }
244 
245 
246 /* emit_copy *******************************************************************
247 
248  Generates a register/memory to register/memory copy.
249 
250 *******************************************************************************/
251 
252 void emit_copy(jitdata *jd, instruction *iptr)
253 {
254  codegendata *cd;
255  varinfo *src;
256  varinfo *dst;
257  s4 s1, d;
258 
259  /* get required compiler data */
260 
261  cd = jd->cd;
262 
263  /* get source and destination variables */
264 
265  src = VAROP(iptr->s1);
266  dst = VAROP(iptr->dst);
267 
268  if ((src->vv.regoff != dst->vv.regoff) ||
269  ((src->flags ^ dst->flags) & INMEMORY)) {
270 
271  if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
272  /* emit nothing, as the value won't be used anyway */
273  return;
274  }
275 
276  /* If one of the variables resides in memory, we can eliminate
277  the register move from/to the temporary register with the
278  order of getting the destination register and the load. */
279 
280  if (IS_INMEMORY(src->flags)) {
281 #if SIZEOF_VOID_P == 4
282  if (IS_2_WORD_TYPE(src->type))
283  d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
284  else
285 #endif
286  d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
287  s1 = emit_load(jd, iptr, src, d);
288  }
289  else {
290  s1 = emit_load(jd, iptr, src, REG_IFTMP);
291 #if SIZEOF_VOID_P == 4
292  if (IS_2_WORD_TYPE(src->type))
293  d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
294  else
295 #endif
296  d = codegen_reg_of_var(iptr->opc, dst, s1);
297  }
298 
299  if (s1 != d) {
300  switch (dst->type) {
301 #if SIZEOF_VOID_P == 8
302  case TYPE_INT:
303  case TYPE_LNG:
304  case TYPE_ADR:
305  M_MOV(s1, d);
306  break;
307 #else
308  case TYPE_INT:
309  case TYPE_ADR:
310  M_MOV(s1, d);
311  break;
312  case TYPE_LNG:
313  M_LNGMOVE(s1, d);
314  break;
315 #endif
316  case TYPE_FLT:
317  M_FMOV(s1, d);
318  break;
319  case TYPE_DBL:
320  M_DMOV(s1, d);
321  break;
322  default:
323  vm_abort("emit_copy: unknown type %d", dst->type);
324  break;
325  }
326  }
327 
328  emit_store(jd, iptr, dst, d);
329  }
330 }
331 
332 
333 /* emit_iconst *****************************************************************
334 
335  XXX
336 
337 *******************************************************************************/
338 
339 void emit_iconst(codegendata *cd, s4 d, s4 value)
340 {
341  s4 disp;
342 
343  if ((value >= -32768) && (value <= 32767))
344  M_IADD_IMM(REG_ZERO, value, d);
345  else if ((value >= 0) && (value <= 0xffff))
346  M_OR_IMM(REG_ZERO, value, d);
347  else {
348  disp = dseg_add_s4(cd, value);
349  M_ILD(d, REG_PV, disp);
350  }
351 }
352 
353 
354 /* emit_lconst *****************************************************************
355 
356  XXX
357 
358 *******************************************************************************/
359 
360 void emit_lconst(codegendata *cd, s4 d, s8 value)
361 {
362  s4 disp;
363 
364 #if SIZEOF_VOID_P == 8
365  if ((value >= -32768) && (value <= 32767))
366  M_LADD_IMM(REG_ZERO, value, d);
367  else if ((value >= 0) && (value <= 0xffff))
368  M_OR_IMM(REG_ZERO, value, d);
369  else {
370  disp = dseg_add_s8(cd, value);
371  M_LLD(d, REG_PV, disp);
372  }
373 #else
374  disp = dseg_add_s8(cd, value);
375  M_LLD(d, REG_PV, disp);
376 #endif
377 }
378 
379 
380 /* emit_branch *****************************************************************
381 
382  Emits the code for conditional and unconditional branchs.
383 
384  NOTE: The reg argument may contain two packed registers.
385 
386 *******************************************************************************/
387 
388 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
389 {
390  // Calculate the displacements.
391  int32_t checkdisp = (disp - 4);
392  int32_t branchdisp = (disp - 4) >> 2;
393 
394  /* check which branch to generate */
395 
396  if (condition == BRANCH_UNCONDITIONAL) {
397  // Check displacement for overflow.
398  if (opt_AlwaysEmitLongBranches || ((checkdisp < (int32_t) 0xffff8000) || (checkdisp > (int32_t) 0x00007fff))) {
399  /* if the long-branches flag isn't set yet, do it */
400 
402  cd->flags |= (CODEGENDATA_FLAG_ERROR |
404  }
405 
406  // Calculate the offset relative to PV.
407  int32_t currentrpc = cd->mcodeptr - cd->mcodebase;
408  int32_t offset = currentrpc + disp;
409 
410  // Sanity check.
411  assert(offset % 4 == 0);
412 
413  // Do the long-branch.
414  M_LUI(REG_ITMP3, offset >> 16);
415  M_OR_IMM(REG_ITMP3, offset, REG_ITMP3);
417  M_JMP(REG_ITMP3);
418  M_NOP;
419  M_NOP; // This nop is to have 6 instructions (see BRANCH_NOPS).
420  }
421  else {
422  M_BR(branchdisp);
423  M_NOP;
424  }
425  }
426  else {
427  // Check displacement for overflow.
428  if (opt_AlwaysEmitLongBranches || ((checkdisp < (int32_t) 0xffff8000) || (checkdisp > (int32_t) 0x00007fff))) {
429  /* if the long-branches flag isn't set yet, do it */
430 
432  cd->flags |= (CODEGENDATA_FLAG_ERROR |
434  }
435 
436  // Calculate the offset relative to PV before we generate
437  // new code.
438  int32_t currentrpc = cd->mcodeptr - cd->mcodebase;
439  int32_t offset = currentrpc + disp;
440 
441  // Sanity check.
442  assert(offset % 4 == 0);
443 
444  switch (condition) {
445  case BRANCH_EQ:
446  M_BNE(GET_HIGH_REG(reg), GET_LOW_REG(reg), 5);
447  break;
448  case BRANCH_NE:
449  M_BEQ(GET_HIGH_REG(reg), GET_LOW_REG(reg), 5);
450  break;
451  case BRANCH_LT:
452  M_BGEZ(reg, 5);
453  break;
454  case BRANCH_GE:
455  M_BLTZ(reg, 5);
456  break;
457  case BRANCH_GT:
458  M_BLEZ(reg, 5);
459  break;
460  case BRANCH_LE:
461  M_BGTZ(reg, 5);
462  break;
463  default:
464  vm_abort("emit_branch: unknown condition %d", condition);
465  break;
466  }
467 
468  // The actual branch code which is over-jumped. NOTE: We
469  // don't use a branch delay slot for the conditional
470  // branch.
471 
472  // Do the long-branch.
473  M_LUI(REG_ITMP3, offset >> 16);
474  M_OR_IMM(REG_ITMP3, offset, REG_ITMP3);
476  M_JMP(REG_ITMP3);
477  M_NOP;
478  }
479  else {
480  switch (condition) {
481  case BRANCH_EQ:
482  M_BEQ(GET_HIGH_REG(reg), GET_LOW_REG(reg), branchdisp);
483  break;
484  case BRANCH_NE:
485  M_BNE(GET_HIGH_REG(reg), GET_LOW_REG(reg), branchdisp);
486  break;
487  case BRANCH_LT:
488  M_BLTZ(reg, branchdisp);
489  break;
490  case BRANCH_GE:
491  M_BGEZ(reg, branchdisp);
492  break;
493  case BRANCH_GT:
494  M_BGTZ(reg, branchdisp);
495  break;
496  case BRANCH_LE:
497  M_BLEZ(reg, branchdisp);
498  break;
499  default:
500  vm_abort("emit_branch: unknown condition %d", condition);
501  break;
502  }
503 
504  /* branch delay */
505  M_NOP;
506  }
507  }
508 }
509 
510 
511 /* emit_arithmetic_check *******************************************************
512 
513  Emit an ArithmeticException check.
514 
515 *******************************************************************************/
516 
518 {
519  if (INSTRUCTION_MUST_CHECK(iptr)) {
520  M_BNEZ(reg, 2);
521  M_NOP;
523  }
524 }
525 
526 
527 /* emit_arrayindexoutofbounds_check ********************************************
528 
529  Emit an ArrayIndexOutOfBoundsException check.
530 
531 *******************************************************************************/
532 
534 {
535  if (INSTRUCTION_MUST_CHECK(iptr)) {
538  M_BNEZ(REG_ITMP3, 2);
539  M_NOP;
541  }
542 }
543 
544 
545 /* emit_arraystore_check *******************************************************
546 
547  Emit an ArrayStoreException check.
548 
549 *******************************************************************************/
550 
552 {
553  if (INSTRUCTION_MUST_CHECK(iptr)) {
554  M_BNEZ(REG_RESULT, 2);
555  M_NOP;
557  }
558 }
559 
560 
561 /* emit_classcast_check ********************************************************
562 
563  Emit a ClassCastException check.
564 
565 *******************************************************************************/
566 
567 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
568 {
569  if (INSTRUCTION_MUST_CHECK(iptr)) {
570  switch (condition) {
571  case ICMD_IFEQ:
572  M_BNEZ(reg, 2);
573  break;
574 
575  case ICMD_IFNE:
576  M_BEQZ(reg, 2);
577  break;
578 
579  case ICMD_IFLE:
580  M_BGTZ(reg, 2);
581  break;
582 
583  default:
584  vm_abort("emit_classcast_check: unknown condition %d", condition);
585  break;
586  }
587 
588  M_NOP;
590  }
591 }
592 
593 
594 /* emit_nullpointer_check ******************************************************
595 
596  Emit a NullPointerException check.
597 
598 *******************************************************************************/
599 
601 {
602  if (INSTRUCTION_MUST_CHECK(iptr)) {
603  M_BNEZ(reg, 2);
604  M_NOP;
606  }
607 }
608 
609 
610 /* emit_exception_check ********************************************************
611 
612  Emit an Exception check.
613 
614 *******************************************************************************/
615 
617 {
618  if (INSTRUCTION_MUST_CHECK(iptr)) {
619  M_BNEZ(REG_RESULT, 2);
620  M_NOP;
622  }
623 }
624 
625 
626 /* emit_trap_compiler **********************************************************
627 
628  Emit a trap instruction which calls the JIT compiler.
629 
630 *******************************************************************************/
631 
633 {
635 }
636 
637 
639 {
641 }
642 
643 
644 /* emit_trap *******************************************************************
645 
646  Emit a trap instruction and return the original machine code.
647 
648 *******************************************************************************/
649 
650 uint32_t emit_trap(codegendata *cd)
651 {
652  // Get machine code which is patched back in later. The trap is 1
653  // instruction word long.
654  uint32_t mcode = *((uint32_t*) cd->mcodeptr);
655 
656  M_RESERVED;
657 
658  return mcode;
659 }
660 
661 
662 /**
663  * Emit code to recompute the procedure vector.
664  */
666 {
667  int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
668 
669  M_LDA(REG_PV, REG_RA, -disp);
670 }
671 
672 
673 /**
674  * Generates synchronization code to enter a monitor.
675  */
676 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
677 {
678  int32_t p;
679  int32_t disp;
680 
681  // Get required compiler data.
682  methodinfo* m = jd->m;
683  codegendata* cd = jd->cd;
684 
685 # if !defined(NDEBUG)
688 
689  for (p = 0; p < INT_ARG_CNT; p++)
691 
692  for (p = 0; p < FLT_ARG_CNT; p++)
693  M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
694 
695  syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
696  }
697 # endif
698 
699  /* get correct lock object */
700 
701  if (m->flags & ACC_STATIC) {
702  disp = dseg_add_address(cd, &m->clazz->object.header);
703  M_ALD(REG_A0, REG_PV, disp);
705  M_ALD(REG_ITMP3, REG_PV, disp);
706  }
707  else {
708 /* emit_nullpointer_check(cd, iptr, REG_A0); */
709  M_BNEZ(REG_A0, 2);
711  M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
713  }
714 
716  M_AST(REG_A0, REG_SP, syncslot_offset); /* branch delay */
717 
718 # if !defined(NDEBUG)
720  for (p = 0; p < INT_ARG_CNT; p++)
722 
723  for (p = 0; p < FLT_ARG_CNT; p++)
724  M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
725 
726 
727  M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
728  }
729 # endif
730 }
731 
732 
733 /**
734  * Generates synchronization code to leave a monitor.
735  */
736 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
737 {
738  int32_t disp;
739 
740  // Get required compiler data.
741  methodinfo* m = jd->m;
742  codegendata* cd = jd->cd;
743 
745  M_ALD(REG_ITMP3, REG_PV, disp);
746 
747  /* we need to save the proper return value */
748 
749  methoddesc* md = m->parseddesc;
750 
751  switch (md->returntype.type) {
752  case TYPE_INT:
753  case TYPE_ADR:
754 #if SIZEOF_VOID_P == 8
755  case TYPE_LNG:
756 #endif
757  M_ALD(REG_A0, REG_SP, syncslot_offset);
759  M_AST(REG_RESULT, REG_SP, syncslot_offset); /* delay slot */
760  break;
761 #if SIZEOF_VOID_P == 4
762  case TYPE_LNG:
763  M_ALD(REG_A0, REG_SP, syncslot_offset);
764  M_LST(REG_RESULT_PACKED, REG_SP, syncslot_offset);
766  M_NOP;
767  break;
768 #endif
769  case TYPE_FLT:
770  case TYPE_DBL:
771  M_ALD(REG_A0, REG_SP, syncslot_offset);
773  M_DST(REG_FRESULT, REG_SP, syncslot_offset); /* delay slot */
774  break;
775  default:
777  M_ALD(REG_A0, REG_SP, syncslot_offset); /* delay*/
778  break;
779  }
780 
781  /* and now restore the proper return value */
782 
783  switch (md->returntype.type) {
784  case TYPE_INT:
785  case TYPE_ADR:
786 #if SIZEOF_VOID_P == 8
787  case TYPE_LNG:
788 #endif
789  M_ALD(REG_RESULT, REG_SP, syncslot_offset);
790  break;
791 #if SIZEOF_VOID_P == 4
792  case TYPE_LNG:
793  M_LLD(REG_RESULT_PACKED, REG_SP, syncslot_offset);
794  break;
795 #endif
796  case TYPE_FLT:
797  case TYPE_DBL:
798  M_DLD(REG_FRESULT, REG_SP, syncslot_offset);
799  break;
800  case TYPE_VOID:
801  break;
802  default:
803  break;
804  }
805 }
806 
807 
808 /* emit_verbosecall_enter ******************************************************
809 
810  Generates the code for the call trace.
811 
812 *******************************************************************************/
813 
814 #if !defined(NDEBUG)
816 {
817  methodinfo *m;
818  codeinfo *code;
819  codegendata *cd;
820  registerdata *rd;
821  methoddesc *md;
822  s4 disp;
823  s4 i, s;
824 
825  /* get required compiler data */
826 
827  m = jd->m;
828  code = jd->code;
829  cd = jd->cd;
830  rd = jd->rd;
831 
832  md = m->parseddesc;
833 
834  /* mark trace code */
835 
836  M_NOP;
837 
838  /* keep stack 16-byte aligned */
839 
840  M_LDA(REG_SP, REG_SP, -(PA_SIZE + (md->paramcount + 2 + TMP_CNT) * 8));
841  M_AST(REG_RA, REG_SP, PA_SIZE + md->paramcount * 8);
842 
843  /* save argument registers (we store the registers as address
844  types, so it's correct for MIPS32 too) */
845 
846  for (i = 0; i < md->paramcount; i++) {
847  if (!md->params[i].inmemory) {
848  s = md->params[i].regoff;
849  switch (md->paramtypes[i].type) {
850  case TYPE_ADR:
851  case TYPE_INT:
852  M_AST(s, REG_SP, PA_SIZE + i * 8);
853  break;
854  case TYPE_LNG:
855  M_LST(s, REG_SP, PA_SIZE + i * 8);
856  break;
857  case TYPE_FLT:
858  M_FST(s, REG_SP, PA_SIZE + i * 8);
859  break;
860  case TYPE_DBL:
861  M_DST(s, REG_SP, PA_SIZE + i * 8);
862  break;
863  default:
864  assert(false);
865  break;
866  }
867  }
868  }
869 
870  /* save temporary registers for leaf methods */
871 
872  if (code_is_leafmethod(code)) {
873  for (i = 0; i < INT_TMP_CNT; i++)
874  M_AST(rd->tmpintregs[i], REG_SP, PA_SIZE + (md->paramcount + 2 + i) * 8);
875 
876  for (i = 0; i < FLT_TMP_CNT; i++)
877  M_DST(rd->tmpfltregs[i], REG_SP, PA_SIZE + (md->paramcount + 2 + INT_TMP_CNT + i) * 8);
878  }
879 
880  disp = dseg_add_address(cd, m);
881  M_ALD(REG_A0, REG_PV, disp);
883  M_LDA(REG_A2, REG_SP, PA_SIZE + (md->paramcount + 2 + TMP_CNT) * 8 + cd->stackframesize * 8);
885  M_ALD(REG_ITMP3, REG_PV, disp);
887  M_NOP;
888 
889  /* restore argument registers */
890 
891  for (i = 0; i < md->paramcount; i++) {
892  if (!md->params[i].inmemory) {
893  s = md->params[i].regoff;
894  switch (md->paramtypes[i].type) {
895  case TYPE_ADR:
896  case TYPE_INT:
897  M_ALD(s, REG_SP, PA_SIZE + i * 8);
898  break;
899  case TYPE_LNG:
900  M_LLD(s, REG_SP, PA_SIZE + i * 8);
901  break;
902  case TYPE_FLT:
903  M_FLD(s, REG_SP, PA_SIZE + i * 8);
904  break;
905  case TYPE_DBL:
906  M_DLD(s, REG_SP, PA_SIZE + i * 8);
907  break;
908  default:
909  assert(false);
910  break;
911  }
912  }
913  }
914 
915  /* restore temporary registers for leaf methods */
916 
917  if (code_is_leafmethod(code)) {
918  for (i = 0; i < INT_TMP_CNT; i++)
919  M_ALD(rd->tmpintregs[i], REG_SP, PA_SIZE + (md->paramcount + 2 + i) * 8);
920 
921  for (i = 0; i < FLT_TMP_CNT; i++)
922  M_DLD(rd->tmpfltregs[i], REG_SP, PA_SIZE + (md->paramcount + 2 + INT_TMP_CNT + i) * 8);
923  }
924 
925  /* keep stack 16-byte aligned */
926 
927  M_ALD(REG_RA, REG_SP, PA_SIZE + md->paramcount * 8);
928  M_LDA(REG_SP, REG_SP, PA_SIZE + (md->paramcount + 2 + TMP_CNT) * 8);
929 
930  /* mark trace code */
931 
932  M_NOP;
933 }
934 #endif /* !defined(NDEBUG) */
935 
936 
937 /* emit_verbosecall_exit *******************************************************
938 
939  Generates the code for the call trace.
940 
941 *******************************************************************************/
942 
943 #if !defined(NDEBUG)
945 {
946  methodinfo *m;
947  codegendata *cd;
948  registerdata *rd;
949  methoddesc *md;
950  s4 disp;
951 
952  /* get required compiler data */
953 
954  m = jd->m;
955  cd = jd->cd;
956  rd = jd->rd;
957 
958  md = m->parseddesc;
959 
960  /* mark trace code */
961 
962  M_NOP;
963 
964  /* keep stack 16-byte aligned */
965 
966 #if SIZEOF_VOID_P == 8
967  assert(0); // XXX: Revisit this code for MIPS64!
968 #endif
969  M_ASUB_IMM(REG_SP, PA_SIZE + 2 * 8, REG_SP);
970  M_AST(REG_RA, REG_SP, PA_SIZE + 1 * 8);
971 
972  /* save return value */
973 
974  switch (md->returntype.type) {
975  case TYPE_ADR:
976  case TYPE_INT:
977  M_AST(REG_RESULT, REG_SP, PA_SIZE + 0 * 8);
978  break;
979  case TYPE_LNG:
980 #if SIZEOF_VOID_P == 8
981  M_LST(REG_RESULT, REG_SP, PA_SIZE + 0 * 8);
982 #else
984 #endif
985  break;
986  case TYPE_FLT:
987  M_FST(REG_FRESULT, REG_SP, PA_SIZE + 0 * 8);
988  break;
989  case TYPE_DBL:
990  M_DST(REG_FRESULT, REG_SP, PA_SIZE + 0 * 8);
991  break;
992  case TYPE_VOID:
993  break;
994  default:
995  assert(false);
996  break;
997  }
998 
999  disp = dseg_add_address(cd, m);
1000  M_ALD(REG_A0, REG_PV, disp);
1003  M_ALD(REG_ITMP3, REG_PV, disp);
1005  M_NOP;
1006 
1007  /* restore return value */
1008 
1009  switch (md->returntype.type) {
1010  case TYPE_ADR:
1011  case TYPE_INT:
1012  M_ALD(REG_RESULT, REG_SP, PA_SIZE + 0 * 8);
1013  break;
1014  case TYPE_LNG:
1015 #if SIZEOF_VOID_P == 8
1016  M_LLD(REG_RESULT, REG_SP, PA_SIZE + 0 * 8);
1017 #else
1019 #endif
1020  break;
1021  case TYPE_FLT:
1022  M_FLD(REG_FRESULT, REG_SP, PA_SIZE + 0 * 8);
1023  break;
1024  case TYPE_DBL:
1025  M_DLD(REG_FRESULT, REG_SP, PA_SIZE + 0 * 8);
1026  break;
1027  case TYPE_VOID:
1028  break;
1029  default:
1030  assert(false);
1031  break;
1032  }
1033 
1034  /* keep stack 16-byte aligned */
1035 
1036  M_ALD(REG_RA, REG_SP, PA_SIZE + 1 * 8);
1037  M_AADD_IMM(REG_SP, PA_SIZE + 2 * 8, REG_SP);
1038 
1039  /* mark trace code */
1040 
1041  M_NOP;
1042 }
1043 #endif /* !defined(NDEBUG) */
1044 
1045 
1046 /*
1047  * These are local overrides for various environment variables in Emacs.
1048  * Please do not remove this and leave it at the end of the file, where
1049  * Emacs will automagically detect them.
1050  * ---------------------------------------------------------------------
1051  * Local variables:
1052  * mode: c++
1053  * indent-tabs-mode: t
1054  * c-basic-offset: 4
1055  * tab-width: 4
1056  * End:
1057  * vim:noexpandtab:sw=4:ts=4:
1058  */
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)
union varinfo::@19 vv
#define REG_PV
Definition: md-abi.hpp:42
#define M_JSR(a, b)
Definition: codegen.hpp:260
dummy_java_lang_Class object
Definition: class.hpp:88
#define M_ALD(a, b, disp)
Definition: codegen.hpp:345
#define M_BGTZ(a, disp)
Definition: codegen.hpp:257
#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
#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 BRANCH_NE
#define M_IST(a, b, disp)
Definition: codegen.hpp:351
#define M_BNE(off)
Definition: codegen.hpp:483
#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 M_OR_IMM(a, b, c)
Definition: codegen.hpp:299
#define M_BEQZ(a, disp)
Definition: codegen.hpp:252
#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 REG_A2
Definition: md-abi.hpp:37
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_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)
int64_t s8
Definition: types.hpp:48
#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
#define REG_IFTMP
Definition: md-abi.hpp:69
#define M_LUI(a, imm)
Definition: codegen.hpp:442
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
#define M_BGEZ(a, disp)
Definition: codegen.hpp:256
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
void emit_exception_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:447
#define GET_LOW_REG(a)
#define M_CMPULT(a, b, c)
Definition: codegen.hpp:285
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
void emit_lconst(codegendata *cd, s4 d, s8 value)
Definition: emit.cpp:233
s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:174
dst_operand_t dst
#define PA_SIZE
Definition: md-abi.hpp:147
#define LOCK_monitor_enter
Definition: builtin.hpp:124
classinfo * clazz
Definition: method.hpp:80
#define M_RESERVED
Definition: codegen.hpp:132
#define M_JMP(a, b)
Definition: codegen.hpp:259
#define M_LNGMOVE(a, b)
#define BRANCH_GE
#define M_ALD_INTERN(a, b, disp)
Definition: codegen.hpp:207
#define M_BLEZ(a, disp)
Definition: codegen.hpp:254
#define INT_ARG_CNT
Definition: md-abi.hpp:74
void emit_trap_compiler(codegendata *cd)
Definition: emit.cpp:463
#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
s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:66
typedesc returntype
Definition: descriptor.hpp:166
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
#define M_AST(a, b, disp)
Definition: codegen.hpp:350
#define REG_RA
Definition: md-abi.hpp:41
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
bool inmemory
Definition: descriptor.hpp:151
void emit_copy(jitdata *jd, instruction *iptr)
Definition: emit.cpp:153
#define M_LADD_IMM(a, b, c)
Definition: codegen.hpp:271
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
methoddesc * parseddesc
Definition: method.hpp:78
#define VAROP(v)
Definition: jit.hpp:251
int * tmpintregs
Definition: reg.hpp:70
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 FLT_ARG_CNT
Definition: md-abi.hpp:81
s4 flags
Definition: reg.hpp:45
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
int8_t s1
Definition: types.hpp:39
s4 dseg_add_s8(codegendata *cd, s8 value)
Definition: dseg.cpp:319
int16_t s2
Definition: types.hpp:42
#define M_DST(a, b, disp)
Definition: codegen.hpp:356
#define REG_ZERO
Definition: md-abi.hpp:54
void emit_iconst(codegendata *cd, s4 d, s4 value)
Definition: emit.cpp:220
#define M_LLD(a, b, disp)
Definition: codegen.hpp:344
#define REG_ITMP3
Definition: md-abi.hpp:48
s4 flags
Definition: method.hpp:70
#define M_IADD_IMM(a, b, c)
Definition: codegen.hpp:270
#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
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 M_BNEZ(a, disp)
Definition: codegen.hpp:255
bool opt_AlwaysEmitLongBranches
Definition: options.cpp:163
#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
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:431
#define M_BLTZ(a, disp)
Definition: codegen.hpp:253
#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