CACAO
emit.cpp
Go to the documentation of this file.
1 /* src/vm/jit/aarch64/emit.cpp - Aarch64 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 #include "vm/types.hpp"
28 
29 #include <cassert>
30 #include <stdint.h>
31 
32 #include "md-abi.hpp"
33 
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"
53 #include "vm/jit/replace.hpp"
54 #include "vm/jit/trace.hpp"
55 #include "vm/jit/trap.hpp"
56 
58 
59 
60 /* emit_load *******************************************************************
61 
62  Emits a possible load of an operand.
63 
64 *******************************************************************************/
65 
66 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
67 {
68  AsmEmitter asme(jd->cd);
69  s4 disp;
70  s4 reg;
71 
72  if (IS_INMEMORY(src->flags)) {
74 
75  disp = src->vv.regoff;
76 
77  switch (src->type) {
78  case TYPE_INT:
79  asme.ild(tempreg, REG_SP, disp);
80  break;
81  case TYPE_LNG:
82  asme.lld(tempreg, REG_SP, disp);
83  break;
84  case TYPE_ADR:
85  asme.ald(tempreg, REG_SP, disp);
86  break;
87  case TYPE_FLT:
88  asme.fld(tempreg, REG_SP, disp);
89  break;
90  case TYPE_DBL:
91  asme.dld(tempreg, REG_SP, disp);
92  break;
93  default:
94  vm_abort("emit_load: unknown type %d", src->type);
95  break;
96  }
97 
98  reg = tempreg;
99  }
100  else
101  reg = src->vv.regoff;
102 
103  return reg;
104 }
105 
106 
107 /* emit_store ******************************************************************
108 
109  Emit a possible store for the given variable.
110 
111 *******************************************************************************/
112 
113 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
114 {
115  AsmEmitter asme(jd->cd);
116  s4 disp;
117 
118  if (IS_INMEMORY(dst->flags)) {
119  COUNT_SPILLS;
120 
121  disp = dst->vv.regoff;
122 
123  switch (dst->type) {
124  case TYPE_INT:
125  asme.ist(d, REG_SP, disp);
126  break;
127  case TYPE_LNG:
128  asme.lst(d, REG_SP, disp);
129  break;
130  case TYPE_ADR:
131  asme.ast(d, REG_SP, disp);
132  break;
133  case TYPE_FLT:
134  asme.fst(d, REG_SP, disp);
135  break;
136  case TYPE_DBL:
137  asme.dst(d, REG_SP, disp);
138  break;
139  default:
140  vm_abort("emit_store: unknown type %d", dst->type);
141  break;
142  }
143  }
144 }
145 
146 
147 /* emit_copy *******************************************************************
148 
149  Generates a register/memory to register/memory copy.
150 
151 *******************************************************************************/
152 
153 void emit_copy(jitdata *jd, instruction *iptr)
154 {
155  codegendata *cd;
156  varinfo *src;
157  varinfo *dst;
158  s4 s1, d;
159 
160  /* get required compiler data */
161 
162  cd = jd->cd;
163 
164  /* get source and destination variables */
165 
166  src = VAROP(iptr->s1);
167  dst = VAROP(iptr->dst);
168 
169  if ((src->vv.regoff != dst->vv.regoff) ||
170  ((src->flags ^ dst->flags) & INMEMORY)) {
171 
172  if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
173  /* emit nothing, as the value won't be used anyway */
174  return;
175  }
176 
177  /* If one of the variables resides in memory, we can eliminate
178  the register move from/to the temporary register with the
179  order of getting the destination register and the load. */
180 
181  if (IS_INMEMORY(src->flags)) {
182  d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
183  s1 = emit_load(jd, iptr, src, d);
184  }
185  else {
186  s1 = emit_load(jd, iptr, src, REG_IFTMP);
187  d = codegen_reg_of_var(iptr->opc, dst, s1);
188  }
189 
190  if (s1 != d) {
191  switch (src->type) {
192  case TYPE_INT:
193  case TYPE_LNG:
194  case TYPE_ADR:
195  M_MOV(s1, d);
196  break;
197  case TYPE_FLT:
198  M_FMOV(s1, d);
199  break;
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  AsmEmitter asme(cd);
223  asme.iconst(d, value);
224 }
225 
226 
227 /* emit_lconst *****************************************************************
228 
229  XXX
230 
231 *******************************************************************************/
232 
233 void emit_lconst(codegendata *cd, s4 d, s8 value)
234 {
235  AsmEmitter asme(cd);
236  asme.lconst(d, value);
237 }
238 
239 
240 /**
241  * Emits code comparing a single register
242  */
243 void emit_icmp_imm(codegendata* cd, int reg, int32_t value) {
244  AsmEmitter asme(cd);
245 
246  if (value >= 0 && value <= 4095) {
247  asme.icmp_imm(reg, value);
248  } else if ((-value) >= 0 && (-value) <= 4095) {
249  asme.icmn_imm(reg, -value);
250  } else {
251  asme.iconst(REG_ITMP2, value);
252  asme.icmp(reg, REG_ITMP2);
253  }
254 }
255 
256 
257 /* emit_branch *****************************************************************
258 
259  Emits the code for conditional and unconditional branchs.
260 
261 *******************************************************************************/
262 
263 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
264 {
265  s4 checkdisp;
266  s4 branchdisp;
267  AsmEmitter asme(cd);
268 
269  /* calculate the different displacements */
270 
271  checkdisp = disp;
272  branchdisp = disp >> 2;
273 
274  /* check which branch to generate */
275 
276  if (condition == BRANCH_UNCONDITIONAL) {
277  /* check displacement for overflow */
278 
279  if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
280  /* if the long-branches flag isn't set yet, do it */
281 
283  log_println("setting error");
284  cd->flags |= (CODEGENDATA_FLAG_ERROR |
286  }
287 
288  vm_abort("emit_branch: emit unconditional long-branch code");
289  }
290  else {
291  asme.b(branchdisp);
292  }
293  }
294  else {
295  /* and displacement for overflow */
296 
297  if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
298  /* if the long-branches flag isn't set yet, do it */
299 
301  log_println("setting error");
302  cd->flags |= (CODEGENDATA_FLAG_ERROR |
304  }
305 
306  vm_abort("emit_branch: emit conditional long-branch code");
307  }
308  else {
309  switch (condition) {
310  case BRANCH_EQ:
311  asme.b_eq(branchdisp);
312  break;
313  case BRANCH_NE:
314  asme.b_ne(branchdisp);
315  break;
316  case BRANCH_LT:
317  asme.b_lt(branchdisp);
318  break;
319  case BRANCH_GE:
320  asme.b_ge(branchdisp);
321  break;
322  case BRANCH_GT:
323  asme.b_gt(branchdisp);
324  break;
325  case BRANCH_LE:
326  asme.b_le(branchdisp);
327  break;
328  case BRANCH_UGT:
329  asme.b_hi(branchdisp);
330  break;
331  default:
332  vm_abort("emit_branch: unknown condition %d", condition);
333  break;
334  }
335  }
336  }
337 }
338 
339 
340 /* emit_arithmetic_check *******************************************************
341 
342  Emit an ArithmeticException check.
343 
344 *******************************************************************************/
345 
347 {
348  if (INSTRUCTION_MUST_CHECK(iptr)) {
349  AsmEmitter asme(cd);
350  asme.cbnz(reg, 2);
352  }
353 }
354 
355 
356 /* emit_arrayindexoutofbounds_check ********************************************
357 
358  Emit an ArrayIndexOutOfBoundsException check.
359 
360 *******************************************************************************/
361 
363 {
364  if (INSTRUCTION_MUST_CHECK(iptr)) {
365  AsmEmitter asme(cd);
366  asme.ild(REG_ITMP3, s1, OFFSET(java_array_t, size));
367  asme.icmp(s2, REG_ITMP3);
368  asme.b_cc(2);
370  }
371 }
372 
373 
374 /* emit_arraystore_check *******************************************************
375 
376  Emit an ArrayStoreException check.
377 
378 *******************************************************************************/
379 
381 {
382  if (INSTRUCTION_MUST_CHECK(iptr)) {
383  AsmEmitter asme(cd);
384  asme.cbnz(REG_RESULT, 2);
386  }
387 }
388 
389 
390 /* emit_classcast_check ********************************************************
391 
392  Emit a ClassCastException check.
393 
394 *******************************************************************************/
395 
396 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
397 {
398  if (INSTRUCTION_MUST_CHECK(iptr)) {
399  AsmEmitter asme(cd);
400  switch (condition) {
401  case BRANCH_EQ:
402  asme.b_ne(2);
403  break;
404  case BRANCH_LE:
405  asme.b_gt(2);
406  break;
407  case BRANCH_NE:
408  asme.b_eq(2);
409  break;
410  case BRANCH_GT:
411  asme.b_le(2);
412  break;
413  case BRANCH_LT:
414  asme.b_ge(2);
415  break;
416  default:
417  vm_abort("emit_classcast_check: unknown condition %d", condition);
418  break;
419  }
421  }
422 }
423 
424 
425 /* emit_nullpointer_check ******************************************************
426 
427  Emit a NullPointerException check.
428 
429 *******************************************************************************/
430 
432 {
433  if (INSTRUCTION_MUST_CHECK(iptr)) {
434  AsmEmitter asme(cd);
435  asme.cbnz(reg, 2);
437  }
438 }
439 
440 
441 /* emit_exception_check ********************************************************
442 
443  Emit an Exception check.
444 
445 *******************************************************************************/
446 
448 {
449  if (INSTRUCTION_MUST_CHECK(iptr)) {
450  AsmEmitter asme(cd);
451  asme.cbnz(REG_RESULT, 2);
453  }
454 }
455 
456 
457 /* emit_trap_compiler **********************************************************
458 
459  Emit a trap instruction which calls the JIT compiler.
460 
461 *******************************************************************************/
462 
464 {
466 }
467 
469 {
471 }
472 
473 
474 /* emit_trap_countdown *********************************************************
475 
476  Emit a countdown trap
477 
478  counter....absolute address of the counter variable
479 
480 *******************************************************************************/
481 
482 void emit_trap_countdown(codegendata *cd, s4 *counter)
483 {
484  AsmEmitter asme(cd);
485  asme.lconst(REG_ITMP1, (s8) counter);
486 
487  // Simple load-sub-store loop
488  asme.ildxr(REG_ITMP2, REG_ITMP1);
489  asme.isub_imm(REG_ITMP2, REG_ITMP2, 1);
491  asme.icbnz(REG_ITMP3, -3);
492 
493  asme.icbnz(REG_ITMP2, 2);
495 }
496 
497 
498 /* emit_trap *******************************************************************
499 
500  Emit a trap instruction and return the original machine code.
501 
502 *******************************************************************************/
503 
504 uint32_t emit_trap(codegendata *cd)
505 {
506  /* Get machine code which is patched back in later. The
507  trap is 1 instruction word long. */
508  uint32_t mcode = *((uint32_t*) cd->mcodeptr);
509 
510  emit_trap(cd, 0, TRAP_PATCHER);
511 
512  return mcode;
513 }
514 
515 
516 /**
517  * Emit code to recompute the procedure vector.
518  */
520 {
521  int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
522 
523  AsmEmitter asme(cd);
524  asme.lda(REG_PV, REG_RA, -disp);
525 }
526 
527 
528 /**
529  * Generates synchronization code to enter a monitor.
530  */
531 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
532 {
533  int32_t p;
534  int32_t disp;
535 
536  // Get required compiler data.
537  methodinfo* m = jd->m;
538  codegendata* cd = jd->cd;
539  AsmEmitter asme(cd);
540 
541 #if !defined(NDEBUG)
543  asme.lda(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
544 
545  for (p = 0; p < INT_ARG_CNT; p++)
546  asme.lst(abi_registers_integer_argument[p], REG_SP, p * 8);
547 
548  for (p = 0; p < FLT_ARG_CNT; p++)
549  asme.dst(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
550 
551  syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
552  }
553 #endif /* !defined(NDEBUG) */
554 
555  /* decide which monitor enter function to call */
556 
557  if (m->flags & ACC_STATIC) {
558  disp = dseg_add_address(cd, &m->clazz->object.header);
559  asme.lld(REG_A0, REG_PV, disp);
560  }
561  else {
562  asme.cbnz(REG_A0, 2);
564  }
565 
566  asme.lst(REG_A0, REG_SP, syncslot_offset);
568  asme.lld(REG_PV, REG_PV, disp);
569  asme.blr(REG_PV);
570  emit_recompute_pv(cd);
571 
572 #if !defined(NDEBUG)
574  for (p = 0; p < INT_ARG_CNT; p++)
575  asme.lld(abi_registers_integer_argument[p], REG_SP, p * 8);
576 
577  for (p = 0; p < FLT_ARG_CNT; p++)
578  asme.dld(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
579 
580  asme.lda(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
581  }
582 #endif
583 }
584 
585 
586 /**
587  * Generates synchronization code to leave a monitor.
588  */
589 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
590 {
591  int32_t disp;
592 
593  // Get required compiler data.
594  methodinfo* m = jd->m;
595  codegendata* cd = jd->cd;
596  AsmEmitter asme(cd);
597 
598  methoddesc* md = m->parseddesc;
599 
600  switch (md->returntype.type) {
601  case TYPE_INT:
602  case TYPE_LNG:
603  case TYPE_ADR:
604  asme.lst(REG_RESULT, REG_SP, syncslot_offset + 8);
605  break;
606  case TYPE_FLT:
607  case TYPE_DBL:
608  asme.dst(REG_FRESULT, REG_SP, syncslot_offset + 8);
609  break;
610  case TYPE_VOID:
611  break;
612  default:
613  assert(false);
614  break;
615  }
616 
617  asme.lld(REG_A0, REG_SP, syncslot_offset);
619  asme.lld(REG_PV, REG_PV, disp);
620  asme.blr(REG_PV);
621  emit_recompute_pv(cd);
622 
623  switch (md->returntype.type) {
624  case TYPE_INT:
625  case TYPE_LNG:
626  case TYPE_ADR:
627  asme.lld(REG_RESULT, REG_SP, syncslot_offset + 8);
628  break;
629  case TYPE_FLT:
630  case TYPE_DBL:
631  asme.dld(REG_FRESULT, REG_SP, syncslot_offset + 8);
632  break;
633  case TYPE_VOID:
634  break;
635  default:
636  assert(false);
637  break;
638  }
639 }
640 
641 
642 /* emit_verbosecall_enter ******************************************************
643 
644  Generates the code for the call trace.
645 
646 *******************************************************************************/
647 
648 #if !defined(NDEBUG)
650 {
651  methodinfo *m;
652  codeinfo *code;
653  codegendata *cd;
654  registerdata *rd;
655  methoddesc *md;
656  int32_t stackframesize;
657  s4 disp;
658  s4 i, j, s;
659 
660  /* get required compiler data */
661 
662  m = jd->m;
663  code = jd->code;
664  cd = jd->cd;
665  rd = jd->rd;
666 
667  md = m->parseddesc;
668  AsmEmitter asme(cd);
669 
670  /* mark trace code */
671 
672  asme.nop();
673 
674  stackframesize = ARG_CNT + TMP_CNT + md->paramcount + 1;
675  stackframesize += stackframesize % 2;
676 
677  asme.lda(REG_SP, REG_SP, -(stackframesize * 8));
678  asme.ast(REG_RA, REG_SP, 0 * 8);
679 
680  /* save all argument and temporary registers for leaf methods */
681 
682  if (code_is_leafmethod(code)) {
683  j = 1 + md->paramcount;
684 
685  for (i = 0; i < INT_ARG_CNT; i++, j++)
686  asme.lst(abi_registers_integer_argument[i], REG_SP, j * 8);
687 
688  for (i = 0; i < FLT_ARG_CNT; i++, j++)
689  asme.dst(abi_registers_float_argument[i], REG_SP, j * 8);
690 
691  for (i = 0; i < INT_TMP_CNT; i++, j++)
692  asme.lst(rd->tmpintregs[i], REG_SP, j * 8);
693 
694  for (i = 0; i < FLT_TMP_CNT; i++, j++)
695  asme.dst(rd->tmpfltregs[i], REG_SP, j * 8);
696  }
697 
698  /* save argument registers */
699 
700  for (i = 0; i < md->paramcount; i++) {
701  if (!md->params[i].inmemory) {
702  s = md->params[i].regoff;
703 
704  switch (md->paramtypes[i].type) {
705  case TYPE_ADR:
706  case TYPE_INT:
707  case TYPE_LNG:
708  asme.lst(s, REG_SP, (1 + i) * 8);
709  break;
710  case TYPE_FLT:
711  case TYPE_DBL:
712  asme.dst(s, REG_SP, (1 + i) * 8);
713  break;
714  default:
715  assert(false);
716  break;
717  }
718  }
719  }
720 
721  disp = dseg_add_address(cd, m);
722  asme.lld(REG_A0, REG_PV, disp);
723  asme.ladd_imm(REG_A1, REG_SP, 1 * 8);
724  asme.lda(REG_A2, REG_SP, stackframesize * 8 + cd->stackframesize * 8);
725 
727  asme.lld(REG_PV, REG_PV, disp);
728  asme.blr(REG_PV);
729  disp = (s4) (cd->mcodeptr - cd->mcodebase);
730  asme.lda(REG_PV, REG_RA, -disp);
731  asme.lld(REG_RA, REG_SP, 0 * 8);
732 
733  /* restore argument registers */
734 
735  for (i = 0; i < md->paramcount; i++) {
736  if (!md->params[i].inmemory) {
737  s = md->params[i].regoff;
738 
739  switch (md->paramtypes[i].type) {
740  case TYPE_ADR:
741  case TYPE_INT:
742  case TYPE_LNG:
743  asme.lld(s, REG_SP, (1 + i) * 8);
744  break;
745  case TYPE_FLT:
746  case TYPE_DBL:
747  asme.dld(s, REG_SP, (1 + i) * 8);
748  break;
749  default:
750  assert(false);
751  break;
752  }
753  }
754  }
755 
756  /* restore all argument and temporary registers for leaf methods */
757 
758  if (code_is_leafmethod(code)) {
759  j = 1 + md->paramcount;
760 
761  for (i = 0; i < INT_ARG_CNT; i++, j++)
762  asme.lld(abi_registers_integer_argument[i], REG_SP, j * 8);
763 
764  for (i = 0; i < FLT_ARG_CNT; i++, j++)
765  asme.dld(abi_registers_float_argument[i], REG_SP, j * 8);
766 
767  for (i = 0; i < INT_TMP_CNT; i++, j++)
768  asme.lld(rd->tmpintregs[i], REG_SP, j * 8);
769 
770  for (i = 0; i < FLT_TMP_CNT; i++, j++)
771  asme.dld(rd->tmpfltregs[i], REG_SP, j * 8);
772  }
773 
774  asme.lda(REG_SP, REG_SP, stackframesize * 8);
775 
776  /* mark trace code */
777 
778  asme.nop();
779 }
780 #endif /* !defined(NDEBUG) */
781 
782 
783 /* emit_verbosecall_exit *******************************************************
784 
785  Generates the code for the call trace.
786 
787 *******************************************************************************/
788 
789 #if !defined(NDEBUG)
791 {
792  methodinfo *m;
793  codegendata *cd;
794  methoddesc *md;
795  s4 disp;
796 
797  /* get required compiler data */
798 
799  m = jd->m;
800  cd = jd->cd;
801 
802  md = m->parseddesc;
803  AsmEmitter asme(cd);
804 
805  /* mark trace code */
806 
807  asme.nop();
808 
809  asme.lsub_imm(REG_SP, REG_SP, 2 * 8);
810  asme.lst(REG_RA, REG_SP, 0 * 8);
811 
812  /* save return value */
813 
814  switch (md->returntype.type) {
815  case TYPE_ADR:
816  case TYPE_INT:
817  case TYPE_LNG:
818  asme.lst(REG_RESULT, REG_SP, 1 * 8);
819  break;
820  case TYPE_FLT:
821  case TYPE_DBL:
822  asme.dst(REG_FRESULT, REG_SP, 1 * 8);
823  break;
824  case TYPE_VOID:
825  break;
826  default:
827  assert(false);
828  break;
829  }
830 
831  disp = dseg_add_address(cd, m);
832  asme.lld(REG_A0, REG_PV, disp);
833  asme.ladd_imm(REG_A1, REG_SP, 1 * 8);
834 
836  asme.lld(REG_PV, REG_PV, disp);
837  asme.blr(REG_PV);
838  disp = (cd->mcodeptr - cd->mcodebase);
839  asme.lda(REG_PV, REG_RA, -disp);
840 
841  /* restore return value */
842 
843  switch (md->returntype.type) {
844  case TYPE_ADR:
845  case TYPE_INT:
846  case TYPE_LNG:
847  asme.lld(REG_RESULT, REG_SP, 1 * 8);
848  break;
849  case TYPE_FLT:
850  case TYPE_DBL:
851  asme.dld(REG_FRESULT, REG_SP, 1 * 8);
852  break;
853  case TYPE_VOID:
854  break;
855  default:
856  assert(false);
857  break;
858  }
859 
860  asme.lld(REG_RA, REG_SP, 0 * 8);
861  asme.ladd_imm(REG_SP, REG_SP, 2 * 8);
862 
863  /* mark trace code */
864 
865  asme.nop();
866 }
867 #endif /* !defined(NDEBUG) */
868 
869 
870 /*
871  * These are local overrides for various environment variables in Emacs.
872  * Please do not remove this and leave it at the end of the file, where
873  * Emacs will automagically detect them.
874  * ---------------------------------------------------------------------
875  * Local variables:
876  * mode: c++
877  * indent-tabs-mode: t
878  * c-basic-offset: 4
879  * tab-width: 4
880  * End:
881  * vim:noexpandtab:sw=4:ts=4:
882  */
const s4 abi_registers_float_argument[]
Definition: md-abi.cpp:107
#define REG_SP
Definition: md-abi.hpp:55
#define CODEGENDATA_FLAG_ERROR
java_object_t header
Definition: class.hpp:73
union varinfo::@19 vv
#define REG_PV
Definition: md-abi.hpp:42
dummy_java_lang_Class object
Definition: class.hpp:88
void icmp(u1 wn, u1 wm)
Definition: codegen.hpp:100
void icbnz(u1 wn, s4 imm)
Definition: codegen.hpp:203
#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:589
#define REG_A0
Definition: md-abi.hpp:35
paramdesc * params
Definition: descriptor.hpp:164
#define BRANCH_LE
void ast(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:122
#define JITDATA_HAS_FLAG_VERBOSECALL(jd)
Definition: jit.hpp:234
#define BRANCH_NE
#define BRANCH_GT
void emit_monitor_enter(jitdata *jd, int32_t syncslot_offset)
Generates synchronization code to enter a monitor.
Definition: emit.cpp:531
void emit_trap_countdown(codegendata *cd, s4 *counter)
Definition: emit.cpp:482
#define BRANCH_EQ
const s4 abi_registers_integer_argument[]
Definition: md-abi.cpp:64
s4 dseg_add_address(codegendata *cd, void *value)
Definition: dseg.cpp:542
codeinfo * code
Definition: jit.hpp:128
#define REG_FRESULT
Definition: md-abi.hpp:61
s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
#define BRANCH_UNCONDITIONAL
void lconst(u1 xt, s8 value)
Definition: codegen.hpp:151
#define dseg_add_functionptr(cd, value)
Definition: dseg.hpp:39
codegendata * cd
Definition: jit.hpp:129
#define REG_A2
Definition: md-abi.hpp:37
void b(s4 imm)
Definition: codegen.hpp:182
void icmp_imm(u1 wd, u2 imm)
Definition: codegen.hpp:95
int * tmpfltregs
Definition: reg.hpp:72
void b_eq(s4 imm)
Definition: codegen.hpp:183
void emit_arraystore_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:380
#define COUNT_SPILLS
Definition: jit.hpp:108
void cbnz(u1 xn, s4 imm)
Definition: codegen.hpp:202
void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
Definition: trace.cpp:240
Type type
Definition: reg.hpp:44
void fld(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:111
void blr(u1 xn)
Definition: codegen.hpp:198
void lst(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:121
#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)
void ald(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:109
int64_t s8
Definition: types.hpp:48
void b_ne(s4 imm)
Definition: codegen.hpp:184
void ist(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:120
void log_println(const char *text,...)
Definition: logging.cpp:193
#define CODEGENDATA_FLAG_LONGBRANCHES
void b_gt(s4 imm)
Definition: codegen.hpp:195
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:519
void emit_abstractmethoderror_trap(codegendata *cd)
Definition: emit.cpp:468
static int code_is_leafmethod(codeinfo *code)
Definition: code.hpp:150
#define M_FMOV(b, c)
Definition: codegen.hpp:347
#define REG_IFTMP
Definition: md-abi.hpp:71
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
s4 regoff
Definition: reg.hpp:47
void b_lt(s4 imm)
Definition: codegen.hpp:194
void emit_verbosecall_enter(jitdata *jd)
Definition: emit.cpp:649
typedesc paramtypes[1]
Definition: descriptor.hpp:167
void emit_exception_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:447
void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
Definition: trace.cpp:149
void ladd_imm(u1 xd, u1 xn, u4 imm)
Definition: codegen.hpp:207
#define FLT_TMP_CNT
Definition: md-abi.hpp:84
void emit_lconst(codegendata *cd, s4 d, s8 value)
Definition: emit.cpp:233
dst_operand_t dst
void dld(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:112
#define LOCK_monitor_enter
Definition: builtin.hpp:124
classinfo * clazz
Definition: method.hpp:80
#define OFFSET(s, el)
Definition: memory.hpp:90
#define ARG_CNT
Definition: abi-asm.hpp:41
#define BRANCH_GE
void b_ge(s4 imm)
Definition: codegen.hpp:193
void b_le(s4 imm)
Definition: codegen.hpp:196
#define INT_ARG_CNT
Definition: md-abi.hpp:76
void emit_trap_compiler(codegendata *cd)
Definition: emit.cpp:463
void lsub_imm(u1 xd, u1 xn, u4 imm)
Definition: codegen.hpp:218
void emit_trap(codegendata *cd, u1 Xd, int type)
Definition: emit-asm.hpp:582
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
int32_t s4
Definition: types.hpp:45
void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
Definition: emit.cpp:113
void b_cc(s4 imm)
Definition: codegen.hpp:186
registerdata * rd
Definition: jit.hpp:130
void isub_imm(u1 xd, u1 xn, u4 imm)
Definition: codegen.hpp:217
#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:346
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
uint32_t u4
Definition: types.hpp:46
#define BRANCH_LT
#define INT_TMP_CNT
Definition: md-abi.hpp:77
void b_hi(s4 imm)
Definition: codegen.hpp:191
void ild(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:107
void lda(u1 xd, u1 xn, s4 imm)
Definition: codegen.hpp:177
methoddesc * parseddesc
Definition: method.hpp:78
void icmn_imm(u1 wd, u2 imm)
Definition: codegen.hpp:97
#define VAROP(v)
Definition: jit.hpp:258
int * tmpintregs
Definition: reg.hpp:70
methodinfo * m
Definition: jit.hpp:127
void ildxr(u1 wt, u1 xn)
Definition: codegen.hpp:132
static bool IS_INMEMORY(s4 flags)
Definition: stack.hpp:51
void nop()
Definition: codegen.hpp:104
#define FLT_ARG_CNT
Definition: md-abi.hpp:83
s4 flags
Definition: reg.hpp:45
void iconst(u1 xt, s4 value)
Definition: codegen.hpp:135
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
int16_t s2
Definition: types.hpp:42
#define REG_ZERO
Definition: md-abi.hpp:56
void emit_iconst(codegendata *cd, s4 d, s4 value)
Definition: emit.cpp:220
void lld(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:108
#define REG_ITMP3
Definition: md-abi.hpp:48
s4 flags
Definition: method.hpp:70
void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
Definition: emit.cpp:362
void istxr(u1 ws, u1 wt, u1 xn)
Definition: codegen.hpp:133
void emit_verbosecall_exit(jitdata *jd)
Definition: emit.cpp:790
uint32_t regoff
Definition: descriptor.hpp:153
#define INSTRUCTION_MUST_CHECK(iptr)
#define REG_RESULT
Definition: md-abi.hpp:33
void fst(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:124
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:431
#define REG_ITMP1
Definition: md-abi.hpp:46
#define M_DMOV(b, c)
Definition: codegen.hpp:348
void dst(u1 xt, u1 xn, s4 imm)
Definition: codegen.hpp:125