Commit 39cf05d3 authored by Fabrice Bellard's avatar Fabrice Bellard
Browse files

more generic call codegen

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4528 c046a42c-6fe2-441c-8c8c-71466251a162
parent cf60bce4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ enum {
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_ESP 
#define TCG_TARGET_STACK_ALIGN 16
#define TCG_TARGET_CALL_STACK_OFFSET 0

/* Note: must be synced with dyngen-exec.h */
#define TCG_AREG0 TCG_REG_EBP
+69 −42
Original line number Diff line number Diff line
@@ -560,7 +560,9 @@ static void tcg_gen_call_internal(TCGContext *s, TCGv func,


#if TCG_TARGET_REG_BITS < 64
/* Note: we convert the 64 bit args to 32 bit */
/* Note: we convert the 64 bit args to 32 bit and do some alignment
   and endian swap. Maybe it would be better to do the alignment
   and endian swap in tcg_reg_alloc_call(). */
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
                  unsigned int nb_rets, const TCGv *rets,
                  unsigned int nb_params, const TCGv *args1)
@@ -572,12 +574,17 @@ void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
        ret = rets[0];
        if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
            nb_rets = 2;
#ifdef TCG_TARGET_WORDS_BIGENDIAN
            rets_2[0] = TCGV_HIGH(ret);
            rets_2[1] = ret;
#else
            rets_2[0] = ret;
            rets_2[1] = TCGV_HIGH(ret);
#endif
            rets = rets_2;
        }
    }
    args2 = alloca((nb_params * 2) * sizeof(TCGv));
    args2 = alloca((nb_params * 3) * sizeof(TCGv));
    j = 0;
    call_type = (flags & TCG_CALL_TYPE_MASK);
    for(i = 0; i < nb_params; i++) {
@@ -593,6 +600,12 @@ void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
            args2[j++] = arg;
            args2[j++] = TCGV_HIGH(arg);
#else
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
            /* some targets want aligned 64 bit args */
            if (j & 1) {
                args2[j++] = TCG_CALL_DUMMY_ARG;
            }
#endif
#ifdef TCG_TARGET_WORDS_BIGENDIAN
            args2[j++] = TCGV_HIGH(arg);
            args2[j++] = arg;
@@ -744,9 +757,13 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile)
            }
            for(i = 0; i < (nb_iargs - 1); i++) {
                fprintf(outfile, ",");
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
                    fprintf(outfile, "<dummy>");
                } else {
                    fprintf(outfile, "%s",
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
                }
            }
        } else {
            if (c == INDEX_op_nopn) {
                /* variable number of arguments */
@@ -983,11 +1000,13 @@ void tcg_liveness_analysis(TCGContext *s)
                    dead_iargs = 0;
                    for(i = 0; i < nb_iargs; i++) {
                        arg = args[i + nb_oargs];
                        if (arg != TCG_CALL_DUMMY_ARG) {
                            if (dead_temps[arg]) {
                                dead_iargs |= (1 << i);
                            }
                            dead_temps[arg] = 0;
                        }
                    }
                    s->op_dead_iargs[op_index] = dead_iargs;
                }
                args--;
@@ -1586,10 +1605,14 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
    if (allocate_args) {
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
    }
    /* XXX: on some architectures it does not start at zero */
    stack_offset = 0;

    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
    for(i = nb_regs; i < nb_params; i++) {
        arg = args[nb_oargs + i];
#ifdef TCG_TARGET_STACK_GROWSUP
        stack_offset -= sizeof(tcg_target_long);
#endif
        if (arg != TCG_CALL_DUMMY_ARG) {
            ts = &s->temps[arg];
            if (ts->val_type == TEMP_VAL_REG) {
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
@@ -1608,14 +1631,17 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
            } else {
                tcg_abort();
            }
        /* XXX: not necessarily in the same order */
        stack_offset += STACK_DIR(sizeof(tcg_target_long));
        }
#ifndef TCG_TARGET_STACK_GROWSUP
        stack_offset += sizeof(tcg_target_long);
#endif
    }
    
    /* assign input registers */
    tcg_regset_set(allocated_regs, s->reserved_regs);
    for(i = 0; i < nb_regs; i++) {
        arg = args[nb_oargs + i];
        if (arg != TCG_CALL_DUMMY_ARG) {
            ts = &s->temps[arg];
            reg = tcg_target_call_iarg_regs[i];
            tcg_reg_free(s, reg);
@@ -1633,6 +1659,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
            }
            tcg_regset_set_reg(allocated_regs, reg);
        }
    }
    
    /* assign function address */
    func_arg = args[nb_oargs + nb_iargs - 1];
+4 −0
Original line number Diff line number Diff line
@@ -153,6 +153,10 @@ typedef int TCGv;
   safely suppressed if the return value is not used. */
#define TCG_CALL_PURE           0x0010 

/* used to align parameters */
#define TCG_CALL_DUMMY_TCGV     MAKE_TCGV(-1)
#define TCG_CALL_DUMMY_ARG      ((TCGArg)(-1))

typedef enum {
    TCG_COND_EQ,
    TCG_COND_NE,
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ enum {
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_RSP 
#define TCG_TARGET_STACK_ALIGN 16
#define TCG_TARGET_CALL_STACK_OFFSET 0

/* optional instructions */
#define TCG_TARGET_HAS_bswap_i32