Commit 39cf05d32217f624e4b2e70cde2b5d4a1e841c89

Authored by bellard
1 parent cf60bce4

more generic call codegen

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4528 c046a42c-6fe2-441c-8c8c-71466251a162
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
... ... @@ -53,6 +53,7 @@ enum {
53 53 /* used for function call generation */
54 54 #define TCG_REG_CALL_STACK TCG_REG_RSP
55 55 #define TCG_TARGET_STACK_ALIGN 16
  56 +#define TCG_TARGET_CALL_STACK_OFFSET 0
56 57  
57 58 /* optional instructions */
58 59 #define TCG_TARGET_HAS_bswap_i32
... ...