mirror of https://github.com/xemu-project/xemu.git
tcg: Make call address a constant parameter
Avoid allocating a tcg temporary to hold the constant address, and instead place it directly into the op_call arguments. At the same time, convert to the newly introduced tcg_out_call backend function, rather than invoking tcg_out_op for the call. Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
dddbb2e1e3
commit
cf06667428
|
@ -513,12 +513,8 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
|
||||||
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||||
TCGArg *args, TCGOpDef *tcg_op_defs)
|
TCGArg *args, TCGOpDef *tcg_op_defs)
|
||||||
{
|
{
|
||||||
int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args;
|
int nb_ops, op_index, nb_temps, nb_globals;
|
||||||
tcg_target_ulong mask, affected;
|
|
||||||
TCGOpcode op;
|
|
||||||
const TCGOpDef *def;
|
|
||||||
TCGArg *gen_args;
|
TCGArg *gen_args;
|
||||||
TCGArg tmp;
|
|
||||||
|
|
||||||
/* Array VALS has an element for each temp.
|
/* Array VALS has an element for each temp.
|
||||||
If this temp holds a constant then its value is kept in VALS' element.
|
If this temp holds a constant then its value is kept in VALS' element.
|
||||||
|
@ -532,22 +528,27 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||||
nb_ops = tcg_opc_ptr - s->gen_opc_buf;
|
nb_ops = tcg_opc_ptr - s->gen_opc_buf;
|
||||||
gen_args = args;
|
gen_args = args;
|
||||||
for (op_index = 0; op_index < nb_ops; op_index++) {
|
for (op_index = 0; op_index < nb_ops; op_index++) {
|
||||||
op = s->gen_opc_buf[op_index];
|
TCGOpcode op = s->gen_opc_buf[op_index];
|
||||||
def = &tcg_op_defs[op];
|
const TCGOpDef *def = &tcg_op_defs[op];
|
||||||
/* Do copy propagation */
|
tcg_target_ulong mask, affected;
|
||||||
|
int nb_oargs, nb_iargs, nb_args, i;
|
||||||
|
TCGArg tmp;
|
||||||
|
|
||||||
if (op == INDEX_op_call) {
|
if (op == INDEX_op_call) {
|
||||||
int nb_oargs = args[0] >> 16;
|
*gen_args++ = tmp = *args++;
|
||||||
int nb_iargs = args[0] & 0xffff;
|
nb_oargs = tmp >> 16;
|
||||||
for (i = nb_oargs + 1; i < nb_oargs + nb_iargs + 1; i++) {
|
nb_iargs = tmp & 0xffff;
|
||||||
if (temps[args[i]].state == TCG_TEMP_COPY) {
|
nb_args = nb_oargs + nb_iargs + def->nb_cargs;
|
||||||
args[i] = find_better_copy(s, args[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
|
nb_oargs = def->nb_oargs;
|
||||||
if (temps[args[i]].state == TCG_TEMP_COPY) {
|
nb_iargs = def->nb_iargs;
|
||||||
args[i] = find_better_copy(s, args[i]);
|
nb_args = def->nb_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do copy propagation */
|
||||||
|
for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
|
||||||
|
if (temps[args[i]].state == TCG_TEMP_COPY) {
|
||||||
|
args[i] = find_better_copy(s, args[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -882,7 +883,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||||
|
|
||||||
CASE_OP_32_64(qemu_ld):
|
CASE_OP_32_64(qemu_ld):
|
||||||
{
|
{
|
||||||
TCGMemOp mop = args[def->nb_oargs + def->nb_iargs];
|
TCGMemOp mop = args[nb_oargs + nb_iargs];
|
||||||
if (!(mop & MO_SIGN)) {
|
if (!(mop & MO_SIGN)) {
|
||||||
mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
|
mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
|
||||||
}
|
}
|
||||||
|
@ -900,15 +901,15 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask == 0) {
|
if (mask == 0) {
|
||||||
assert(def->nb_oargs == 1);
|
assert(nb_oargs == 1);
|
||||||
s->gen_opc_buf[op_index] = op_to_movi(op);
|
s->gen_opc_buf[op_index] = op_to_movi(op);
|
||||||
tcg_opt_gen_movi(gen_args, args[0], 0);
|
tcg_opt_gen_movi(gen_args, args[0], 0);
|
||||||
args += def->nb_oargs + def->nb_iargs + def->nb_cargs;
|
args += nb_args;
|
||||||
gen_args += 2;
|
gen_args += 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (affected == 0) {
|
if (affected == 0) {
|
||||||
assert(def->nb_oargs == 1);
|
assert(nb_oargs == 1);
|
||||||
if (temps_are_copies(args[0], args[1])) {
|
if (temps_are_copies(args[0], args[1])) {
|
||||||
s->gen_opc_buf[op_index] = INDEX_op_nop;
|
s->gen_opc_buf[op_index] = INDEX_op_nop;
|
||||||
} else if (temps[args[1]].state != TCG_TEMP_CONST) {
|
} else if (temps[args[1]].state != TCG_TEMP_CONST) {
|
||||||
|
@ -920,7 +921,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||||
tcg_opt_gen_movi(gen_args, args[0], temps[args[1]].val);
|
tcg_opt_gen_movi(gen_args, args[0], temps[args[1]].val);
|
||||||
gen_args += 2;
|
gen_args += 2;
|
||||||
}
|
}
|
||||||
args += def->nb_iargs + 1;
|
args += nb_args;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1246,24 +1247,13 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_call:
|
case INDEX_op_call:
|
||||||
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
|
if (!(args[nb_oargs + nb_iargs + 1]
|
||||||
if (!(args[nb_call_args + 1] & (TCG_CALL_NO_READ_GLOBALS |
|
& (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
|
||||||
TCG_CALL_NO_WRITE_GLOBALS))) {
|
|
||||||
for (i = 0; i < nb_globals; i++) {
|
for (i = 0; i < nb_globals; i++) {
|
||||||
reset_temp(i);
|
reset_temp(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < (args[0] >> 16); i++) {
|
goto do_reset_output;
|
||||||
reset_temp(args[i + 1]);
|
|
||||||
}
|
|
||||||
i = nb_call_args + 3;
|
|
||||||
while (i) {
|
|
||||||
*gen_args = *args;
|
|
||||||
args++;
|
|
||||||
gen_args++;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
do_default:
|
do_default:
|
||||||
|
@ -1275,7 +1265,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||||
if (def->flags & TCG_OPF_BB_END) {
|
if (def->flags & TCG_OPF_BB_END) {
|
||||||
reset_all_temps(nb_temps);
|
reset_all_temps(nb_temps);
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < def->nb_oargs; i++) {
|
do_reset_output:
|
||||||
|
for (i = 0; i < nb_oargs; i++) {
|
||||||
reset_temp(args[i]);
|
reset_temp(args[i]);
|
||||||
/* Save the corresponding known-zero bits mask for the
|
/* Save the corresponding known-zero bits mask for the
|
||||||
first output argument (only one supported so far). */
|
first output argument (only one supported so far). */
|
||||||
|
@ -1284,11 +1275,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < def->nb_args; i++) {
|
for (i = 0; i < nb_args; i++) {
|
||||||
gen_args[i] = args[i];
|
gen_args[i] = args[i];
|
||||||
}
|
}
|
||||||
args += def->nb_args;
|
args += nb_args;
|
||||||
gen_args += def->nb_args;
|
gen_args += nb_args;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
tcg/tcg-op.h
16
tcg/tcg-op.h
|
@ -390,11 +390,7 @@ static inline int tcg_gen_sizemask(int n, int is_64bit, int is_signed)
|
||||||
static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
|
static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
|
||||||
TCGArg ret, int nargs, TCGArg *args)
|
TCGArg ret, int nargs, TCGArg *args)
|
||||||
{
|
{
|
||||||
TCGv_ptr fn;
|
tcg_gen_callN(&tcg_ctx, func, flags, sizemask, ret, nargs, args);
|
||||||
fn = tcg_const_ptr(func);
|
|
||||||
tcg_gen_callN(&tcg_ctx, fn, flags, sizemask, ret,
|
|
||||||
nargs, args);
|
|
||||||
tcg_temp_free_ptr(fn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: Both tcg_gen_helper32() and tcg_gen_helper64() are currently
|
/* Note: Both tcg_gen_helper32() and tcg_gen_helper64() are currently
|
||||||
|
@ -405,29 +401,23 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
|
||||||
static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret,
|
static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret,
|
||||||
TCGv_i32 a, TCGv_i32 b)
|
TCGv_i32 a, TCGv_i32 b)
|
||||||
{
|
{
|
||||||
TCGv_ptr fn;
|
|
||||||
TCGArg args[2];
|
TCGArg args[2];
|
||||||
fn = tcg_const_ptr(func);
|
|
||||||
args[0] = GET_TCGV_I32(a);
|
args[0] = GET_TCGV_I32(a);
|
||||||
args[1] = GET_TCGV_I32(b);
|
args[1] = GET_TCGV_I32(b);
|
||||||
tcg_gen_callN(&tcg_ctx, fn,
|
tcg_gen_callN(&tcg_ctx, func,
|
||||||
TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
|
TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
|
||||||
sizemask, GET_TCGV_I32(ret), 2, args);
|
sizemask, GET_TCGV_I32(ret), 2, args);
|
||||||
tcg_temp_free_ptr(fn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_gen_helper64(void *func, int sizemask, TCGv_i64 ret,
|
static inline void tcg_gen_helper64(void *func, int sizemask, TCGv_i64 ret,
|
||||||
TCGv_i64 a, TCGv_i64 b)
|
TCGv_i64 a, TCGv_i64 b)
|
||||||
{
|
{
|
||||||
TCGv_ptr fn;
|
|
||||||
TCGArg args[2];
|
TCGArg args[2];
|
||||||
fn = tcg_const_ptr(func);
|
|
||||||
args[0] = GET_TCGV_I64(a);
|
args[0] = GET_TCGV_I64(a);
|
||||||
args[1] = GET_TCGV_I64(b);
|
args[1] = GET_TCGV_I64(b);
|
||||||
tcg_gen_callN(&tcg_ctx, fn,
|
tcg_gen_callN(&tcg_ctx, func,
|
||||||
TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
|
TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
|
||||||
sizemask, GET_TCGV_I64(ret), 2, args);
|
sizemask, GET_TCGV_I64(ret), 2, args);
|
||||||
tcg_temp_free_ptr(fn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 32 bit ops */
|
/* 32 bit ops */
|
||||||
|
|
|
@ -40,7 +40,7 @@ DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT)
|
||||||
DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)
|
DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)
|
||||||
|
|
||||||
/* variable number of parameters */
|
/* variable number of parameters */
|
||||||
DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER)
|
DEF(call, 0, 0, 3, TCG_OPF_CALL_CLOBBER)
|
||||||
|
|
||||||
DEF(br, 0, 0, 1, TCG_OPF_BB_END)
|
DEF(br, 0, 0, 1, TCG_OPF_BB_END)
|
||||||
|
|
||||||
|
|
129
tcg/tcg.c
129
tcg/tcg.c
|
@ -101,6 +101,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
||||||
const int *const_args);
|
const int *const_args);
|
||||||
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
|
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
|
||||||
intptr_t arg2);
|
intptr_t arg2);
|
||||||
|
static void tcg_out_call(TCGContext *s, tcg_insn_unit *target);
|
||||||
static int tcg_target_const_match(tcg_target_long val, TCGType type,
|
static int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||||
const TCGArgConstraint *arg_ct);
|
const TCGArgConstraint *arg_ct);
|
||||||
static void tcg_out_tb_init(TCGContext *s);
|
static void tcg_out_tb_init(TCGContext *s);
|
||||||
|
@ -705,7 +706,7 @@ int tcg_check_temp_count(void)
|
||||||
/* Note: we convert the 64 bit args to 32 bit and do some alignment
|
/* 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. Maybe it would be better to do the alignment
|
||||||
and endian swap in tcg_reg_alloc_call(). */
|
and endian swap in tcg_reg_alloc_call(). */
|
||||||
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
|
void tcg_gen_callN(TCGContext *s, void *func, unsigned int flags,
|
||||||
int sizemask, TCGArg ret, int nargs, TCGArg *args)
|
int sizemask, TCGArg ret, int nargs, TCGArg *args)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -832,11 +833,10 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
|
||||||
*s->gen_opparam_ptr++ = args[i];
|
*s->gen_opparam_ptr++ = args[i];
|
||||||
real_args++;
|
real_args++;
|
||||||
}
|
}
|
||||||
*s->gen_opparam_ptr++ = GET_TCGV_PTR(func);
|
*s->gen_opparam_ptr++ = (uintptr_t)func;
|
||||||
|
|
||||||
*s->gen_opparam_ptr++ = flags;
|
*s->gen_opparam_ptr++ = flags;
|
||||||
|
|
||||||
*nparam = (nb_rets << 16) | (real_args + 1);
|
*nparam = (nb_rets << 16) | real_args;
|
||||||
|
|
||||||
/* total parameters, needed to go backward in the instruction stream */
|
/* total parameters, needed to go backward in the instruction stream */
|
||||||
*s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
|
*s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
|
||||||
|
@ -1243,49 +1243,21 @@ void tcg_dump_ops(TCGContext *s)
|
||||||
nb_iargs = arg & 0xffff;
|
nb_iargs = arg & 0xffff;
|
||||||
nb_cargs = def->nb_cargs;
|
nb_cargs = def->nb_cargs;
|
||||||
|
|
||||||
qemu_log(" %s ", def->name);
|
/* function name, flags, out args */
|
||||||
|
qemu_log(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name,
|
||||||
/* function name */
|
tcg_find_helper(s, args[nb_oargs + nb_iargs]),
|
||||||
qemu_log("%s",
|
args[nb_oargs + nb_iargs + 1], nb_oargs);
|
||||||
tcg_get_arg_str_idx(s, buf, sizeof(buf),
|
for (i = 0; i < nb_oargs; i++) {
|
||||||
args[nb_oargs + nb_iargs - 1]));
|
qemu_log(",%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
|
||||||
/* flags */
|
|
||||||
qemu_log(",$0x%" TCG_PRIlx, args[nb_oargs + nb_iargs]);
|
|
||||||
/* nb out args */
|
|
||||||
qemu_log(",$%d", nb_oargs);
|
|
||||||
for(i = 0; i < nb_oargs; i++) {
|
|
||||||
qemu_log(",");
|
|
||||||
qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
|
|
||||||
args[i]));
|
args[i]));
|
||||||
}
|
}
|
||||||
for(i = 0; i < (nb_iargs - 1); i++) {
|
for (i = 0; i < nb_iargs; i++) {
|
||||||
qemu_log(",");
|
TCGArg arg = args[nb_oargs + i];
|
||||||
if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
|
const char *t = "<dummy>";
|
||||||
qemu_log("<dummy>");
|
if (arg != TCG_CALL_DUMMY_ARG) {
|
||||||
} else {
|
t = tcg_get_arg_str_idx(s, buf, sizeof(buf), arg);
|
||||||
qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
|
|
||||||
args[nb_oargs + i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) {
|
|
||||||
tcg_target_ulong val;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
nb_oargs = def->nb_oargs;
|
|
||||||
nb_iargs = def->nb_iargs;
|
|
||||||
nb_cargs = def->nb_cargs;
|
|
||||||
qemu_log(" %s %s,$", def->name,
|
|
||||||
tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
|
|
||||||
val = args[1];
|
|
||||||
name = tcg_find_helper(s, val);
|
|
||||||
if (name) {
|
|
||||||
qemu_log("%s", name);
|
|
||||||
} else {
|
|
||||||
if (c == INDEX_op_movi_i32) {
|
|
||||||
qemu_log("0x%x", (uint32_t)val);
|
|
||||||
} else {
|
|
||||||
qemu_log("0x%" PRIx64 , (uint64_t)val);
|
|
||||||
}
|
}
|
||||||
|
qemu_log(",%s", t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qemu_log(" %s ", def->name);
|
qemu_log(" %s ", def->name);
|
||||||
|
@ -1548,9 +1520,9 @@ static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps,
|
||||||
temporaries are removed. */
|
temporaries are removed. */
|
||||||
static void tcg_liveness_analysis(TCGContext *s)
|
static void tcg_liveness_analysis(TCGContext *s)
|
||||||
{
|
{
|
||||||
int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
|
int i, op_index, nb_args, nb_iargs, nb_oargs, nb_ops;
|
||||||
TCGOpcode op, op_new, op_new2;
|
TCGOpcode op, op_new, op_new2;
|
||||||
TCGArg *args;
|
TCGArg *args, arg;
|
||||||
const TCGOpDef *def;
|
const TCGOpDef *def;
|
||||||
uint8_t *dead_temps, *mem_temps;
|
uint8_t *dead_temps, *mem_temps;
|
||||||
uint16_t dead_args;
|
uint16_t dead_args;
|
||||||
|
@ -1580,15 +1552,15 @@ static void tcg_liveness_analysis(TCGContext *s)
|
||||||
|
|
||||||
nb_args = args[-1];
|
nb_args = args[-1];
|
||||||
args -= nb_args;
|
args -= nb_args;
|
||||||
nb_iargs = args[0] & 0xffff;
|
arg = *args++;
|
||||||
nb_oargs = args[0] >> 16;
|
nb_iargs = arg & 0xffff;
|
||||||
args++;
|
nb_oargs = arg >> 16;
|
||||||
call_flags = args[nb_oargs + nb_iargs];
|
call_flags = args[nb_oargs + nb_iargs + 1];
|
||||||
|
|
||||||
/* pure functions can be removed if their result is not
|
/* pure functions can be removed if their result is not
|
||||||
used */
|
used */
|
||||||
if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
|
if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
|
||||||
for(i = 0; i < nb_oargs; i++) {
|
for (i = 0; i < nb_oargs; i++) {
|
||||||
arg = args[i];
|
arg = args[i];
|
||||||
if (!dead_temps[arg] || mem_temps[arg]) {
|
if (!dead_temps[arg] || mem_temps[arg]) {
|
||||||
goto do_not_remove_call;
|
goto do_not_remove_call;
|
||||||
|
@ -1602,7 +1574,7 @@ static void tcg_liveness_analysis(TCGContext *s)
|
||||||
/* output args are dead */
|
/* output args are dead */
|
||||||
dead_args = 0;
|
dead_args = 0;
|
||||||
sync_args = 0;
|
sync_args = 0;
|
||||||
for(i = 0; i < nb_oargs; i++) {
|
for (i = 0; i < nb_oargs; i++) {
|
||||||
arg = args[i];
|
arg = args[i];
|
||||||
if (dead_temps[arg]) {
|
if (dead_temps[arg]) {
|
||||||
dead_args |= (1 << i);
|
dead_args |= (1 << i);
|
||||||
|
@ -1625,7 +1597,7 @@ static void tcg_liveness_analysis(TCGContext *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* input args are live */
|
/* input args are live */
|
||||||
for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
|
for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
|
||||||
arg = args[i];
|
arg = args[i];
|
||||||
if (arg != TCG_CALL_DUMMY_ARG) {
|
if (arg != TCG_CALL_DUMMY_ARG) {
|
||||||
if (dead_temps[arg]) {
|
if (dead_temps[arg]) {
|
||||||
|
@ -2372,26 +2344,27 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||||
uint16_t dead_args, uint8_t sync_args)
|
uint16_t dead_args, uint8_t sync_args)
|
||||||
{
|
{
|
||||||
int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
|
int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
|
||||||
TCGArg arg, func_arg;
|
TCGArg arg;
|
||||||
TCGTemp *ts;
|
TCGTemp *ts;
|
||||||
intptr_t stack_offset;
|
intptr_t stack_offset;
|
||||||
size_t call_stack_size;
|
size_t call_stack_size;
|
||||||
uintptr_t func_addr;
|
tcg_insn_unit *func_addr;
|
||||||
int const_func_arg, allocate_args;
|
int allocate_args;
|
||||||
TCGRegSet allocated_regs;
|
TCGRegSet allocated_regs;
|
||||||
const TCGArgConstraint *arg_ct;
|
|
||||||
|
|
||||||
arg = *args++;
|
arg = *args++;
|
||||||
|
|
||||||
nb_oargs = arg >> 16;
|
nb_oargs = arg >> 16;
|
||||||
nb_iargs = arg & 0xffff;
|
nb_iargs = arg & 0xffff;
|
||||||
nb_params = nb_iargs - 1;
|
nb_params = nb_iargs;
|
||||||
|
|
||||||
flags = args[nb_oargs + nb_iargs];
|
func_addr = (tcg_insn_unit *)(intptr_t)args[nb_oargs + nb_iargs];
|
||||||
|
flags = args[nb_oargs + nb_iargs + 1];
|
||||||
|
|
||||||
nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
|
nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
|
||||||
if (nb_regs > nb_params)
|
if (nb_regs > nb_params) {
|
||||||
nb_regs = nb_params;
|
nb_regs = nb_params;
|
||||||
|
}
|
||||||
|
|
||||||
/* assign stack slots first */
|
/* assign stack slots first */
|
||||||
call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
|
call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
|
||||||
|
@ -2459,40 +2432,6 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assign function address */
|
|
||||||
func_arg = args[nb_oargs + nb_iargs - 1];
|
|
||||||
arg_ct = &def->args_ct[0];
|
|
||||||
ts = &s->temps[func_arg];
|
|
||||||
func_addr = ts->val;
|
|
||||||
const_func_arg = 0;
|
|
||||||
if (ts->val_type == TEMP_VAL_MEM) {
|
|
||||||
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
|
|
||||||
tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
|
|
||||||
func_arg = reg;
|
|
||||||
tcg_regset_set_reg(allocated_regs, reg);
|
|
||||||
} else if (ts->val_type == TEMP_VAL_REG) {
|
|
||||||
reg = ts->reg;
|
|
||||||
if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
|
|
||||||
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
|
|
||||||
tcg_out_mov(s, ts->type, reg, ts->reg);
|
|
||||||
}
|
|
||||||
func_arg = reg;
|
|
||||||
tcg_regset_set_reg(allocated_regs, reg);
|
|
||||||
} else if (ts->val_type == TEMP_VAL_CONST) {
|
|
||||||
if (tcg_target_const_match(func_addr, ts->type, arg_ct)) {
|
|
||||||
const_func_arg = 1;
|
|
||||||
func_arg = func_addr;
|
|
||||||
} else {
|
|
||||||
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
|
|
||||||
tcg_out_movi(s, ts->type, reg, func_addr);
|
|
||||||
func_arg = reg;
|
|
||||||
tcg_regset_set_reg(allocated_regs, reg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tcg_abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* mark dead temporaries and free the associated registers */
|
/* mark dead temporaries and free the associated registers */
|
||||||
for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
|
for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
|
||||||
if (IS_DEAD_ARG(i)) {
|
if (IS_DEAD_ARG(i)) {
|
||||||
|
@ -2517,7 +2456,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||||
save_globals(s, allocated_regs);
|
save_globals(s, allocated_regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_out_op(s, opc, &func_arg, &const_func_arg);
|
tcg_out_call(s, func_addr);
|
||||||
|
|
||||||
/* assign output registers and emit moves if needed */
|
/* assign output registers and emit moves if needed */
|
||||||
for(i = 0; i < nb_oargs; i++) {
|
for(i = 0; i < nb_oargs; i++) {
|
||||||
|
|
|
@ -725,7 +725,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
|
||||||
#define tcg_temp_free_ptr(T) tcg_temp_free_i64(TCGV_PTR_TO_NAT(T))
|
#define tcg_temp_free_ptr(T) tcg_temp_free_i64(TCGV_PTR_TO_NAT(T))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
|
void tcg_gen_callN(TCGContext *s, void *func, unsigned int flags,
|
||||||
int sizemask, TCGArg ret, int nargs, TCGArg *args);
|
int sizemask, TCGArg ret, int nargs, TCGArg *args);
|
||||||
|
|
||||||
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
|
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
|
||||||
|
|
Loading…
Reference in New Issue