diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-07 18:18:09 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-07 18:18:09 +0000 |
commit | 1ffc346f951f99ab85bbc75047ff79aec219595a (patch) | |
tree | 7e73dd9db19efc612c7e6749f1333f4b0cc60456 /target-mips | |
parent | 9c6c6662d1f95a098c764adf8d5d2ea0f23f1b30 (diff) |
Be more economical with local temporaries.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4384 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips')
-rw-r--r-- | target-mips/translate.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/target-mips/translate.c b/target-mips/translate.c index c81151d68c..05aa298c9a 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -424,6 +424,46 @@ enum { /* global register indices */ static TCGv cpu_env, current_tc_gprs, cpu_T[2]; +/* The code generator doesn't like lots of temporaries, so maintain our own + cache for reuse within a function. */ +#define MAX_TEMPS 4 +static int num_temps; +static TCGv temps[MAX_TEMPS]; + +/* Allocate a temporary variable. */ +static TCGv new_tmp(void) +{ + TCGv tmp; + if (num_temps == MAX_TEMPS) + abort(); + + if (GET_TCGV(temps[num_temps])) + return temps[num_temps++]; + + tmp = tcg_temp_new(TCG_TYPE_I32); + temps[num_temps++] = tmp; + return tmp; +} + +/* Release a temporary variable. */ +static void dead_tmp(TCGv tmp) +{ + int i; + num_temps--; + i = num_temps; + if (GET_TCGV(temps[i]) == GET_TCGV(tmp)) + return; + + /* Shuffle this temp to the last slot. */ + while (GET_TCGV(temps[i]) != GET_TCGV(tmp)) + i--; + while (i < num_temps) { + temps[i] = temps[i + 1]; + i++; + } + temps[i] = tmp; +} + /* General purpose registers moves */ const unsigned char *regnames[] = { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", @@ -464,7 +504,7 @@ static inline void gen_op_store_gpr_T1(int reg) /* Moves to/from shadow registers */ static inline void gen_op_load_srsgpr_T0(int reg) { - int r_tmp = tcg_temp_new(TCG_TYPE_I32); + int r_tmp = new_tmp(); tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl)); tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS); @@ -473,11 +513,12 @@ static inline void gen_op_load_srsgpr_T0(int reg) tcg_gen_add_i32(r_tmp, cpu_env, r_tmp); tcg_gen_ld_tl(cpu_T[0], r_tmp, sizeof(target_ulong) * reg); + dead_tmp(r_tmp); } static inline void gen_op_store_srsgpr_T0(int reg) { - int r_tmp = tcg_temp_new(TCG_TYPE_I32); + int r_tmp = new_tmp(); tcg_gen_ld_i32(r_tmp, cpu_env, offsetof(CPUState, CP0_SRSCtl)); tcg_gen_shri_i32(r_tmp, r_tmp, CP0SRSCtl_PSS); @@ -486,6 +527,7 @@ static inline void gen_op_store_srsgpr_T0(int reg) tcg_gen_add_i32(r_tmp, cpu_env, r_tmp); tcg_gen_st_tl(cpu_T[0], r_tmp, sizeof(target_ulong) * reg); + dead_tmp(r_tmp); } /* Load immediates, zero being a special case. */ |