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,6 +42,7 @@ enum { | ||
| 42 | /* used for function call generation */ | 42 | /* used for function call generation */ |
| 43 | #define TCG_REG_CALL_STACK TCG_REG_ESP | 43 | #define TCG_REG_CALL_STACK TCG_REG_ESP |
| 44 | #define TCG_TARGET_STACK_ALIGN 16 | 44 | #define TCG_TARGET_STACK_ALIGN 16 |
| 45 | +#define TCG_TARGET_CALL_STACK_OFFSET 0 | ||
| 45 | 46 | ||
| 46 | /* Note: must be synced with dyngen-exec.h */ | 47 | /* Note: must be synced with dyngen-exec.h */ |
| 47 | #define TCG_AREG0 TCG_REG_EBP | 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,7 +560,9 @@ static void tcg_gen_call_internal(TCGContext *s, TCGv func, | ||
| 560 | 560 | ||
| 561 | 561 | ||
| 562 | #if TCG_TARGET_REG_BITS < 64 | 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 | void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, | 566 | void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, |
| 565 | unsigned int nb_rets, const TCGv *rets, | 567 | unsigned int nb_rets, const TCGv *rets, |
| 566 | unsigned int nb_params, const TCGv *args1) | 568 | unsigned int nb_params, const TCGv *args1) |
| @@ -572,12 +574,17 @@ void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, | @@ -572,12 +574,17 @@ void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, | ||
| 572 | ret = rets[0]; | 574 | ret = rets[0]; |
| 573 | if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) { | 575 | if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) { |
| 574 | nb_rets = 2; | 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 | rets_2[0] = ret; | 581 | rets_2[0] = ret; |
| 576 | rets_2[1] = TCGV_HIGH(ret); | 582 | rets_2[1] = TCGV_HIGH(ret); |
| 583 | +#endif | ||
| 577 | rets = rets_2; | 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 | j = 0; | 588 | j = 0; |
| 582 | call_type = (flags & TCG_CALL_TYPE_MASK); | 589 | call_type = (flags & TCG_CALL_TYPE_MASK); |
| 583 | for(i = 0; i < nb_params; i++) { | 590 | for(i = 0; i < nb_params; i++) { |
| @@ -593,6 +600,12 @@ void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, | @@ -593,6 +600,12 @@ void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags, | ||
| 593 | args2[j++] = arg; | 600 | args2[j++] = arg; |
| 594 | args2[j++] = TCGV_HIGH(arg); | 601 | args2[j++] = TCGV_HIGH(arg); |
| 595 | #else | 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 | #ifdef TCG_TARGET_WORDS_BIGENDIAN | 609 | #ifdef TCG_TARGET_WORDS_BIGENDIAN |
| 597 | args2[j++] = TCGV_HIGH(arg); | 610 | args2[j++] = TCGV_HIGH(arg); |
| 598 | args2[j++] = arg; | 611 | args2[j++] = arg; |
| @@ -744,8 +757,12 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) | @@ -744,8 +757,12 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile) | ||
| 744 | } | 757 | } |
| 745 | for(i = 0; i < (nb_iargs - 1); i++) { | 758 | for(i = 0; i < (nb_iargs - 1); i++) { |
| 746 | fprintf(outfile, ","); | 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 | } else { | 767 | } else { |
| 751 | if (c == INDEX_op_nopn) { | 768 | if (c == INDEX_op_nopn) { |
| @@ -983,10 +1000,12 @@ void tcg_liveness_analysis(TCGContext *s) | @@ -983,10 +1000,12 @@ void tcg_liveness_analysis(TCGContext *s) | ||
| 983 | dead_iargs = 0; | 1000 | dead_iargs = 0; |
| 984 | for(i = 0; i < nb_iargs; i++) { | 1001 | for(i = 0; i < nb_iargs; i++) { |
| 985 | arg = args[i + nb_oargs]; | 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 | s->op_dead_iargs[op_index] = dead_iargs; | 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,52 +1605,60 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, | ||
| 1586 | if (allocate_args) { | 1605 | if (allocate_args) { |
| 1587 | tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size)); | 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 | for(i = nb_regs; i < nb_params; i++) { | 1610 | for(i = nb_regs; i < nb_params; i++) { |
| 1592 | arg = args[nb_oargs + i]; | 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 | /* assign input registers */ | 1640 | /* assign input registers */ |
| 1616 | tcg_regset_set(allocated_regs, s->reserved_regs); | 1641 | tcg_regset_set(allocated_regs, s->reserved_regs); |
| 1617 | for(i = 0; i < nb_regs; i++) { | 1642 | for(i = 0; i < nb_regs; i++) { |
| 1618 | arg = args[nb_oargs + i]; | 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 | /* assign function address */ | 1664 | /* assign function address */ |
tcg/tcg.h
| @@ -153,6 +153,10 @@ typedef int TCGv; | @@ -153,6 +153,10 @@ typedef int TCGv; | ||
| 153 | safely suppressed if the return value is not used. */ | 153 | safely suppressed if the return value is not used. */ |
| 154 | #define TCG_CALL_PURE 0x0010 | 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 | typedef enum { | 160 | typedef enum { |
| 157 | TCG_COND_EQ, | 161 | TCG_COND_EQ, |
| 158 | TCG_COND_NE, | 162 | TCG_COND_NE, |
tcg/x86_64/tcg-target.h
| @@ -53,6 +53,7 @@ enum { | @@ -53,6 +53,7 @@ enum { | ||
| 53 | /* used for function call generation */ | 53 | /* used for function call generation */ |
| 54 | #define TCG_REG_CALL_STACK TCG_REG_RSP | 54 | #define TCG_REG_CALL_STACK TCG_REG_RSP |
| 55 | #define TCG_TARGET_STACK_ALIGN 16 | 55 | #define TCG_TARGET_STACK_ALIGN 16 |
| 56 | +#define TCG_TARGET_CALL_STACK_OFFSET 0 | ||
| 56 | 57 | ||
| 57 | /* optional instructions */ | 58 | /* optional instructions */ |
| 58 | #define TCG_TARGET_HAS_bswap_i32 | 59 | #define TCG_TARGET_HAS_bswap_i32 |