summaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-07 18:18:09 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-07 18:18:09 +0000
commit5844bb2d778ccdd76e5384987f4dd8e7b6a1c0f9 (patch)
tree7e73dd9db19efc612c7e6749f1333f4b0cc60456 /target-mips
parentebe2a043f8ad540ab87509c2d69be3ec5d019998 (diff)
downloadqemu-5844bb2d778ccdd76e5384987f4dd8e7b6a1c0f9.tar.gz
qemu-5844bb2d778ccdd76e5384987f4dd8e7b6a1c0f9.tar.bz2
qemu-5844bb2d778ccdd76e5384987f4dd8e7b6a1c0f9.zip
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.c46
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. */