2 * Helpers for HPPA instructions.
4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
23 #include "exec/exec-all.h"
24 #include "exec/helper-proto.h"
25 #include "exec/cpu_ldst.h"
26 #include "qemu/timer.h"
29 G_NORETURN
void HELPER(excp
)(CPUHPPAState
*env
, int excp
)
31 CPUState
*cs
= env_cpu(env
);
33 cs
->exception_index
= excp
;
37 G_NORETURN
void hppa_dynamic_excp(CPUHPPAState
*env
, int excp
, uintptr_t ra
)
39 CPUState
*cs
= env_cpu(env
);
41 cs
->exception_index
= excp
;
42 cpu_loop_exit_restore(cs
, ra
);
45 static void atomic_store_mask32(CPUHPPAState
*env
, target_ulong addr
,
46 uint32_t val
, uint32_t mask
, uintptr_t ra
)
48 int mmu_idx
= cpu_mmu_index(env_cpu(env
), 0);
49 uint32_t old
, new, cmp
, *haddr
;
52 vaddr
= probe_access(env
, addr
, 3, MMU_DATA_STORE
, mmu_idx
, ra
);
54 cpu_loop_exit_atomic(env_cpu(env
), ra
);
56 haddr
= (uint32_t *)((uintptr_t)vaddr
& -4);
57 mask
= addr
& 1 ? 0x00ffffffu
: 0xffffff00u
;
61 new = be32_to_cpu((cpu_to_be32(old
) & ~mask
) | (val
& mask
));
62 cmp
= qatomic_cmpxchg(haddr
, old
, new);
70 static void atomic_store_mask64(CPUHPPAState
*env
, target_ulong addr
,
71 uint64_t val
, uint64_t mask
,
72 int size
, uintptr_t ra
)
74 #ifdef CONFIG_ATOMIC64
75 int mmu_idx
= cpu_mmu_index(env_cpu(env
), 0);
76 uint64_t old
, new, cmp
, *haddr
;
79 vaddr
= probe_access(env
, addr
, size
, MMU_DATA_STORE
, mmu_idx
, ra
);
81 cpu_loop_exit_atomic(env_cpu(env
), ra
);
83 haddr
= (uint64_t *)((uintptr_t)vaddr
& -8);
87 new = be32_to_cpu((cpu_to_be32(old
) & ~mask
) | (val
& mask
));
88 cmp
= qatomic_cmpxchg__nocheck(haddr
, old
, new);
95 cpu_loop_exit_atomic(env_cpu(env
), ra
);
99 static void do_stby_b(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
,
100 bool parallel
, uintptr_t ra
)
104 cpu_stb_data_ra(env
, addr
, val
, ra
);
107 cpu_stw_data_ra(env
, addr
, val
, ra
);
110 /* The 3 byte store must appear atomic. */
112 atomic_store_mask32(env
, addr
, val
, 0x00ffffffu
, ra
);
114 cpu_stb_data_ra(env
, addr
, val
>> 16, ra
);
115 cpu_stw_data_ra(env
, addr
+ 1, val
, ra
);
119 cpu_stl_data_ra(env
, addr
, val
, ra
);
124 static void do_stdby_b(CPUHPPAState
*env
, target_ulong addr
, uint64_t val
,
125 bool parallel
, uintptr_t ra
)
129 cpu_stb_data_ra(env
, addr
, val
, ra
);
132 cpu_stw_data_ra(env
, addr
, val
, ra
);
135 /* The 3 byte store must appear atomic. */
137 atomic_store_mask32(env
, addr
, val
, 0x00ffffffu
, ra
);
139 cpu_stb_data_ra(env
, addr
, val
>> 16, ra
);
140 cpu_stw_data_ra(env
, addr
+ 1, val
, ra
);
144 cpu_stl_data_ra(env
, addr
, val
, ra
);
147 /* The 5 byte store must appear atomic. */
149 atomic_store_mask64(env
, addr
, val
, 0x000000ffffffffffull
, 5, ra
);
151 cpu_stb_data_ra(env
, addr
, val
>> 32, ra
);
152 cpu_stl_data_ra(env
, addr
+ 1, val
, ra
);
156 /* The 6 byte store must appear atomic. */
158 atomic_store_mask64(env
, addr
, val
, 0x0000ffffffffffffull
, 6, ra
);
160 cpu_stw_data_ra(env
, addr
, val
>> 32, ra
);
161 cpu_stl_data_ra(env
, addr
+ 2, val
, ra
);
165 /* The 7 byte store must appear atomic. */
167 atomic_store_mask64(env
, addr
, val
, 0x00ffffffffffffffull
, 7, ra
);
169 cpu_stb_data_ra(env
, addr
, val
>> 48, ra
);
170 cpu_stw_data_ra(env
, addr
+ 1, val
>> 32, ra
);
171 cpu_stl_data_ra(env
, addr
+ 3, val
, ra
);
175 cpu_stq_data_ra(env
, addr
, val
, ra
);
180 void HELPER(stby_b
)(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
)
182 do_stby_b(env
, addr
, val
, false, GETPC());
185 void HELPER(stby_b_parallel
)(CPUHPPAState
*env
, target_ulong addr
,
188 do_stby_b(env
, addr
, val
, true, GETPC());
191 void HELPER(stdby_b
)(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
)
193 do_stdby_b(env
, addr
, val
, false, GETPC());
196 void HELPER(stdby_b_parallel
)(CPUHPPAState
*env
, target_ulong addr
,
199 do_stdby_b(env
, addr
, val
, true, GETPC());
202 static void do_stby_e(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
,
203 bool parallel
, uintptr_t ra
)
207 /* The 3 byte store must appear atomic. */
209 atomic_store_mask32(env
, addr
- 3, val
, 0xffffff00u
, ra
);
211 cpu_stw_data_ra(env
, addr
- 3, val
>> 16, ra
);
212 cpu_stb_data_ra(env
, addr
- 1, val
>> 8, ra
);
216 cpu_stw_data_ra(env
, addr
- 2, val
>> 16, ra
);
219 cpu_stb_data_ra(env
, addr
- 1, val
>> 24, ra
);
222 /* Nothing is stored, but protection is checked and the
223 cacheline is marked dirty. */
224 probe_write(env
, addr
, 0, cpu_mmu_index(env_cpu(env
), 0), ra
);
229 static void do_stdby_e(CPUHPPAState
*env
, target_ulong addr
, uint64_t val
,
230 bool parallel
, uintptr_t ra
)
234 /* The 7 byte store must appear atomic. */
236 atomic_store_mask64(env
, addr
- 7, val
,
237 0xffffffffffffff00ull
, 7, ra
);
239 cpu_stl_data_ra(env
, addr
- 7, val
>> 32, ra
);
240 cpu_stw_data_ra(env
, addr
- 3, val
>> 16, ra
);
241 cpu_stb_data_ra(env
, addr
- 1, val
>> 8, ra
);
245 /* The 6 byte store must appear atomic. */
247 atomic_store_mask64(env
, addr
- 6, val
,
248 0xffffffffffff0000ull
, 6, ra
);
250 cpu_stl_data_ra(env
, addr
- 6, val
>> 32, ra
);
251 cpu_stw_data_ra(env
, addr
- 2, val
>> 16, ra
);
255 /* The 5 byte store must appear atomic. */
257 atomic_store_mask64(env
, addr
- 5, val
,
258 0xffffffffff000000ull
, 5, ra
);
260 cpu_stl_data_ra(env
, addr
- 5, val
>> 32, ra
);
261 cpu_stb_data_ra(env
, addr
- 1, val
>> 24, ra
);
265 cpu_stl_data_ra(env
, addr
- 4, val
>> 32, ra
);
268 /* The 3 byte store must appear atomic. */
270 atomic_store_mask32(env
, addr
- 3, val
>> 32, 0xffffff00u
, ra
);
272 cpu_stw_data_ra(env
, addr
- 3, val
>> 48, ra
);
273 cpu_stb_data_ra(env
, addr
- 1, val
>> 40, ra
);
277 cpu_stw_data_ra(env
, addr
- 2, val
>> 48, ra
);
280 cpu_stb_data_ra(env
, addr
- 1, val
>> 56, ra
);
283 /* Nothing is stored, but protection is checked and the
284 cacheline is marked dirty. */
285 probe_write(env
, addr
, 0, cpu_mmu_index(env_cpu(env
), 0), ra
);
290 void HELPER(stby_e
)(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
)
292 do_stby_e(env
, addr
, val
, false, GETPC());
295 void HELPER(stby_e_parallel
)(CPUHPPAState
*env
, target_ulong addr
,
298 do_stby_e(env
, addr
, val
, true, GETPC());
301 void HELPER(stdby_e
)(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
)
303 do_stdby_e(env
, addr
, val
, false, GETPC());
306 void HELPER(stdby_e_parallel
)(CPUHPPAState
*env
, target_ulong addr
,
309 do_stdby_e(env
, addr
, val
, true, GETPC());
312 void HELPER(ldc_check
)(target_ulong addr
)
314 if (unlikely(addr
& 0xf)) {
315 qemu_log_mask(LOG_GUEST_ERROR
,
316 "Undefined ldc to unaligned address mod 16: "
317 TARGET_FMT_lx
"\n", addr
);
321 target_ulong
HELPER(probe
)(CPUHPPAState
*env
, target_ulong addr
,
322 uint32_t level
, uint32_t want
)
324 #ifdef CONFIG_USER_ONLY
325 return page_check_range(addr
, 1, want
);
327 int prot
, excp
, mmu_idx
;
330 trace_hppa_tlb_probe(addr
, level
, want
);
331 /* Fail if the requested privilege level is higher than current. */
332 if (level
< (env
->iaoq_f
& 3)) {
336 mmu_idx
= PRIV_P_TO_MMU_IDX(level
, env
->psw
& PSW_P
);
337 excp
= hppa_get_physical_address(env
, addr
, mmu_idx
, 0, 0, &phys
, &prot
);
339 cpu_restore_state(env_cpu(env
), GETPC());
340 hppa_set_ior_and_isr(env
, addr
, MMU_IDX_MMU_DISABLED(mmu_idx
));
341 if (excp
== EXCP_DTLB_MISS
) {
342 excp
= EXCP_NA_DTLB_MISS
;
344 helper_excp(env
, excp
);
346 return (want
& prot
) != 0;
350 target_ulong
HELPER(read_interval_timer
)(void)
352 #ifdef CONFIG_USER_ONLY
353 /* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist.
354 Just pass through the host cpu clock ticks. */
355 return cpu_get_host_ticks();
357 /* In system mode we have access to a decent high-resolution clock.
358 In order to make OS-level time accounting work with the cr16,
359 present it with a well-timed clock fixed at 250MHz. */
360 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) >> 2;
364 uint64_t HELPER(hadd_ss
)(uint64_t r1
, uint64_t r2
)
368 for (int i
= 0; i
< 64; i
+= 16) {
369 int f1
= sextract64(r1
, i
, 16);
370 int f2
= sextract64(r2
, i
, 16);
373 fr
= MIN(fr
, INT16_MAX
);
374 fr
= MAX(fr
, INT16_MIN
);
375 ret
= deposit64(ret
, i
, 16, fr
);
380 uint64_t HELPER(hadd_us
)(uint64_t r1
, uint64_t r2
)
384 for (int i
= 0; i
< 64; i
+= 16) {
385 int f1
= extract64(r1
, i
, 16);
386 int f2
= sextract64(r2
, i
, 16);
389 fr
= MIN(fr
, UINT16_MAX
);
391 ret
= deposit64(ret
, i
, 16, fr
);
396 uint64_t HELPER(havg
)(uint64_t r1
, uint64_t r2
)
400 for (int i
= 0; i
< 64; i
+= 16) {
401 int f1
= extract64(r1
, i
, 16);
402 int f2
= extract64(r2
, i
, 16);
405 ret
= deposit64(ret
, i
, 16, (fr
>> 1) | (fr
& 1));
410 uint64_t HELPER(hsub_ss
)(uint64_t r1
, uint64_t r2
)
414 for (int i
= 0; i
< 64; i
+= 16) {
415 int f1
= sextract64(r1
, i
, 16);
416 int f2
= sextract64(r2
, i
, 16);
419 fr
= MIN(fr
, INT16_MAX
);
420 fr
= MAX(fr
, INT16_MIN
);
421 ret
= deposit64(ret
, i
, 16, fr
);
426 uint64_t HELPER(hsub_us
)(uint64_t r1
, uint64_t r2
)
430 for (int i
= 0; i
< 64; i
+= 16) {
431 int f1
= extract64(r1
, i
, 16);
432 int f2
= sextract64(r2
, i
, 16);
435 fr
= MIN(fr
, UINT16_MAX
);
437 ret
= deposit64(ret
, i
, 16, fr
);
442 uint64_t HELPER(hshladd
)(uint64_t r1
, uint64_t r2
, uint32_t sh
)
446 for (int i
= 0; i
< 64; i
+= 16) {
447 int f1
= sextract64(r1
, i
, 16);
448 int f2
= sextract64(r2
, i
, 16);
449 int fr
= (f1
<< sh
) + f2
;
451 fr
= MIN(fr
, INT16_MAX
);
452 fr
= MAX(fr
, INT16_MIN
);
453 ret
= deposit64(ret
, i
, 16, fr
);
458 uint64_t HELPER(hshradd
)(uint64_t r1
, uint64_t r2
, uint32_t sh
)
462 for (int i
= 0; i
< 64; i
+= 16) {
463 int f1
= sextract64(r1
, i
, 16);
464 int f2
= sextract64(r2
, i
, 16);
465 int fr
= (f1
>> sh
) + f2
;
467 fr
= MIN(fr
, INT16_MAX
);
468 fr
= MAX(fr
, INT16_MIN
);
469 ret
= deposit64(ret
, i
, 16, fr
);