root / target-sh4 / op_helper.c @ feature-archipelago
History | View | Annotate | Download (14.5 kB)
1 | fdf9b3e8 | bellard | /*
|
---|---|---|---|
2 | fdf9b3e8 | bellard | * SH4 emulation
|
3 | 5fafdf24 | ths | *
|
4 | fdf9b3e8 | bellard | * Copyright (c) 2005 Samuel Tardieu
|
5 | fdf9b3e8 | bellard | *
|
6 | fdf9b3e8 | bellard | * This library is free software; you can redistribute it and/or
|
7 | fdf9b3e8 | bellard | * modify it under the terms of the GNU Lesser General Public
|
8 | fdf9b3e8 | bellard | * License as published by the Free Software Foundation; either
|
9 | fdf9b3e8 | bellard | * version 2 of the License, or (at your option) any later version.
|
10 | fdf9b3e8 | bellard | *
|
11 | fdf9b3e8 | bellard | * This library is distributed in the hope that it will be useful,
|
12 | fdf9b3e8 | bellard | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | fdf9b3e8 | bellard | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | fdf9b3e8 | bellard | * Lesser General Public License for more details.
|
15 | fdf9b3e8 | bellard | *
|
16 | fdf9b3e8 | bellard | * You should have received a copy of the GNU Lesser General Public
|
17 | 8167ee88 | Blue Swirl | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
18 | fdf9b3e8 | bellard | */
|
19 | fdf9b3e8 | bellard | #include <assert.h> |
20 | 852d481f | edgar_igl | #include <stdlib.h> |
21 | 3e457172 | Blue Swirl | #include "cpu.h" |
22 | a7812ae4 | pbrook | #include "helper.h" |
23 | fdf9b3e8 | bellard | |
24 | fdf9b3e8 | bellard | #ifndef CONFIG_USER_ONLY
|
25 | 022c62cb | Paolo Bonzini | #include "exec/softmmu_exec.h" |
26 | fdf9b3e8 | bellard | |
27 | fdf9b3e8 | bellard | #define MMUSUFFIX _mmu
|
28 | fdf9b3e8 | bellard | |
29 | fdf9b3e8 | bellard | #define SHIFT 0 |
30 | 022c62cb | Paolo Bonzini | #include "exec/softmmu_template.h" |
31 | fdf9b3e8 | bellard | |
32 | fdf9b3e8 | bellard | #define SHIFT 1 |
33 | 022c62cb | Paolo Bonzini | #include "exec/softmmu_template.h" |
34 | fdf9b3e8 | bellard | |
35 | fdf9b3e8 | bellard | #define SHIFT 2 |
36 | 022c62cb | Paolo Bonzini | #include "exec/softmmu_template.h" |
37 | fdf9b3e8 | bellard | |
38 | fdf9b3e8 | bellard | #define SHIFT 3 |
39 | 022c62cb | Paolo Bonzini | #include "exec/softmmu_template.h" |
40 | fdf9b3e8 | bellard | |
41 | 485d0035 | Blue Swirl | void tlb_fill(CPUSH4State *env, target_ulong addr, int is_write, int mmu_idx, |
42 | 20503968 | Blue Swirl | uintptr_t retaddr) |
43 | fdf9b3e8 | bellard | { |
44 | fdf9b3e8 | bellard | int ret;
|
45 | fdf9b3e8 | bellard | |
46 | 97b348e7 | Blue Swirl | ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx); |
47 | fdf9b3e8 | bellard | if (ret) {
|
48 | 21829e9b | Aurelien Jarno | /* now we have a real cpu fault */
|
49 | a8a826a3 | Blue Swirl | if (retaddr) {
|
50 | a8a826a3 | Blue Swirl | cpu_restore_state(env, retaddr); |
51 | a8a826a3 | Blue Swirl | } |
52 | 1162c041 | Blue Swirl | cpu_loop_exit(env); |
53 | fdf9b3e8 | bellard | } |
54 | fdf9b3e8 | bellard | } |
55 | fdf9b3e8 | bellard | |
56 | fdf9b3e8 | bellard | #endif
|
57 | fdf9b3e8 | bellard | |
58 | 485d0035 | Blue Swirl | void helper_ldtlb(CPUSH4State *env)
|
59 | ea2b542a | aurel32 | { |
60 | ea2b542a | aurel32 | #ifdef CONFIG_USER_ONLY
|
61 | ea2b542a | aurel32 | /* XXXXX */
|
62 | 43dc2a64 | Blue Swirl | cpu_abort(env, "Unhandled ldtlb");
|
63 | ea2b542a | aurel32 | #else
|
64 | ea2b542a | aurel32 | cpu_load_tlb(env); |
65 | ea2b542a | aurel32 | #endif
|
66 | ea2b542a | aurel32 | } |
67 | ea2b542a | aurel32 | |
68 | 10127400 | Aurelien Jarno | static inline void QEMU_NORETURN raise_exception(CPUSH4State *env, int index, |
69 | 10127400 | Aurelien Jarno | uintptr_t retaddr) |
70 | e6afc2f4 | aurel32 | { |
71 | fd4bab10 | Aurelien Jarno | env->exception_index = index; |
72 | a8a826a3 | Blue Swirl | if (retaddr) {
|
73 | a8a826a3 | Blue Swirl | cpu_restore_state(env, retaddr); |
74 | a8a826a3 | Blue Swirl | } |
75 | 1162c041 | Blue Swirl | cpu_loop_exit(env); |
76 | e6afc2f4 | aurel32 | } |
77 | e6afc2f4 | aurel32 | |
78 | 485d0035 | Blue Swirl | void helper_raise_illegal_instruction(CPUSH4State *env)
|
79 | fd4bab10 | Aurelien Jarno | { |
80 | 10127400 | Aurelien Jarno | raise_exception(env, 0x180, 0); |
81 | fd4bab10 | Aurelien Jarno | } |
82 | fd4bab10 | Aurelien Jarno | |
83 | 485d0035 | Blue Swirl | void helper_raise_slot_illegal_instruction(CPUSH4State *env)
|
84 | e6afc2f4 | aurel32 | { |
85 | 10127400 | Aurelien Jarno | raise_exception(env, 0x1a0, 0); |
86 | e6afc2f4 | aurel32 | } |
87 | e6afc2f4 | aurel32 | |
88 | 485d0035 | Blue Swirl | void helper_raise_fpu_disable(CPUSH4State *env)
|
89 | d8299bcc | aurel32 | { |
90 | 10127400 | Aurelien Jarno | raise_exception(env, 0x800, 0); |
91 | d8299bcc | aurel32 | } |
92 | d8299bcc | aurel32 | |
93 | 485d0035 | Blue Swirl | void helper_raise_slot_fpu_disable(CPUSH4State *env)
|
94 | d8299bcc | aurel32 | { |
95 | 10127400 | Aurelien Jarno | raise_exception(env, 0x820, 0); |
96 | d8299bcc | aurel32 | } |
97 | d8299bcc | aurel32 | |
98 | 485d0035 | Blue Swirl | void helper_debug(CPUSH4State *env)
|
99 | e6afc2f4 | aurel32 | { |
100 | 10127400 | Aurelien Jarno | raise_exception(env, EXCP_DEBUG, 0);
|
101 | e6afc2f4 | aurel32 | } |
102 | e6afc2f4 | aurel32 | |
103 | 10127400 | Aurelien Jarno | void helper_sleep(CPUSH4State *env)
|
104 | e6afc2f4 | aurel32 | { |
105 | 259186a7 | Andreas Färber | CPUState *cs = CPU(sh_env_get_cpu(env)); |
106 | 259186a7 | Andreas Färber | |
107 | 259186a7 | Andreas Färber | cs->halted = 1;
|
108 | efac4154 | Aurelien Jarno | env->in_sleep = 1;
|
109 | 10127400 | Aurelien Jarno | raise_exception(env, EXCP_HLT, 0);
|
110 | e6afc2f4 | aurel32 | } |
111 | e6afc2f4 | aurel32 | |
112 | 485d0035 | Blue Swirl | void helper_trapa(CPUSH4State *env, uint32_t tra)
|
113 | e6afc2f4 | aurel32 | { |
114 | e6afc2f4 | aurel32 | env->tra = tra << 2;
|
115 | 10127400 | Aurelien Jarno | raise_exception(env, 0x160, 0); |
116 | e6afc2f4 | aurel32 | } |
117 | e6afc2f4 | aurel32 | |
118 | 485d0035 | Blue Swirl | void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value)
|
119 | 852d481f | edgar_igl | { |
120 | 852d481f | edgar_igl | if (cpu_sh4_is_cached (env, address))
|
121 | 852d481f | edgar_igl | { |
122 | 852d481f | edgar_igl | memory_content *r = malloc (sizeof(memory_content));
|
123 | 852d481f | edgar_igl | r->address = address; |
124 | 852d481f | edgar_igl | r->value = value; |
125 | 852d481f | edgar_igl | r->next = NULL;
|
126 | 852d481f | edgar_igl | |
127 | 852d481f | edgar_igl | *(env->movcal_backup_tail) = r; |
128 | 852d481f | edgar_igl | env->movcal_backup_tail = &(r->next); |
129 | 852d481f | edgar_igl | } |
130 | 852d481f | edgar_igl | } |
131 | 852d481f | edgar_igl | |
132 | 485d0035 | Blue Swirl | void helper_discard_movcal_backup(CPUSH4State *env)
|
133 | 852d481f | edgar_igl | { |
134 | 852d481f | edgar_igl | memory_content *current = env->movcal_backup; |
135 | 852d481f | edgar_igl | |
136 | 852d481f | edgar_igl | while(current)
|
137 | 852d481f | edgar_igl | { |
138 | 852d481f | edgar_igl | memory_content *next = current->next; |
139 | 852d481f | edgar_igl | free (current); |
140 | 852d481f | edgar_igl | env->movcal_backup = current = next; |
141 | b9d38e95 | Blue Swirl | if (current == NULL) |
142 | 852d481f | edgar_igl | env->movcal_backup_tail = &(env->movcal_backup); |
143 | 852d481f | edgar_igl | } |
144 | 852d481f | edgar_igl | } |
145 | 852d481f | edgar_igl | |
146 | 485d0035 | Blue Swirl | void helper_ocbi(CPUSH4State *env, uint32_t address)
|
147 | 852d481f | edgar_igl | { |
148 | 852d481f | edgar_igl | memory_content **current = &(env->movcal_backup); |
149 | 852d481f | edgar_igl | while (*current)
|
150 | 852d481f | edgar_igl | { |
151 | 852d481f | edgar_igl | uint32_t a = (*current)->address; |
152 | 852d481f | edgar_igl | if ((a & ~0x1F) == (address & ~0x1F)) |
153 | 852d481f | edgar_igl | { |
154 | 852d481f | edgar_igl | memory_content *next = (*current)->next; |
155 | 485d0035 | Blue Swirl | cpu_stl_data(env, a, (*current)->value); |
156 | 852d481f | edgar_igl | |
157 | b9d38e95 | Blue Swirl | if (next == NULL) |
158 | 852d481f | edgar_igl | { |
159 | 852d481f | edgar_igl | env->movcal_backup_tail = current; |
160 | 852d481f | edgar_igl | } |
161 | 852d481f | edgar_igl | |
162 | 852d481f | edgar_igl | free (*current); |
163 | 852d481f | edgar_igl | *current = next; |
164 | 852d481f | edgar_igl | break;
|
165 | 852d481f | edgar_igl | } |
166 | 852d481f | edgar_igl | } |
167 | 852d481f | edgar_igl | } |
168 | 852d481f | edgar_igl | |
169 | fdf9b3e8 | bellard | #define T (env->sr & SR_T)
|
170 | fdf9b3e8 | bellard | #define Q (env->sr & SR_Q ? 1 : 0) |
171 | fdf9b3e8 | bellard | #define M (env->sr & SR_M ? 1 : 0) |
172 | fdf9b3e8 | bellard | #define SETT env->sr |= SR_T
|
173 | fdf9b3e8 | bellard | #define CLRT env->sr &= ~SR_T
|
174 | fdf9b3e8 | bellard | #define SETQ env->sr |= SR_Q
|
175 | fdf9b3e8 | bellard | #define CLRQ env->sr &= ~SR_Q
|
176 | fdf9b3e8 | bellard | #define SETM env->sr |= SR_M
|
177 | fdf9b3e8 | bellard | #define CLRM env->sr &= ~SR_M
|
178 | fdf9b3e8 | bellard | |
179 | 485d0035 | Blue Swirl | uint32_t helper_div1(CPUSH4State *env, uint32_t arg0, uint32_t arg1) |
180 | fdf9b3e8 | bellard | { |
181 | fdf9b3e8 | bellard | uint32_t tmp0, tmp2; |
182 | fdf9b3e8 | bellard | uint8_t old_q, tmp1 = 0xff;
|
183 | fdf9b3e8 | bellard | |
184 | 69d6275b | aurel32 | //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
|
185 | fdf9b3e8 | bellard | old_q = Q; |
186 | 69d6275b | aurel32 | if ((0x80000000 & arg1) != 0) |
187 | fdf9b3e8 | bellard | SETQ; |
188 | fdf9b3e8 | bellard | else
|
189 | fdf9b3e8 | bellard | CLRQ; |
190 | 69d6275b | aurel32 | tmp2 = arg0; |
191 | 69d6275b | aurel32 | arg1 <<= 1;
|
192 | 69d6275b | aurel32 | arg1 |= T; |
193 | fdf9b3e8 | bellard | switch (old_q) {
|
194 | fdf9b3e8 | bellard | case 0: |
195 | fdf9b3e8 | bellard | switch (M) {
|
196 | fdf9b3e8 | bellard | case 0: |
197 | 69d6275b | aurel32 | tmp0 = arg1; |
198 | 69d6275b | aurel32 | arg1 -= tmp2; |
199 | 69d6275b | aurel32 | tmp1 = arg1 > tmp0; |
200 | fdf9b3e8 | bellard | switch (Q) {
|
201 | fdf9b3e8 | bellard | case 0: |
202 | fdf9b3e8 | bellard | if (tmp1)
|
203 | fdf9b3e8 | bellard | SETQ; |
204 | fdf9b3e8 | bellard | else
|
205 | fdf9b3e8 | bellard | CLRQ; |
206 | fdf9b3e8 | bellard | break;
|
207 | fdf9b3e8 | bellard | case 1: |
208 | fdf9b3e8 | bellard | if (tmp1 == 0) |
209 | fdf9b3e8 | bellard | SETQ; |
210 | fdf9b3e8 | bellard | else
|
211 | fdf9b3e8 | bellard | CLRQ; |
212 | fdf9b3e8 | bellard | break;
|
213 | fdf9b3e8 | bellard | } |
214 | fdf9b3e8 | bellard | break;
|
215 | fdf9b3e8 | bellard | case 1: |
216 | 69d6275b | aurel32 | tmp0 = arg1; |
217 | 69d6275b | aurel32 | arg1 += tmp2; |
218 | 69d6275b | aurel32 | tmp1 = arg1 < tmp0; |
219 | fdf9b3e8 | bellard | switch (Q) {
|
220 | fdf9b3e8 | bellard | case 0: |
221 | fdf9b3e8 | bellard | if (tmp1 == 0) |
222 | fdf9b3e8 | bellard | SETQ; |
223 | fdf9b3e8 | bellard | else
|
224 | fdf9b3e8 | bellard | CLRQ; |
225 | fdf9b3e8 | bellard | break;
|
226 | fdf9b3e8 | bellard | case 1: |
227 | fdf9b3e8 | bellard | if (tmp1)
|
228 | fdf9b3e8 | bellard | SETQ; |
229 | fdf9b3e8 | bellard | else
|
230 | fdf9b3e8 | bellard | CLRQ; |
231 | fdf9b3e8 | bellard | break;
|
232 | fdf9b3e8 | bellard | } |
233 | fdf9b3e8 | bellard | break;
|
234 | fdf9b3e8 | bellard | } |
235 | fdf9b3e8 | bellard | break;
|
236 | fdf9b3e8 | bellard | case 1: |
237 | fdf9b3e8 | bellard | switch (M) {
|
238 | fdf9b3e8 | bellard | case 0: |
239 | 69d6275b | aurel32 | tmp0 = arg1; |
240 | 69d6275b | aurel32 | arg1 += tmp2; |
241 | 69d6275b | aurel32 | tmp1 = arg1 < tmp0; |
242 | fdf9b3e8 | bellard | switch (Q) {
|
243 | fdf9b3e8 | bellard | case 0: |
244 | fdf9b3e8 | bellard | if (tmp1)
|
245 | fdf9b3e8 | bellard | SETQ; |
246 | fdf9b3e8 | bellard | else
|
247 | fdf9b3e8 | bellard | CLRQ; |
248 | fdf9b3e8 | bellard | break;
|
249 | fdf9b3e8 | bellard | case 1: |
250 | fdf9b3e8 | bellard | if (tmp1 == 0) |
251 | fdf9b3e8 | bellard | SETQ; |
252 | fdf9b3e8 | bellard | else
|
253 | fdf9b3e8 | bellard | CLRQ; |
254 | fdf9b3e8 | bellard | break;
|
255 | fdf9b3e8 | bellard | } |
256 | fdf9b3e8 | bellard | break;
|
257 | fdf9b3e8 | bellard | case 1: |
258 | 69d6275b | aurel32 | tmp0 = arg1; |
259 | 69d6275b | aurel32 | arg1 -= tmp2; |
260 | 69d6275b | aurel32 | tmp1 = arg1 > tmp0; |
261 | fdf9b3e8 | bellard | switch (Q) {
|
262 | fdf9b3e8 | bellard | case 0: |
263 | fdf9b3e8 | bellard | if (tmp1 == 0) |
264 | fdf9b3e8 | bellard | SETQ; |
265 | fdf9b3e8 | bellard | else
|
266 | fdf9b3e8 | bellard | CLRQ; |
267 | fdf9b3e8 | bellard | break;
|
268 | fdf9b3e8 | bellard | case 1: |
269 | fdf9b3e8 | bellard | if (tmp1)
|
270 | fdf9b3e8 | bellard | SETQ; |
271 | fdf9b3e8 | bellard | else
|
272 | fdf9b3e8 | bellard | CLRQ; |
273 | fdf9b3e8 | bellard | break;
|
274 | fdf9b3e8 | bellard | } |
275 | fdf9b3e8 | bellard | break;
|
276 | fdf9b3e8 | bellard | } |
277 | fdf9b3e8 | bellard | break;
|
278 | fdf9b3e8 | bellard | } |
279 | fdf9b3e8 | bellard | if (Q == M)
|
280 | fdf9b3e8 | bellard | SETT; |
281 | fdf9b3e8 | bellard | else
|
282 | fdf9b3e8 | bellard | CLRT; |
283 | 69d6275b | aurel32 | //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
|
284 | 69d6275b | aurel32 | return arg1;
|
285 | fdf9b3e8 | bellard | } |
286 | fdf9b3e8 | bellard | |
287 | 485d0035 | Blue Swirl | void helper_macl(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
|
288 | fdf9b3e8 | bellard | { |
289 | fdf9b3e8 | bellard | int64_t res; |
290 | fdf9b3e8 | bellard | |
291 | fdf9b3e8 | bellard | res = ((uint64_t) env->mach << 32) | env->macl;
|
292 | 6f06939b | aurel32 | res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1; |
293 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
294 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
295 | fdf9b3e8 | bellard | if (env->sr & SR_S) {
|
296 | fdf9b3e8 | bellard | if (res < 0) |
297 | fdf9b3e8 | bellard | env->mach |= 0xffff0000;
|
298 | fdf9b3e8 | bellard | else
|
299 | fdf9b3e8 | bellard | env->mach &= 0x00007fff;
|
300 | fdf9b3e8 | bellard | } |
301 | fdf9b3e8 | bellard | } |
302 | fdf9b3e8 | bellard | |
303 | 485d0035 | Blue Swirl | void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
|
304 | fdf9b3e8 | bellard | { |
305 | fdf9b3e8 | bellard | int64_t res; |
306 | fdf9b3e8 | bellard | |
307 | fdf9b3e8 | bellard | res = ((uint64_t) env->mach << 32) | env->macl;
|
308 | 6f06939b | aurel32 | res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1; |
309 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
310 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
311 | fdf9b3e8 | bellard | if (env->sr & SR_S) {
|
312 | fdf9b3e8 | bellard | if (res < -0x80000000) { |
313 | fdf9b3e8 | bellard | env->mach = 1;
|
314 | fdf9b3e8 | bellard | env->macl = 0x80000000;
|
315 | fdf9b3e8 | bellard | } else if (res > 0x000000007fffffff) { |
316 | fdf9b3e8 | bellard | env->mach = 1;
|
317 | fdf9b3e8 | bellard | env->macl = 0x7fffffff;
|
318 | fdf9b3e8 | bellard | } |
319 | fdf9b3e8 | bellard | } |
320 | fdf9b3e8 | bellard | } |
321 | fdf9b3e8 | bellard | |
322 | 485d0035 | Blue Swirl | static inline void set_t(CPUSH4State *env) |
323 | cc4ba6a9 | aurel32 | { |
324 | cc4ba6a9 | aurel32 | env->sr |= SR_T; |
325 | cc4ba6a9 | aurel32 | } |
326 | cc4ba6a9 | aurel32 | |
327 | 485d0035 | Blue Swirl | static inline void clr_t(CPUSH4State *env) |
328 | cc4ba6a9 | aurel32 | { |
329 | cc4ba6a9 | aurel32 | env->sr &= ~SR_T; |
330 | cc4ba6a9 | aurel32 | } |
331 | cc4ba6a9 | aurel32 | |
332 | 485d0035 | Blue Swirl | void helper_ld_fpscr(CPUSH4State *env, uint32_t val)
|
333 | 390af821 | aurel32 | { |
334 | 26ac1ea5 | Aurelien Jarno | env->fpscr = val & FPSCR_MASK; |
335 | 26ac1ea5 | Aurelien Jarno | if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
|
336 | 390af821 | aurel32 | set_float_rounding_mode(float_round_to_zero, &env->fp_status); |
337 | 26ac1ea5 | Aurelien Jarno | } else {
|
338 | 390af821 | aurel32 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
339 | 26ac1ea5 | Aurelien Jarno | } |
340 | a0d4ac33 | Aurelien Jarno | set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
|
341 | 390af821 | aurel32 | } |
342 | cc4ba6a9 | aurel32 | |
343 | 485d0035 | Blue Swirl | static void update_fpscr(CPUSH4State *env, uintptr_t retaddr) |
344 | 21829e9b | Aurelien Jarno | { |
345 | 21829e9b | Aurelien Jarno | int xcpt, cause, enable;
|
346 | 21829e9b | Aurelien Jarno | |
347 | 21829e9b | Aurelien Jarno | xcpt = get_float_exception_flags(&env->fp_status); |
348 | 21829e9b | Aurelien Jarno | |
349 | 21829e9b | Aurelien Jarno | /* Clear the flag entries */
|
350 | 21829e9b | Aurelien Jarno | env->fpscr &= ~FPSCR_FLAG_MASK; |
351 | 21829e9b | Aurelien Jarno | |
352 | 21829e9b | Aurelien Jarno | if (unlikely(xcpt)) {
|
353 | 21829e9b | Aurelien Jarno | if (xcpt & float_flag_invalid) {
|
354 | 21829e9b | Aurelien Jarno | env->fpscr |= FPSCR_FLAG_V; |
355 | 21829e9b | Aurelien Jarno | } |
356 | 21829e9b | Aurelien Jarno | if (xcpt & float_flag_divbyzero) {
|
357 | 21829e9b | Aurelien Jarno | env->fpscr |= FPSCR_FLAG_Z; |
358 | 21829e9b | Aurelien Jarno | } |
359 | 21829e9b | Aurelien Jarno | if (xcpt & float_flag_overflow) {
|
360 | 21829e9b | Aurelien Jarno | env->fpscr |= FPSCR_FLAG_O; |
361 | 21829e9b | Aurelien Jarno | } |
362 | 21829e9b | Aurelien Jarno | if (xcpt & float_flag_underflow) {
|
363 | 21829e9b | Aurelien Jarno | env->fpscr |= FPSCR_FLAG_U; |
364 | 21829e9b | Aurelien Jarno | } |
365 | 21829e9b | Aurelien Jarno | if (xcpt & float_flag_inexact) {
|
366 | 21829e9b | Aurelien Jarno | env->fpscr |= FPSCR_FLAG_I; |
367 | 21829e9b | Aurelien Jarno | } |
368 | 21829e9b | Aurelien Jarno | |
369 | 21829e9b | Aurelien Jarno | /* Accumulate in cause entries */
|
370 | 21829e9b | Aurelien Jarno | env->fpscr |= (env->fpscr & FPSCR_FLAG_MASK) |
371 | 21829e9b | Aurelien Jarno | << (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT); |
372 | 21829e9b | Aurelien Jarno | |
373 | 21829e9b | Aurelien Jarno | /* Generate an exception if enabled */
|
374 | 21829e9b | Aurelien Jarno | cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT; |
375 | 21829e9b | Aurelien Jarno | enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT; |
376 | 21829e9b | Aurelien Jarno | if (cause & enable) {
|
377 | 10127400 | Aurelien Jarno | raise_exception(env, 0x120, retaddr);
|
378 | 21829e9b | Aurelien Jarno | } |
379 | 21829e9b | Aurelien Jarno | } |
380 | 21829e9b | Aurelien Jarno | } |
381 | 21829e9b | Aurelien Jarno | |
382 | d6c424c5 | Aurelien Jarno | float32 helper_fabs_FT(float32 t0) |
383 | cc4ba6a9 | aurel32 | { |
384 | d6c424c5 | Aurelien Jarno | return float32_abs(t0);
|
385 | cc4ba6a9 | aurel32 | } |
386 | cc4ba6a9 | aurel32 | |
387 | d6c424c5 | Aurelien Jarno | float64 helper_fabs_DT(float64 t0) |
388 | cc4ba6a9 | aurel32 | { |
389 | d6c424c5 | Aurelien Jarno | return float64_abs(t0);
|
390 | cc4ba6a9 | aurel32 | } |
391 | cc4ba6a9 | aurel32 | |
392 | 485d0035 | Blue Swirl | float32 helper_fadd_FT(CPUSH4State *env, float32 t0, float32 t1) |
393 | cc4ba6a9 | aurel32 | { |
394 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
395 | d6c424c5 | Aurelien Jarno | t0 = float32_add(t0, t1, &env->fp_status); |
396 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
397 | d6c424c5 | Aurelien Jarno | return t0;
|
398 | cc4ba6a9 | aurel32 | } |
399 | cc4ba6a9 | aurel32 | |
400 | 485d0035 | Blue Swirl | float64 helper_fadd_DT(CPUSH4State *env, float64 t0, float64 t1) |
401 | cc4ba6a9 | aurel32 | { |
402 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
403 | d6c424c5 | Aurelien Jarno | t0 = float64_add(t0, t1, &env->fp_status); |
404 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
405 | d6c424c5 | Aurelien Jarno | return t0;
|
406 | cc4ba6a9 | aurel32 | } |
407 | cc4ba6a9 | aurel32 | |
408 | 485d0035 | Blue Swirl | void helper_fcmp_eq_FT(CPUSH4State *env, float32 t0, float32 t1)
|
409 | cc4ba6a9 | aurel32 | { |
410 | 21829e9b | Aurelien Jarno | int relation;
|
411 | 9850d1e8 | aurel32 | |
412 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
413 | d6c424c5 | Aurelien Jarno | relation = float32_compare(t0, t1, &env->fp_status); |
414 | 21829e9b | Aurelien Jarno | if (unlikely(relation == float_relation_unordered)) {
|
415 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
416 | 21829e9b | Aurelien Jarno | } else if (relation == float_relation_equal) { |
417 | 485d0035 | Blue Swirl | set_t(env); |
418 | 21829e9b | Aurelien Jarno | } else {
|
419 | 485d0035 | Blue Swirl | clr_t(env); |
420 | 21829e9b | Aurelien Jarno | } |
421 | cc4ba6a9 | aurel32 | } |
422 | cc4ba6a9 | aurel32 | |
423 | 485d0035 | Blue Swirl | void helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1)
|
424 | cc4ba6a9 | aurel32 | { |
425 | 21829e9b | Aurelien Jarno | int relation;
|
426 | 9850d1e8 | aurel32 | |
427 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
428 | d6c424c5 | Aurelien Jarno | relation = float64_compare(t0, t1, &env->fp_status); |
429 | 21829e9b | Aurelien Jarno | if (unlikely(relation == float_relation_unordered)) {
|
430 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
431 | 21829e9b | Aurelien Jarno | } else if (relation == float_relation_equal) { |
432 | 485d0035 | Blue Swirl | set_t(env); |
433 | 21829e9b | Aurelien Jarno | } else {
|
434 | 485d0035 | Blue Swirl | clr_t(env); |
435 | 21829e9b | Aurelien Jarno | } |
436 | cc4ba6a9 | aurel32 | } |
437 | cc4ba6a9 | aurel32 | |
438 | 485d0035 | Blue Swirl | void helper_fcmp_gt_FT(CPUSH4State *env, float32 t0, float32 t1)
|
439 | cc4ba6a9 | aurel32 | { |
440 | 21829e9b | Aurelien Jarno | int relation;
|
441 | 9850d1e8 | aurel32 | |
442 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
443 | d6c424c5 | Aurelien Jarno | relation = float32_compare(t0, t1, &env->fp_status); |
444 | 21829e9b | Aurelien Jarno | if (unlikely(relation == float_relation_unordered)) {
|
445 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
446 | 21829e9b | Aurelien Jarno | } else if (relation == float_relation_greater) { |
447 | 485d0035 | Blue Swirl | set_t(env); |
448 | 21829e9b | Aurelien Jarno | } else {
|
449 | 485d0035 | Blue Swirl | clr_t(env); |
450 | 21829e9b | Aurelien Jarno | } |
451 | cc4ba6a9 | aurel32 | } |
452 | cc4ba6a9 | aurel32 | |
453 | 485d0035 | Blue Swirl | void helper_fcmp_gt_DT(CPUSH4State *env, float64 t0, float64 t1)
|
454 | cc4ba6a9 | aurel32 | { |
455 | 21829e9b | Aurelien Jarno | int relation;
|
456 | 9850d1e8 | aurel32 | |
457 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
458 | d6c424c5 | Aurelien Jarno | relation = float64_compare(t0, t1, &env->fp_status); |
459 | 21829e9b | Aurelien Jarno | if (unlikely(relation == float_relation_unordered)) {
|
460 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
461 | 21829e9b | Aurelien Jarno | } else if (relation == float_relation_greater) { |
462 | 485d0035 | Blue Swirl | set_t(env); |
463 | 21829e9b | Aurelien Jarno | } else {
|
464 | 485d0035 | Blue Swirl | clr_t(env); |
465 | 21829e9b | Aurelien Jarno | } |
466 | cc4ba6a9 | aurel32 | } |
467 | cc4ba6a9 | aurel32 | |
468 | 485d0035 | Blue Swirl | float64 helper_fcnvsd_FT_DT(CPUSH4State *env, float32 t0) |
469 | cc4ba6a9 | aurel32 | { |
470 | d6c424c5 | Aurelien Jarno | float64 ret; |
471 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
472 | d6c424c5 | Aurelien Jarno | ret = float32_to_float64(t0, &env->fp_status); |
473 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
474 | d6c424c5 | Aurelien Jarno | return ret;
|
475 | cc4ba6a9 | aurel32 | } |
476 | cc4ba6a9 | aurel32 | |
477 | 485d0035 | Blue Swirl | float32 helper_fcnvds_DT_FT(CPUSH4State *env, float64 t0) |
478 | cc4ba6a9 | aurel32 | { |
479 | d6c424c5 | Aurelien Jarno | float32 ret; |
480 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
481 | d6c424c5 | Aurelien Jarno | ret = float64_to_float32(t0, &env->fp_status); |
482 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
483 | d6c424c5 | Aurelien Jarno | return ret;
|
484 | cc4ba6a9 | aurel32 | } |
485 | cc4ba6a9 | aurel32 | |
486 | 485d0035 | Blue Swirl | float32 helper_fdiv_FT(CPUSH4State *env, float32 t0, float32 t1) |
487 | cc4ba6a9 | aurel32 | { |
488 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
489 | d6c424c5 | Aurelien Jarno | t0 = float32_div(t0, t1, &env->fp_status); |
490 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
491 | d6c424c5 | Aurelien Jarno | return t0;
|
492 | cc4ba6a9 | aurel32 | } |
493 | cc4ba6a9 | aurel32 | |
494 | 485d0035 | Blue Swirl | float64 helper_fdiv_DT(CPUSH4State *env, float64 t0, float64 t1) |
495 | cc4ba6a9 | aurel32 | { |
496 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
497 | d6c424c5 | Aurelien Jarno | t0 = float64_div(t0, t1, &env->fp_status); |
498 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
499 | d6c424c5 | Aurelien Jarno | return t0;
|
500 | cc4ba6a9 | aurel32 | } |
501 | cc4ba6a9 | aurel32 | |
502 | 485d0035 | Blue Swirl | float32 helper_float_FT(CPUSH4State *env, uint32_t t0) |
503 | cc4ba6a9 | aurel32 | { |
504 | d6c424c5 | Aurelien Jarno | float32 ret; |
505 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
506 | d6c424c5 | Aurelien Jarno | ret = int32_to_float32(t0, &env->fp_status); |
507 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
508 | d6c424c5 | Aurelien Jarno | return ret;
|
509 | cc4ba6a9 | aurel32 | } |
510 | cc4ba6a9 | aurel32 | |
511 | 485d0035 | Blue Swirl | float64 helper_float_DT(CPUSH4State *env, uint32_t t0) |
512 | cc4ba6a9 | aurel32 | { |
513 | d6c424c5 | Aurelien Jarno | float64 ret; |
514 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
515 | d6c424c5 | Aurelien Jarno | ret = int32_to_float64(t0, &env->fp_status); |
516 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
517 | d6c424c5 | Aurelien Jarno | return ret;
|
518 | cc4ba6a9 | aurel32 | } |
519 | cc4ba6a9 | aurel32 | |
520 | 485d0035 | Blue Swirl | float32 helper_fmac_FT(CPUSH4State *env, float32 t0, float32 t1, float32 t2) |
521 | 5b7141a1 | aurel32 | { |
522 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
523 | ff2086fe | Aurelien Jarno | t0 = float32_muladd(t0, t1, t2, 0, &env->fp_status);
|
524 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
525 | d6c424c5 | Aurelien Jarno | return t0;
|
526 | 5b7141a1 | aurel32 | } |
527 | 5b7141a1 | aurel32 | |
528 | 485d0035 | Blue Swirl | float32 helper_fmul_FT(CPUSH4State *env, float32 t0, float32 t1) |
529 | cc4ba6a9 | aurel32 | { |
530 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
531 | d6c424c5 | Aurelien Jarno | t0 = float32_mul(t0, t1, &env->fp_status); |
532 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
533 | d6c424c5 | Aurelien Jarno | return t0;
|
534 | cc4ba6a9 | aurel32 | } |
535 | cc4ba6a9 | aurel32 | |
536 | 485d0035 | Blue Swirl | float64 helper_fmul_DT(CPUSH4State *env, float64 t0, float64 t1) |
537 | cc4ba6a9 | aurel32 | { |
538 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
539 | d6c424c5 | Aurelien Jarno | t0 = float64_mul(t0, t1, &env->fp_status); |
540 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
541 | d6c424c5 | Aurelien Jarno | return t0;
|
542 | cc4ba6a9 | aurel32 | } |
543 | cc4ba6a9 | aurel32 | |
544 | d6c424c5 | Aurelien Jarno | float32 helper_fneg_T(float32 t0) |
545 | 7fdf924f | aurel32 | { |
546 | d6c424c5 | Aurelien Jarno | return float32_chs(t0);
|
547 | 7fdf924f | aurel32 | } |
548 | 7fdf924f | aurel32 | |
549 | 485d0035 | Blue Swirl | float32 helper_fsqrt_FT(CPUSH4State *env, float32 t0) |
550 | cc4ba6a9 | aurel32 | { |
551 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
552 | d6c424c5 | Aurelien Jarno | t0 = float32_sqrt(t0, &env->fp_status); |
553 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
554 | d6c424c5 | Aurelien Jarno | return t0;
|
555 | cc4ba6a9 | aurel32 | } |
556 | cc4ba6a9 | aurel32 | |
557 | 485d0035 | Blue Swirl | float64 helper_fsqrt_DT(CPUSH4State *env, float64 t0) |
558 | cc4ba6a9 | aurel32 | { |
559 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
560 | d6c424c5 | Aurelien Jarno | t0 = float64_sqrt(t0, &env->fp_status); |
561 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
562 | d6c424c5 | Aurelien Jarno | return t0;
|
563 | cc4ba6a9 | aurel32 | } |
564 | cc4ba6a9 | aurel32 | |
565 | 485d0035 | Blue Swirl | float32 helper_fsub_FT(CPUSH4State *env, float32 t0, float32 t1) |
566 | cc4ba6a9 | aurel32 | { |
567 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
568 | d6c424c5 | Aurelien Jarno | t0 = float32_sub(t0, t1, &env->fp_status); |
569 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
570 | d6c424c5 | Aurelien Jarno | return t0;
|
571 | cc4ba6a9 | aurel32 | } |
572 | cc4ba6a9 | aurel32 | |
573 | 485d0035 | Blue Swirl | float64 helper_fsub_DT(CPUSH4State *env, float64 t0, float64 t1) |
574 | cc4ba6a9 | aurel32 | { |
575 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
576 | d6c424c5 | Aurelien Jarno | t0 = float64_sub(t0, t1, &env->fp_status); |
577 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
578 | d6c424c5 | Aurelien Jarno | return t0;
|
579 | cc4ba6a9 | aurel32 | } |
580 | cc4ba6a9 | aurel32 | |
581 | 485d0035 | Blue Swirl | uint32_t helper_ftrc_FT(CPUSH4State *env, float32 t0) |
582 | cc4ba6a9 | aurel32 | { |
583 | 21829e9b | Aurelien Jarno | uint32_t ret; |
584 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
585 | d6c424c5 | Aurelien Jarno | ret = float32_to_int32_round_to_zero(t0, &env->fp_status); |
586 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
587 | 21829e9b | Aurelien Jarno | return ret;
|
588 | cc4ba6a9 | aurel32 | } |
589 | cc4ba6a9 | aurel32 | |
590 | 485d0035 | Blue Swirl | uint32_t helper_ftrc_DT(CPUSH4State *env, float64 t0) |
591 | cc4ba6a9 | aurel32 | { |
592 | 21829e9b | Aurelien Jarno | uint32_t ret; |
593 | 21829e9b | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
594 | d6c424c5 | Aurelien Jarno | ret = float64_to_int32_round_to_zero(t0, &env->fp_status); |
595 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
596 | 21829e9b | Aurelien Jarno | return ret;
|
597 | cc4ba6a9 | aurel32 | } |
598 | af8c2bde | Aurelien Jarno | |
599 | 485d0035 | Blue Swirl | void helper_fipr(CPUSH4State *env, uint32_t m, uint32_t n)
|
600 | af8c2bde | Aurelien Jarno | { |
601 | af8c2bde | Aurelien Jarno | int bank, i;
|
602 | af8c2bde | Aurelien Jarno | float32 r, p; |
603 | af8c2bde | Aurelien Jarno | |
604 | af8c2bde | Aurelien Jarno | bank = (env->sr & FPSCR_FR) ? 16 : 0; |
605 | af8c2bde | Aurelien Jarno | r = float32_zero; |
606 | af8c2bde | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
607 | af8c2bde | Aurelien Jarno | |
608 | af8c2bde | Aurelien Jarno | for (i = 0 ; i < 4 ; i++) { |
609 | af8c2bde | Aurelien Jarno | p = float32_mul(env->fregs[bank + m + i], |
610 | af8c2bde | Aurelien Jarno | env->fregs[bank + n + i], |
611 | af8c2bde | Aurelien Jarno | &env->fp_status); |
612 | af8c2bde | Aurelien Jarno | r = float32_add(r, p, &env->fp_status); |
613 | af8c2bde | Aurelien Jarno | } |
614 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
615 | af8c2bde | Aurelien Jarno | |
616 | af8c2bde | Aurelien Jarno | env->fregs[bank + n + 3] = r;
|
617 | af8c2bde | Aurelien Jarno | } |
618 | 17075f10 | Aurelien Jarno | |
619 | 485d0035 | Blue Swirl | void helper_ftrv(CPUSH4State *env, uint32_t n)
|
620 | 17075f10 | Aurelien Jarno | { |
621 | 17075f10 | Aurelien Jarno | int bank_matrix, bank_vector;
|
622 | 17075f10 | Aurelien Jarno | int i, j;
|
623 | 17075f10 | Aurelien Jarno | float32 r[4];
|
624 | 17075f10 | Aurelien Jarno | float32 p; |
625 | 17075f10 | Aurelien Jarno | |
626 | 17075f10 | Aurelien Jarno | bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16; |
627 | 17075f10 | Aurelien Jarno | bank_vector = (env->sr & FPSCR_FR) ? 16 : 0; |
628 | 17075f10 | Aurelien Jarno | set_float_exception_flags(0, &env->fp_status);
|
629 | 17075f10 | Aurelien Jarno | for (i = 0 ; i < 4 ; i++) { |
630 | 17075f10 | Aurelien Jarno | r[i] = float32_zero; |
631 | 17075f10 | Aurelien Jarno | for (j = 0 ; j < 4 ; j++) { |
632 | 17075f10 | Aurelien Jarno | p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
|
633 | 17075f10 | Aurelien Jarno | env->fregs[bank_vector + j], |
634 | 17075f10 | Aurelien Jarno | &env->fp_status); |
635 | 17075f10 | Aurelien Jarno | r[i] = float32_add(r[i], p, &env->fp_status); |
636 | 17075f10 | Aurelien Jarno | } |
637 | 17075f10 | Aurelien Jarno | } |
638 | 485d0035 | Blue Swirl | update_fpscr(env, GETPC()); |
639 | 17075f10 | Aurelien Jarno | |
640 | 17075f10 | Aurelien Jarno | for (i = 0 ; i < 4 ; i++) { |
641 | 17075f10 | Aurelien Jarno | env->fregs[bank_vector + i] = r[i]; |
642 | 17075f10 | Aurelien Jarno | } |
643 | 17075f10 | Aurelien Jarno | } |