CACAO
emit.cpp
Go to the documentation of this file.
1 /* src/vm/jit/powerpc/emit.cpp - PowerPC 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 #include <stdint.h>
30 
31 #include "vm/types.hpp"
32 
33 #include "md-abi.hpp"
34 
36 
37 #include "mm/memory.hpp"
38 
39 #include "threads/lock.hpp"
40 
41 #include "vm/descriptor.hpp" // for typedesc, methoddesc, etc
42 #include "vm/options.hpp"
43 
44 #include "vm/jit/abi.hpp"
45 #include "vm/jit/abi-asm.hpp"
46 #include "vm/jit/asmpart.hpp"
47 #include "vm/jit/builtin.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 
59 
60 
61 /* emit_load *******************************************************************
62 
63  Emits a possible load of an operand.
64 
65 *******************************************************************************/
66 
67 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
68 {
69  codegendata *cd;
70  s4 disp;
71  s4 reg;
72 
73  /* get required compiler data */
74 
75  cd = jd->cd;
76 
77  if (IS_INMEMORY(src->flags)) {
79 
80  disp = src->vv.regoff;
81 
82  switch (src->type) {
83  case TYPE_INT:
84  case TYPE_ADR:
85  M_ILD(tempreg, REG_SP, disp);
86  break;
87  case TYPE_LNG:
88  M_LLD(tempreg, REG_SP, disp);
89  break;
90  case TYPE_FLT:
91  M_FLD(tempreg, REG_SP, disp);
92  break;
93  case TYPE_DBL:
94  M_DLD(tempreg, REG_SP, disp);
95  break;
96  default:
97  vm_abort("emit_load: unknown type %d", src->type);
98  break;
99  }
100 
101  reg = tempreg;
102  }
103  else
104  reg = src->vv.regoff;
105 
106  return reg;
107 }
108 
109 
110 /* emit_load_low ***************************************************************
111 
112  Emits a possible load of the low 32-bits of an operand.
113 
114 *******************************************************************************/
115 
116 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
117 {
118  codegendata *cd;
119  s4 disp;
120  s4 reg;
121 
122  assert(src->type == TYPE_LNG);
123 
124  /* get required compiler data */
125 
126  cd = jd->cd;
127 
128  if (IS_INMEMORY(src->flags)) {
129  COUNT_SPILLS;
130 
131  disp = src->vv.regoff;
132 
133  M_ILD(tempreg, REG_SP, disp + 4);
134 
135  reg = tempreg;
136  }
137  else
138  reg = GET_LOW_REG(src->vv.regoff);
139 
140  return reg;
141 }
142 
143 
144 /* emit_load_high **************************************************************
145 
146  Emits a possible load of the high 32-bits of an operand.
147 
148 *******************************************************************************/
149 
150 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
151 {
152  codegendata *cd;
153  s4 disp;
154  s4 reg;
155 
156  assert(src->type == TYPE_LNG);
157 
158  /* get required compiler data */
159 
160  cd = jd->cd;
161 
162  if (IS_INMEMORY(src->flags)) {
163  COUNT_SPILLS;
164 
165  disp = src->vv.regoff;
166 
167  M_ILD(tempreg, REG_SP, disp);
168 
169  reg = tempreg;
170  }
171  else
172  reg = GET_HIGH_REG(src->vv.regoff);
173 
174  return reg;
175 }
176 
177 
178 /* emit_store ******************************************************************
179 
180  Emit a possible store for the given variable.
181 
182 *******************************************************************************/
183 
184 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
185 {
186  codegendata *cd;
187  s4 disp;
188 
189  /* get required compiler data */
190 
191  cd = jd->cd;
192 
193  if (IS_INMEMORY(dst->flags)) {
194  COUNT_SPILLS;
195 
196  disp = dst->vv.regoff;
197 
198  switch (dst->type) {
199  case TYPE_INT:
200  case TYPE_ADR:
201  M_IST(d, REG_SP, disp);
202  break;
203  case TYPE_LNG:
204  M_LST(d, REG_SP, disp);
205  break;
206  case TYPE_FLT:
207  M_FST(d, REG_SP, disp);
208  break;
209  case TYPE_DBL:
210  M_DST(d, REG_SP, disp);
211  break;
212  default:
213  vm_abort("emit_store: unknown type %d", dst->type);
214  break;
215  }
216  }
217 }
218 
219 
220 /* emit_copy *******************************************************************
221 
222  Generates a register/memory to register/memory copy.
223 
224 *******************************************************************************/
225 
226 void emit_copy(jitdata *jd, instruction *iptr)
227 {
228  codegendata *cd;
229  varinfo *src;
230  varinfo *dst;
231  s4 s1, d;
232 
233  /* get required compiler data */
234 
235  cd = jd->cd;
236 
237  /* get source and destination variables */
238 
239  src = VAROP(iptr->s1);
240  dst = VAROP(iptr->dst);
241 
242  if ((src->vv.regoff != dst->vv.regoff) ||
243  (IS_INMEMORY(src->flags ^ dst->flags))) {
244 
245  if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
246  /* emit nothing, as the value won't be used anyway */
247  return;
248  }
249 
250  /* If one of the variables resides in memory, we can eliminate
251  the register move from/to the temporary register with the
252  order of getting the destination register and the load. */
253 
254  if (IS_INMEMORY(src->flags)) {
255  if (IS_LNG_TYPE(src->type))
256  d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
257  else
258  d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
259 
260  s1 = emit_load(jd, iptr, src, d);
261  }
262  else {
263  if (IS_LNG_TYPE(src->type))
264  s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
265  else
266  s1 = emit_load(jd, iptr, src, REG_IFTMP);
267 
268  d = codegen_reg_of_var(iptr->opc, dst, s1);
269  }
270 
271  if (s1 != d) {
272  switch (src->type) {
273  case TYPE_INT:
274  case TYPE_ADR:
275  M_MOV(s1, d);
276  break;
277  case TYPE_LNG:
278  M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d));
280  break;
281  case TYPE_FLT:
282  case TYPE_DBL:
283  M_FMOV(s1, d);
284  break;
285  default:
286  vm_abort("emit_copy: unknown type %d", src->type);
287  break;
288  }
289  }
290 
291  emit_store(jd, iptr, dst, d);
292  }
293 }
294 
295 
296 /* emit_iconst *****************************************************************
297 
298  XXX
299 
300 *******************************************************************************/
301 
302 void emit_iconst(codegendata *cd, s4 d, s4 value)
303 {
304  s4 disp;
305 
306  if ((value >= -32768) && (value <= 32767))
307  M_LDA_INTERN(d, REG_ZERO, value);
308  else {
309  disp = dseg_add_s4(cd, value);
310  M_ILD(d, REG_PV, disp);
311  }
312 }
313 
314 
315 /**
316  * Emits code updating the condition register by comparing one integer
317  * register to an immediate integer value.
318  */
319 void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
320 {
321  int32_t disp;
322 
323  if ((value >= -32768) && (value <= 32767)) {
324  M_CMPI(reg, value);
325  }
326  else {
327  assert(reg != REG_ITMP2);
328  disp = dseg_add_s4(cd, value);
329  M_ILD(REG_ITMP2, REG_PV, disp);
330  M_CMP(reg, REG_ITMP2);
331  }
332 }
333 
334 
335 /* emit_branch *****************************************************************
336 
337  Emits the code for conditional and unconditional branchs.
338 
339 *******************************************************************************/
340 
341 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
342 {
343  s4 checkdisp;
344  s4 branchdisp;
345 
346  /* calculate the different displacements */
347 
348  checkdisp = disp + 4;
349  branchdisp = (disp - 4) >> 2;
350 
351  /* check which branch to generate */
352 
353  if (condition == BRANCH_UNCONDITIONAL) {
354  /* check displacement for overflow */
355 
356  if ((checkdisp < (s4) 0xfe000000) || (checkdisp > (s4) 0x01fffffc)) {
357  /* if the long-branches flag isn't set yet, do it */
358 
360  cd->flags |= (CODEGENDATA_FLAG_ERROR |
362  }
363 
364  vm_abort("emit_branch: emit unconditional long-branch code");
365  }
366  else {
367  M_BR(branchdisp);
368  }
369  }
370  else {
371  /* and displacement for overflow */
372 
373  if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
374  /* if the long-branches flag isn't set yet, do it */
375 
377  cd->flags |= (CODEGENDATA_FLAG_ERROR |
379  }
380 
381  // Subtract 1 instruction from the displacement as the
382  // actual branch is the second instruction.
383  checkdisp = checkdisp - 4;
384  branchdisp = branchdisp - 1;
385 
386  if ((checkdisp < (int32_t) 0xfe000000) || (checkdisp > (int32_t) 0x01fffffc)) {
387  vm_abort("emit_branch: emit conditional long-branch code");
388  }
389  else {
390  switch (condition) {
391  case BRANCH_EQ:
392  M_BNE(1);
393  M_BR(branchdisp);
394  break;
395  case BRANCH_NE:
396  M_BEQ(1);
397  M_BR(branchdisp);
398  break;
399  case BRANCH_LT:
400  M_BGE(1);
401  M_BR(branchdisp);
402  break;
403  case BRANCH_GE:
404  M_BLT(1);
405  M_BR(branchdisp);
406  break;
407  case BRANCH_GT:
408  M_BLE(1);
409  M_BR(branchdisp);
410  break;
411  case BRANCH_LE:
412  M_BGT(1);
413  M_BR(branchdisp);
414  break;
415  case BRANCH_NAN:
416  vm_abort("emit_branch: long BRANCH_NAN");
417  break;
418  default:
419  vm_abort("emit_branch: unknown condition %d", condition);
420  break;
421  }
422  }
423  }
424  else {
425  switch (condition) {
426  case BRANCH_EQ:
427  M_BEQ(branchdisp);
428  break;
429  case BRANCH_NE:
430  M_BNE(branchdisp);
431  break;
432  case BRANCH_LT:
433  M_BLT(branchdisp);
434  break;
435  case BRANCH_GE:
436  M_BGE(branchdisp);
437  break;
438  case BRANCH_GT:
439  M_BGT(branchdisp);
440  break;
441  case BRANCH_LE:
442  M_BLE(branchdisp);
443  break;
444  case BRANCH_NAN:
445  M_BNAN(branchdisp);
446  break;
447  default:
448  vm_abort("emit_branch: unknown condition %d", condition);
449  break;
450  }
451  }
452  }
453 }
454 
455 
456 /* emit_arithmetic_check *******************************************************
457 
458  Emit an ArithmeticException check.
459 
460 *******************************************************************************/
461 
463 {
464  if (INSTRUCTION_MUST_CHECK(iptr)) {
465  M_TST(reg);
466  M_BNE(1);
468  }
469 }
470 
471 
472 /* emit_arrayindexoutofbounds_check ********************************************
473 
474  Emit a ArrayIndexOutOfBoundsException check.
475 
476 *******************************************************************************/
477 
479 {
480  if (INSTRUCTION_MUST_CHECK(iptr)) {
482  M_TRAPGEU(s2, REG_ITMP3);
483  }
484 }
485 
486 
487 /* emit_arraystore_check *******************************************************
488 
489  Emit an ArrayStoreException check.
490 
491 *******************************************************************************/
492 
494 {
495  if (INSTRUCTION_MUST_CHECK(iptr)) {
496  M_TST(REG_RESULT);
497  M_BNE(1);
499  }
500 }
501 
502 
503 /* emit_classcast_check ********************************************************
504 
505  Emit a ClassCastException check.
506 
507 *******************************************************************************/
508 
509 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
510 {
511  if (INSTRUCTION_MUST_CHECK(iptr)) {
512  switch (condition) {
513  case BRANCH_LE:
514  M_BGT(1);
515  break;
516  case BRANCH_EQ:
517  M_BNE(1);
518  break;
519  case BRANCH_NE:
520  M_BEQ(1);
521  break;
522  case BRANCH_GT:
523  M_BLE(1);
524  break;
525  default:
526  vm_abort("emit_classcast_check: unknown condition %d", condition);
527  break;
528  }
530  }
531 }
532 
533 
534 /* emit_nullpointer_check ******************************************************
535 
536  Emit a NullPointerException check.
537 
538 *******************************************************************************/
539 
541 {
542  if (INSTRUCTION_MUST_CHECK(iptr)) {
543  M_TST(reg);
544  M_BNE(1);
546  }
547 }
548 
549 
550 /* emit_exception_check ********************************************************
551 
552  Emit an Exception check.
553 
554 *******************************************************************************/
555 
557 {
558  if (INSTRUCTION_MUST_CHECK(iptr)) {
559  M_TST(REG_RESULT);
560  M_BNE(1);
562  }
563 }
564 
565 
566 /* emit_trap_compiler **********************************************************
567 
568  Emit a trap instruction which calls the JIT compiler.
569 
570 *******************************************************************************/
571 
573 {
575 }
576 
578 {
580 }
581 
582 
583 /* emit_trap *******************************************************************
584 
585  Emit a trap instruction and return the original machine code.
586 
587 *******************************************************************************/
588 
589 uint32_t emit_trap(codegendata *cd)
590 {
591  // Get machine code which is patched back in later. The rap is 1
592  // instruction word long.
593  uint32_t mcode = *((uint32_t*) cd->mcodeptr);
594 
595  M_ILLEGAL;
596 
597  return mcode;
598 }
599 
600 
601 /**
602  * Emit code to recompute the procedure vector.
603  */
605 {
606  int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
607 
608  M_MFLR(REG_ITMP1);
609  M_LDA(REG_PV, REG_ITMP1, -disp);
610 }
611 
612 
613 /**
614  * Generates synchronization code to enter a monitor.
615  */
616 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
617 {
618  int32_t p;
619  int32_t disp;
620 
621  // Get required compiler data.
622  methodinfo* m = jd->m;
623  codegendata* cd = jd->cd;
624 
625 # if !defined(NDEBUG)
628 
629  for (p = 0; p < INT_ARG_CNT; p++)
631 
632  for (p = 0; p < FLT_ARG_CNT; p++)
633  M_DST(abi_registers_float_argument[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8);
634 
635  syncslot_offset += (LA_SIZE_IN_POINTERS + ARG_CNT) * 8;
636  }
637 # endif
638 
640  M_ALD(REG_ITMP3, REG_PV, disp);
642 
643  /* get or test the lock object */
644 
645  if (m->flags & ACC_STATIC) {
646  disp = dseg_add_address(cd, &m->clazz->object.header);
647  M_ALD(REG_A0, REG_PV, disp);
648  }
649  else {
650  M_TST(REG_A0);
651  M_BNE(1);
653  }
654 
655  M_AST(REG_A0, REG_SP, syncslot_offset);
656  M_JSR;
657 
658 # if !defined(NDEBUG)
660  for (p = 0; p < INT_ARG_CNT; p++)
662 
663  for (p = 0; p < FLT_ARG_CNT; p++)
664  M_DLD(abi_registers_float_argument[p], REG_SP, LA_SIZE + (INT_ARG_CNT + p) * 8);
665 
667  }
668 # endif
669 }
670 
671 
672 /**
673  * Generates synchronization code to leave a monitor.
674  */
675 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
676 {
677  int32_t disp;
678 
679  // Get required compiler data.
680  methodinfo* m = jd->m;
681  codegendata* cd = jd->cd;
682 
684  M_ALD(REG_ITMP3, REG_PV, disp);
686 
687  /* we need to save the proper return value */
688 
689  methoddesc* md = m->parseddesc;
690 
691  switch (md->returntype.type) {
692  case TYPE_LNG:
693  M_IST(REG_RESULT2, REG_SP, syncslot_offset + 8);
694  /* fall through */
695  case TYPE_INT:
696  case TYPE_ADR:
697  M_IST(REG_RESULT , REG_SP, syncslot_offset + 4);
698  break;
699  case TYPE_FLT:
700  case TYPE_DBL:
701  M_DST(REG_FRESULT, REG_SP, syncslot_offset + 4);
702  break;
703  case TYPE_VOID:
704  break;
705  default:
706  assert(false);
707  break;
708  }
709 
710  M_ALD(REG_A0, REG_SP, syncslot_offset);
711  M_JSR;
712 
713  /* and now restore the proper return value */
714 
715  switch (md->returntype.type) {
716  case TYPE_LNG:
717  M_ILD(REG_RESULT2, REG_SP, syncslot_offset + 8);
718  /* fall through */
719  case TYPE_INT:
720  case TYPE_ADR:
721  M_ILD(REG_RESULT , REG_SP, syncslot_offset + 4);
722  break;
723  case TYPE_FLT:
724  case TYPE_DBL:
725  M_DLD(REG_FRESULT, REG_SP, syncslot_offset + 4);
726  break;
727  case TYPE_VOID:
728  break;
729  default:
730  assert(false);
731  break;
732  }
733 }
734 
735 
736 /**
737  * Emit profiling code for method frequency counting.
738  */
739 #if defined(ENABLE_PROFILING)
740 void emit_profile_method(codegendata* cd, codeinfo* code)
741 {
743  M_ALD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
745  M_AST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
746 }
747 #endif
748 
749 
750 /**
751  * Emit profiling code for basicblock frequency counting.
752  */
753 #if defined(ENABLE_PROFILING)
754 void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
755 {
756  int32_t disp = dseg_add_address(cd, code->bbfrequency);
757 
758  M_ALD(REG_ITMP2, REG_PV, disp);
759  M_ALD(REG_ITMP3, REG_ITMP2, bptr->nr * 4);
761  M_AST(REG_ITMP3, REG_ITMP2, bptr->nr * 4);
762 }
763 #endif
764 
765 
766 /**
767  * Emit profiling code to start CPU cycle counting.
768  */
769 #if defined(ENABLE_PROFILING)
770 void emit_profile_cycle_start(codegendata* cd, codeinfo* code)
771 {
772  // XXX Not implemented yet!
773 }
774 #endif
775 
776 
777 /**
778  * Emit profiling code to stop CPU cycle counting.
779  */
780 #if defined(ENABLE_PROFILING)
781 void emit_profile_cycle_stop(codegendata* cd, codeinfo* code)
782 {
783  // XXX Not implemented yet!
784 }
785 #endif
786 
787 
788 /* emit_verbosecall_enter ******************************************************
789 
790  Generates the code for the call trace.
791 
792 *******************************************************************************/
793 
795 {
796 #if !defined(NDEBUG)
797  methodinfo *m;
798  codegendata *cd;
799  registerdata *rd;
800  methoddesc *md;
801  int32_t disp;
802  int32_t i;
803  int32_t s, d;
804 
806  return;
807 
808  /* get required compiler data */
809 
810  m = jd->m;
811  cd = jd->cd;
812  rd = jd->rd;
813 
814  md = m->parseddesc;
815 
816  /* mark trace code */
817 
818  M_NOP;
819 
820  /* On Darwin we need to allocate an additional 3*4 bytes of stack
821  for the arguments to trace_java_call_enter, we make it 2*8. */
822 
823  M_MFLR(REG_ZERO);
825  M_STWU(REG_SP, REG_SP, -(LA_SIZE + (2 + ARG_CNT + TMP_CNT) * 8));
826 
827  /* save argument registers */
828 
829  for (i = 0; i < md->paramcount; i++) {
830  if (!md->params[i].inmemory) {
831  s = md->params[i].regoff;
832  d = LA_SIZE + (i + 2) * 8;
833 
834  switch (md->paramtypes[i].type) {
835  case TYPE_INT:
836  case TYPE_ADR:
837  M_IST(s, REG_SP, d);
838  break;
839  case TYPE_LNG:
840  M_LST(s, REG_SP, d);
841  break;
842  case TYPE_FLT:
843  M_FST(s, REG_SP, d);
844  break;
845  case TYPE_DBL:
846  M_DST(s, REG_SP, d);
847  break;
848  default:
849  assert(false);
850  break;
851  }
852  }
853  }
854 
855  /* pass methodinfo and pointers to the tracer function */
856 
857  disp = dseg_add_address(cd, m);
858  M_ALD(REG_A0, REG_PV, disp);
859  M_AADD_IMM(REG_SP, LA_SIZE + 2 * 8, REG_A1);
861 
863  M_ALD(REG_ITMP2, REG_PV, disp);
865  M_JSR;
866 
867  /* restore argument registers */
868 
869  for (i = 0; i < md->paramcount; i++) {
870  if (!md->params[i].inmemory) {
871  s = LA_SIZE + (i + 2) * 8;
872  d = md->params[i].regoff;
873 
874  switch (md->paramtypes[i].type) {
875  case TYPE_INT:
876  case TYPE_ADR:
877  M_ILD(d, REG_SP, s);
878  break;
879  case TYPE_LNG:
880  M_LLD(d, REG_SP, s);
881  break;
882  case TYPE_FLT:
883  M_FLD(d, REG_SP, s);
884  break;
885  case TYPE_DBL:
886  M_DLD(d, REG_SP, s);
887  break;
888  default:
889  assert(false);
890  break;
891  }
892  }
893  }
894 
896  M_MTLR(REG_ZERO);
897  M_LDA(REG_SP, REG_SP, LA_SIZE + (2 + ARG_CNT + TMP_CNT) * 8);
898 
899  /* mark trace code */
900 
901  M_NOP;
902 #endif /* !defined(NDEBUG) */
903 }
904 
905 
906 /* emit_verbosecall_exit *******************************************************
907 
908  Generates the code for the call trace.
909 
910 *******************************************************************************/
911 
913 {
914 #if !defined(NDEBUG)
915  methodinfo *m;
916  codegendata *cd;
917  registerdata *rd;
918  methoddesc *md;
919  s4 disp;
920 
922  return;
923 
924  /* get required compiler data */
925 
926  m = jd->m;
927  cd = jd->cd;
928  rd = jd->rd;
929 
930  md = m->parseddesc;
931 
932  /* mark trace code */
933 
934  M_NOP;
935 
936  /* On Darwin we need to allocate an additional 2*4 bytes of stack
937  for the arguments to trace_java_call_exit, we make it 1*8. */
938 
939  M_MFLR(REG_ZERO);
941  M_STWU(REG_SP, REG_SP, -(LA_SIZE + (1 + 1) * 8));
942 
943  /* save return value */
944 
945  switch (md->returntype.type) {
946  case TYPE_INT:
947  case TYPE_ADR:
948  M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
949  break;
950  case TYPE_LNG:
952  break;
953  case TYPE_FLT:
954  M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
955  break;
956  case TYPE_DBL:
957  M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
958  break;
959  case TYPE_VOID:
960  break;
961  default:
962  assert(false);
963  break;
964  }
965 
966  disp = dseg_add_address(cd, m);
967  M_ALD(REG_A0, REG_PV, disp);
968  M_AADD_IMM(REG_SP, LA_SIZE + 1 * 8, REG_A1);
969 
971  M_ALD(REG_ITMP2, REG_PV, disp);
973  M_JSR;
974 
975  /* restore return value */
976 
977  switch (md->returntype.type) {
978  case TYPE_INT:
979  case TYPE_ADR:
980  M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
981  break;
982  case TYPE_LNG:
984  break;
985  case TYPE_FLT:
986  M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
987  break;
988  case TYPE_DBL:
989  M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
990  break;
991  case TYPE_VOID:
992  break;
993  default:
994  assert(false);
995  break;
996  }
997 
998  M_ALD(REG_ZERO, REG_SP, LA_SIZE + (1 + 1) * 8 + LA_LR_OFFSET);
999  M_MTLR(REG_ZERO);
1000  M_LDA(REG_SP, REG_SP, LA_SIZE + (1 + 1) * 8);
1001 
1002  /* mark trace code */
1003 
1004  M_NOP;
1005 #endif /* !defined(NDEBUG) */
1006 }
1007 
1008 
1009 /*
1010  * These are local overrides for various environment variables in Emacs.
1011  * Please do not remove this and leave it at the end of the file, where
1012  * Emacs will automagically detect them.
1013  * ---------------------------------------------------------------------
1014  * Local variables:
1015  * mode: c++
1016  * indent-tabs-mode: t
1017  * c-basic-offset: 4
1018  * tab-width: 4
1019  * End:
1020  * vim:noexpandtab:sw=4:ts=4:
1021  */
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 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 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 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
#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_TRAPGEU(a, b)
Definition: codegen.hpp:256
#define M_CMPI(a, b)
Definition: codegen.hpp:208
#define LA_LR_OFFSET
Definition: md-abi.hpp:97
#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
#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
#define M_ILLEGAL
Definition: codegen.hpp:176
#define M_FMOV(b, c)
Definition: codegen.hpp:341
#define REG_IFTMP
Definition: md-abi.hpp:69
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
void emit_exception_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:447
#define GET_LOW_REG(a)
#define M_MFLR(a)
Definition: codegen.hpp:224
void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
Definition: trace.cpp:149
#define M_BNAN(a)
Definition: codegen.hpp:202
#define LA_SIZE
Definition: md-abi.hpp:93
s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:174
dst_operand_t dst
#define LOCK_monitor_enter
Definition: builtin.hpp:124
classinfo * clazz
Definition: method.hpp:80
#define M_MTLR(a)
Definition: codegen.hpp:227
#define M_MTCTR(a)
Definition: codegen.hpp:226
#define ARG_CNT
Definition: abi-asm.hpp:41
#define M_STWU(a, b, disp)
Definition: codegen.hpp:338
#define BRANCH_GE
#define M_ALD_INTERN(a, b, disp)
Definition: codegen.hpp:207
#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
#define CodeinfoPointer
s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:66
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
#define M_AST(a, b, disp)
Definition: codegen.hpp:350
#define BRANCH_NAN
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
#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
#define IS_LNG_TYPE(a)
Definition: global.hpp:135
uint32_t u4
Definition: types.hpp:46
#define BRANCH_LT
#define M_BGT(off)
Definition: codegen.hpp:485
methoddesc * parseddesc
Definition: method.hpp:78
#define VAROP(v)
Definition: jit.hpp:251
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
#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
s4 nr
Definition: jit.hpp:312
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 REG_ZERO
Definition: md-abi.hpp:54
void emit_iconst(codegendata *cd, s4 d, s4 value)
Definition: emit.cpp:220
#define REG_RESULT2
Definition: md-abi.hpp:37
#define M_LDA_INTERN(a, b, disp)
Definition: codegen.hpp:161
#define M_LLD(a, b, disp)
Definition: codegen.hpp:344
#define REG_ITMP3
Definition: md-abi.hpp:48
#define M_BLE(off)
Definition: codegen.hpp:487
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 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 LA_SIZE_IN_POINTERS
Definition: md-abi.hpp:95
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