]> git.proxmox.com Git - mirror_qemu.git/blob - target/hppa/op_helper.c
target-hppa: Implement system and memory-management insns
[mirror_qemu.git] / target / hppa / op_helper.c
1 /*
2 * Helpers for HPPA instructions.
3 *
4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net>
5 *
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 of the License, or (at your option) any later version.
10 *
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.
15 *
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/>.
18 */
19
20 #include "qemu/osdep.h"
21 #include "cpu.h"
22 #include "exec/exec-all.h"
23 #include "exec/helper-proto.h"
24 #include "exec/cpu_ldst.h"
25
26 void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp)
27 {
28 HPPACPU *cpu = hppa_env_get_cpu(env);
29 CPUState *cs = CPU(cpu);
30
31 cs->exception_index = excp;
32 cpu_loop_exit(cs);
33 }
34
35 static void QEMU_NORETURN dynexcp(CPUHPPAState *env, int excp, uintptr_t ra)
36 {
37 HPPACPU *cpu = hppa_env_get_cpu(env);
38 CPUState *cs = CPU(cpu);
39
40 cs->exception_index = excp;
41 cpu_loop_exit_restore(cs, ra);
42 }
43
44 void HELPER(tsv)(CPUHPPAState *env, target_ulong cond)
45 {
46 if (unlikely((target_long)cond < 0)) {
47 dynexcp(env, EXCP_SIGFPE, GETPC());
48 }
49 }
50
51 void HELPER(tcond)(CPUHPPAState *env, target_ulong cond)
52 {
53 if (unlikely(cond)) {
54 dynexcp(env, EXCP_SIGFPE, GETPC());
55 }
56 }
57
58 static void atomic_store_3(CPUHPPAState *env, target_ulong addr, uint32_t val,
59 uint32_t mask, uintptr_t ra)
60 {
61 uint32_t old, new, cmp;
62
63 #ifdef CONFIG_USER_ONLY
64 uint32_t *haddr = g2h(addr - 1);
65 old = *haddr;
66 while (1) {
67 new = (old & ~mask) | (val & mask);
68 cmp = atomic_cmpxchg(haddr, old, new);
69 if (cmp == old) {
70 return;
71 }
72 old = cmp;
73 }
74 #else
75 #error "Not implemented."
76 #endif
77 }
78
79 void HELPER(stby_b)(CPUHPPAState *env, target_ulong addr, target_ulong val)
80 {
81 uintptr_t ra = GETPC();
82
83 switch (addr & 3) {
84 case 3:
85 cpu_stb_data_ra(env, addr, val, ra);
86 break;
87 case 2:
88 cpu_stw_data_ra(env, addr, val, ra);
89 break;
90 case 1:
91 /* The 3 byte store must appear atomic. */
92 if (parallel_cpus) {
93 atomic_store_3(env, addr, val, 0x00ffffffu, ra);
94 } else {
95 cpu_stb_data_ra(env, addr, val >> 16, ra);
96 cpu_stw_data_ra(env, addr + 1, val, ra);
97 }
98 break;
99 default:
100 cpu_stl_data_ra(env, addr, val, ra);
101 break;
102 }
103 }
104
105 void HELPER(stby_e)(CPUHPPAState *env, target_ulong addr, target_ulong val)
106 {
107 uintptr_t ra = GETPC();
108
109 switch (addr & 3) {
110 case 3:
111 /* The 3 byte store must appear atomic. */
112 if (parallel_cpus) {
113 atomic_store_3(env, addr - 3, val, 0xffffff00u, ra);
114 } else {
115 cpu_stw_data_ra(env, addr - 3, val >> 16, ra);
116 cpu_stb_data_ra(env, addr - 1, val >> 8, ra);
117 }
118 break;
119 case 2:
120 cpu_stw_data_ra(env, addr - 2, val >> 16, ra);
121 break;
122 case 1:
123 cpu_stb_data_ra(env, addr - 1, val >> 24, ra);
124 break;
125 default:
126 /* Nothing is stored, but protection is checked and the
127 cacheline is marked dirty. */
128 #ifndef CONFIG_USER_ONLY
129 probe_write(env, addr, cpu_mmu_index(env, 0), ra);
130 #endif
131 break;
132 }
133 }
134
135 target_ulong HELPER(probe_r)(target_ulong addr)
136 {
137 return page_check_range(addr, 1, PAGE_READ);
138 }
139
140 target_ulong HELPER(probe_w)(target_ulong addr)
141 {
142 return page_check_range(addr, 1, PAGE_WRITE);
143 }
144
145 void HELPER(loaded_fr0)(CPUHPPAState *env)
146 {
147 uint32_t shadow = env->fr[0] >> 32;
148 int rm, d;
149
150 env->fr0_shadow = shadow;
151
152 switch (extract32(shadow, 9, 2)) {
153 default:
154 rm = float_round_nearest_even;
155 break;
156 case 1:
157 rm = float_round_to_zero;
158 break;
159 case 2:
160 rm = float_round_up;
161 break;
162 case 3:
163 rm = float_round_down;
164 break;
165 }
166 set_float_rounding_mode(rm, &env->fp_status);
167
168 d = extract32(shadow, 5, 1);
169 set_flush_to_zero(d, &env->fp_status);
170 set_flush_inputs_to_zero(d, &env->fp_status);
171 }
172
173 void cpu_hppa_loaded_fr0(CPUHPPAState *env)
174 {
175 helper_loaded_fr0(env);
176 }