Révision | eed142195c95a6c50545fa7a28e725d780ab9636 (tree) |
---|---|
l'heure | 2018-01-31 22:30:50 |
Auteur | Richard Henderson <richard.henderson@lina...> |
Commiter | Richard Henderson |
target/hppa: Implement PROBE for system mode
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
@@ -17,8 +17,7 @@ DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tr) | ||
17 | 17 | DEF_HELPER_FLAGS_3(stby_e, TCG_CALL_NO_WG, void, env, tl, tr) |
18 | 18 | DEF_HELPER_FLAGS_3(stby_e_parallel, TCG_CALL_NO_WG, void, env, tl, tr) |
19 | 19 | |
20 | -DEF_HELPER_FLAGS_1(probe_r, TCG_CALL_NO_RWG_SE, tr, tl) | |
21 | -DEF_HELPER_FLAGS_1(probe_w, TCG_CALL_NO_RWG_SE, tr, tl) | |
20 | +DEF_HELPER_FLAGS_4(probe, TCG_CALL_NO_WG, tr, env, tl, i32, i32) | |
22 | 21 | |
23 | 22 | DEF_HELPER_FLAGS_1(loaded_fr0, TCG_CALL_NO_RWG, void, env) |
24 | 23 |
@@ -160,21 +160,33 @@ void HELPER(stby_e_parallel)(CPUHPPAState *env, target_ulong addr, | ||
160 | 160 | do_stby_e(env, addr, val, true); |
161 | 161 | } |
162 | 162 | |
163 | -target_ureg HELPER(probe_r)(target_ulong addr) | |
163 | +target_ureg HELPER(probe)(CPUHPPAState *env, target_ulong addr, | |
164 | + uint32_t level, uint32_t want) | |
164 | 165 | { |
165 | 166 | #ifdef CONFIG_USER_ONLY |
166 | - return page_check_range(addr, 1, PAGE_READ); | |
167 | + return page_check_range(addr, 1, want); | |
167 | 168 | #else |
168 | - return 1; /* FIXME */ | |
169 | -#endif | |
170 | -} | |
169 | + int prot, excp; | |
170 | + hwaddr phys; | |
171 | 171 | |
172 | -target_ureg HELPER(probe_w)(target_ulong addr) | |
173 | -{ | |
174 | -#ifdef CONFIG_USER_ONLY | |
175 | - return page_check_range(addr, 1, PAGE_WRITE); | |
176 | -#else | |
177 | - return 1; /* FIXME */ | |
172 | + /* Fail if the requested privilege level is higher than current. */ | |
173 | + if (level < (env->iaoq_f & 3)) { | |
174 | + return 0; | |
175 | + } | |
176 | + | |
177 | + excp = hppa_get_physical_address(env, addr, level, 0, &phys, &prot); | |
178 | + if (excp >= 0) { | |
179 | + if (env->psw & PSW_Q) { | |
180 | + /* ??? Needs tweaking for hppa64. */ | |
181 | + env->cr[CR_IOR] = addr; | |
182 | + env->cr[CR_ISR] = addr >> 32; | |
183 | + } | |
184 | + if (excp == EXCP_DTLB_MISS) { | |
185 | + excp = EXCP_NA_DTLB_MISS; | |
186 | + } | |
187 | + hppa_dynamic_excp(env, excp, GETPC()); | |
188 | + } | |
189 | + return (want & prot) != 0; | |
178 | 190 | #endif |
179 | 191 | } |
180 | 192 |
@@ -2380,21 +2380,33 @@ static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn, | ||
2380 | 2380 | { |
2381 | 2381 | unsigned rt = extract32(insn, 0, 5); |
2382 | 2382 | unsigned sp = extract32(insn, 14, 2); |
2383 | + unsigned rr = extract32(insn, 16, 5); | |
2383 | 2384 | unsigned rb = extract32(insn, 21, 5); |
2384 | 2385 | unsigned is_write = extract32(insn, 6, 1); |
2386 | + unsigned is_imm = extract32(insn, 13, 1); | |
2385 | 2387 | TCGv_reg dest, ofs; |
2388 | + TCGv_i32 level, want; | |
2386 | 2389 | TCGv_tl addr; |
2387 | 2390 | |
2388 | 2391 | nullify_over(ctx); |
2389 | 2392 | |
2390 | - /* ??? Do something with priv level operand. */ | |
2391 | 2393 | dest = dest_gpr(ctx, rt); |
2392 | 2394 | form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false); |
2393 | - if (is_write) { | |
2394 | - gen_helper_probe_w(dest, addr); | |
2395 | + | |
2396 | + if (is_imm) { | |
2397 | + level = tcg_const_i32(extract32(insn, 16, 2)); | |
2395 | 2398 | } else { |
2396 | - gen_helper_probe_r(dest, addr); | |
2399 | + level = tcg_temp_new_i32(); | |
2400 | + tcg_gen_trunc_reg_i32(level, load_gpr(ctx, rr)); | |
2401 | + tcg_gen_andi_i32(level, level, 3); | |
2397 | 2402 | } |
2403 | + want = tcg_const_i32(is_write ? PAGE_WRITE : PAGE_READ); | |
2404 | + | |
2405 | + gen_helper_probe(dest, cpu_env, addr, level, want); | |
2406 | + | |
2407 | + tcg_temp_free_i32(want); | |
2408 | + tcg_temp_free_i32(level); | |
2409 | + | |
2398 | 2410 | save_gpr(ctx, rt, dest); |
2399 | 2411 | return nullify_end(ctx, DISAS_NEXT); |
2400 | 2412 | } |