Commit 3979144c49d62d23c4a31a07cf8282217ed3dde3

Authored by pbrook
1 parent e6bb7d7e

Fix ARM host TLB.



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4564 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 44 additions and 61 deletions
tcg/arm/tcg-target.c
@@ -90,8 +90,6 @@ static inline int tcg_target_get_call_iarg_regs_count(int flags) @@ -90,8 +90,6 @@ static inline int tcg_target_get_call_iarg_regs_count(int flags)
90 return 4; 90 return 4;
91 } 91 }
92 92
93 -#define USE_TLB  
94 -  
95 /* parse target specific constraints */ 93 /* parse target specific constraints */
96 int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) 94 int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
97 { 95 {
@@ -115,22 +113,8 @@ int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) @@ -115,22 +113,8 @@ int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
115 case 'x': 113 case 'x':
116 ct->ct |= TCG_CT_REG; 114 ct->ct |= TCG_CT_REG;
117 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1); 115 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
118 -# ifdef USE_TLB  
119 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); 116 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
120 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); 117 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
121 -# endif  
122 - break;  
123 -  
124 - /* qemu_ld/st data_reg */  
125 - case 'd':  
126 - ct->ct |= TCG_CT_REG;  
127 - tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);  
128 - /* r0 and optionally r1 will be overwritten by the address  
129 - * so don't use these. */  
130 - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);  
131 -# if TARGET_LONG_BITS == 64 || defined(USE_TLB)  
132 - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);  
133 -# endif  
134 break; 118 break;
135 119
136 /* qemu_ld/st64 data_reg2 */ 120 /* qemu_ld/st64 data_reg2 */
@@ -153,9 +137,7 @@ int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) @@ -153,9 +137,7 @@ int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
153 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1); 137 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
154 /* r0 will be overwritten by the low word of base, so don't use it. */ 138 /* r0 will be overwritten by the low word of base, so don't use it. */
155 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); 139 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
156 -# ifdef USE_TLB  
157 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); 140 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
158 -# endif  
159 break; 141 break;
160 # endif 142 # endif
161 #endif 143 #endif
@@ -210,6 +192,7 @@ enum arm_data_opc_e { @@ -210,6 +192,7 @@ enum arm_data_opc_e {
210 ARITH_ADC = 0x5, 192 ARITH_ADC = 0x5,
211 ARITH_SBC = 0x6, 193 ARITH_SBC = 0x6,
212 ARITH_RSC = 0x7, 194 ARITH_RSC = 0x7,
  195 + ARITH_TST = 0x8,
213 ARITH_CMP = 0xa, 196 ARITH_CMP = 0xa,
214 ARITH_CMN = 0xb, 197 ARITH_CMN = 0xb,
215 ARITH_ORR = 0xc, 198 ARITH_ORR = 0xc,
@@ -218,7 +201,8 @@ enum arm_data_opc_e { @@ -218,7 +201,8 @@ enum arm_data_opc_e {
218 ARITH_MVN = 0xf, 201 ARITH_MVN = 0xf,
219 }; 202 };
220 203
221 -#define TO_CPSR(opc) ((opc == ARITH_CMP || opc == ARITH_CMN) << 20) 204 +#define TO_CPSR(opc) \
  205 + ((opc == ARITH_CMP || opc == ARITH_CMN || opc == ARITH_TST) << 20)
222 206
223 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00) 207 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
224 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20) 208 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
@@ -309,7 +293,7 @@ static inline void tcg_out_dat_reg2(TCGContext *s, @@ -309,7 +293,7 @@ static inline void tcg_out_dat_reg2(TCGContext *s,
309 static inline void tcg_out_dat_imm(TCGContext *s, 293 static inline void tcg_out_dat_imm(TCGContext *s,
310 int cond, int opc, int rd, int rn, int im) 294 int cond, int opc, int rd, int rn, int im)
311 { 295 {
312 - tcg_out32(s, (cond << 28) | (1 << 25) | (opc << 21) | 296 + tcg_out32(s, (cond << 28) | (1 << 25) | (opc << 21) | TO_CPSR(opc) |
313 (rn << 16) | (rd << 12) | im); 297 (rn << 16) | (rd << 12) | im);
314 } 298 }
315 299
@@ -428,6 +412,21 @@ static inline void tcg_out_st32_r(TCGContext *s, int cond, @@ -428,6 +412,21 @@ static inline void tcg_out_st32_r(TCGContext *s, int cond,
428 (rn << 16) | (rd << 12) | rm); 412 (rn << 16) | (rd << 12) | rm);
429 } 413 }
430 414
  415 +/* Register pre-increment with base writeback. */
  416 +static inline void tcg_out_ld32_rwb(TCGContext *s, int cond,
  417 + int rd, int rn, int rm)
  418 +{
  419 + tcg_out32(s, (cond << 28) | 0x07b00000 |
  420 + (rn << 16) | (rd << 12) | rm);
  421 +}
  422 +
  423 +static inline void tcg_out_st32_rwb(TCGContext *s, int cond,
  424 + int rd, int rn, int rm)
  425 +{
  426 + tcg_out32(s, (cond << 28) | 0x07a00000 |
  427 + (rn << 16) | (rd << 12) | rm);
  428 +}
  429 +
431 static inline void tcg_out_ld16u_8(TCGContext *s, int cond, 430 static inline void tcg_out_ld16u_8(TCGContext *s, int cond,
432 int rd, int rn, tcg_target_long im) 431 int rd, int rn, tcg_target_long im)
433 { 432 {
@@ -826,6 +825,8 @@ static void *qemu_st_helpers[4] = { @@ -826,6 +825,8 @@ static void *qemu_st_helpers[4] = {
826 }; 825 };
827 #endif 826 #endif
828 827
  828 +#define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
  829 +
829 static inline void tcg_out_qemu_ld(TCGContext *s, int cond, 830 static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
830 const TCGArg *args, int opc) 831 const TCGArg *args, int opc)
831 { 832 {
@@ -835,9 +836,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, @@ -835,9 +836,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
835 # if TARGET_LONG_BITS == 64 836 # if TARGET_LONG_BITS == 64
836 int addr_reg2; 837 int addr_reg2;
837 # endif 838 # endif
838 -# ifdef USE_TLB  
839 uint32_t *label_ptr; 839 uint32_t *label_ptr;
840 -# endif  
841 #endif 840 #endif
842 841
843 data_reg = *args++; 842 data_reg = *args++;
@@ -853,17 +852,16 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, @@ -853,17 +852,16 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
853 mem_index = *args; 852 mem_index = *args;
854 s_bits = opc & 3; 853 s_bits = opc & 3;
855 854
856 -# ifdef USE_TLB  
857 /* Should generate something like the following: 855 /* Should generate something like the following:
858 - * ror r8, addr_reg, #TARGET_PAGE_BITS 856 + * shr r8, addr_reg, #TARGET_PAGE_BITS
859 * and r0, r8, #(CPU_TLB_SIZE - 1) @ Assumption: CPU_TLB_BITS <= 8 857 * and r0, r8, #(CPU_TLB_SIZE - 1) @ Assumption: CPU_TLB_BITS <= 8
860 - * add r0, T0, r0 lsl #CPU_TLB_ENTRY_BITS 858 + * add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
861 */ 859 */
862 # if CPU_TLB_BITS > 8 860 # if CPU_TLB_BITS > 8
863 # error 861 # error
864 # endif 862 # endif
865 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 863 tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
866 - 8, 0, addr_reg, SHIFT_IMM_ROR(TARGET_PAGE_BITS)); 864 + 8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
867 tcg_out_dat_imm(s, COND_AL, ARITH_AND, 865 tcg_out_dat_imm(s, COND_AL, ARITH_AND,
868 0, 8, CPU_TLB_SIZE - 1); 866 0, 8, CPU_TLB_SIZE - 1);
869 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, 867 tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
@@ -875,7 +873,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, @@ -875,7 +873,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
875 * add r0, r0, #(mem_index * sizeof *CPUState.tlb_table) 873 * add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
876 * before. 874 * before.
877 */ 875 */
878 -# define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)  
879 if (mem_index) 876 if (mem_index)
880 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 0, 0, 877 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 0, 0,
881 (mem_index << (TLB_SHIFT & 1)) | 878 (mem_index << (TLB_SHIFT & 1)) |
@@ -884,11 +881,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, @@ -884,11 +881,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
884 offsetof(CPUState, tlb_table[0][0].addr_read)); 881 offsetof(CPUState, tlb_table[0][0].addr_read));
885 tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 882 tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
886 0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS)); 883 0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
887 - /* TODO: alignment check?  
888 - * if (s_bits)  
889 - * tcg_out_data_reg(s, COND_EQ, ARITH_EOR,  
890 - * 0, 1, 8, SHIFT_IMM_LSR(32 - s_bits));  
891 - */ 884 + /* Check alignment. */
  885 + if (s_bits)
  886 + tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
  887 + 0, addr_reg, (1 << s_bits) - 1);
892 # if TARGET_LONG_BITS == 64 888 # if TARGET_LONG_BITS == 64
893 /* XXX: possibly we could use a block data load or writeback in 889 /* XXX: possibly we could use a block data load or writeback in
894 * the first access. */ 890 * the first access. */
@@ -918,15 +914,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, @@ -918,15 +914,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
918 tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, 1); 914 tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, 1);
919 break; 915 break;
920 case 3: 916 case 3:
921 - /* TODO: must write back */  
922 - tcg_out_ld32_r(s, COND_EQ, data_reg, 1, addr_reg); 917 + tcg_out_ld32_rwb(s, COND_EQ, data_reg, 1, addr_reg);
923 tcg_out_ld32_12(s, COND_EQ, data_reg2, 1, 4); 918 tcg_out_ld32_12(s, COND_EQ, data_reg2, 1, 4);
924 break; 919 break;
925 } 920 }
926 921
927 label_ptr = (void *) s->code_ptr; 922 label_ptr = (void *) s->code_ptr;
928 tcg_out_b(s, COND_EQ, 8); 923 tcg_out_b(s, COND_EQ, 8);
929 -# endif  
930 924
931 # ifdef SAVE_LR 925 # ifdef SAVE_LR
932 tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 14, SHIFT_IMM_LSL(0)); 926 tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 14, SHIFT_IMM_LSL(0));
@@ -969,12 +963,11 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, @@ -969,12 +963,11 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
969 data_reg, 0, 0, SHIFT_IMM_LSL(0)); 963 data_reg, 0, 0, SHIFT_IMM_LSL(0));
970 break; 964 break;
971 case 3: 965 case 3:
  966 + tcg_out_dat_reg(s, cond, ARITH_MOV,
  967 + data_reg, 0, 0, SHIFT_IMM_LSL(0));
972 if (data_reg2 != 1) 968 if (data_reg2 != 1)
973 tcg_out_dat_reg(s, cond, ARITH_MOV, 969 tcg_out_dat_reg(s, cond, ARITH_MOV,
974 data_reg2, 0, 1, SHIFT_IMM_LSL(0)); 970 data_reg2, 0, 1, SHIFT_IMM_LSL(0));
975 - if (data_reg != 0)  
976 - tcg_out_dat_reg(s, cond, ARITH_MOV,  
977 - data_reg, 0, 0, SHIFT_IMM_LSL(0));  
978 break; 971 break;
979 } 972 }
980 973
@@ -982,9 +975,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, @@ -982,9 +975,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
982 tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0)); 975 tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
983 # endif 976 # endif
984 977
985 -# ifdef USE_TLB  
986 *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; 978 *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
987 -# endif  
988 #else 979 #else
989 switch (opc) { 980 switch (opc) {
990 case 0: 981 case 0:
@@ -1021,9 +1012,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, @@ -1021,9 +1012,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
1021 # if TARGET_LONG_BITS == 64 1012 # if TARGET_LONG_BITS == 64
1022 int addr_reg2; 1013 int addr_reg2;
1023 # endif 1014 # endif
1024 -# ifdef USE_TLB  
1025 uint32_t *label_ptr; 1015 uint32_t *label_ptr;
1026 -# endif  
1027 #endif 1016 #endif
1028 1017
1029 data_reg = *args++; 1018 data_reg = *args++;
@@ -1039,14 +1028,13 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, @@ -1039,14 +1028,13 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
1039 mem_index = *args; 1028 mem_index = *args;
1040 s_bits = opc & 3; 1029 s_bits = opc & 3;
1041 1030
1042 -# ifdef USE_TLB  
1043 /* Should generate something like the following: 1031 /* Should generate something like the following:
1044 - * ror r8, addr_reg, #TARGET_PAGE_BITS 1032 + * shr r8, addr_reg, #TARGET_PAGE_BITS
1045 * and r0, r8, #(CPU_TLB_SIZE - 1) @ Assumption: CPU_TLB_BITS <= 8 1033 * and r0, r8, #(CPU_TLB_SIZE - 1) @ Assumption: CPU_TLB_BITS <= 8
1046 - * add r0, T0, r0 lsl #CPU_TLB_ENTRY_BITS 1034 + * add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
1047 */ 1035 */
1048 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 1036 tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1049 - 8, 0, addr_reg, SHIFT_IMM_ROR(TARGET_PAGE_BITS)); 1037 + 8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1050 tcg_out_dat_imm(s, COND_AL, ARITH_AND, 1038 tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1051 0, 8, CPU_TLB_SIZE - 1); 1039 0, 8, CPU_TLB_SIZE - 1);
1052 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, 1040 tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
@@ -1066,11 +1054,10 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, @@ -1066,11 +1054,10 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
1066 offsetof(CPUState, tlb_table[0][0].addr_write)); 1054 offsetof(CPUState, tlb_table[0][0].addr_write));
1067 tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 1055 tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
1068 0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS)); 1056 0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1069 - /* TODO: alignment check?  
1070 - * if (s_bits)  
1071 - * tcg_out_data_reg(s, COND_EQ, ARITH_EOR,  
1072 - * 0, 1, 8, SHIFT_IMM_LSR(32 - s_bits));  
1073 - */ 1057 + /* Check alignment. */
  1058 + if (s_bits)
  1059 + tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
  1060 + 0, addr_reg, (1 << s_bits) - 1);
1074 # if TARGET_LONG_BITS == 64 1061 # if TARGET_LONG_BITS == 64
1075 /* XXX: possibly we could use a block data load or writeback in 1062 /* XXX: possibly we could use a block data load or writeback in
1076 * the first access. */ 1063 * the first access. */
@@ -1101,15 +1088,13 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, @@ -1101,15 +1088,13 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
1101 tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, 1); 1088 tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, 1);
1102 break; 1089 break;
1103 case 3: 1090 case 3:
1104 - /* TODO: must write back */  
1105 - tcg_out_st32_r(s, COND_EQ, data_reg, 1, addr_reg); 1091 + tcg_out_st32_rwb(s, COND_EQ, data_reg, 1, addr_reg);
1106 tcg_out_st32_12(s, COND_EQ, data_reg2, 1, 4); 1092 tcg_out_st32_12(s, COND_EQ, data_reg2, 1, 4);
1107 break; 1093 break;
1108 } 1094 }
1109 1095
1110 label_ptr = (void *) s->code_ptr; 1096 label_ptr = (void *) s->code_ptr;
1111 tcg_out_b(s, COND_EQ, 8); 1097 tcg_out_b(s, COND_EQ, 8);
1112 -# endif  
1113 1098
1114 /* TODO: move this code to where the constants pool will be */ 1099 /* TODO: move this code to where the constants pool will be */
1115 if (addr_reg) 1100 if (addr_reg)
@@ -1195,9 +1180,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, @@ -1195,9 +1180,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
1195 tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0)); 1180 tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
1196 # endif 1181 # endif
1197 1182
1198 -# ifdef USE_TLB  
1199 *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; 1183 *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
1200 -# endif  
1201 #else 1184 #else
1202 switch (opc) { 1185 switch (opc) {
1203 case 0: 1186 case 0:
@@ -1512,12 +1495,12 @@ static const TCGTargetOpDef arm_op_defs[] = { @@ -1512,12 +1495,12 @@ static const TCGTargetOpDef arm_op_defs[] = {
1512 { INDEX_op_qemu_ld16u, { "r", "x", "X" } }, 1495 { INDEX_op_qemu_ld16u, { "r", "x", "X" } },
1513 { INDEX_op_qemu_ld16s, { "r", "x", "X" } }, 1496 { INDEX_op_qemu_ld16s, { "r", "x", "X" } },
1514 { INDEX_op_qemu_ld32u, { "r", "x", "X" } }, 1497 { INDEX_op_qemu_ld32u, { "r", "x", "X" } },
1515 - { INDEX_op_qemu_ld64, { "r", "d", "x", "X" } }, 1498 + { INDEX_op_qemu_ld64, { "x", "r", "x", "X" } },
1516 1499
1517 - { INDEX_op_qemu_st8, { "d", "x", "X" } },  
1518 - { INDEX_op_qemu_st16, { "d", "x", "X" } },  
1519 - { INDEX_op_qemu_st32, { "d", "x", "X" } },  
1520 - { INDEX_op_qemu_st64, { "d", "D", "x", "X" } }, 1500 + { INDEX_op_qemu_st8, { "x", "x", "X" } },
  1501 + { INDEX_op_qemu_st16, { "x", "x", "X" } },
  1502 + { INDEX_op_qemu_st32, { "x", "x", "X" } },
  1503 + { INDEX_op_qemu_st64, { "x", "D", "x", "X" } },
1521 1504
1522 { INDEX_op_ext8s_i32, { "r", "r" } }, 1505 { INDEX_op_ext8s_i32, { "r", "r" } },
1523 { INDEX_op_ext16s_i32, { "r", "r" } }, 1506 { INDEX_op_ext16s_i32, { "r", "r" } },