Commit a018d617f889d486b215ac342b7f49f6ec76fad6

Authored by Filip Navara
1 parent 1fb3d0da

Use tcg_global_mem_new_i32 to allocate ARM registers in TCG.

Currently each read/write of ARM register involves a LD/ST TCG operation. This
patch uses TCG memory-backed registers to represent the ARM register set. With
memory-backed registers the LD/ST operations are transparently generated by TCG
and host registers could be used to optimize the generated code.

Signed-off-by: Filip Navara <filip.navara@gmail.com>
Showing 1 changed file with 23 additions and 17 deletions
target-arm/translate.c
@@ -76,6 +76,7 @@ typedef struct DisasContext { @@ -76,6 +76,7 @@ typedef struct DisasContext {
76 static TCGv_ptr cpu_env; 76 static TCGv_ptr cpu_env;
77 /* We reuse the same 64-bit temporaries for efficiency. */ 77 /* We reuse the same 64-bit temporaries for efficiency. */
78 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0; 78 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
  79 +static TCGv_i32 cpu_R[16];
79 80
80 /* FIXME: These should be removed. */ 81 /* FIXME: These should be removed. */
81 static TCGv cpu_T[2]; 82 static TCGv cpu_T[2];
@@ -85,14 +86,26 @@ static TCGv_i64 cpu_F0d, cpu_F1d; @@ -85,14 +86,26 @@ static TCGv_i64 cpu_F0d, cpu_F1d;
85 #define ICOUNT_TEMP cpu_T[0] 86 #define ICOUNT_TEMP cpu_T[0]
86 #include "gen-icount.h" 87 #include "gen-icount.h"
87 88
  89 +static const char *regnames[] =
  90 + { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  91 + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
  92 +
88 /* initialize TCG globals. */ 93 /* initialize TCG globals. */
89 void arm_translate_init(void) 94 void arm_translate_init(void)
90 { 95 {
  96 + int i;
  97 +
91 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); 98 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
92 99
93 cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0"); 100 cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0");
94 cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1"); 101 cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1");
95 102
  103 + for (i = 0; i < 16; i++) {
  104 + cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
  105 + offsetof(CPUState, regs[i]),
  106 + regnames[i]);
  107 + }
  108 +
96 #define GEN_HELPER 2 109 #define GEN_HELPER 2
97 #include "helpers.h" 110 #include "helpers.h"
98 } 111 }
@@ -167,7 +180,7 @@ static void load_reg_var(DisasContext *s, TCGv var, int reg) @@ -167,7 +180,7 @@ static void load_reg_var(DisasContext *s, TCGv var, int reg)
167 addr = (long)s->pc + 4; 180 addr = (long)s->pc + 4;
168 tcg_gen_movi_i32(var, addr); 181 tcg_gen_movi_i32(var, addr);
169 } else { 182 } else {
170 - tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg])); 183 + tcg_gen_mov_i32(var, cpu_R[reg]);
171 } 184 }
172 } 185 }
173 186
@@ -187,7 +200,7 @@ static void store_reg(DisasContext *s, int reg, TCGv var) @@ -187,7 +200,7 @@ static void store_reg(DisasContext *s, int reg, TCGv var)
187 tcg_gen_andi_i32(var, var, ~1); 200 tcg_gen_andi_i32(var, var, ~1);
188 s->is_jmp = DISAS_JUMP; 201 s->is_jmp = DISAS_JUMP;
189 } 202 }
190 - tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg])); 203 + tcg_gen_mov_i32(cpu_R[reg], var);
191 dead_tmp(var); 204 dead_tmp(var);
192 } 205 }
193 206
@@ -789,27 +802,22 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr) @@ -789,27 +802,22 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr)
789 TCGv tmp; 802 TCGv tmp;
790 803
791 s->is_jmp = DISAS_UPDATE; 804 s->is_jmp = DISAS_UPDATE;
792 - tmp = new_tmp();  
793 if (s->thumb != (addr & 1)) { 805 if (s->thumb != (addr & 1)) {
  806 + tmp = new_tmp();
794 tcg_gen_movi_i32(tmp, addr & 1); 807 tcg_gen_movi_i32(tmp, addr & 1);
795 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb)); 808 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
  809 + dead_tmp(tmp);
796 } 810 }
797 - tcg_gen_movi_i32(tmp, addr & ~1);  
798 - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));  
799 - dead_tmp(tmp); 811 + tcg_gen_mov_i32(cpu_R[15], addr & ~1);
800 } 812 }
801 813
802 /* Set PC and Thumb state from var. var is marked as dead. */ 814 /* Set PC and Thumb state from var. var is marked as dead. */
803 static inline void gen_bx(DisasContext *s, TCGv var) 815 static inline void gen_bx(DisasContext *s, TCGv var)
804 { 816 {
805 - TCGv tmp;  
806 -  
807 s->is_jmp = DISAS_UPDATE; 817 s->is_jmp = DISAS_UPDATE;
808 - tmp = new_tmp();  
809 - tcg_gen_andi_i32(tmp, var, 1);  
810 - store_cpu_field(tmp, thumb);  
811 - tcg_gen_andi_i32(var, var, ~1);  
812 - store_cpu_field(var, regs[15]); 818 + tcg_gen_andi_i32(cpu_R[15], var, ~1);
  819 + tcg_gen_andi_i32(var, var, 1);
  820 + store_cpu_field(var, thumb);
813 } 821 }
814 822
815 /* Variant of store_reg which uses branch&exchange logic when storing 823 /* Variant of store_reg which uses branch&exchange logic when storing
@@ -888,9 +896,7 @@ static inline void gen_movl_T2_reg(DisasContext *s, int reg) @@ -888,9 +896,7 @@ static inline void gen_movl_T2_reg(DisasContext *s, int reg)
888 896
889 static inline void gen_set_pc_im(uint32_t val) 897 static inline void gen_set_pc_im(uint32_t val)
890 { 898 {
891 - TCGv tmp = new_tmp();  
892 - tcg_gen_movi_i32(tmp, val);  
893 - store_cpu_field(tmp, regs[15]); 899 + tcg_gen_movi_i32(cpu_R[15], val);
894 } 900 }
895 901
896 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t) 902 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
@@ -902,7 +908,7 @@ static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t) @@ -902,7 +908,7 @@ static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
902 } else { 908 } else {
903 tmp = cpu_T[t]; 909 tmp = cpu_T[t];
904 } 910 }
905 - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg])); 911 + tcg_gen_mov_i32(cpu_R[reg], tmp);
906 if (reg == 15) { 912 if (reg == 15) {
907 dead_tmp(tmp); 913 dead_tmp(tmp);
908 s->is_jmp = DISAS_JUMP; 914 s->is_jmp = DISAS_JUMP;