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 void HELPER(tsv
)(CPUHPPAState
*env
, target_ulong cond
)
47 if (unlikely((target_long
)cond
< 0)) {
48 hppa_dynamic_excp(env
, EXCP_OVERFLOW
, GETPC());
52 void HELPER(tcond
)(CPUHPPAState
*env
, target_ulong cond
)
55 hppa_dynamic_excp(env
, EXCP_COND
, GETPC());
59 static void atomic_store_mask32(CPUHPPAState
*env
, target_ulong addr
,
60 uint32_t val
, uint32_t mask
, uintptr_t ra
)
62 int mmu_idx
= cpu_mmu_index(env_cpu(env
), 0);
63 uint32_t old
, new, cmp
, *haddr
;
66 vaddr
= probe_access(env
, addr
, 3, MMU_DATA_STORE
, mmu_idx
, ra
);
68 cpu_loop_exit_atomic(env_cpu(env
), ra
);
70 haddr
= (uint32_t *)((uintptr_t)vaddr
& -4);
71 mask
= addr
& 1 ? 0x00ffffffu
: 0xffffff00u
;
75 new = be32_to_cpu((cpu_to_be32(old
) & ~mask
) | (val
& mask
));
76 cmp
= qatomic_cmpxchg(haddr
, old
, new);
84 static void atomic_store_mask64(CPUHPPAState
*env
, target_ulong addr
,
85 uint64_t val
, uint64_t mask
,
86 int size
, uintptr_t ra
)
88 #ifdef CONFIG_ATOMIC64
89 int mmu_idx
= cpu_mmu_index(env_cpu(env
), 0);
90 uint64_t old
, new, cmp
, *haddr
;
93 vaddr
= probe_access(env
, addr
, size
, MMU_DATA_STORE
, mmu_idx
, ra
);
95 cpu_loop_exit_atomic(env_cpu(env
), ra
);
97 haddr
= (uint64_t *)((uintptr_t)vaddr
& -8);
101 new = be32_to_cpu((cpu_to_be32(old
) & ~mask
) | (val
& mask
));
102 cmp
= qatomic_cmpxchg__nocheck(haddr
, old
, new);
109 cpu_loop_exit_atomic(env_cpu(env
), ra
);
113 static void do_stby_b(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
,
114 bool parallel
, uintptr_t ra
)
118 cpu_stb_data_ra(env
, addr
, val
, ra
);
121 cpu_stw_data_ra(env
, addr
, val
, ra
);
124 /* The 3 byte store must appear atomic. */
126 atomic_store_mask32(env
, addr
, val
, 0x00ffffffu
, ra
);
128 cpu_stb_data_ra(env
, addr
, val
>> 16, ra
);
129 cpu_stw_data_ra(env
, addr
+ 1, val
, ra
);
133 cpu_stl_data_ra(env
, addr
, val
, ra
);
138 static void do_stdby_b(CPUHPPAState
*env
, target_ulong addr
, uint64_t val
,
139 bool parallel
, uintptr_t ra
)
143 cpu_stb_data_ra(env
, addr
, val
, ra
);
146 cpu_stw_data_ra(env
, addr
, val
, ra
);
149 /* The 3 byte store must appear atomic. */
151 atomic_store_mask32(env
, addr
, val
, 0x00ffffffu
, ra
);
153 cpu_stb_data_ra(env
, addr
, val
>> 16, ra
);
154 cpu_stw_data_ra(env
, addr
+ 1, val
, ra
);
158 cpu_stl_data_ra(env
, addr
, val
, ra
);
161 /* The 5 byte store must appear atomic. */
163 atomic_store_mask64(env
, addr
, val
, 0x000000ffffffffffull
, 5, ra
);
165 cpu_stb_data_ra(env
, addr
, val
>> 32, ra
);
166 cpu_stl_data_ra(env
, addr
+ 1, val
, ra
);
170 /* The 6 byte store must appear atomic. */
172 atomic_store_mask64(env
, addr
, val
, 0x0000ffffffffffffull
, 6, ra
);
174 cpu_stw_data_ra(env
, addr
, val
>> 32, ra
);
175 cpu_stl_data_ra(env
, addr
+ 2, val
, ra
);
179 /* The 7 byte store must appear atomic. */
181 atomic_store_mask64(env
, addr
, val
, 0x00ffffffffffffffull
, 7, ra
);
183 cpu_stb_data_ra(env
, addr
, val
>> 48, ra
);
184 cpu_stw_data_ra(env
, addr
+ 1, val
>> 32, ra
);
185 cpu_stl_data_ra(env
, addr
+ 3, val
, ra
);
189 cpu_stq_data_ra(env
, addr
, val
, ra
);
194 void HELPER(stby_b
)(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
)
196 do_stby_b(env
, addr
, val
, false, GETPC());
199 void HELPER(stby_b_parallel
)(CPUHPPAState
*env
, target_ulong addr
,
202 do_stby_b(env
, addr
, val
, true, GETPC());
205 void HELPER(stdby_b
)(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
)
207 do_stdby_b(env
, addr
, val
, false, GETPC());
210 void HELPER(stdby_b_parallel
)(CPUHPPAState
*env
, target_ulong addr
,
213 do_stdby_b(env
, addr
, val
, true, GETPC());
216 static void do_stby_e(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
,
217 bool parallel
, uintptr_t ra
)
221 /* The 3 byte store must appear atomic. */
223 atomic_store_mask32(env
, addr
- 3, val
, 0xffffff00u
, ra
);
225 cpu_stw_data_ra(env
, addr
- 3, val
>> 16, ra
);
226 cpu_stb_data_ra(env
, addr
- 1, val
>> 8, ra
);
230 cpu_stw_data_ra(env
, addr
- 2, val
>> 16, ra
);
233 cpu_stb_data_ra(env
, addr
- 1, val
>> 24, ra
);
236 /* Nothing is stored, but protection is checked and the
237 cacheline is marked dirty. */
238 probe_write(env
, addr
, 0, cpu_mmu_index(env_cpu(env
), 0), ra
);
243 static void do_stdby_e(CPUHPPAState
*env
, target_ulong addr
, uint64_t val
,
244 bool parallel
, uintptr_t ra
)
248 /* The 7 byte store must appear atomic. */
250 atomic_store_mask64(env
, addr
- 7, val
,
251 0xffffffffffffff00ull
, 7, ra
);
253 cpu_stl_data_ra(env
, addr
- 7, val
>> 32, ra
);
254 cpu_stw_data_ra(env
, addr
- 3, val
>> 16, ra
);
255 cpu_stb_data_ra(env
, addr
- 1, val
>> 8, ra
);
259 /* The 6 byte store must appear atomic. */
261 atomic_store_mask64(env
, addr
- 6, val
,
262 0xffffffffffff0000ull
, 6, ra
);
264 cpu_stl_data_ra(env
, addr
- 6, val
>> 32, ra
);
265 cpu_stw_data_ra(env
, addr
- 2, val
>> 16, ra
);
269 /* The 5 byte store must appear atomic. */
271 atomic_store_mask64(env
, addr
- 5, val
,
272 0xffffffffff000000ull
, 5, ra
);
274 cpu_stl_data_ra(env
, addr
- 5, val
>> 32, ra
);
275 cpu_stb_data_ra(env
, addr
- 1, val
>> 24, ra
);
279 cpu_stl_data_ra(env
, addr
- 4, val
>> 32, ra
);
282 /* The 3 byte store must appear atomic. */
284 atomic_store_mask32(env
, addr
- 3, val
, 0xffffff00u
, ra
);
286 cpu_stw_data_ra(env
, addr
- 3, val
>> 16, ra
);
287 cpu_stb_data_ra(env
, addr
- 1, val
>> 8, ra
);
291 cpu_stw_data_ra(env
, addr
- 2, val
>> 16, ra
);
294 cpu_stb_data_ra(env
, addr
- 1, val
>> 24, ra
);
297 /* Nothing is stored, but protection is checked and the
298 cacheline is marked dirty. */
299 probe_write(env
, addr
, 0, cpu_mmu_index(env_cpu(env
), 0), ra
);
304 void HELPER(stby_e
)(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
)
306 do_stby_e(env
, addr
, val
, false, GETPC());
309 void HELPER(stby_e_parallel
)(CPUHPPAState
*env
, target_ulong addr
,
312 do_stby_e(env
, addr
, val
, true, GETPC());
315 void HELPER(stdby_e
)(CPUHPPAState
*env
, target_ulong addr
, target_ulong val
)
317 do_stdby_e(env
, addr
, val
, false, GETPC());
320 void HELPER(stdby_e_parallel
)(CPUHPPAState
*env
, target_ulong addr
,
323 do_stdby_e(env
, addr
, val
, true, GETPC());
326 void HELPER(ldc_check
)(target_ulong addr
)
328 if (unlikely(addr
& 0xf)) {
329 qemu_log_mask(LOG_GUEST_ERROR
,
330 "Undefined ldc to unaligned address mod 16: "
331 TARGET_FMT_lx
"\n", addr
);
335 target_ulong
HELPER(probe
)(CPUHPPAState
*env
, target_ulong addr
,
336 uint32_t level
, uint32_t want
)
338 #ifdef CONFIG_USER_ONLY
339 return page_check_range(addr
, 1, want
);
341 int prot
, excp
, mmu_idx
;
344 trace_hppa_tlb_probe(addr
, level
, want
);
345 /* Fail if the requested privilege level is higher than current. */
346 if (level
< (env
->iaoq_f
& 3)) {
350 mmu_idx
= PRIV_P_TO_MMU_IDX(level
, env
->psw
& PSW_P
);
351 excp
= hppa_get_physical_address(env
, addr
, mmu_idx
, 0, &phys
,
354 hppa_set_ior_and_isr(env
, addr
, MMU_IDX_MMU_DISABLED(mmu_idx
));
355 if (excp
== EXCP_DTLB_MISS
) {
356 excp
= EXCP_NA_DTLB_MISS
;
358 hppa_dynamic_excp(env
, excp
, GETPC());
360 return (want
& prot
) != 0;
364 target_ulong
HELPER(read_interval_timer
)(void)
366 #ifdef CONFIG_USER_ONLY
367 /* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist.
368 Just pass through the host cpu clock ticks. */
369 return cpu_get_host_ticks();
371 /* In system mode we have access to a decent high-resolution clock.
372 In order to make OS-level time accounting work with the cr16,
373 present it with a well-timed clock fixed at 250MHz. */
374 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) >> 2;
378 uint64_t HELPER(hadd_ss
)(uint64_t r1
, uint64_t r2
)
382 for (int i
= 0; i
< 64; i
+= 16) {
383 int f1
= sextract64(r1
, i
, 16);
384 int f2
= sextract64(r2
, i
, 16);
387 fr
= MIN(fr
, INT16_MAX
);
388 fr
= MAX(fr
, INT16_MIN
);
389 ret
= deposit64(ret
, i
, 16, fr
);
394 uint64_t HELPER(hadd_us
)(uint64_t r1
, uint64_t r2
)
398 for (int i
= 0; i
< 64; i
+= 16) {
399 int f1
= extract64(r1
, i
, 16);
400 int f2
= sextract64(r2
, i
, 16);
403 fr
= MIN(fr
, UINT16_MAX
);
405 ret
= deposit64(ret
, i
, 16, fr
);
410 uint64_t HELPER(havg
)(uint64_t r1
, uint64_t r2
)
414 for (int i
= 0; i
< 64; i
+= 16) {
415 int f1
= extract64(r1
, i
, 16);
416 int f2
= extract64(r2
, i
, 16);
419 ret
= deposit64(ret
, i
, 16, (fr
>> 1) | (fr
& 1));
424 uint64_t HELPER(hsub_ss
)(uint64_t r1
, uint64_t r2
)
428 for (int i
= 0; i
< 64; i
+= 16) {
429 int f1
= sextract64(r1
, i
, 16);
430 int f2
= sextract64(r2
, i
, 16);
433 fr
= MIN(fr
, INT16_MAX
);
434 fr
= MAX(fr
, INT16_MIN
);
435 ret
= deposit64(ret
, i
, 16, fr
);
440 uint64_t HELPER(hsub_us
)(uint64_t r1
, uint64_t r2
)
444 for (int i
= 0; i
< 64; i
+= 16) {
445 int f1
= extract64(r1
, i
, 16);
446 int f2
= sextract64(r2
, i
, 16);
449 fr
= MIN(fr
, UINT16_MAX
);
451 ret
= deposit64(ret
, i
, 16, fr
);
456 uint64_t HELPER(hshladd
)(uint64_t r1
, uint64_t r2
, uint32_t sh
)
460 for (int i
= 0; i
< 64; i
+= 16) {
461 int f1
= sextract64(r1
, i
, 16);
462 int f2
= sextract64(r2
, i
, 16);
463 int fr
= (f1
<< sh
) + f2
;
465 fr
= MIN(fr
, INT16_MAX
);
466 fr
= MAX(fr
, INT16_MIN
);
467 ret
= deposit64(ret
, i
, 16, fr
);
472 uint64_t HELPER(hshradd
)(uint64_t r1
, uint64_t r2
, uint32_t sh
)
476 for (int i
= 0; i
< 64; i
+= 16) {
477 int f1
= sextract64(r1
, i
, 16);
478 int f2
= sextract64(r2
, i
, 16);
479 int fr
= (f1
>> sh
) + f2
;
481 fr
= MIN(fr
, INT16_MAX
);
482 fr
= MAX(fr
, INT16_MIN
);
483 ret
= deposit64(ret
, i
, 16, fr
);