root / target-sh4 / op_helper.c @ 44e4c0ba
History | View | Annotate | Download (12 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 | fdf9b3e8 | bellard | #include "exec.h" |
22 | a7812ae4 | pbrook | #include "helper.h" |
23 | fdf9b3e8 | bellard | |
24 | fdf9b3e8 | bellard | #ifndef CONFIG_USER_ONLY
|
25 | fdf9b3e8 | bellard | |
26 | fdf9b3e8 | bellard | #define MMUSUFFIX _mmu
|
27 | fdf9b3e8 | bellard | |
28 | fdf9b3e8 | bellard | #define SHIFT 0 |
29 | fdf9b3e8 | bellard | #include "softmmu_template.h" |
30 | fdf9b3e8 | bellard | |
31 | fdf9b3e8 | bellard | #define SHIFT 1 |
32 | fdf9b3e8 | bellard | #include "softmmu_template.h" |
33 | fdf9b3e8 | bellard | |
34 | fdf9b3e8 | bellard | #define SHIFT 2 |
35 | fdf9b3e8 | bellard | #include "softmmu_template.h" |
36 | fdf9b3e8 | bellard | |
37 | fdf9b3e8 | bellard | #define SHIFT 3 |
38 | fdf9b3e8 | bellard | #include "softmmu_template.h" |
39 | fdf9b3e8 | bellard | |
40 | 6ebbf390 | j_mayer | void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
41 | fdf9b3e8 | bellard | { |
42 | fdf9b3e8 | bellard | TranslationBlock *tb; |
43 | fdf9b3e8 | bellard | CPUState *saved_env; |
44 | fdf9b3e8 | bellard | unsigned long pc; |
45 | fdf9b3e8 | bellard | int ret;
|
46 | fdf9b3e8 | bellard | |
47 | fdf9b3e8 | bellard | /* XXX: hack to restore env in all cases, even if not called from
|
48 | fdf9b3e8 | bellard | generated code */
|
49 | fdf9b3e8 | bellard | saved_env = env; |
50 | fdf9b3e8 | bellard | env = cpu_single_env; |
51 | 6ebbf390 | j_mayer | ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
|
52 | fdf9b3e8 | bellard | if (ret) {
|
53 | fdf9b3e8 | bellard | if (retaddr) {
|
54 | fdf9b3e8 | bellard | /* now we have a real cpu fault */
|
55 | fdf9b3e8 | bellard | pc = (unsigned long) retaddr; |
56 | fdf9b3e8 | bellard | tb = tb_find_pc(pc); |
57 | fdf9b3e8 | bellard | if (tb) {
|
58 | fdf9b3e8 | bellard | /* the PC is inside the translated code. It means that we have
|
59 | fdf9b3e8 | bellard | a virtual CPU fault */
|
60 | fdf9b3e8 | bellard | cpu_restore_state(tb, env, pc, NULL);
|
61 | fdf9b3e8 | bellard | } |
62 | fdf9b3e8 | bellard | } |
63 | e6afc2f4 | aurel32 | cpu_loop_exit(); |
64 | fdf9b3e8 | bellard | } |
65 | fdf9b3e8 | bellard | env = saved_env; |
66 | fdf9b3e8 | bellard | } |
67 | fdf9b3e8 | bellard | |
68 | fdf9b3e8 | bellard | #endif
|
69 | fdf9b3e8 | bellard | |
70 | ea2b542a | aurel32 | void helper_ldtlb(void) |
71 | ea2b542a | aurel32 | { |
72 | ea2b542a | aurel32 | #ifdef CONFIG_USER_ONLY
|
73 | ea2b542a | aurel32 | /* XXXXX */
|
74 | ea2b542a | aurel32 | assert(0);
|
75 | ea2b542a | aurel32 | #else
|
76 | ea2b542a | aurel32 | cpu_load_tlb(env); |
77 | ea2b542a | aurel32 | #endif
|
78 | ea2b542a | aurel32 | } |
79 | ea2b542a | aurel32 | |
80 | e6afc2f4 | aurel32 | void helper_raise_illegal_instruction(void) |
81 | e6afc2f4 | aurel32 | { |
82 | e6afc2f4 | aurel32 | env->exception_index = 0x180;
|
83 | e6afc2f4 | aurel32 | cpu_loop_exit(); |
84 | e6afc2f4 | aurel32 | } |
85 | e6afc2f4 | aurel32 | |
86 | e6afc2f4 | aurel32 | void helper_raise_slot_illegal_instruction(void) |
87 | e6afc2f4 | aurel32 | { |
88 | e6afc2f4 | aurel32 | env->exception_index = 0x1a0;
|
89 | e6afc2f4 | aurel32 | cpu_loop_exit(); |
90 | e6afc2f4 | aurel32 | } |
91 | e6afc2f4 | aurel32 | |
92 | d8299bcc | aurel32 | void helper_raise_fpu_disable(void) |
93 | d8299bcc | aurel32 | { |
94 | d8299bcc | aurel32 | env->exception_index = 0x800;
|
95 | d8299bcc | aurel32 | cpu_loop_exit(); |
96 | d8299bcc | aurel32 | } |
97 | d8299bcc | aurel32 | |
98 | d8299bcc | aurel32 | void helper_raise_slot_fpu_disable(void) |
99 | d8299bcc | aurel32 | { |
100 | d8299bcc | aurel32 | env->exception_index = 0x820;
|
101 | d8299bcc | aurel32 | cpu_loop_exit(); |
102 | d8299bcc | aurel32 | } |
103 | d8299bcc | aurel32 | |
104 | e6afc2f4 | aurel32 | void helper_debug(void) |
105 | e6afc2f4 | aurel32 | { |
106 | e6afc2f4 | aurel32 | env->exception_index = EXCP_DEBUG; |
107 | e6afc2f4 | aurel32 | cpu_loop_exit(); |
108 | e6afc2f4 | aurel32 | } |
109 | e6afc2f4 | aurel32 | |
110 | f24f381b | aurel32 | void helper_sleep(uint32_t next_pc)
|
111 | e6afc2f4 | aurel32 | { |
112 | e6afc2f4 | aurel32 | env->halted = 1;
|
113 | e6afc2f4 | aurel32 | env->exception_index = EXCP_HLT; |
114 | f24f381b | aurel32 | env->pc = next_pc; |
115 | e6afc2f4 | aurel32 | cpu_loop_exit(); |
116 | e6afc2f4 | aurel32 | } |
117 | e6afc2f4 | aurel32 | |
118 | e6afc2f4 | aurel32 | void helper_trapa(uint32_t tra)
|
119 | e6afc2f4 | aurel32 | { |
120 | e6afc2f4 | aurel32 | env->tra = tra << 2;
|
121 | e6afc2f4 | aurel32 | env->exception_index = 0x160;
|
122 | e6afc2f4 | aurel32 | cpu_loop_exit(); |
123 | e6afc2f4 | aurel32 | } |
124 | e6afc2f4 | aurel32 | |
125 | 852d481f | edgar_igl | void helper_movcal(uint32_t address, uint32_t value)
|
126 | 852d481f | edgar_igl | { |
127 | 852d481f | edgar_igl | if (cpu_sh4_is_cached (env, address))
|
128 | 852d481f | edgar_igl | { |
129 | 852d481f | edgar_igl | memory_content *r = malloc (sizeof(memory_content));
|
130 | 852d481f | edgar_igl | r->address = address; |
131 | 852d481f | edgar_igl | r->value = value; |
132 | 852d481f | edgar_igl | r->next = NULL;
|
133 | 852d481f | edgar_igl | |
134 | 852d481f | edgar_igl | *(env->movcal_backup_tail) = r; |
135 | 852d481f | edgar_igl | env->movcal_backup_tail = &(r->next); |
136 | 852d481f | edgar_igl | } |
137 | 852d481f | edgar_igl | } |
138 | 852d481f | edgar_igl | |
139 | 852d481f | edgar_igl | void helper_discard_movcal_backup(void) |
140 | 852d481f | edgar_igl | { |
141 | 852d481f | edgar_igl | memory_content *current = env->movcal_backup; |
142 | 852d481f | edgar_igl | |
143 | 852d481f | edgar_igl | while(current)
|
144 | 852d481f | edgar_igl | { |
145 | 852d481f | edgar_igl | memory_content *next = current->next; |
146 | 852d481f | edgar_igl | free (current); |
147 | 852d481f | edgar_igl | env->movcal_backup = current = next; |
148 | b9d38e95 | Blue Swirl | if (current == NULL) |
149 | 852d481f | edgar_igl | env->movcal_backup_tail = &(env->movcal_backup); |
150 | 852d481f | edgar_igl | } |
151 | 852d481f | edgar_igl | } |
152 | 852d481f | edgar_igl | |
153 | 852d481f | edgar_igl | void helper_ocbi(uint32_t address)
|
154 | 852d481f | edgar_igl | { |
155 | 852d481f | edgar_igl | memory_content **current = &(env->movcal_backup); |
156 | 852d481f | edgar_igl | while (*current)
|
157 | 852d481f | edgar_igl | { |
158 | 852d481f | edgar_igl | uint32_t a = (*current)->address; |
159 | 852d481f | edgar_igl | if ((a & ~0x1F) == (address & ~0x1F)) |
160 | 852d481f | edgar_igl | { |
161 | 852d481f | edgar_igl | memory_content *next = (*current)->next; |
162 | 852d481f | edgar_igl | stl(a, (*current)->value); |
163 | 852d481f | edgar_igl | |
164 | b9d38e95 | Blue Swirl | if (next == NULL) |
165 | 852d481f | edgar_igl | { |
166 | 852d481f | edgar_igl | env->movcal_backup_tail = current; |
167 | 852d481f | edgar_igl | } |
168 | 852d481f | edgar_igl | |
169 | 852d481f | edgar_igl | free (*current); |
170 | 852d481f | edgar_igl | *current = next; |
171 | 852d481f | edgar_igl | break;
|
172 | 852d481f | edgar_igl | } |
173 | 852d481f | edgar_igl | } |
174 | 852d481f | edgar_igl | } |
175 | 852d481f | edgar_igl | |
176 | 6f06939b | aurel32 | uint32_t helper_addc(uint32_t arg0, uint32_t arg1) |
177 | fdf9b3e8 | bellard | { |
178 | fdf9b3e8 | bellard | uint32_t tmp0, tmp1; |
179 | fdf9b3e8 | bellard | |
180 | 6f06939b | aurel32 | tmp1 = arg0 + arg1; |
181 | 6f06939b | aurel32 | tmp0 = arg1; |
182 | 6f06939b | aurel32 | arg1 = tmp1 + (env->sr & 1);
|
183 | fdf9b3e8 | bellard | if (tmp0 > tmp1)
|
184 | fdf9b3e8 | bellard | env->sr |= SR_T; |
185 | fdf9b3e8 | bellard | else
|
186 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
187 | 6f06939b | aurel32 | if (tmp1 > arg1)
|
188 | fdf9b3e8 | bellard | env->sr |= SR_T; |
189 | 6f06939b | aurel32 | return arg1;
|
190 | fdf9b3e8 | bellard | } |
191 | fdf9b3e8 | bellard | |
192 | 6f06939b | aurel32 | uint32_t helper_addv(uint32_t arg0, uint32_t arg1) |
193 | fdf9b3e8 | bellard | { |
194 | fdf9b3e8 | bellard | uint32_t dest, src, ans; |
195 | fdf9b3e8 | bellard | |
196 | 6f06939b | aurel32 | if ((int32_t) arg1 >= 0) |
197 | fdf9b3e8 | bellard | dest = 0;
|
198 | fdf9b3e8 | bellard | else
|
199 | fdf9b3e8 | bellard | dest = 1;
|
200 | 6f06939b | aurel32 | if ((int32_t) arg0 >= 0) |
201 | fdf9b3e8 | bellard | src = 0;
|
202 | fdf9b3e8 | bellard | else
|
203 | fdf9b3e8 | bellard | src = 1;
|
204 | fdf9b3e8 | bellard | src += dest; |
205 | 6f06939b | aurel32 | arg1 += arg0; |
206 | 6f06939b | aurel32 | if ((int32_t) arg1 >= 0) |
207 | fdf9b3e8 | bellard | ans = 0;
|
208 | fdf9b3e8 | bellard | else
|
209 | fdf9b3e8 | bellard | ans = 1;
|
210 | fdf9b3e8 | bellard | ans += dest; |
211 | fdf9b3e8 | bellard | if (src == 0 || src == 2) { |
212 | fdf9b3e8 | bellard | if (ans == 1) |
213 | fdf9b3e8 | bellard | env->sr |= SR_T; |
214 | fdf9b3e8 | bellard | else
|
215 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
216 | fdf9b3e8 | bellard | } else
|
217 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
218 | 6f06939b | aurel32 | return arg1;
|
219 | fdf9b3e8 | bellard | } |
220 | fdf9b3e8 | bellard | |
221 | fdf9b3e8 | bellard | #define T (env->sr & SR_T)
|
222 | fdf9b3e8 | bellard | #define Q (env->sr & SR_Q ? 1 : 0) |
223 | fdf9b3e8 | bellard | #define M (env->sr & SR_M ? 1 : 0) |
224 | fdf9b3e8 | bellard | #define SETT env->sr |= SR_T
|
225 | fdf9b3e8 | bellard | #define CLRT env->sr &= ~SR_T
|
226 | fdf9b3e8 | bellard | #define SETQ env->sr |= SR_Q
|
227 | fdf9b3e8 | bellard | #define CLRQ env->sr &= ~SR_Q
|
228 | fdf9b3e8 | bellard | #define SETM env->sr |= SR_M
|
229 | fdf9b3e8 | bellard | #define CLRM env->sr &= ~SR_M
|
230 | fdf9b3e8 | bellard | |
231 | 69d6275b | aurel32 | uint32_t helper_div1(uint32_t arg0, uint32_t arg1) |
232 | fdf9b3e8 | bellard | { |
233 | fdf9b3e8 | bellard | uint32_t tmp0, tmp2; |
234 | fdf9b3e8 | bellard | uint8_t old_q, tmp1 = 0xff;
|
235 | fdf9b3e8 | bellard | |
236 | 69d6275b | aurel32 | //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
|
237 | fdf9b3e8 | bellard | old_q = Q; |
238 | 69d6275b | aurel32 | if ((0x80000000 & arg1) != 0) |
239 | fdf9b3e8 | bellard | SETQ; |
240 | fdf9b3e8 | bellard | else
|
241 | fdf9b3e8 | bellard | CLRQ; |
242 | 69d6275b | aurel32 | tmp2 = arg0; |
243 | 69d6275b | aurel32 | arg1 <<= 1;
|
244 | 69d6275b | aurel32 | arg1 |= T; |
245 | fdf9b3e8 | bellard | switch (old_q) {
|
246 | fdf9b3e8 | bellard | case 0: |
247 | fdf9b3e8 | bellard | switch (M) {
|
248 | fdf9b3e8 | bellard | case 0: |
249 | 69d6275b | aurel32 | tmp0 = arg1; |
250 | 69d6275b | aurel32 | arg1 -= tmp2; |
251 | 69d6275b | aurel32 | tmp1 = arg1 > tmp0; |
252 | fdf9b3e8 | bellard | switch (Q) {
|
253 | fdf9b3e8 | bellard | case 0: |
254 | fdf9b3e8 | bellard | if (tmp1)
|
255 | fdf9b3e8 | bellard | SETQ; |
256 | fdf9b3e8 | bellard | else
|
257 | fdf9b3e8 | bellard | CLRQ; |
258 | fdf9b3e8 | bellard | break;
|
259 | fdf9b3e8 | bellard | case 1: |
260 | fdf9b3e8 | bellard | if (tmp1 == 0) |
261 | fdf9b3e8 | bellard | SETQ; |
262 | fdf9b3e8 | bellard | else
|
263 | fdf9b3e8 | bellard | CLRQ; |
264 | fdf9b3e8 | bellard | break;
|
265 | fdf9b3e8 | bellard | } |
266 | fdf9b3e8 | bellard | break;
|
267 | fdf9b3e8 | bellard | case 1: |
268 | 69d6275b | aurel32 | tmp0 = arg1; |
269 | 69d6275b | aurel32 | arg1 += tmp2; |
270 | 69d6275b | aurel32 | tmp1 = arg1 < tmp0; |
271 | fdf9b3e8 | bellard | switch (Q) {
|
272 | fdf9b3e8 | bellard | case 0: |
273 | fdf9b3e8 | bellard | if (tmp1 == 0) |
274 | fdf9b3e8 | bellard | SETQ; |
275 | fdf9b3e8 | bellard | else
|
276 | fdf9b3e8 | bellard | CLRQ; |
277 | fdf9b3e8 | bellard | break;
|
278 | fdf9b3e8 | bellard | case 1: |
279 | fdf9b3e8 | bellard | if (tmp1)
|
280 | fdf9b3e8 | bellard | SETQ; |
281 | fdf9b3e8 | bellard | else
|
282 | fdf9b3e8 | bellard | CLRQ; |
283 | fdf9b3e8 | bellard | break;
|
284 | fdf9b3e8 | bellard | } |
285 | fdf9b3e8 | bellard | break;
|
286 | fdf9b3e8 | bellard | } |
287 | fdf9b3e8 | bellard | break;
|
288 | fdf9b3e8 | bellard | case 1: |
289 | fdf9b3e8 | bellard | switch (M) {
|
290 | fdf9b3e8 | bellard | case 0: |
291 | 69d6275b | aurel32 | tmp0 = arg1; |
292 | 69d6275b | aurel32 | arg1 += tmp2; |
293 | 69d6275b | aurel32 | tmp1 = arg1 < tmp0; |
294 | fdf9b3e8 | bellard | switch (Q) {
|
295 | fdf9b3e8 | bellard | case 0: |
296 | fdf9b3e8 | bellard | if (tmp1)
|
297 | fdf9b3e8 | bellard | SETQ; |
298 | fdf9b3e8 | bellard | else
|
299 | fdf9b3e8 | bellard | CLRQ; |
300 | fdf9b3e8 | bellard | break;
|
301 | fdf9b3e8 | bellard | case 1: |
302 | fdf9b3e8 | bellard | if (tmp1 == 0) |
303 | fdf9b3e8 | bellard | SETQ; |
304 | fdf9b3e8 | bellard | else
|
305 | fdf9b3e8 | bellard | CLRQ; |
306 | fdf9b3e8 | bellard | break;
|
307 | fdf9b3e8 | bellard | } |
308 | fdf9b3e8 | bellard | break;
|
309 | fdf9b3e8 | bellard | case 1: |
310 | 69d6275b | aurel32 | tmp0 = arg1; |
311 | 69d6275b | aurel32 | arg1 -= tmp2; |
312 | 69d6275b | aurel32 | tmp1 = arg1 > tmp0; |
313 | fdf9b3e8 | bellard | switch (Q) {
|
314 | fdf9b3e8 | bellard | case 0: |
315 | fdf9b3e8 | bellard | if (tmp1 == 0) |
316 | fdf9b3e8 | bellard | SETQ; |
317 | fdf9b3e8 | bellard | else
|
318 | fdf9b3e8 | bellard | CLRQ; |
319 | fdf9b3e8 | bellard | break;
|
320 | fdf9b3e8 | bellard | case 1: |
321 | fdf9b3e8 | bellard | if (tmp1)
|
322 | fdf9b3e8 | bellard | SETQ; |
323 | fdf9b3e8 | bellard | else
|
324 | fdf9b3e8 | bellard | CLRQ; |
325 | fdf9b3e8 | bellard | break;
|
326 | fdf9b3e8 | bellard | } |
327 | fdf9b3e8 | bellard | break;
|
328 | fdf9b3e8 | bellard | } |
329 | fdf9b3e8 | bellard | break;
|
330 | fdf9b3e8 | bellard | } |
331 | fdf9b3e8 | bellard | if (Q == M)
|
332 | fdf9b3e8 | bellard | SETT; |
333 | fdf9b3e8 | bellard | else
|
334 | fdf9b3e8 | bellard | CLRT; |
335 | 69d6275b | aurel32 | //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
|
336 | 69d6275b | aurel32 | return arg1;
|
337 | fdf9b3e8 | bellard | } |
338 | fdf9b3e8 | bellard | |
339 | 6f06939b | aurel32 | void helper_macl(uint32_t arg0, uint32_t arg1)
|
340 | fdf9b3e8 | bellard | { |
341 | fdf9b3e8 | bellard | int64_t res; |
342 | fdf9b3e8 | bellard | |
343 | fdf9b3e8 | bellard | res = ((uint64_t) env->mach << 32) | env->macl;
|
344 | 6f06939b | aurel32 | res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1; |
345 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
346 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
347 | fdf9b3e8 | bellard | if (env->sr & SR_S) {
|
348 | fdf9b3e8 | bellard | if (res < 0) |
349 | fdf9b3e8 | bellard | env->mach |= 0xffff0000;
|
350 | fdf9b3e8 | bellard | else
|
351 | fdf9b3e8 | bellard | env->mach &= 0x00007fff;
|
352 | fdf9b3e8 | bellard | } |
353 | fdf9b3e8 | bellard | } |
354 | fdf9b3e8 | bellard | |
355 | 6f06939b | aurel32 | void helper_macw(uint32_t arg0, uint32_t arg1)
|
356 | fdf9b3e8 | bellard | { |
357 | fdf9b3e8 | bellard | int64_t res; |
358 | fdf9b3e8 | bellard | |
359 | fdf9b3e8 | bellard | res = ((uint64_t) env->mach << 32) | env->macl;
|
360 | 6f06939b | aurel32 | res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1; |
361 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
362 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
363 | fdf9b3e8 | bellard | if (env->sr & SR_S) {
|
364 | fdf9b3e8 | bellard | if (res < -0x80000000) { |
365 | fdf9b3e8 | bellard | env->mach = 1;
|
366 | fdf9b3e8 | bellard | env->macl = 0x80000000;
|
367 | fdf9b3e8 | bellard | } else if (res > 0x000000007fffffff) { |
368 | fdf9b3e8 | bellard | env->mach = 1;
|
369 | fdf9b3e8 | bellard | env->macl = 0x7fffffff;
|
370 | fdf9b3e8 | bellard | } |
371 | fdf9b3e8 | bellard | } |
372 | fdf9b3e8 | bellard | } |
373 | fdf9b3e8 | bellard | |
374 | 6f06939b | aurel32 | uint32_t helper_negc(uint32_t arg) |
375 | fdf9b3e8 | bellard | { |
376 | fdf9b3e8 | bellard | uint32_t temp; |
377 | fdf9b3e8 | bellard | |
378 | 6f06939b | aurel32 | temp = -arg; |
379 | 6f06939b | aurel32 | arg = temp - (env->sr & SR_T); |
380 | fdf9b3e8 | bellard | if (0 < temp) |
381 | fdf9b3e8 | bellard | env->sr |= SR_T; |
382 | fdf9b3e8 | bellard | else
|
383 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
384 | 6f06939b | aurel32 | if (temp < arg)
|
385 | fdf9b3e8 | bellard | env->sr |= SR_T; |
386 | 6f06939b | aurel32 | return arg;
|
387 | fdf9b3e8 | bellard | } |
388 | fdf9b3e8 | bellard | |
389 | 6f06939b | aurel32 | uint32_t helper_subc(uint32_t arg0, uint32_t arg1) |
390 | fdf9b3e8 | bellard | { |
391 | fdf9b3e8 | bellard | uint32_t tmp0, tmp1; |
392 | fdf9b3e8 | bellard | |
393 | 6f06939b | aurel32 | tmp1 = arg1 - arg0; |
394 | 6f06939b | aurel32 | tmp0 = arg1; |
395 | 6f06939b | aurel32 | arg1 = tmp1 - (env->sr & SR_T); |
396 | fdf9b3e8 | bellard | if (tmp0 < tmp1)
|
397 | fdf9b3e8 | bellard | env->sr |= SR_T; |
398 | fdf9b3e8 | bellard | else
|
399 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
400 | 6f06939b | aurel32 | if (tmp1 < arg1)
|
401 | fdf9b3e8 | bellard | env->sr |= SR_T; |
402 | 6f06939b | aurel32 | return arg1;
|
403 | fdf9b3e8 | bellard | } |
404 | fdf9b3e8 | bellard | |
405 | 6f06939b | aurel32 | uint32_t helper_subv(uint32_t arg0, uint32_t arg1) |
406 | fdf9b3e8 | bellard | { |
407 | fdf9b3e8 | bellard | int32_t dest, src, ans; |
408 | fdf9b3e8 | bellard | |
409 | 6f06939b | aurel32 | if ((int32_t) arg1 >= 0) |
410 | fdf9b3e8 | bellard | dest = 0;
|
411 | fdf9b3e8 | bellard | else
|
412 | fdf9b3e8 | bellard | dest = 1;
|
413 | 6f06939b | aurel32 | if ((int32_t) arg0 >= 0) |
414 | fdf9b3e8 | bellard | src = 0;
|
415 | fdf9b3e8 | bellard | else
|
416 | fdf9b3e8 | bellard | src = 1;
|
417 | fdf9b3e8 | bellard | src += dest; |
418 | 6f06939b | aurel32 | arg1 -= arg0; |
419 | 6f06939b | aurel32 | if ((int32_t) arg1 >= 0) |
420 | fdf9b3e8 | bellard | ans = 0;
|
421 | fdf9b3e8 | bellard | else
|
422 | fdf9b3e8 | bellard | ans = 1;
|
423 | fdf9b3e8 | bellard | ans += dest; |
424 | fdf9b3e8 | bellard | if (src == 1) { |
425 | fdf9b3e8 | bellard | if (ans == 1) |
426 | fdf9b3e8 | bellard | env->sr |= SR_T; |
427 | fdf9b3e8 | bellard | else
|
428 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
429 | fdf9b3e8 | bellard | } else
|
430 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
431 | 6f06939b | aurel32 | return arg1;
|
432 | fdf9b3e8 | bellard | } |
433 | fdf9b3e8 | bellard | |
434 | cc4ba6a9 | aurel32 | static inline void set_t(void) |
435 | cc4ba6a9 | aurel32 | { |
436 | cc4ba6a9 | aurel32 | env->sr |= SR_T; |
437 | cc4ba6a9 | aurel32 | } |
438 | cc4ba6a9 | aurel32 | |
439 | cc4ba6a9 | aurel32 | static inline void clr_t(void) |
440 | cc4ba6a9 | aurel32 | { |
441 | cc4ba6a9 | aurel32 | env->sr &= ~SR_T; |
442 | cc4ba6a9 | aurel32 | } |
443 | cc4ba6a9 | aurel32 | |
444 | 390af821 | aurel32 | void helper_ld_fpscr(uint32_t val)
|
445 | 390af821 | aurel32 | { |
446 | 390af821 | aurel32 | env->fpscr = val & 0x003fffff;
|
447 | 390af821 | aurel32 | if (val & 0x01) |
448 | 390af821 | aurel32 | set_float_rounding_mode(float_round_to_zero, &env->fp_status); |
449 | 390af821 | aurel32 | else
|
450 | 390af821 | aurel32 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
451 | 390af821 | aurel32 | } |
452 | cc4ba6a9 | aurel32 | |
453 | cc4ba6a9 | aurel32 | uint32_t helper_fabs_FT(uint32_t t0) |
454 | cc4ba6a9 | aurel32 | { |
455 | 9850d1e8 | aurel32 | CPU_FloatU f; |
456 | 9850d1e8 | aurel32 | f.l = t0; |
457 | 9850d1e8 | aurel32 | f.f = float32_abs(f.f); |
458 | 9850d1e8 | aurel32 | return f.l;
|
459 | cc4ba6a9 | aurel32 | } |
460 | cc4ba6a9 | aurel32 | |
461 | cc4ba6a9 | aurel32 | uint64_t helper_fabs_DT(uint64_t t0) |
462 | cc4ba6a9 | aurel32 | { |
463 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
464 | 9850d1e8 | aurel32 | d.ll = t0; |
465 | 9850d1e8 | aurel32 | d.d = float64_abs(d.d); |
466 | 9850d1e8 | aurel32 | return d.ll;
|
467 | cc4ba6a9 | aurel32 | } |
468 | cc4ba6a9 | aurel32 | |
469 | cc4ba6a9 | aurel32 | uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1) |
470 | cc4ba6a9 | aurel32 | { |
471 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
472 | 9850d1e8 | aurel32 | f0.l = t0; |
473 | 9850d1e8 | aurel32 | f1.l = t1; |
474 | 9850d1e8 | aurel32 | f0.f = float32_add(f0.f, f1.f, &env->fp_status); |
475 | 9850d1e8 | aurel32 | return f0.l;
|
476 | cc4ba6a9 | aurel32 | } |
477 | cc4ba6a9 | aurel32 | |
478 | cc4ba6a9 | aurel32 | uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1) |
479 | cc4ba6a9 | aurel32 | { |
480 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
481 | 9850d1e8 | aurel32 | d0.ll = t0; |
482 | 9850d1e8 | aurel32 | d1.ll = t1; |
483 | 9850d1e8 | aurel32 | d0.d = float64_add(d0.d, d1.d, &env->fp_status); |
484 | 9850d1e8 | aurel32 | return d0.ll;
|
485 | cc4ba6a9 | aurel32 | } |
486 | cc4ba6a9 | aurel32 | |
487 | cc4ba6a9 | aurel32 | void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
|
488 | cc4ba6a9 | aurel32 | { |
489 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
490 | 9850d1e8 | aurel32 | f0.l = t0; |
491 | 9850d1e8 | aurel32 | f1.l = t1; |
492 | 9850d1e8 | aurel32 | |
493 | 9850d1e8 | aurel32 | if (float32_compare(f0.f, f1.f, &env->fp_status) == 0) |
494 | cc4ba6a9 | aurel32 | set_t(); |
495 | cc4ba6a9 | aurel32 | else
|
496 | cc4ba6a9 | aurel32 | clr_t(); |
497 | cc4ba6a9 | aurel32 | } |
498 | cc4ba6a9 | aurel32 | |
499 | cc4ba6a9 | aurel32 | void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
|
500 | cc4ba6a9 | aurel32 | { |
501 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
502 | 9850d1e8 | aurel32 | d0.ll = t0; |
503 | 9850d1e8 | aurel32 | d1.ll = t1; |
504 | 9850d1e8 | aurel32 | |
505 | 9850d1e8 | aurel32 | if (float64_compare(d0.d, d1.d, &env->fp_status) == 0) |
506 | cc4ba6a9 | aurel32 | set_t(); |
507 | cc4ba6a9 | aurel32 | else
|
508 | cc4ba6a9 | aurel32 | clr_t(); |
509 | cc4ba6a9 | aurel32 | } |
510 | cc4ba6a9 | aurel32 | |
511 | cc4ba6a9 | aurel32 | void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
|
512 | cc4ba6a9 | aurel32 | { |
513 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
514 | 9850d1e8 | aurel32 | f0.l = t0; |
515 | 9850d1e8 | aurel32 | f1.l = t1; |
516 | 9850d1e8 | aurel32 | |
517 | 9850d1e8 | aurel32 | if (float32_compare(f0.f, f1.f, &env->fp_status) == 1) |
518 | cc4ba6a9 | aurel32 | set_t(); |
519 | cc4ba6a9 | aurel32 | else
|
520 | cc4ba6a9 | aurel32 | clr_t(); |
521 | cc4ba6a9 | aurel32 | } |
522 | cc4ba6a9 | aurel32 | |
523 | cc4ba6a9 | aurel32 | void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
|
524 | cc4ba6a9 | aurel32 | { |
525 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
526 | 9850d1e8 | aurel32 | d0.ll = t0; |
527 | 9850d1e8 | aurel32 | d1.ll = t1; |
528 | 9850d1e8 | aurel32 | |
529 | 9850d1e8 | aurel32 | if (float64_compare(d0.d, d1.d, &env->fp_status) == 1) |
530 | cc4ba6a9 | aurel32 | set_t(); |
531 | cc4ba6a9 | aurel32 | else
|
532 | cc4ba6a9 | aurel32 | clr_t(); |
533 | cc4ba6a9 | aurel32 | } |
534 | cc4ba6a9 | aurel32 | |
535 | cc4ba6a9 | aurel32 | uint64_t helper_fcnvsd_FT_DT(uint32_t t0) |
536 | cc4ba6a9 | aurel32 | { |
537 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
538 | 9850d1e8 | aurel32 | CPU_FloatU f; |
539 | 9850d1e8 | aurel32 | f.l = t0; |
540 | 9850d1e8 | aurel32 | d.d = float32_to_float64(f.f, &env->fp_status); |
541 | 9850d1e8 | aurel32 | return d.ll;
|
542 | cc4ba6a9 | aurel32 | } |
543 | cc4ba6a9 | aurel32 | |
544 | cc4ba6a9 | aurel32 | uint32_t helper_fcnvds_DT_FT(uint64_t t0) |
545 | cc4ba6a9 | aurel32 | { |
546 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
547 | 9850d1e8 | aurel32 | CPU_FloatU f; |
548 | 9850d1e8 | aurel32 | d.ll = t0; |
549 | 9850d1e8 | aurel32 | f.f = float64_to_float32(d.d, &env->fp_status); |
550 | 9850d1e8 | aurel32 | return f.l;
|
551 | cc4ba6a9 | aurel32 | } |
552 | cc4ba6a9 | aurel32 | |
553 | cc4ba6a9 | aurel32 | uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1) |
554 | cc4ba6a9 | aurel32 | { |
555 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
556 | 9850d1e8 | aurel32 | f0.l = t0; |
557 | 9850d1e8 | aurel32 | f1.l = t1; |
558 | 9850d1e8 | aurel32 | f0.f = float32_div(f0.f, f1.f, &env->fp_status); |
559 | 9850d1e8 | aurel32 | return f0.l;
|
560 | cc4ba6a9 | aurel32 | } |
561 | cc4ba6a9 | aurel32 | |
562 | cc4ba6a9 | aurel32 | uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1) |
563 | cc4ba6a9 | aurel32 | { |
564 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
565 | 9850d1e8 | aurel32 | d0.ll = t0; |
566 | 9850d1e8 | aurel32 | d1.ll = t1; |
567 | 9850d1e8 | aurel32 | d0.d = float64_div(d0.d, d1.d, &env->fp_status); |
568 | 9850d1e8 | aurel32 | return d0.ll;
|
569 | cc4ba6a9 | aurel32 | } |
570 | cc4ba6a9 | aurel32 | |
571 | cc4ba6a9 | aurel32 | uint32_t helper_float_FT(uint32_t t0) |
572 | cc4ba6a9 | aurel32 | { |
573 | 9850d1e8 | aurel32 | CPU_FloatU f; |
574 | 9850d1e8 | aurel32 | f.f = int32_to_float32(t0, &env->fp_status); |
575 | 9850d1e8 | aurel32 | return f.l;
|
576 | cc4ba6a9 | aurel32 | } |
577 | cc4ba6a9 | aurel32 | |
578 | cc4ba6a9 | aurel32 | uint64_t helper_float_DT(uint32_t t0) |
579 | cc4ba6a9 | aurel32 | { |
580 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
581 | 9850d1e8 | aurel32 | d.d = int32_to_float64(t0, &env->fp_status); |
582 | 9850d1e8 | aurel32 | return d.ll;
|
583 | cc4ba6a9 | aurel32 | } |
584 | cc4ba6a9 | aurel32 | |
585 | 5b7141a1 | aurel32 | uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2) |
586 | 5b7141a1 | aurel32 | { |
587 | 5b7141a1 | aurel32 | CPU_FloatU f0, f1, f2; |
588 | 5b7141a1 | aurel32 | f0.l = t0; |
589 | 5b7141a1 | aurel32 | f1.l = t1; |
590 | 5b7141a1 | aurel32 | f2.l = t2; |
591 | 5b7141a1 | aurel32 | f0.f = float32_mul(f0.f, f1.f, &env->fp_status); |
592 | 5b7141a1 | aurel32 | f0.f = float32_add(f0.f, f2.f, &env->fp_status); |
593 | 5b7141a1 | aurel32 | return f0.l;
|
594 | 5b7141a1 | aurel32 | } |
595 | 5b7141a1 | aurel32 | |
596 | cc4ba6a9 | aurel32 | uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1) |
597 | cc4ba6a9 | aurel32 | { |
598 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
599 | 9850d1e8 | aurel32 | f0.l = t0; |
600 | 9850d1e8 | aurel32 | f1.l = t1; |
601 | 9850d1e8 | aurel32 | f0.f = float32_mul(f0.f, f1.f, &env->fp_status); |
602 | 9850d1e8 | aurel32 | return f0.l;
|
603 | cc4ba6a9 | aurel32 | } |
604 | cc4ba6a9 | aurel32 | |
605 | cc4ba6a9 | aurel32 | uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1) |
606 | cc4ba6a9 | aurel32 | { |
607 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
608 | 9850d1e8 | aurel32 | d0.ll = t0; |
609 | 9850d1e8 | aurel32 | d1.ll = t1; |
610 | 9850d1e8 | aurel32 | d0.d = float64_mul(d0.d, d1.d, &env->fp_status); |
611 | 9850d1e8 | aurel32 | return d0.ll;
|
612 | cc4ba6a9 | aurel32 | } |
613 | cc4ba6a9 | aurel32 | |
614 | 7fdf924f | aurel32 | uint32_t helper_fneg_T(uint32_t t0) |
615 | 7fdf924f | aurel32 | { |
616 | 9850d1e8 | aurel32 | CPU_FloatU f; |
617 | 9850d1e8 | aurel32 | f.l = t0; |
618 | 9850d1e8 | aurel32 | f.f = float32_chs(f.f); |
619 | 9850d1e8 | aurel32 | return f.l;
|
620 | 7fdf924f | aurel32 | } |
621 | 7fdf924f | aurel32 | |
622 | cc4ba6a9 | aurel32 | uint32_t helper_fsqrt_FT(uint32_t t0) |
623 | cc4ba6a9 | aurel32 | { |
624 | 9850d1e8 | aurel32 | CPU_FloatU f; |
625 | 9850d1e8 | aurel32 | f.l = t0; |
626 | 9850d1e8 | aurel32 | f.f = float32_sqrt(f.f, &env->fp_status); |
627 | 9850d1e8 | aurel32 | return f.l;
|
628 | cc4ba6a9 | aurel32 | } |
629 | cc4ba6a9 | aurel32 | |
630 | cc4ba6a9 | aurel32 | uint64_t helper_fsqrt_DT(uint64_t t0) |
631 | cc4ba6a9 | aurel32 | { |
632 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
633 | 9850d1e8 | aurel32 | d.ll = t0; |
634 | 9850d1e8 | aurel32 | d.d = float64_sqrt(d.d, &env->fp_status); |
635 | 9850d1e8 | aurel32 | return d.ll;
|
636 | cc4ba6a9 | aurel32 | } |
637 | cc4ba6a9 | aurel32 | |
638 | cc4ba6a9 | aurel32 | uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1) |
639 | cc4ba6a9 | aurel32 | { |
640 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
641 | 9850d1e8 | aurel32 | f0.l = t0; |
642 | 9850d1e8 | aurel32 | f1.l = t1; |
643 | 9850d1e8 | aurel32 | f0.f = float32_sub(f0.f, f1.f, &env->fp_status); |
644 | 9850d1e8 | aurel32 | return f0.l;
|
645 | cc4ba6a9 | aurel32 | } |
646 | cc4ba6a9 | aurel32 | |
647 | cc4ba6a9 | aurel32 | uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1) |
648 | cc4ba6a9 | aurel32 | { |
649 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
650 | 9850d1e8 | aurel32 | d0.ll = t0; |
651 | 9850d1e8 | aurel32 | d1.ll = t1; |
652 | 9850d1e8 | aurel32 | d0.d = float64_sub(d0.d, d1.d, &env->fp_status); |
653 | 9850d1e8 | aurel32 | return d0.ll;
|
654 | cc4ba6a9 | aurel32 | } |
655 | cc4ba6a9 | aurel32 | |
656 | cc4ba6a9 | aurel32 | uint32_t helper_ftrc_FT(uint32_t t0) |
657 | cc4ba6a9 | aurel32 | { |
658 | 9850d1e8 | aurel32 | CPU_FloatU f; |
659 | 9850d1e8 | aurel32 | f.l = t0; |
660 | 9850d1e8 | aurel32 | return float32_to_int32_round_to_zero(f.f, &env->fp_status);
|
661 | cc4ba6a9 | aurel32 | } |
662 | cc4ba6a9 | aurel32 | |
663 | cc4ba6a9 | aurel32 | uint32_t helper_ftrc_DT(uint64_t t0) |
664 | cc4ba6a9 | aurel32 | { |
665 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
666 | 9850d1e8 | aurel32 | d.ll = t0; |
667 | 9850d1e8 | aurel32 | return float64_to_int32_round_to_zero(d.d, &env->fp_status);
|
668 | cc4ba6a9 | aurel32 | } |