Commit 39cf05d32217f624e4b2e70cde2b5d4a1e841c89
1 parent
cf60bce4
more generic call codegen
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4528 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
75 additions
and
42 deletions
tcg/i386/tcg-target.h
... | ... | @@ -42,6 +42,7 @@ enum { |
42 | 42 | /* used for function call generation */ |
43 | 43 | #define TCG_REG_CALL_STACK TCG_REG_ESP |
44 | 44 | #define TCG_TARGET_STACK_ALIGN 16 |
45 | +#define TCG_TARGET_CALL_STACK_OFFSET 0 | |
45 | 46 | |
46 | 47 | /* Note: must be synced with dyngen-exec.h */ |
47 | 48 | #define TCG_AREG0 TCG_REG_EBP | ... | ... |
tcg/tcg.c
... | ... | @@ -560,7 +560,9 @@ static void tcg_gen_call_internal(TCGContext *s, TCGv func, |
560 | 560 | |
561 | 561 | |
562 | 562 | #if TCG_TARGET_REG_BITS < 64 |
563 | -/* Note: we convert the 64 bit args to 32 bit */ | |
563 | +/* Note: we convert the 64 bit args to 32 bit and do some alignment | |
564 | + and endian swap. Maybe it would be better to do the alignment | |
565 | + and endian swap in tcg_reg_alloc_call(). */ | |
564 | 566 | void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, |
565 | 567 | unsigned int nb_rets, const TCGv *rets, |
566 | 568 | unsigned int nb_params, const TCGv *args1) |
... | ... | @@ -572,12 +574,17 @@ void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, |
572 | 574 | ret = rets[0]; |
573 | 575 | if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) { |
574 | 576 | nb_rets = 2; |
577 | +#ifdef TCG_TARGET_WORDS_BIGENDIAN | |
578 | + rets_2[0] = TCGV_HIGH(ret); | |
579 | + rets_2[1] = ret; | |
580 | +#else | |
575 | 581 | rets_2[0] = ret; |
576 | 582 | rets_2[1] = TCGV_HIGH(ret); |
583 | +#endif | |
577 | 584 | rets = rets_2; |
578 | 585 | } |
579 | 586 | } |
580 | - args2 = alloca((nb_params * 2) * sizeof(TCGv)); | |
587 | + args2 = alloca((nb_params * 3) * sizeof(TCGv)); | |
581 | 588 | j = 0; |
582 | 589 | call_type = (flags & TCG_CALL_TYPE_MASK); |
583 | 590 | for(i = 0; i < nb_params; i++) { |
... | ... | @@ -593,6 +600,12 @@ void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, |
593 | 600 | args2[j++] = arg; |
594 | 601 | args2[j++] = TCGV_HIGH(arg); |
595 | 602 | #else |
603 | +#ifdef TCG_TARGET_CALL_ALIGN_ARGS | |
604 | + /* some targets want aligned 64 bit args */ | |
605 | + if (j & 1) { | |
606 | + args2[j++] = TCG_CALL_DUMMY_ARG; | |
607 | + } | |
608 | +#endif | |
596 | 609 | #ifdef TCG_TARGET_WORDS_BIGENDIAN |
597 | 610 | args2[j++] = TCGV_HIGH(arg); |
598 | 611 | args2[j++] = arg; |
... | ... | @@ -744,8 +757,12 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) |
744 | 757 | } |
745 | 758 | for(i = 0; i < (nb_iargs - 1); i++) { |
746 | 759 | fprintf(outfile, ","); |
747 | - fprintf(outfile, "%s", | |
748 | - tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i])); | |
760 | + if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) { | |
761 | + fprintf(outfile, "<dummy>"); | |
762 | + } else { | |
763 | + fprintf(outfile, "%s", | |
764 | + tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i])); | |
765 | + } | |
749 | 766 | } |
750 | 767 | } else { |
751 | 768 | if (c == INDEX_op_nopn) { |
... | ... | @@ -983,10 +1000,12 @@ void tcg_liveness_analysis(TCGContext *s) |
983 | 1000 | dead_iargs = 0; |
984 | 1001 | for(i = 0; i < nb_iargs; i++) { |
985 | 1002 | arg = args[i + nb_oargs]; |
986 | - if (dead_temps[arg]) { | |
987 | - dead_iargs |= (1 << i); | |
1003 | + if (arg != TCG_CALL_DUMMY_ARG) { | |
1004 | + if (dead_temps[arg]) { | |
1005 | + dead_iargs |= (1 << i); | |
1006 | + } | |
1007 | + dead_temps[arg] = 0; | |
988 | 1008 | } |
989 | - dead_temps[arg] = 0; | |
990 | 1009 | } |
991 | 1010 | s->op_dead_iargs[op_index] = dead_iargs; |
992 | 1011 | } |
... | ... | @@ -1586,52 +1605,60 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, |
1586 | 1605 | if (allocate_args) { |
1587 | 1606 | tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size)); |
1588 | 1607 | } |
1589 | - /* XXX: on some architectures it does not start at zero */ | |
1590 | - stack_offset = 0; | |
1608 | + | |
1609 | + stack_offset = TCG_TARGET_CALL_STACK_OFFSET; | |
1591 | 1610 | for(i = nb_regs; i < nb_params; i++) { |
1592 | 1611 | arg = args[nb_oargs + i]; |
1593 | - ts = &s->temps[arg]; | |
1594 | - if (ts->val_type == TEMP_VAL_REG) { | |
1595 | - tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset); | |
1596 | - } else if (ts->val_type == TEMP_VAL_MEM) { | |
1597 | - reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], | |
1598 | - s->reserved_regs); | |
1599 | - /* XXX: not correct if reading values from the stack */ | |
1600 | - tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); | |
1601 | - tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset); | |
1602 | - } else if (ts->val_type == TEMP_VAL_CONST) { | |
1603 | - reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], | |
1604 | - s->reserved_regs); | |
1605 | - /* XXX: sign extend may be needed on some targets */ | |
1606 | - tcg_out_movi(s, ts->type, reg, ts->val); | |
1607 | - tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset); | |
1608 | - } else { | |
1609 | - tcg_abort(); | |
1612 | +#ifdef TCG_TARGET_STACK_GROWSUP | |
1613 | + stack_offset -= sizeof(tcg_target_long); | |
1614 | +#endif | |
1615 | + if (arg != TCG_CALL_DUMMY_ARG) { | |
1616 | + ts = &s->temps[arg]; | |
1617 | + if (ts->val_type == TEMP_VAL_REG) { | |
1618 | + tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset); | |
1619 | + } else if (ts->val_type == TEMP_VAL_MEM) { | |
1620 | + reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], | |
1621 | + s->reserved_regs); | |
1622 | + /* XXX: not correct if reading values from the stack */ | |
1623 | + tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); | |
1624 | + tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset); | |
1625 | + } else if (ts->val_type == TEMP_VAL_CONST) { | |
1626 | + reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], | |
1627 | + s->reserved_regs); | |
1628 | + /* XXX: sign extend may be needed on some targets */ | |
1629 | + tcg_out_movi(s, ts->type, reg, ts->val); | |
1630 | + tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset); | |
1631 | + } else { | |
1632 | + tcg_abort(); | |
1633 | + } | |
1610 | 1634 | } |
1611 | - /* XXX: not necessarily in the same order */ | |
1612 | - stack_offset += STACK_DIR(sizeof(tcg_target_long)); | |
1635 | +#ifndef TCG_TARGET_STACK_GROWSUP | |
1636 | + stack_offset += sizeof(tcg_target_long); | |
1637 | +#endif | |
1613 | 1638 | } |
1614 | 1639 | |
1615 | 1640 | /* assign input registers */ |
1616 | 1641 | tcg_regset_set(allocated_regs, s->reserved_regs); |
1617 | 1642 | for(i = 0; i < nb_regs; i++) { |
1618 | 1643 | arg = args[nb_oargs + i]; |
1619 | - ts = &s->temps[arg]; | |
1620 | - reg = tcg_target_call_iarg_regs[i]; | |
1621 | - tcg_reg_free(s, reg); | |
1622 | - if (ts->val_type == TEMP_VAL_REG) { | |
1623 | - if (ts->reg != reg) { | |
1624 | - tcg_out_mov(s, reg, ts->reg); | |
1644 | + if (arg != TCG_CALL_DUMMY_ARG) { | |
1645 | + ts = &s->temps[arg]; | |
1646 | + reg = tcg_target_call_iarg_regs[i]; | |
1647 | + tcg_reg_free(s, reg); | |
1648 | + if (ts->val_type == TEMP_VAL_REG) { | |
1649 | + if (ts->reg != reg) { | |
1650 | + tcg_out_mov(s, reg, ts->reg); | |
1651 | + } | |
1652 | + } else if (ts->val_type == TEMP_VAL_MEM) { | |
1653 | + tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); | |
1654 | + } else if (ts->val_type == TEMP_VAL_CONST) { | |
1655 | + /* XXX: sign extend ? */ | |
1656 | + tcg_out_movi(s, ts->type, reg, ts->val); | |
1657 | + } else { | |
1658 | + tcg_abort(); | |
1625 | 1659 | } |
1626 | - } else if (ts->val_type == TEMP_VAL_MEM) { | |
1627 | - tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); | |
1628 | - } else if (ts->val_type == TEMP_VAL_CONST) { | |
1629 | - /* XXX: sign extend ? */ | |
1630 | - tcg_out_movi(s, ts->type, reg, ts->val); | |
1631 | - } else { | |
1632 | - tcg_abort(); | |
1660 | + tcg_regset_set_reg(allocated_regs, reg); | |
1633 | 1661 | } |
1634 | - tcg_regset_set_reg(allocated_regs, reg); | |
1635 | 1662 | } |
1636 | 1663 | |
1637 | 1664 | /* assign function address */ | ... | ... |
tcg/tcg.h
... | ... | @@ -153,6 +153,10 @@ typedef int TCGv; |
153 | 153 | safely suppressed if the return value is not used. */ |
154 | 154 | #define TCG_CALL_PURE 0x0010 |
155 | 155 | |
156 | +/* used to align parameters */ | |
157 | +#define TCG_CALL_DUMMY_TCGV MAKE_TCGV(-1) | |
158 | +#define TCG_CALL_DUMMY_ARG ((TCGArg)(-1)) | |
159 | + | |
156 | 160 | typedef enum { |
157 | 161 | TCG_COND_EQ, |
158 | 162 | TCG_COND_NE, | ... | ... |
tcg/x86_64/tcg-target.h