@@ -811,6 +811,7 @@ void tcg_gen_lookup_and_goto_ptr(void);
#define tcg_global_mem_new tcg_global_mem_new_i32
#define tcg_temp_local_new() tcg_temp_local_new_i32()
#define tcg_temp_free tcg_temp_free_i32
+#define tcg_temp_try_free tcg_temp_try_free_i32
#define tcg_gen_qemu_ld_tl tcg_gen_qemu_ld_i32
#define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i32
#else
@@ -819,6 +820,7 @@ void tcg_gen_lookup_and_goto_ptr(void);
#define tcg_global_mem_new tcg_global_mem_new_i64
#define tcg_temp_local_new() tcg_temp_local_new_i64()
#define tcg_temp_free tcg_temp_free_i64
+#define tcg_temp_try_free tcg_temp_try_free_i64
#define tcg_gen_qemu_ld_tl tcg_gen_qemu_ld_i64
#define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i64
#endif
@@ -1072,11 +1072,15 @@ TCGv_vec tcg_temp_new_vec_matching(TCGv_vec match)
return temp_tcgv_vec(t);
}
-static void tcg_temp_free_internal(TCGTemp *ts)
+static void tcg_temp_free_internal(TCGTemp *ts, bool try)
{
TCGContext *s = tcg_ctx;
int k, idx;
+ if (try && ts->temp_allocated == 0) {
+ return;
+ }
+
#if defined(CONFIG_DEBUG_TCG)
s->temps_in_use--;
if (s->temps_in_use < 0) {
@@ -1095,17 +1099,27 @@ static void tcg_temp_free_internal(TCGTemp *ts)
void tcg_temp_free_i32(TCGv_i32 arg)
{
- tcg_temp_free_internal(tcgv_i32_temp(arg));
+ tcg_temp_free_internal(tcgv_i32_temp(arg), false);
}
void tcg_temp_free_i64(TCGv_i64 arg)
{
- tcg_temp_free_internal(tcgv_i64_temp(arg));
+ tcg_temp_free_internal(tcgv_i64_temp(arg), false);
+}
+
+void tcg_temp_try_free_i32(TCGv_i32 arg)
+{
+ tcg_temp_free_internal(tcgv_i32_temp(arg), true);
+}
+
+void tcg_temp_try_free_i64(TCGv_i64 arg)
+{
+ tcg_temp_free_internal(tcgv_i64_temp(arg), true);
}
void tcg_temp_free_vec(TCGv_vec arg)
{
- tcg_temp_free_internal(tcgv_vec_temp(arg));
+ tcg_temp_free_internal(tcgv_vec_temp(arg), false);
}
TCGv_i32 tcg_const_i32(int32_t val)
@@ -1572,8 +1586,8 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
for (i = real_args = 0; i < orig_nargs; ++i) {
int is_64bit = orig_sizemask & (1 << (i+1)*2);
if (is_64bit) {
- tcg_temp_free_internal(args[real_args++]);
- tcg_temp_free_internal(args[real_args++]);
+ tcg_temp_free_internal(args[real_args++], false);
+ tcg_temp_free_internal(args[real_args++], false);
} else {
real_args++;
}
@@ -1590,7 +1604,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
for (i = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2);
if (!is_64bit) {
- tcg_temp_free_internal(args[i]);
+ tcg_temp_free_internal(args[i], false);
}
}
#endif /* TCG_TARGET_EXTEND_ARGS */
@@ -890,6 +890,9 @@ void tcg_temp_free_i32(TCGv_i32 arg);
void tcg_temp_free_i64(TCGv_i64 arg);
void tcg_temp_free_vec(TCGv_vec arg);
+void tcg_temp_try_free_i32(TCGv_i32 arg);
+void tcg_temp_try_free_i64(TCGv_i64 arg);
+
static inline TCGv_i32 tcg_global_mem_new_i32(TCGv_ptr reg, intptr_t offset,
const char *name)
{
m68k has some functions returning either locally allocated TCGv or memory allocated TCGv (registers). We want to free locally allocated TCGv to avoid overflow in sequence like: 0xc00ae406: movel %fp@(-132),%fp@(-268) 0xc00ae40c: movel %fp@(-128),%fp@(-264) 0xc00ae412: movel %fp@(-20),%fp@(-212) 0xc00ae418: movel %fp@(-16),%fp@(-208) 0xc00ae41e: movel %fp@(-60),%fp@(-220) 0xc00ae424: movel %fp@(-56),%fp@(-216) 0xc00ae42a: movel %fp@(-124),%fp@(-252) 0xc00ae430: movel %fp@(-120),%fp@(-248) 0xc00ae436: movel %fp@(-12),%fp@(-260) 0xc00ae43c: movel %fp@(-8),%fp@(-256) 0xc00ae442: movel %fp@(-52),%fp@(-276) 0xc00ae448: movel %fp@(-48),%fp@(-272) ... That can fill a lot of TCGv entries in a sequence, especially since 15fa08f845 ("tcg: Dynamically allocate TCGOps") Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- tcg/tcg-op.h | 2 ++ tcg/tcg.c | 28 +++++++++++++++++++++------- tcg/tcg.h | 3 +++ 3 files changed, 26 insertions(+), 7 deletions(-)