1 /* src/vm/jit/alpha/emit.c - Alpha code emitter functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
34 #include "vm/jit/alpha/codegen.h"
36 #include "mm/memory.hpp"
38 #include "threads/lock.hpp"
40 #include "vm/options.h"
42 #include "vm/jit/abi.h"
43 #include "vm/jit/abi-asm.h"
44 #include "vm/jit/asmpart.h"
45 #include "vm/jit/dseg.h"
46 #include "vm/jit/emit-common.hpp"
47 #include "vm/jit/jit.hpp"
48 #include "vm/jit/patcher-common.hpp"
49 #include "vm/jit/replace.hpp"
50 #include "vm/jit/trace.hpp"
51 #include "vm/jit/trap.hpp"
54 /* emit_load *******************************************************************
56 Emits a possible load of an operand.
58 *******************************************************************************/
60 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
66 /* get required compiler data */
70 if (IS_INMEMORY(src->flags)) {
73 disp = src->vv.regoff;
79 M_LLD(tempreg, REG_SP, disp);
83 M_DLD(tempreg, REG_SP, disp);
86 vm_abort("emit_load: unknown type %d", src->type);
98 /* emit_store ******************************************************************
100 Emit a possible store for the given variable.
102 *******************************************************************************/
104 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
109 /* get required compiler data */
113 if (IS_INMEMORY(dst->flags)) {
116 disp = dst->vv.regoff;
122 M_LST(d, REG_SP, disp);
126 M_DST(d, REG_SP, disp);
129 vm_abort("emit_store: unknown type %d", dst->type);
135 /* emit_copy *******************************************************************
137 Generates a register/memory to register/memory copy.
139 *******************************************************************************/
141 void emit_copy(jitdata *jd, instruction *iptr)
148 /* get required compiler data */
152 /* get source and destination variables */
154 src = VAROP(iptr->s1);
155 dst = VAROP(iptr->dst);
157 if ((src->vv.regoff != dst->vv.regoff) ||
158 ((src->flags ^ dst->flags) & INMEMORY)) {
160 if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
161 /* emit nothing, as the value won't be used anyway */
165 /* If one of the variables resides in memory, we can eliminate
166 the register move from/to the temporary register with the
167 order of getting the destination register and the load. */
169 if (IS_INMEMORY(src->flags)) {
170 d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
171 s1 = emit_load(jd, iptr, src, d);
174 s1 = emit_load(jd, iptr, src, REG_IFTMP);
175 d = codegen_reg_of_var(iptr->opc, dst, s1);
190 vm_abort("emit_copy: unknown type %d", src->type);
194 emit_store(jd, iptr, dst, d);
199 /* emit_iconst *****************************************************************
203 *******************************************************************************/
205 void emit_iconst(codegendata *cd, s4 d, s4 value)
209 if ((value >= -32768) && (value <= 32767))
210 M_LDA_INTERN(d, REG_ZERO, value);
212 disp = dseg_add_s4(cd, value);
213 M_ILD(d, REG_PV, disp);
218 /* emit_lconst *****************************************************************
222 *******************************************************************************/
224 void emit_lconst(codegendata *cd, s4 d, s8 value)
228 if ((value >= -32768) && (value <= 32767))
229 M_LDA_INTERN(d, REG_ZERO, value);
231 disp = dseg_add_s8(cd, value);
232 M_LLD(d, REG_PV, disp);
238 * Emits code comparing one integer register to an immediate value.
240 void emit_icmpeq_imm(codegendata* cd, int reg, int32_t value, int d)
244 if ((value >= 0) && (value <= 255)) {
245 M_CMPEQ_IMM(reg, value, d);
247 assert(reg != REG_ITMP2);
248 if ((value >= -32768) && (value <= 32767)) {
249 M_LDA(REG_ITMP2, REG_ZERO, value);
251 disp = dseg_add_s4(cd, value);
252 M_ILD(REG_ITMP2, REG_PV, disp);
254 M_CMPEQ(reg, REG_ITMP2, d);
259 /* emit_branch *****************************************************************
261 Emits the code for conditional and unconditional branchs.
263 *******************************************************************************/
265 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
270 /* calculate the different displacements */
272 checkdisp = (disp - 4);
273 branchdisp = (disp - 4) >> 2;
275 /* check which branch to generate */
277 if (condition == BRANCH_UNCONDITIONAL) {
278 /* check displacement for overflow */
280 if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
281 /* if the long-branches flag isn't set yet, do it */
283 if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
284 log_println("setting error");
285 cd->flags |= (CODEGENDATA_FLAG_ERROR |
286 CODEGENDATA_FLAG_LONGBRANCHES);
289 vm_abort("emit_branch: emit unconditional long-branch code");
296 /* and displacement for overflow */
298 if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
299 /* if the long-branches flag isn't set yet, do it */
301 if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
302 log_println("setting error");
303 cd->flags |= (CODEGENDATA_FLAG_ERROR |
304 CODEGENDATA_FLAG_LONGBRANCHES);
307 vm_abort("emit_branch: emit conditional long-branch code");
312 M_BEQZ(reg, branchdisp);
315 M_BNEZ(reg, branchdisp);
318 M_BLTZ(reg, branchdisp);
321 M_BGEZ(reg, branchdisp);
324 M_BGTZ(reg, branchdisp);
327 M_BLEZ(reg, branchdisp);
330 vm_abort("emit_branch: unknown condition %d", condition);
337 /* emit_arithmetic_check *******************************************************
339 Emit an ArithmeticException check.
341 *******************************************************************************/
343 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
345 if (INSTRUCTION_MUST_CHECK(iptr)) {
347 /* Destination register must not be REG_ZERO, because then no
348 SIGSEGV is thrown. */
349 M_ALD_INTERN(reg, REG_ZERO, TRAP_ArithmeticException);
354 /* emit_arrayindexoutofbounds_check ********************************************
356 Emit an ArrayIndexOutOfBoundsException check.
358 *******************************************************************************/
360 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
362 if (INSTRUCTION_MUST_CHECK(iptr)) {
363 M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
364 M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
365 M_BNEZ(REG_ITMP3, 1);
366 M_ALD_INTERN(s2, REG_ZERO, TRAP_ArrayIndexOutOfBoundsException);
371 /* emit_arraystore_check *******************************************************
373 Emit an ArrayStoreException check.
375 *******************************************************************************/
377 void emit_arraystore_check(codegendata *cd, instruction *iptr)
379 if (INSTRUCTION_MUST_CHECK(iptr)) {
380 M_BNEZ(REG_RESULT, 1);
381 /* Destination register must not be REG_ZERO, because then no
382 SIGSEGV is thrown. */
383 M_ALD_INTERN(REG_RESULT, REG_ZERO, TRAP_ArrayStoreException);
388 /* emit_classcast_check ********************************************************
390 Emit a ClassCastException check.
392 *******************************************************************************/
394 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
396 if (INSTRUCTION_MUST_CHECK(iptr)) {
405 vm_abort("emit_classcast_check: unknown condition %d", condition);
407 M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
412 /* emit_nullpointer_check ******************************************************
414 Emit a NullPointerException check.
416 *******************************************************************************/
418 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
420 if (INSTRUCTION_MUST_CHECK(iptr)) {
422 /* Destination register must not be REG_ZERO, because then no
423 SIGSEGV is thrown. */
424 M_ALD_INTERN(reg, REG_ZERO, TRAP_NullPointerException);
429 /* emit_exception_check ********************************************************
431 Emit an Exception check.
433 *******************************************************************************/
435 void emit_exception_check(codegendata *cd, instruction *iptr)
437 if (INSTRUCTION_MUST_CHECK(iptr)) {
438 M_BNEZ(REG_RESULT, 1);
439 /* Destination register must not be REG_ZERO, because then no
440 SIGSEGV is thrown. */
441 M_ALD_INTERN(REG_RESULT, REG_ZERO, TRAP_CHECK_EXCEPTION);
446 /* emit_trap_compiler **********************************************************
448 Emit a trap instruction which calls the JIT compiler.
450 *******************************************************************************/
452 void emit_trap_compiler(codegendata *cd)
454 M_ALD_INTERN(REG_METHODPTR, REG_ZERO, TRAP_COMPILER);
458 /* emit_trap *******************************************************************
460 Emit a trap instruction and return the original machine code.
462 *******************************************************************************/
464 uint32_t emit_trap(codegendata *cd)
468 /* Get machine code which is patched back in later. The
469 trap is 1 instruction word long. */
471 mcode = *((uint32_t*) cd->mcodeptr);
473 // Generate a SIGILL.
481 * Emit code to recompute the procedure vector.
483 void emit_recompute_pv(codegendata *cd)
485 int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
487 M_LDA(REG_PV, REG_RA, -disp);
492 * Generates synchronization code to enter a monitor.
494 #if defined(ENABLE_THREADS)
495 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
500 // Get required compiler data.
501 methodinfo* m = jd->m;
502 codegendata* cd = jd->cd;
505 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
506 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
508 for (p = 0; p < INT_ARG_CNT; p++)
509 M_LST(abi_registers_integer_argument[p], REG_SP, p * 8);
511 for (p = 0; p < FLT_ARG_CNT; p++)
512 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
514 syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
516 #endif /* !defined(NDEBUG) */
518 /* decide which monitor enter function to call */
520 if (m->flags & ACC_STATIC) {
521 disp = dseg_add_address(cd, &m->clazz->object.header);
522 M_ALD(REG_A0, REG_PV, disp);
526 M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
529 M_AST(REG_A0, REG_SP, syncslot_offset);
530 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
531 M_ALD(REG_PV, REG_PV, disp);
532 M_JSR(REG_RA, REG_PV);
533 emit_recompute_pv(cd);
536 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
537 for (p = 0; p < INT_ARG_CNT; p++)
538 M_LLD(abi_registers_integer_argument[p], REG_SP, p * 8);
540 for (p = 0; p < FLT_ARG_CNT; p++)
541 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
543 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
551 * Generates synchronization code to leave a monitor.
553 #if defined(ENABLE_THREADS)
554 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
558 // Get required compiler data.
559 methodinfo* m = jd->m;
560 codegendata* cd = jd->cd;
562 M_ALD(REG_A0, REG_SP, syncslot_offset);
564 methoddesc* md = m->parseddesc;
566 switch (md->returntype.type) {
570 M_LST(REG_RESULT, REG_SP, syncslot_offset);
574 M_DST(REG_FRESULT, REG_SP, syncslot_offset);
578 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
579 M_ALD(REG_PV, REG_PV, disp);
580 M_JSR(REG_RA, REG_PV);
581 emit_recompute_pv(cd);
583 switch (md->returntype.type) {
587 M_LLD(REG_RESULT, REG_SP, syncslot_offset);
591 M_DLD(REG_FRESULT, REG_SP, syncslot_offset);
598 /* emit_verbosecall_enter ******************************************************
600 Generates the code for the call trace.
602 *******************************************************************************/
605 void emit_verbosecall_enter(jitdata *jd)
612 int32_t stackframesize;
616 /* get required compiler data */
625 /* mark trace code */
629 stackframesize = ARG_CNT + TMP_CNT + md->paramcount + 1;
631 M_LDA(REG_SP, REG_SP, -(stackframesize * 8));
632 M_AST(REG_RA, REG_SP, 0 * 8);
634 /* save all argument and temporary registers for leaf methods */
636 if (code_is_leafmethod(code)) {
637 j = 1 + md->paramcount;
639 for (i = 0; i < INT_ARG_CNT; i++, j++)
640 M_LST(abi_registers_integer_argument[i], REG_SP, j * 8);
642 for (i = 0; i < FLT_ARG_CNT; i++, j++)
643 M_DST(abi_registers_float_argument[i], REG_SP, j * 8);
645 for (i = 0; i < INT_TMP_CNT; i++, j++)
646 M_LST(rd->tmpintregs[i], REG_SP, j * 8);
648 for (i = 0; i < FLT_TMP_CNT; i++, j++)
649 M_DST(rd->tmpfltregs[i], REG_SP, j * 8);
652 /* save argument registers */
654 for (i = 0; i < md->paramcount; i++) {
655 if (!md->params[i].inmemory) {
656 s = md->params[i].regoff;
658 switch (md->paramtypes[i].type) {
662 M_LST(s, REG_SP, (1 + i) * 8);
666 M_DST(s, REG_SP, (1 + i) * 8);
672 disp = dseg_add_address(cd, m);
673 M_ALD(REG_A0, REG_PV, disp);
674 M_AADD_IMM(REG_SP, 1 * 8, REG_A1);
675 M_LDA(REG_A2, REG_SP, stackframesize * 8 + cd->stackframesize * 8);
677 disp = dseg_add_functionptr(cd, trace_java_call_enter);
678 M_ALD(REG_PV, REG_PV, disp);
679 M_JSR(REG_RA, REG_PV);
680 disp = (s4) (cd->mcodeptr - cd->mcodebase);
681 M_LDA(REG_PV, REG_RA, -disp);
682 M_ALD(REG_RA, REG_SP, 0 * 8);
684 /* restore argument registers */
686 for (i = 0; i < md->paramcount; i++) {
687 if (!md->params[i].inmemory) {
688 s = md->params[i].regoff;
690 switch (md->paramtypes[i].type) {
694 M_LLD(s, REG_SP, (1 + i) * 8);
698 M_DLD(s, REG_SP, (1 + i) * 8);
704 /* restore all argument and temporary registers for leaf methods */
706 if (code_is_leafmethod(code)) {
707 j = 1 + md->paramcount;
709 for (i = 0; i < INT_ARG_CNT; i++, j++)
710 M_LLD(abi_registers_integer_argument[i], REG_SP, j * 8);
712 for (i = 0; i < FLT_ARG_CNT; i++, j++)
713 M_DLD(abi_registers_float_argument[i], REG_SP, j * 8);
715 for (i = 0; i < INT_TMP_CNT; i++, j++)
716 M_LLD(rd->tmpintregs[i], REG_SP, j * 8);
718 for (i = 0; i < FLT_TMP_CNT; i++, j++)
719 M_DLD(rd->tmpfltregs[i], REG_SP, j * 8);
722 M_LDA(REG_SP, REG_SP, stackframesize * 8);
724 /* mark trace code */
728 #endif /* !defined(NDEBUG) */
731 /* emit_verbosecall_exit *******************************************************
733 Generates the code for the call trace.
735 *******************************************************************************/
738 void emit_verbosecall_exit(jitdata *jd)
746 /* get required compiler data */
754 /* mark trace code */
758 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
759 M_AST(REG_RA, REG_SP, 0 * 8);
761 /* save return value */
763 switch (md->returntype.type) {
767 M_LST(REG_RESULT, REG_SP, 1 * 8);
771 M_DST(REG_FRESULT, REG_SP, 1 * 8);
775 disp = dseg_add_address(cd, m);
776 M_ALD(REG_A0, REG_PV, disp);
777 M_AADD_IMM(REG_SP, 1 * 8, REG_A1);
779 disp = dseg_add_functionptr(cd, trace_java_call_exit);
780 M_ALD(REG_PV, REG_PV, disp);
781 M_JSR(REG_RA, REG_PV);
782 disp = (cd->mcodeptr - cd->mcodebase);
783 M_LDA(REG_PV, REG_RA, -disp);
785 /* restore return value */
787 switch (md->returntype.type) {
791 M_LLD(REG_RESULT, REG_SP, 1 * 8);
795 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
799 M_ALD(REG_RA, REG_SP, 0 * 8);
800 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
802 /* mark trace code */
806 #endif /* !defined(NDEBUG) */
810 * These are local overrides for various environment variables in Emacs.
811 * Please do not remove this and leave it at the end of the file, where
812 * Emacs will automagically detect them.
813 * ---------------------------------------------------------------------
816 * indent-tabs-mode: t
820 * vim:noexpandtab:sw=4:ts=4: