Commit cf360a32af84ee473b4bcba1dcaa4646f10ef937
1 parent
bdb4b689
target-ppc: convert load/store with reservation instructions to TCG
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5830 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
72 additions
and
264 deletions
target-ppc/op_mem.h
... | ... | @@ -20,232 +20,6 @@ |
20 | 20 | |
21 | 21 | #include "op_mem_access.h" |
22 | 22 | |
23 | -/* Load and set reservation */ | |
24 | -void OPPROTO glue(op_lwarx, MEMSUFFIX) (void) | |
25 | -{ | |
26 | - if (unlikely(T0 & 0x03)) { | |
27 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
28 | - } else { | |
29 | - T1 = glue(ldu32, MEMSUFFIX)((uint32_t)T0); | |
30 | - env->reserve = (uint32_t)T0; | |
31 | - } | |
32 | - RETURN(); | |
33 | -} | |
34 | - | |
35 | -#if defined(TARGET_PPC64) | |
36 | -void OPPROTO glue(op_lwarx_64, MEMSUFFIX) (void) | |
37 | -{ | |
38 | - if (unlikely(T0 & 0x03)) { | |
39 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
40 | - } else { | |
41 | - T1 = glue(ldu32, MEMSUFFIX)((uint64_t)T0); | |
42 | - env->reserve = (uint64_t)T0; | |
43 | - } | |
44 | - RETURN(); | |
45 | -} | |
46 | - | |
47 | -void OPPROTO glue(op_ldarx, MEMSUFFIX) (void) | |
48 | -{ | |
49 | - if (unlikely(T0 & 0x03)) { | |
50 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
51 | - } else { | |
52 | - T1 = glue(ldu64, MEMSUFFIX)((uint32_t)T0); | |
53 | - env->reserve = (uint32_t)T0; | |
54 | - } | |
55 | - RETURN(); | |
56 | -} | |
57 | - | |
58 | -void OPPROTO glue(op_ldarx_64, MEMSUFFIX) (void) | |
59 | -{ | |
60 | - if (unlikely(T0 & 0x03)) { | |
61 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
62 | - } else { | |
63 | - T1 = glue(ldu64, MEMSUFFIX)((uint64_t)T0); | |
64 | - env->reserve = (uint64_t)T0; | |
65 | - } | |
66 | - RETURN(); | |
67 | -} | |
68 | -#endif | |
69 | - | |
70 | -void OPPROTO glue(op_lwarx_le, MEMSUFFIX) (void) | |
71 | -{ | |
72 | - if (unlikely(T0 & 0x03)) { | |
73 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
74 | - } else { | |
75 | - T1 = glue(ldu32r, MEMSUFFIX)((uint32_t)T0); | |
76 | - env->reserve = (uint32_t)T0; | |
77 | - } | |
78 | - RETURN(); | |
79 | -} | |
80 | - | |
81 | -#if defined(TARGET_PPC64) | |
82 | -void OPPROTO glue(op_lwarx_le_64, MEMSUFFIX) (void) | |
83 | -{ | |
84 | - if (unlikely(T0 & 0x03)) { | |
85 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
86 | - } else { | |
87 | - T1 = glue(ldu32r, MEMSUFFIX)((uint64_t)T0); | |
88 | - env->reserve = (uint64_t)T0; | |
89 | - } | |
90 | - RETURN(); | |
91 | -} | |
92 | - | |
93 | -void OPPROTO glue(op_ldarx_le, MEMSUFFIX) (void) | |
94 | -{ | |
95 | - if (unlikely(T0 & 0x03)) { | |
96 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
97 | - } else { | |
98 | - T1 = glue(ldu64r, MEMSUFFIX)((uint32_t)T0); | |
99 | - env->reserve = (uint32_t)T0; | |
100 | - } | |
101 | - RETURN(); | |
102 | -} | |
103 | - | |
104 | -void OPPROTO glue(op_ldarx_le_64, MEMSUFFIX) (void) | |
105 | -{ | |
106 | - if (unlikely(T0 & 0x03)) { | |
107 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
108 | - } else { | |
109 | - T1 = glue(ldu64r, MEMSUFFIX)((uint64_t)T0); | |
110 | - env->reserve = (uint64_t)T0; | |
111 | - } | |
112 | - RETURN(); | |
113 | -} | |
114 | -#endif | |
115 | - | |
116 | -/* Store with reservation */ | |
117 | -void OPPROTO glue(op_stwcx, MEMSUFFIX) (void) | |
118 | -{ | |
119 | - if (unlikely(T0 & 0x03)) { | |
120 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
121 | - } else { | |
122 | - if (unlikely(env->reserve != (uint32_t)T0)) { | |
123 | - env->crf[0] = xer_so; | |
124 | - } else { | |
125 | - glue(st32, MEMSUFFIX)((uint32_t)T0, T1); | |
126 | - env->crf[0] = xer_so | 0x02; | |
127 | - } | |
128 | - } | |
129 | - env->reserve = (target_ulong)-1ULL; | |
130 | - RETURN(); | |
131 | -} | |
132 | - | |
133 | -#if defined(TARGET_PPC64) | |
134 | -void OPPROTO glue(op_stwcx_64, MEMSUFFIX) (void) | |
135 | -{ | |
136 | - if (unlikely(T0 & 0x03)) { | |
137 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
138 | - } else { | |
139 | - if (unlikely(env->reserve != (uint64_t)T0)) { | |
140 | - env->crf[0] = xer_so; | |
141 | - } else { | |
142 | - glue(st32, MEMSUFFIX)((uint64_t)T0, T1); | |
143 | - env->crf[0] = xer_so | 0x02; | |
144 | - } | |
145 | - } | |
146 | - env->reserve = (target_ulong)-1ULL; | |
147 | - RETURN(); | |
148 | -} | |
149 | - | |
150 | -void OPPROTO glue(op_stdcx, MEMSUFFIX) (void) | |
151 | -{ | |
152 | - if (unlikely(T0 & 0x03)) { | |
153 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
154 | - } else { | |
155 | - if (unlikely(env->reserve != (uint32_t)T0)) { | |
156 | - env->crf[0] = xer_so; | |
157 | - } else { | |
158 | - glue(st64, MEMSUFFIX)((uint32_t)T0, T1); | |
159 | - env->crf[0] = xer_so | 0x02; | |
160 | - } | |
161 | - } | |
162 | - env->reserve = (target_ulong)-1ULL; | |
163 | - RETURN(); | |
164 | -} | |
165 | - | |
166 | -void OPPROTO glue(op_stdcx_64, MEMSUFFIX) (void) | |
167 | -{ | |
168 | - if (unlikely(T0 & 0x03)) { | |
169 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
170 | - } else { | |
171 | - if (unlikely(env->reserve != (uint64_t)T0)) { | |
172 | - env->crf[0] = xer_so; | |
173 | - } else { | |
174 | - glue(st64, MEMSUFFIX)((uint64_t)T0, T1); | |
175 | - env->crf[0] = xer_so | 0x02; | |
176 | - } | |
177 | - } | |
178 | - env->reserve = (target_ulong)-1ULL; | |
179 | - RETURN(); | |
180 | -} | |
181 | -#endif | |
182 | - | |
183 | -void OPPROTO glue(op_stwcx_le, MEMSUFFIX) (void) | |
184 | -{ | |
185 | - if (unlikely(T0 & 0x03)) { | |
186 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
187 | - } else { | |
188 | - if (unlikely(env->reserve != (uint32_t)T0)) { | |
189 | - env->crf[0] = xer_so; | |
190 | - } else { | |
191 | - glue(st32r, MEMSUFFIX)((uint32_t)T0, T1); | |
192 | - env->crf[0] = xer_so | 0x02; | |
193 | - } | |
194 | - } | |
195 | - env->reserve = (target_ulong)-1ULL; | |
196 | - RETURN(); | |
197 | -} | |
198 | - | |
199 | -#if defined(TARGET_PPC64) | |
200 | -void OPPROTO glue(op_stwcx_le_64, MEMSUFFIX) (void) | |
201 | -{ | |
202 | - if (unlikely(T0 & 0x03)) { | |
203 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
204 | - } else { | |
205 | - if (unlikely(env->reserve != (uint64_t)T0)) { | |
206 | - env->crf[0] = xer_so; | |
207 | - } else { | |
208 | - glue(st32r, MEMSUFFIX)((uint64_t)T0, T1); | |
209 | - env->crf[0] = xer_so | 0x02; | |
210 | - } | |
211 | - } | |
212 | - env->reserve = (target_ulong)-1ULL; | |
213 | - RETURN(); | |
214 | -} | |
215 | - | |
216 | -void OPPROTO glue(op_stdcx_le, MEMSUFFIX) (void) | |
217 | -{ | |
218 | - if (unlikely(T0 & 0x03)) { | |
219 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
220 | - } else { | |
221 | - if (unlikely(env->reserve != (uint32_t)T0)) { | |
222 | - env->crf[0] = xer_so; | |
223 | - } else { | |
224 | - glue(st64r, MEMSUFFIX)((uint32_t)T0, T1); | |
225 | - env->crf[0] = xer_so | 0x02; | |
226 | - } | |
227 | - } | |
228 | - env->reserve = (target_ulong)-1ULL; | |
229 | - RETURN(); | |
230 | -} | |
231 | - | |
232 | -void OPPROTO glue(op_stdcx_le_64, MEMSUFFIX) (void) | |
233 | -{ | |
234 | - if (unlikely(T0 & 0x03)) { | |
235 | - raise_exception(env, POWERPC_EXCP_ALIGN); | |
236 | - } else { | |
237 | - if (unlikely(env->reserve != (uint64_t)T0)) { | |
238 | - env->crf[0] = xer_so; | |
239 | - } else { | |
240 | - glue(st64r, MEMSUFFIX)((uint64_t)T0, T1); | |
241 | - env->crf[0] = xer_so | 0x02; | |
242 | - } | |
243 | - } | |
244 | - env->reserve = (target_ulong)-1ULL; | |
245 | - RETURN(); | |
246 | -} | |
247 | -#endif | |
248 | - | |
249 | 23 | /* External access */ |
250 | 24 | void OPPROTO glue(op_eciwx, MEMSUFFIX) (void) |
251 | 25 | { | ... | ... |
target-ppc/translate.c
... | ... | @@ -66,6 +66,7 @@ static TCGv cpu_nip; |
66 | 66 | static TCGv cpu_ctr; |
67 | 67 | static TCGv cpu_lr; |
68 | 68 | static TCGv cpu_xer; |
69 | +static TCGv cpu_reserve; | |
69 | 70 | static TCGv_i32 cpu_fpscr; |
70 | 71 | static TCGv_i32 cpu_access_type; |
71 | 72 | |
... | ... | @@ -161,6 +162,9 @@ void ppc_translate_init(void) |
161 | 162 | cpu_xer = tcg_global_mem_new(TCG_AREG0, |
162 | 163 | offsetof(CPUState, xer), "xer"); |
163 | 164 | |
165 | + cpu_reserve = tcg_global_mem_new(TCG_AREG0, | |
166 | + offsetof(CPUState, reserve), "reserve"); | |
167 | + | |
164 | 168 | cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0, |
165 | 169 | offsetof(CPUState, fpscr), "fpscr"); |
166 | 170 | |
... | ... | @@ -2468,6 +2472,24 @@ static always_inline void gen_addr_register (TCGv EA, |
2468 | 2472 | tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]); |
2469 | 2473 | } |
2470 | 2474 | |
2475 | +static always_inline void gen_check_align (DisasContext *ctx, TCGv EA, int mask) | |
2476 | +{ | |
2477 | + int l1 = gen_new_label(); | |
2478 | + TCGv t0 = tcg_temp_new(); | |
2479 | + TCGv_i32 t1, t2; | |
2480 | + /* NIP cannot be restored if the memory exception comes from an helper */ | |
2481 | + gen_update_nip(ctx, ctx->nip - 4); | |
2482 | + tcg_gen_andi_tl(t0, EA, mask); | |
2483 | + tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); | |
2484 | + t1 = tcg_const_i32(POWERPC_EXCP_ALIGN); | |
2485 | + t2 = tcg_const_i32(0); | |
2486 | + gen_helper_raise_exception_err(t1, t2); | |
2487 | + tcg_temp_free_i32(t1); | |
2488 | + tcg_temp_free_i32(t2); | |
2489 | + gen_set_label(l1); | |
2490 | + tcg_temp_free(t0); | |
2491 | +} | |
2492 | + | |
2471 | 2493 | #if defined(TARGET_PPC64) |
2472 | 2494 | #define _GEN_MEM_FUNCS(name, mode) \ |
2473 | 2495 | &gen_op_##name##_##mode, \ |
... | ... | @@ -3220,67 +3242,79 @@ GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM) |
3220 | 3242 | GEN_STOP(ctx); |
3221 | 3243 | } |
3222 | 3244 | |
3223 | -#define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])() | |
3224 | -#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])() | |
3225 | -static GenOpFunc *gen_op_lwarx[NB_MEM_FUNCS] = { | |
3226 | - GEN_MEM_FUNCS(lwarx), | |
3227 | -}; | |
3228 | -static GenOpFunc *gen_op_stwcx[NB_MEM_FUNCS] = { | |
3229 | - GEN_MEM_FUNCS(stwcx), | |
3230 | -}; | |
3231 | - | |
3232 | 3245 | /* lwarx */ |
3233 | 3246 | GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES) |
3234 | 3247 | { |
3235 | - /* NIP cannot be restored if the memory exception comes from an helper */ | |
3236 | - gen_update_nip(ctx, ctx->nip - 4); | |
3248 | + TCGv t0 = tcg_temp_local_new(); | |
3237 | 3249 | gen_set_access_type(ACCESS_RES); |
3238 | - gen_addr_reg_index(cpu_T[0], ctx); | |
3239 | - op_lwarx(); | |
3240 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); | |
3250 | + gen_addr_reg_index(t0, ctx); | |
3251 | + gen_check_align(ctx, t0, 0x03); | |
3252 | +#if defined(TARGET_PPC64) | |
3253 | + if (!ctx->sf_mode) | |
3254 | + tcg_gen_ext32u_tl(t0, t0); | |
3255 | +#endif | |
3256 | + gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx); | |
3257 | + tcg_gen_mov_tl(cpu_reserve, t0); | |
3258 | + tcg_temp_free(t0); | |
3241 | 3259 | } |
3242 | 3260 | |
3243 | 3261 | /* stwcx. */ |
3244 | 3262 | GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES) |
3245 | 3263 | { |
3246 | - /* NIP cannot be restored if the memory exception comes from an helper */ | |
3247 | - gen_update_nip(ctx, ctx->nip - 4); | |
3264 | + int l1 = gen_new_label(); | |
3265 | + TCGv t0 = tcg_temp_local_new(); | |
3248 | 3266 | gen_set_access_type(ACCESS_RES); |
3249 | - gen_addr_reg_index(cpu_T[0], ctx); | |
3250 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); | |
3251 | - op_stwcx(); | |
3267 | + gen_addr_reg_index(t0, ctx); | |
3268 | + gen_check_align(ctx, t0, 0x03); | |
3269 | +#if defined(TARGET_PPC64) | |
3270 | + if (!ctx->sf_mode) | |
3271 | + tcg_gen_ext32u_tl(t0, t0); | |
3272 | +#endif | |
3273 | + tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); | |
3274 | + tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); | |
3275 | + tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); | |
3276 | + tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1); | |
3277 | + tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); | |
3278 | + gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], t0, ctx->mem_idx); | |
3279 | + gen_set_label(l1); | |
3280 | + tcg_gen_movi_tl(cpu_reserve, -1); | |
3281 | + tcg_temp_free(t0); | |
3252 | 3282 | } |
3253 | 3283 | |
3254 | 3284 | #if defined(TARGET_PPC64) |
3255 | -#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])() | |
3256 | -#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])() | |
3257 | -static GenOpFunc *gen_op_ldarx[NB_MEM_FUNCS] = { | |
3258 | - GEN_MEM_FUNCS(ldarx), | |
3259 | -}; | |
3260 | -static GenOpFunc *gen_op_stdcx[NB_MEM_FUNCS] = { | |
3261 | - GEN_MEM_FUNCS(stdcx), | |
3262 | -}; | |
3263 | - | |
3264 | 3285 | /* ldarx */ |
3265 | 3286 | GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B) |
3266 | 3287 | { |
3267 | - /* NIP cannot be restored if the memory exception comes from an helper */ | |
3268 | - gen_update_nip(ctx, ctx->nip - 4); | |
3288 | + TCGv t0 = tcg_temp_local_new(); | |
3269 | 3289 | gen_set_access_type(ACCESS_RES); |
3270 | - gen_addr_reg_index(cpu_T[0], ctx); | |
3271 | - op_ldarx(); | |
3272 | - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); | |
3290 | + gen_addr_reg_index(t0, ctx); | |
3291 | + gen_check_align(ctx, t0, 0x07); | |
3292 | + if (!ctx->sf_mode) | |
3293 | + tcg_gen_ext32u_tl(t0, t0); | |
3294 | + gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx); | |
3295 | + tcg_gen_mov_tl(cpu_reserve, t0); | |
3296 | + tcg_temp_free(t0); | |
3273 | 3297 | } |
3274 | 3298 | |
3275 | 3299 | /* stdcx. */ |
3276 | 3300 | GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B) |
3277 | 3301 | { |
3278 | - /* NIP cannot be restored if the memory exception comes from an helper */ | |
3279 | - gen_update_nip(ctx, ctx->nip - 4); | |
3302 | + int l1 = gen_new_label(); | |
3303 | + TCGv t0 = tcg_temp_local_new(); | |
3280 | 3304 | gen_set_access_type(ACCESS_RES); |
3281 | - gen_addr_reg_index(cpu_T[0], ctx); | |
3282 | - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); | |
3283 | - op_stdcx(); | |
3305 | + gen_addr_reg_index(t0, ctx); | |
3306 | + gen_check_align(ctx, t0, 0x07); | |
3307 | + if (!ctx->sf_mode) | |
3308 | + tcg_gen_ext32u_tl(t0, t0); | |
3309 | + tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); | |
3310 | + tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); | |
3311 | + tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); | |
3312 | + tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1); | |
3313 | + tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); | |
3314 | + gen_qemu_st64(cpu_gpr[rS(ctx->opcode)], t0, ctx->mem_idx); | |
3315 | + gen_set_label(l1); | |
3316 | + tcg_gen_movi_tl(cpu_reserve, -1); | |
3317 | + tcg_temp_free(t0); | |
3284 | 3318 | } |
3285 | 3319 | #endif /* defined(TARGET_PPC64) */ |
3286 | 3320 | ... | ... |