CACAO
emit.cpp
Go to the documentation of this file.
1 /* src/vm/jit/sparc64/emit.cpp - SPARC 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 
34 #include "vm/jit/sparc64/emit.hpp"
35 
36 #include "mm/memory.hpp"
37 
38 #include "vm/descriptor.hpp" // for typedesc, methoddesc, etc
39 #include "vm/options.hpp"
40 
41 #include "vm/jit/abi.hpp"
42 #include "vm/jit/abi-asm.hpp"
43 #include "vm/jit/asmpart.hpp"
44 #include "vm/jit/builtin.hpp"
45 #include "vm/jit/code.hpp"
47 #include "vm/jit/dseg.hpp"
48 #include "vm/jit/emit-common.hpp"
49 #include "vm/jit/jit.hpp"
51 #include "vm/jit/replace.hpp"
52 #include "vm/jit/trace.hpp"
53 #include "vm/jit/trap.hpp"
54 
56 
58 
59 
60 /* how to leaf optimization in the emitted stubs?? */
61 #define REG_PV REG_PV_CALLEE
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 = JITSTACK + src->vv.regoff;
84 
85  switch(src->type)
86  {
87  case TYPE_INT:
88  case TYPE_LNG:
89  case TYPE_ADR:
90  M_LDX(tempreg, REG_SP, disp);
91  break;
92  case TYPE_FLT:
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_store ******************************************************************
111 
112  Emits a possible store to variable.
113 
114 *******************************************************************************/
115 
116 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
117 {
118  codegendata *cd;
119  s4 disp;
120 
121  /* get required compiler data */
122 
123  cd = jd->cd;
124 
125  if (dst->flags & INMEMORY) {
126  COUNT_WRITE_SPILLS(dst)
127 
128  disp = JITSTACK + dst->vv.regoff;
129 
130  switch(dst->type)
131  {
132  case TYPE_INT:
133  case TYPE_LNG:
134  case TYPE_ADR:
135  M_STX(d, REG_SP, disp);
136  break;
137  case TYPE_FLT:
138  case TYPE_DBL:
139  M_DST(d, REG_SP, disp);
140  break;
141  default:
142  vm_abort("emit_store: unknown type %d", dst->type);
143  break;
144  }
145  }
146 }
147 
148 
149 /* emit_copy *******************************************************************
150 
151  Generates a register/memory to register/memory copy.
152 
153 *******************************************************************************/
154 
155 void emit_copy(jitdata *jd, instruction *iptr)
156 {
157  codegendata *cd;
158  varinfo *src;
159  varinfo *dst;
160  s4 s1, d;
161 
162  /* get required compiler data */
163 
164  cd = jd->cd;
165 
166  /* get source and destination variables */
167 
168  src = VAROP(iptr->s1);
169  dst = VAROP(iptr->dst);
170 
171  if ((src->vv.regoff != dst->vv.regoff) ||
172  ((src->flags ^ dst->flags) & INMEMORY)) {
173 
174  if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
175  /* emit nothing, as the value won't be used anyway */
176  return;
177  }
178 
179  /* If one of the variables resides in memory, we can eliminate
180  the register move from/to the temporary register with the
181  order of getting the destination register and the load. */
182 
183  if (IS_INMEMORY(src->flags)) {
184  d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
185  s1 = emit_load(jd, iptr, src, d);
186  }
187  else {
188  s1 = emit_load(jd, iptr, src, REG_IFTMP);
189  d = codegen_reg_of_var(iptr->opc, dst, s1);
190  }
191 
192  if (s1 != d) {
193  switch(src->type) {
194  case TYPE_INT:
195  case TYPE_LNG:
196  case TYPE_ADR:
197  M_MOV(s1, d);
198  break;
199  case TYPE_FLT:
200  case TYPE_DBL:
201  M_DMOV(s1, d);
202  break;
203  default:
204  vm_abort("emit_copy: unknown type %d", src->type);
205  break;
206  }
207  }
208 
209  emit_store(jd, iptr, dst, d);
210  }
211 }
212 
213 
214 /* emit_iconst *****************************************************************
215 
216  XXX
217 
218 *******************************************************************************/
219 
220 void emit_iconst(codegendata *cd, s4 d, s4 value)
221 {
222  s4 disp;
223 
224  if ((value >= -4096) && (value <= 4095)) {
225  M_XOR_IMM(REG_ZERO, value, d);
226  } else {
227  disp = dseg_add_s4(cd, value);
228  M_ILD(d, REG_PV_CALLEE, disp);
229  }
230 }
231 
232 
233 /* emit_lconst *****************************************************************
234 
235  XXX
236 
237 *******************************************************************************/
238 
239 void emit_lconst(codegendata *cd, s4 d, s8 value)
240 {
241  s4 disp;
242 
243  if ((value >= -4096) && (value <= 4095)) {
244  M_XOR_IMM(REG_ZERO, value, d);
245  } else {
246  disp = dseg_add_s8(cd, value);
247  M_LDX(d, REG_PV_CALLEE, disp);
248  }
249 }
250 
251 
252 /**
253  * Emits code updating the condition register by comparing one integer
254  * register to an immediate integer value.
255  */
256 void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
257 {
258  if ((value >= -4096) && (value <= 4095)) {
259  M_CMP_IMM(reg, value);
260  } else {
261  assert(reg != REG_ITMP2);
262  ICONST(REG_ITMP2, value);
263  M_CMP(reg, REG_ITMP2);
264  }
265 }
266 
267 
268 /* emit_branch *****************************************************************
269 
270  Emits the code for conditional and unconditional branchs.
271 
272 *******************************************************************************/
273 
274 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
275 {
276  s4 branchdisp;
277 
278  /* calculate the different displacements */
279 
280  branchdisp = disp >> 2;
281 
282  /* check which branch to generate */
283 
284  if (condition == BRANCH_UNCONDITIONAL) {
285  /* check displacement for overflow (19-bit)*/
286 
287  if ((branchdisp < (s4) 0xfffc0000) || (branchdisp > (s4) 0x003ffff)) {
288  /* if the long-branches flag isn't set yet, do it */
289 
291  cd->flags |= (CODEGENDATA_FLAG_ERROR |
293  }
294 
295  vm_abort("emit_branch: emit unconditional long-branch code");
296  }
297  else {
298  M_BR(branchdisp);
299  M_NOP;
300  }
301  }
302  else if (reg == -1) {
303  /* branch on condition codes */
304 
305  /* check displacement for overflow (19-bit)*/
306 
307  if ((branchdisp < (s4) 0xfffc0000) || (branchdisp > (s4) 0x003ffff)) {
308  /* if the long-branches flag isn't set yet, do it */
309 
311  log_println("setting error");
312  cd->flags |= (CODEGENDATA_FLAG_ERROR |
314  }
315 
316  vm_abort("emit_branch: emit long-branch on cc code");
317  }
318  else {
319  /* check whether to branch on 64-bit condition code */
320  if (BRANCH_CHECKS_XCC(opt)) {
321  switch (condition) {
322  case BRANCH_EQ:
323  M_XBEQ(branchdisp);
324  break;
325  case BRANCH_NE:
326  M_XBNE(branchdisp);
327  break;
328  case BRANCH_LT:
329  M_XBLT(branchdisp);
330  break;
331  case BRANCH_GE:
332  M_XBGE(branchdisp);
333  break;
334  case BRANCH_GT:
335  M_XBGT(branchdisp);
336  break;
337  case BRANCH_LE:
338  M_XBLE(branchdisp);
339  break;
340  case BRANCH_UGT:
341  M_XBUGT(branchdisp);
342  break;
343  case BRANCH_ULT:
344  M_XBULT(branchdisp);
345  break;
346  default:
347  vm_abort("emit_branch: unknown condition %d", condition);
348  break;
349  }
350 
351  /* branch delay */
352  M_NOP;
353  }
354  else {
355  switch (condition) {
356  case BRANCH_EQ:
357  M_BEQ(branchdisp);
358  break;
359  case BRANCH_NE:
360  M_BNE(branchdisp);
361  break;
362  case BRANCH_LT:
363  M_BLT(branchdisp);
364  break;
365  case BRANCH_GE:
366  M_BGE(branchdisp);
367  break;
368  case BRANCH_GT:
369  M_BGT(branchdisp);
370  break;
371  case BRANCH_LE:
372  M_BLE(branchdisp);
373  break;
374  case BRANCH_UGT:
375  M_BUGT(branchdisp);
376  break;
377  case BRANCH_ULT:
378  M_BULT(branchdisp);
379  break;
380  default:
381  vm_abort("emit_branch: unknown condition %d", condition);
382  break;
383  }
384 
385  /* branch delay */
386  M_NOP;
387  }
388  }
389  }
390  else {
391  /* branch on register */
392 
393  /* check displacement for overflow (16-bit) */
394 
395  if ((branchdisp < (s4) 0xffff8000) || (branchdisp > (s4) 0x0007fff)) {
396  /* if the long-branches flag isn't set yet, do it */
397 
399  log_println("setting error");
400  cd->flags |= (CODEGENDATA_FLAG_ERROR |
402  }
403 
404  vm_abort("emit_branch: emit long-branch on reg code");
405  }
406  else {
407  switch (condition) {
408  case BRANCH_EQ:
409  M_BEQZ(reg, branchdisp);
410  break;
411  case BRANCH_NE:
412  M_BNEZ(reg, branchdisp);
413  break;
414  case BRANCH_LT:
415  M_BLTZ(reg, branchdisp);
416  break;
417  case BRANCH_GE:
418  M_BGEZ(reg, branchdisp);
419  break;
420  case BRANCH_GT:
421  M_BGTZ(reg, branchdisp);
422  break;
423  case BRANCH_LE:
424  M_BLEZ(reg, branchdisp);
425  break;
426  default:
427  vm_abort("emit_branch: unknown condition %d", condition);
428  break;
429  }
430 
431  /* branch delay */
432  M_NOP;
433  }
434  }
435 }
436 
437 
438 /* emit_bxx_xcc*****************************************************************
439 
440  Wrappers for branches on 64-bit condition codes (SPARC specific).
441 
442 *******************************************************************************/
443 
445 {
446  emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_XCC);
447 }
448 
450 {
451  emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_XCC);
452 }
453 
455 {
456  emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_XCC);
457 }
458 
460 {
461  emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_XCC);
462 }
463 
465 {
466  emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_XCC);
467 }
468 
470 {
471  emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_XCC);
472 }
473 
474 
475 
476 
477 
478 /* emit_arithmetic_check *******************************************************
479 
480  Emit an ArithmeticException check.
481 
482 *******************************************************************************/
483 
485 {
486  if (INSTRUCTION_MUST_CHECK(iptr)) {
487  M_BNEZ(reg, 3);
488  M_NOP;
490  }
491 }
492 
493 
494 /* emit_arrayindexoutofbounds_check ********************************************
495 
496  Emit an ArrayIndexOutOfBoundsException check.
497 
498 *******************************************************************************/
499 
501 {
502  if (INSTRUCTION_MUST_CHECK(iptr)) {
504  M_CMP(s2, REG_ITMP3);
505  M_XBULT(3);
506  M_NOP;
508  }
509 }
510 
511 
512 /* emit_arraystore_check *******************************************************
513 
514  Emit an ArrayStoreException check.
515 
516 *******************************************************************************/
517 
519 {
520  if (INSTRUCTION_MUST_CHECK(iptr)) {
522  M_NOP;
524  }
525 }
526 
527 
528 /* emit_classcast_check ********************************************************
529 
530  Emit a ClassCastException check.
531 
532 *******************************************************************************/
533 
534 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
535 {
536 /* XXX: use 64-bit or 32-bit compares??? */
537 
538  if (INSTRUCTION_MUST_CHECK(iptr)) {
539  switch (condition) {
540  case ICMD_IFEQ:
541  M_BNEZ(reg, 3);
542  break;
543 
544  case ICMD_IFLE:
545  M_BGTZ(reg, 3);
546  break;
547 
548  case BRANCH_ULT:
549  M_XBUGE(3);
550  break;
551 
552  default:
553  vm_abort("emit_classcast_check: unknown condition %d", condition);
554  break;
555  }
556 
557  M_NOP;
559  }
560 }
561 
562 
563 /* emit_nullpointer_check ******************************************************
564 
565  Emit a NullPointerException check.
566 
567 *******************************************************************************/
568 
570 {
571  if (INSTRUCTION_MUST_CHECK(iptr)) {
572  M_BNEZ(reg, 3);
573  M_NOP;
575  }
576 }
577 
578 
579 /* emit_exception_check ********************************************************
580 
581  Emit an Exception check.
582 
583 *******************************************************************************/
584 
586 {
587  if (INSTRUCTION_MUST_CHECK(iptr)) {
589  M_NOP;
591  }
592 }
593 
594 
595 /* emit_trap *******************************************************************
596 
597  Emit a trap instruction and return the original machine code.
598 
599 *******************************************************************************/
600 
601 uint32_t emit_trap(codegendata *cd)
602 {
603  uint32_t mcode;
604 
605  /* Get machine code which is patched back in later. The
606  trap is 1 instruction word long. */
607 
608  mcode = *((uint32_t *) cd->mcodeptr);
609 
611 
612  return mcode;
613 }
614 
615 
616 /**
617  * Emit code to recompute the procedure vector.
618  */
620 {
621  int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
622 
623  /* REG_RA holds the value of the jmp instruction, therefore +8 */
624  M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
625 }
626 
627 
628 /**
629  * Generates synchronization code to enter a monitor.
630  */
631 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
632 {
633  int32_t i, slots;
634  int32_t disp;
635 
636  // Get required compiler data.
637  methodinfo* m = jd->m;
638  codegendata* cd = jd->cd;
639 
640 # if !defined(NDEBUG)
642  /* save float argument registers */
643 
644  /* XXX jit-c-call */
645  slots = FLT_ARG_CNT;
646  ALIGN_STACK_SLOTS(slots);
647 
648  M_LDA(REG_SP, REG_SP, -(slots * 8));
649  for (i = 0; i < FLT_ARG_CNT; i++)
651 
652  syncslot_offset += slots * 8;
653  }
654 # endif
655 
656  /* get correct lock object */
657 
658  if (m->flags & ACC_STATIC) {
659  disp = dseg_add_address(cd, &m->clazz->object.header);
660  M_ALD(REG_OUT0, REG_PV, disp);
662  M_ALD(REG_ITMP3, REG_PV, disp);
663  }
664  else {
665  /* copy class pointer: $i0 -> $o0 */
667  M_BNEZ(REG_OUT0, 3);
669  M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
671  }
672 
674  M_AST(REG_OUT0, REG_SP, CSTACK + syncslot_offset); /* branch delay */
675 
676 # if !defined(NDEBUG)
678  /* restore float argument registers */
679 
680  for (i = 0; i < FLT_ARG_CNT; i++)
682 
683  M_LDA(REG_SP, REG_SP, slots * 8);
684  }
685 # endif
686 }
687 
688 
689 /**
690  * Generates synchronization code to leave a monitor.
691  */
692 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
693 {
694  int32_t disp;
695 
696  // Get required compiler data.
697  methodinfo* m = jd->m;
698  codegendata* cd = jd->cd;
699 
700  /* XXX jit-c-call */
702  M_ALD(REG_ITMP3, REG_PV, disp);
703 
704  /* we need to save fp return value (int saved by window) */
705 
706  methoddesc* md = m->parseddesc;
707 
708  switch (md->returntype.type) {
709  case TYPE_FLT:
710  case TYPE_DBL:
711  M_ALD(REG_OUT0, REG_SP, CSTACK + syncslot_offset);
713  M_DST(REG_FRESULT, REG_SP, CSTACK + syncslot_offset); /* delay */
714 
715  /* restore the fp return value */
716 
717  M_DLD(REG_FRESULT, REG_SP, CSTACK + syncslot_offset);
718  break;
719  case TYPE_INT:
720  case TYPE_LNG:
721  case TYPE_DBL:
722  default:
724  M_ALD(REG_OUT0, REG_SP, CSTACK + syncslot_offset); /* delay */
725  break;
726  case TYPE_VOID:
727  break;
728  default:
729  assert(false);
730  break;
731  }
732 }
733 
734 
735 /* emit_patcher_stubs **********************************************************
736 
737  Generates the code for the patcher stubs.
738 
739 *******************************************************************************/
740 
742 {
743  codegendata *cd;
744  patchref *pref;
745  u4 mcode[2];
746  u1 *savedmcodeptr;
747  u1 *tmpmcodeptr;
748  s4 targetdisp;
749  s4 disp;
750 
751  /* get required compiler data */
752 
753  cd = jd->cd;
754 
755  /* generate code patching stub call code */
756 
757  targetdisp = 0;
758 
759  for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
760  /* check code segment size */
761 
762  MCODECHECK(100);
763 
764  /* Get machine code which is patched back in later. The
765  call is 2 instruction words long. */
766 
767  tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
768 
769  /* We use 2 loads here as an unaligned 8-byte read on 64-bit
770  SPARC causes a SIGSEGV */
771 
772  mcode[0] = ((u4 *) tmpmcodeptr)[0];
773  mcode[1] = ((u4 *) tmpmcodeptr)[1];
774 
775  /* Patch in the call to call the following code (done at
776  compile time). */
777 
778  savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
779  cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
780 
781  disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) );
782 
783  if ((disp < (s4) 0xfffc0000) || (disp > (s4) 0x003ffff)) {
784  vm_abort("Jump offset is out of range: %d > +/-%d",
785  disp, 0x003ffff);
786  return;
787  }
788 
789  M_BR(disp);
790  M_NOP;
791 
792  cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
793 
794  /* extend stack frame for wrapper data */
795 
796  M_ASUB_IMM(REG_SP, 6 * 8, REG_SP);
797 
798  /* calculate return address and move it onto the stack */
799 
800  M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
801  M_AST(REG_ITMP3, REG_SP, JITSTACK + 5 * 8);
802 
803  /* move pointer to java_objectheader onto stack */
804 
805  /* create a virtual java_objectheader */
806 
807  (void) dseg_add_unique_address(cd, NULL); /* flcword */
808  (void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
809  disp = dseg_add_unique_address(cd, NULL); /* vftbl */
810 
811  M_LDA(REG_ITMP3, REG_PV, disp);
812  M_AST(REG_ITMP3, REG_SP, JITSTACK + 4 * 8);
813 
814  /* move machine code onto stack */
815 
816  disp = dseg_add_s4(cd, mcode[0]);
817  M_ILD(REG_ITMP3, REG_PV, disp);
818  M_IST(REG_ITMP3, REG_SP, JITSTACK + 3 * 8);
819 
820  disp = dseg_add_s4(cd, mcode[1]);
821  M_ILD(REG_ITMP3, REG_PV, disp);
822  M_IST(REG_ITMP3, REG_SP, JITSTACK + 3 * 8 + 4);
823 
824  /* move class/method/field reference onto stack */
825 
826  disp = dseg_add_address(cd, pref->ref);
827  M_ALD(REG_ITMP3, REG_PV, disp);
828  M_AST(REG_ITMP3, REG_SP, JITSTACK + 2 * 8);
829 
830  /* move data segment displacement onto stack */
831 
832  disp = dseg_add_s4(cd, pref->disp);
833  M_ILD(REG_ITMP3, REG_PV, disp);
834  M_IST(REG_ITMP3, REG_SP, JITSTACK + 1 * 8);
835 
836  /* move patcher function pointer onto stack */
837 
838  disp = dseg_add_functionptr(cd, pref->patcher);
839  M_ALD(REG_ITMP3, REG_PV, disp);
840  M_AST(REG_ITMP3, REG_SP, JITSTACK + 0 * 8);
841 
842  if (targetdisp == 0) {
843  targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
844 
846  M_ALD(REG_ITMP3, REG_PV, disp);
848  M_NOP;
849  }
850  else {
851  disp = (((u4 *) cd->mcodebase) + targetdisp) -
852  (((u4 *) cd->mcodeptr));
853 
854  M_BR(disp);
855  M_NOP;
856  }
857  }
858 }
859 
860 
861 /* emit_verbosecall_enter ******************************************************
862 
863  Generates the code for the call trace.
864 
865 *******************************************************************************/
866 
867 #if !defined(NDEBUG)
869 {
870  methodinfo *m;
871  codegendata *cd;
872  registerdata *rd;
873  methoddesc *md;
874  s4 disp;
875  s4 i, t;
876  s4 stackslots;
877 
878  /* get required compiler data */
879 
880  m = jd->m;
881  cd = jd->cd;
882  rd = jd->rd;
883 
884  md = m->parseddesc;
885 
886  /* mark trace code */
887 
888  M_NOP;
889 
890  /* XXX jit-c-call */
891  stackslots = 1 + FLT_ARG_CNT;
892  ALIGN_STACK_SLOTS(stackslots);
893 
894  M_LDA(REG_SP, REG_SP, -(stackslots * 8));
895 
896  /* save float argument registers */
897 
898  for (i = 0; i < FLT_ARG_CNT; i++)
900 
901  /* save temporary registers for leaf methods */
902 /* XXX no leaf optimization yet
903  if (code_is_leafmethod(code)) {
904  for (i = 0; i < INT_TMP_CNT; i++)
905  M_LST(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
906 
907  for (i = 0; i < FLT_TMP_CNT; i++)
908  M_DST(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
909  }
910 */
911  /* load int/float arguments into integer argument registers */
912 
913  for (i = 0; i < md->paramcount && i < INT_NATARG_CNT; i++) {
914  t = md->paramtypes[i].type;
915 
916  /* all available argument registers used, which adds a little complexity */
917 
918  if (IS_INT_LNG_TYPE(t)) {
919  if (i < INT_ARG_CNT) {
922  }
923  else {
924  assert(i == 5);
926  }
927  }
928  else {
929  if (i < FLT_ARG_CNT) {
930 
931  /* reg -> mem -> reg */
932 
933  if (IS_2_WORD_TYPE(t)) {
936  }
937  else {
940  }
941  }
942  else {
943 
944  /* mem -> reg */
945 
946  assert(i == 5);
947  if (IS_2_WORD_TYPE(t)) {
949  }
950  else {
952  }
953  }
954  }
955  }
956 
957 
958  /* method info pointer is passed via stack */
959  disp = dseg_add_address(cd, m);
960  M_ALD(REG_ITMP1, REG_PV_CALLEE, disp);
962  disp = dseg_add_functionptr(cd, builtin_verbosecall_enter);
963  M_ALD(REG_ITMP1, REG_PV_CALLEE, disp);
965  M_NOP;
966 
967  /* restore float argument registers */
968 
969  for (i = 0; i < FLT_ARG_CNT; i++)
971 
972  /* restore temporary registers for leaf methods */
973 /* XXX no leaf optimization yet
974  if (code_is_leafmethod(code)) {
975  for (i = 0; i < INT_TMP_CNT; i++)
976  M_LLD(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
977 
978  for (i = 0; i < FLT_TMP_CNT; i++)
979  M_DLD(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
980  }
981 */
982  M_LDA(REG_SP, REG_SP, stackslots * 8);
983 
984  /* mark trace code */
985 
986  M_NOP;
987 }
988 #endif /* !defined(NDEBUG) */
989 
990 
991 /* emit_verbosecall_exit *******************************************************
992 
993  Generates the code for the call trace.
994 
995 *******************************************************************************/
996 
997 #if !defined(NDEBUG)
999 {
1000  methodinfo *m;
1001  codegendata *cd;
1002  registerdata *rd;
1003  s4 disp;
1004 
1005  /* get required compiler data */
1006 
1007  m = jd->m;
1008  cd = jd->cd;
1009  rd = jd->rd;
1010 
1011  /* mark trace code */
1012 
1013  M_NOP;
1014 
1015  /* XXX jit-c-call (keep stack aligned)*/
1016  M_LDA(REG_SP, REG_SP, -(2 * 8));
1017 
1019 
1021  M_DMOV(REG_FRESULT, 1); /* logical dreg 1 => f2 */
1022  M_FMOV(REG_FRESULT, 2); /* logical freg 2 => f5 */
1023 
1024  disp = dseg_add_functionptr(cd, m);
1025  M_ALD(REG_OUT3, REG_PV_CALLEE, disp);
1026 
1028  M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
1030  M_NOP;
1031 
1033 
1034  M_LDA(REG_SP, REG_SP, 2 * 8);
1035 
1036  /* mark trace code */
1037 
1038  M_NOP;
1039 }
1040 #endif /* !defined(NDEBUG) */
1041 
1042 
1043 /*
1044  * These are local overrides for various environment variables in Emacs.
1045  * Please do not remove this and leave it at the end of the file, where
1046  * Emacs will automagically detect them.
1047  * ---------------------------------------------------------------------
1048  * Local variables:
1049  * mode: c++
1050  * indent-tabs-mode: t
1051  * c-basic-offset: 4
1052  * tab-width: 4
1053  * End:
1054  * vim:noexpandtab:sw=4:ts=4:
1055  */
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 REG_RESULT_CALLEE
Definition: md-abi.hpp:38
union varinfo::@19 vv
dummy_java_lang_Class object
Definition: class.hpp:88
#define REG_RA_CALLER
Definition: md-abi.hpp:42
#define M_ALD(a, b, disp)
Definition: codegen.hpp:345
#define REG_WINDOW_TRANSPOSE(reg)
Definition: md-abi.hpp:123
#define M_BGTZ(a, disp)
Definition: codegen.hpp:257
#define INT_NATARG_CNT
Definition: md-abi.hpp:100
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
void emit_ble_xcc(codegendata *cd, basicblock *target)
Definition: emit.cpp:469
#define M_XBULT(disp)
Definition: codegen.hpp:513
#define BRANCH_LE
#define JITDATA_HAS_FLAG_VERBOSECALL(jd)
Definition: jit.hpp:227
#define REG_OUT3
Definition: md-abi.hpp:66
void emit_bne_xcc(codegendata *cd, basicblock *target)
Definition: emit.cpp:449
#define M_BEQ(off)
Definition: codegen.hpp:482
#define M_ILD(a, b, disp)
Definition: codegen.hpp:347
s4 dseg_add_unique_address(codegendata *cd, void *value)
Definition: dseg.cpp:525
#define M_CMP(a, b)
Definition: codegen.hpp:430
#define IS_INT_LNG_TYPE(a)
Definition: global.hpp:130
#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 M_LDA(a, b, disp)
Definition: codegen.hpp:163
#define BRANCH_GT
#define ALIGN_STACK_SLOTS(slots)
Definition: codegen.hpp:90
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
void emit_bgt_xcc(codegendata *cd, basicblock *target)
Definition: emit.cpp:464
#define REG_OUT0
Definition: md-abi.hpp:63
s4 dseg_add_address(codegendata *cd, void *value)
Definition: dseg.cpp:542
#define M_BEQZ(a, disp)
Definition: codegen.hpp:252
#define M_XBGT(disp)
Definition: codegen.hpp:507
#define REG_FRESULT
Definition: md-abi.hpp:59
s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
#define BRANCH_UNCONDITIONAL
#define dseg_add_functionptr(cd, value)
Definition: dseg.hpp:39
codegendata * cd
Definition: jit.hpp:129
#define M_XBUGE(disp)
Definition: codegen.hpp:511
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
#define REG_PV
Definition: emit.cpp:61
#define M_STX(rd, rs, disp)
Definition: codegen.hpp:465
void emit_patcher_stubs(jitdata *jd)
Definition: emit.cpp:741
void emit_arraystore_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:380
#define M_FST(a, b, disp)
Definition: codegen.hpp:357
void asm_patcher_wrapper(void)
#define REG_FP
Definition: md-abi.hpp:60
uint8_t u1
Definition: types.hpp:40
#define M_LDX(rd, rs, disp)
Definition: codegen.hpp:432
Type type
Definition: reg.hpp:44
#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)
int64_t s8
Definition: types.hpp:48
void log_println(const char *text,...)
Definition: logging.cpp:193
#define CODEGENDATA_FLAG_LONGBRANCHES
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
Definition: reg.hpp:43
void emit_bge_xcc(codegendata *cd, basicblock *target)
Definition: emit.cpp:459
void emit_recompute_pv(codegendata *cd)
Emit code to recompute the procedure vector.
Definition: emit.cpp:495
#define M_FMOV(b, c)
Definition: codegen.hpp:341
#define REG_IFTMP
Definition: md-abi.hpp:69
void emit_blt_xcc(codegendata *cd, basicblock *target)
Definition: emit.cpp:454
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
#define M_CMP_IMM(a, i)
Definition: codegen.hpp:446
void emit_exception_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:447
#define M_XBUGT(disp)
Definition: codegen.hpp:512
#define CSTACK
Definition: md-abi.hpp:118
void emit_lconst(codegendata *cd, s4 d, s8 value)
Definition: emit.cpp:233
#define M_BULT(disp)
Definition: codegen.hpp:526
dst_operand_t dst
#define M_XOR_IMM(a, b, c)
Definition: codegen.hpp:300
#define LOCK_monitor_enter
Definition: builtin.hpp:124
#define M_BUGT(disp)
Definition: codegen.hpp:525
classinfo * clazz
Definition: method.hpp:80
#define M_JMP(a, b)
Definition: codegen.hpp:259
#define BRANCH_GE
void emit_beq_xcc(codegendata *cd, basicblock *target)
Definition: emit.cpp:444
#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
#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
#define REG_RESULT_CALLER
Definition: md-abi.hpp:39
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
#define M_XBLE(disp)
Definition: codegen.hpp:510
registerdata * rd
Definition: jit.hpp:130
#define M_AST(a, b, disp)
Definition: codegen.hpp:350
#define JITSTACK
Definition: md-abi.hpp:117
#define COUNT_READ_SPILLS(x)
Definition: jit.hpp:109
#define BRANCH_CHECKS_XCC(options)
Definition: emit-arch.hpp:38
void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:346
#define LOCK_monitor_exit
Definition: builtin.hpp:132
#define M_MOV(a, b)
Definition: codegen.hpp:340
#define COUNT_WRITE_SPILLS(x)
Definition: jit.hpp:110
#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
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
#define FLT_ARG_CNT
Definition: md-abi.hpp:81
void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
Definition: builtin.cpp:1224
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
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
#define M_XBGE(disp)
Definition: codegen.hpp:509
void emit_iconst(codegendata *cd, s4 d, s4 value)
Definition: emit.cpp:220
#define BRANCH_ULT
BeginInst * target
#define REG_ITMP3
Definition: md-abi.hpp:48
#define MCODECHECK(icnt)
Definition: codegen.hpp:40
#define M_BLE(off)
Definition: codegen.hpp:487
#define BRANCH_OPT_XCC
Definition: emit-arch.hpp:34
s4 flags
Definition: method.hpp:70
#define M_XBLT(disp)
Definition: codegen.hpp:508
#define REG_PV_CALLEE
Definition: md-abi.hpp:44
#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_XBNE(disp)
Definition: codegen.hpp:506
#define M_DLD(a, b, disp)
Definition: codegen.hpp:353
void emit_verbosecall_exit(jitdata *jd)
Definition: emit.cpp:766
#define REG_OUT5
Definition: md-abi.hpp:68
#define M_BNEZ(a, disp)
Definition: codegen.hpp:255
#define OFFSET(s, el)
Definition: memory.hpp:90
#define INSTRUCTION_MUST_CHECK(iptr)
#define M_BR(disp)
Definition: codegen.hpp:250
#define M_INTMOVE(a, b)
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:431
#define M_XBEQ(disp)
Definition: codegen.hpp:505
#define M_BLTZ(a, disp)
Definition: codegen.hpp:253
#define REG_ITMP1
Definition: md-abi.hpp:46
#define M_DMOV(b, c)
Definition: codegen.hpp:342