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,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