root / target-sh4 / op_helper.c @ b8c18e4c
History | View | Annotate | Download (11.1 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 | fdf9b3e8 | bellard | * License along with this library; if not, write to the Free Software
|
18 | fad6cb1a | aurel32 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
19 | fdf9b3e8 | bellard | */
|
20 | fdf9b3e8 | bellard | #include <assert.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 | 6f06939b | aurel32 | uint32_t helper_addc(uint32_t arg0, uint32_t arg1) |
126 | fdf9b3e8 | bellard | { |
127 | fdf9b3e8 | bellard | uint32_t tmp0, tmp1; |
128 | fdf9b3e8 | bellard | |
129 | 6f06939b | aurel32 | tmp1 = arg0 + arg1; |
130 | 6f06939b | aurel32 | tmp0 = arg1; |
131 | 6f06939b | aurel32 | arg1 = tmp1 + (env->sr & 1);
|
132 | fdf9b3e8 | bellard | if (tmp0 > tmp1)
|
133 | fdf9b3e8 | bellard | env->sr |= SR_T; |
134 | fdf9b3e8 | bellard | else
|
135 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
136 | 6f06939b | aurel32 | if (tmp1 > arg1)
|
137 | fdf9b3e8 | bellard | env->sr |= SR_T; |
138 | 6f06939b | aurel32 | return arg1;
|
139 | fdf9b3e8 | bellard | } |
140 | fdf9b3e8 | bellard | |
141 | 6f06939b | aurel32 | uint32_t helper_addv(uint32_t arg0, uint32_t arg1) |
142 | fdf9b3e8 | bellard | { |
143 | fdf9b3e8 | bellard | uint32_t dest, src, ans; |
144 | fdf9b3e8 | bellard | |
145 | 6f06939b | aurel32 | if ((int32_t) arg1 >= 0) |
146 | fdf9b3e8 | bellard | dest = 0;
|
147 | fdf9b3e8 | bellard | else
|
148 | fdf9b3e8 | bellard | dest = 1;
|
149 | 6f06939b | aurel32 | if ((int32_t) arg0 >= 0) |
150 | fdf9b3e8 | bellard | src = 0;
|
151 | fdf9b3e8 | bellard | else
|
152 | fdf9b3e8 | bellard | src = 1;
|
153 | fdf9b3e8 | bellard | src += dest; |
154 | 6f06939b | aurel32 | arg1 += arg0; |
155 | 6f06939b | aurel32 | if ((int32_t) arg1 >= 0) |
156 | fdf9b3e8 | bellard | ans = 0;
|
157 | fdf9b3e8 | bellard | else
|
158 | fdf9b3e8 | bellard | ans = 1;
|
159 | fdf9b3e8 | bellard | ans += dest; |
160 | fdf9b3e8 | bellard | if (src == 0 || src == 2) { |
161 | fdf9b3e8 | bellard | if (ans == 1) |
162 | fdf9b3e8 | bellard | env->sr |= SR_T; |
163 | fdf9b3e8 | bellard | else
|
164 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
165 | fdf9b3e8 | bellard | } else
|
166 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
167 | 6f06939b | aurel32 | return arg1;
|
168 | fdf9b3e8 | bellard | } |
169 | fdf9b3e8 | bellard | |
170 | fdf9b3e8 | bellard | #define T (env->sr & SR_T)
|
171 | fdf9b3e8 | bellard | #define Q (env->sr & SR_Q ? 1 : 0) |
172 | fdf9b3e8 | bellard | #define M (env->sr & SR_M ? 1 : 0) |
173 | fdf9b3e8 | bellard | #define SETT env->sr |= SR_T
|
174 | fdf9b3e8 | bellard | #define CLRT env->sr &= ~SR_T
|
175 | fdf9b3e8 | bellard | #define SETQ env->sr |= SR_Q
|
176 | fdf9b3e8 | bellard | #define CLRQ env->sr &= ~SR_Q
|
177 | fdf9b3e8 | bellard | #define SETM env->sr |= SR_M
|
178 | fdf9b3e8 | bellard | #define CLRM env->sr &= ~SR_M
|
179 | fdf9b3e8 | bellard | |
180 | 69d6275b | aurel32 | uint32_t helper_div1(uint32_t arg0, uint32_t arg1) |
181 | fdf9b3e8 | bellard | { |
182 | fdf9b3e8 | bellard | uint32_t tmp0, tmp2; |
183 | fdf9b3e8 | bellard | uint8_t old_q, tmp1 = 0xff;
|
184 | fdf9b3e8 | bellard | |
185 | 69d6275b | aurel32 | //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
|
186 | fdf9b3e8 | bellard | old_q = Q; |
187 | 69d6275b | aurel32 | if ((0x80000000 & arg1) != 0) |
188 | fdf9b3e8 | bellard | SETQ; |
189 | fdf9b3e8 | bellard | else
|
190 | fdf9b3e8 | bellard | CLRQ; |
191 | 69d6275b | aurel32 | tmp2 = arg0; |
192 | 69d6275b | aurel32 | arg1 <<= 1;
|
193 | 69d6275b | aurel32 | arg1 |= T; |
194 | fdf9b3e8 | bellard | switch (old_q) {
|
195 | fdf9b3e8 | bellard | case 0: |
196 | fdf9b3e8 | bellard | switch (M) {
|
197 | fdf9b3e8 | bellard | case 0: |
198 | 69d6275b | aurel32 | tmp0 = arg1; |
199 | 69d6275b | aurel32 | arg1 -= tmp2; |
200 | 69d6275b | aurel32 | tmp1 = arg1 > tmp0; |
201 | fdf9b3e8 | bellard | switch (Q) {
|
202 | fdf9b3e8 | bellard | case 0: |
203 | fdf9b3e8 | bellard | if (tmp1)
|
204 | fdf9b3e8 | bellard | SETQ; |
205 | fdf9b3e8 | bellard | else
|
206 | fdf9b3e8 | bellard | CLRQ; |
207 | fdf9b3e8 | bellard | break;
|
208 | fdf9b3e8 | bellard | case 1: |
209 | fdf9b3e8 | bellard | if (tmp1 == 0) |
210 | fdf9b3e8 | bellard | SETQ; |
211 | fdf9b3e8 | bellard | else
|
212 | fdf9b3e8 | bellard | CLRQ; |
213 | fdf9b3e8 | bellard | break;
|
214 | fdf9b3e8 | bellard | } |
215 | fdf9b3e8 | bellard | break;
|
216 | fdf9b3e8 | bellard | case 1: |
217 | 69d6275b | aurel32 | tmp0 = arg1; |
218 | 69d6275b | aurel32 | arg1 += tmp2; |
219 | 69d6275b | aurel32 | tmp1 = arg1 < tmp0; |
220 | fdf9b3e8 | bellard | switch (Q) {
|
221 | fdf9b3e8 | bellard | case 0: |
222 | fdf9b3e8 | bellard | if (tmp1 == 0) |
223 | fdf9b3e8 | bellard | SETQ; |
224 | fdf9b3e8 | bellard | else
|
225 | fdf9b3e8 | bellard | CLRQ; |
226 | fdf9b3e8 | bellard | break;
|
227 | fdf9b3e8 | bellard | case 1: |
228 | fdf9b3e8 | bellard | if (tmp1)
|
229 | fdf9b3e8 | bellard | SETQ; |
230 | fdf9b3e8 | bellard | else
|
231 | fdf9b3e8 | bellard | CLRQ; |
232 | fdf9b3e8 | bellard | break;
|
233 | fdf9b3e8 | bellard | } |
234 | fdf9b3e8 | bellard | break;
|
235 | fdf9b3e8 | bellard | } |
236 | fdf9b3e8 | bellard | break;
|
237 | fdf9b3e8 | bellard | case 1: |
238 | fdf9b3e8 | bellard | switch (M) {
|
239 | fdf9b3e8 | bellard | case 0: |
240 | 69d6275b | aurel32 | tmp0 = arg1; |
241 | 69d6275b | aurel32 | arg1 += tmp2; |
242 | 69d6275b | aurel32 | tmp1 = arg1 < tmp0; |
243 | fdf9b3e8 | bellard | switch (Q) {
|
244 | fdf9b3e8 | bellard | case 0: |
245 | fdf9b3e8 | bellard | if (tmp1)
|
246 | fdf9b3e8 | bellard | SETQ; |
247 | fdf9b3e8 | bellard | else
|
248 | fdf9b3e8 | bellard | CLRQ; |
249 | fdf9b3e8 | bellard | break;
|
250 | fdf9b3e8 | bellard | case 1: |
251 | fdf9b3e8 | bellard | if (tmp1 == 0) |
252 | fdf9b3e8 | bellard | SETQ; |
253 | fdf9b3e8 | bellard | else
|
254 | fdf9b3e8 | bellard | CLRQ; |
255 | fdf9b3e8 | bellard | break;
|
256 | fdf9b3e8 | bellard | } |
257 | fdf9b3e8 | bellard | break;
|
258 | fdf9b3e8 | bellard | case 1: |
259 | 69d6275b | aurel32 | tmp0 = arg1; |
260 | 69d6275b | aurel32 | arg1 -= tmp2; |
261 | 69d6275b | aurel32 | tmp1 = arg1 > tmp0; |
262 | fdf9b3e8 | bellard | switch (Q) {
|
263 | fdf9b3e8 | bellard | case 0: |
264 | fdf9b3e8 | bellard | if (tmp1 == 0) |
265 | fdf9b3e8 | bellard | SETQ; |
266 | fdf9b3e8 | bellard | else
|
267 | fdf9b3e8 | bellard | CLRQ; |
268 | fdf9b3e8 | bellard | break;
|
269 | fdf9b3e8 | bellard | case 1: |
270 | fdf9b3e8 | bellard | if (tmp1)
|
271 | fdf9b3e8 | bellard | SETQ; |
272 | fdf9b3e8 | bellard | else
|
273 | fdf9b3e8 | bellard | CLRQ; |
274 | fdf9b3e8 | bellard | break;
|
275 | fdf9b3e8 | bellard | } |
276 | fdf9b3e8 | bellard | break;
|
277 | fdf9b3e8 | bellard | } |
278 | fdf9b3e8 | bellard | break;
|
279 | fdf9b3e8 | bellard | } |
280 | fdf9b3e8 | bellard | if (Q == M)
|
281 | fdf9b3e8 | bellard | SETT; |
282 | fdf9b3e8 | bellard | else
|
283 | fdf9b3e8 | bellard | CLRT; |
284 | 69d6275b | aurel32 | //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
|
285 | 69d6275b | aurel32 | return arg1;
|
286 | fdf9b3e8 | bellard | } |
287 | fdf9b3e8 | bellard | |
288 | 6f06939b | aurel32 | void helper_macl(uint32_t arg0, uint32_t arg1)
|
289 | fdf9b3e8 | bellard | { |
290 | fdf9b3e8 | bellard | int64_t res; |
291 | fdf9b3e8 | bellard | |
292 | fdf9b3e8 | bellard | res = ((uint64_t) env->mach << 32) | env->macl;
|
293 | 6f06939b | aurel32 | res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1; |
294 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
295 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
296 | fdf9b3e8 | bellard | if (env->sr & SR_S) {
|
297 | fdf9b3e8 | bellard | if (res < 0) |
298 | fdf9b3e8 | bellard | env->mach |= 0xffff0000;
|
299 | fdf9b3e8 | bellard | else
|
300 | fdf9b3e8 | bellard | env->mach &= 0x00007fff;
|
301 | fdf9b3e8 | bellard | } |
302 | fdf9b3e8 | bellard | } |
303 | fdf9b3e8 | bellard | |
304 | 6f06939b | aurel32 | void helper_macw(uint32_t arg0, uint32_t arg1)
|
305 | fdf9b3e8 | bellard | { |
306 | fdf9b3e8 | bellard | int64_t res; |
307 | fdf9b3e8 | bellard | |
308 | fdf9b3e8 | bellard | res = ((uint64_t) env->mach << 32) | env->macl;
|
309 | 6f06939b | aurel32 | res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1; |
310 | fdf9b3e8 | bellard | env->mach = (res >> 32) & 0xffffffff; |
311 | fdf9b3e8 | bellard | env->macl = res & 0xffffffff;
|
312 | fdf9b3e8 | bellard | if (env->sr & SR_S) {
|
313 | fdf9b3e8 | bellard | if (res < -0x80000000) { |
314 | fdf9b3e8 | bellard | env->mach = 1;
|
315 | fdf9b3e8 | bellard | env->macl = 0x80000000;
|
316 | fdf9b3e8 | bellard | } else if (res > 0x000000007fffffff) { |
317 | fdf9b3e8 | bellard | env->mach = 1;
|
318 | fdf9b3e8 | bellard | env->macl = 0x7fffffff;
|
319 | fdf9b3e8 | bellard | } |
320 | fdf9b3e8 | bellard | } |
321 | fdf9b3e8 | bellard | } |
322 | fdf9b3e8 | bellard | |
323 | 6f06939b | aurel32 | uint32_t helper_negc(uint32_t arg) |
324 | fdf9b3e8 | bellard | { |
325 | fdf9b3e8 | bellard | uint32_t temp; |
326 | fdf9b3e8 | bellard | |
327 | 6f06939b | aurel32 | temp = -arg; |
328 | 6f06939b | aurel32 | arg = temp - (env->sr & SR_T); |
329 | fdf9b3e8 | bellard | if (0 < temp) |
330 | fdf9b3e8 | bellard | env->sr |= SR_T; |
331 | fdf9b3e8 | bellard | else
|
332 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
333 | 6f06939b | aurel32 | if (temp < arg)
|
334 | fdf9b3e8 | bellard | env->sr |= SR_T; |
335 | 6f06939b | aurel32 | return arg;
|
336 | fdf9b3e8 | bellard | } |
337 | fdf9b3e8 | bellard | |
338 | 6f06939b | aurel32 | uint32_t helper_subc(uint32_t arg0, uint32_t arg1) |
339 | fdf9b3e8 | bellard | { |
340 | fdf9b3e8 | bellard | uint32_t tmp0, tmp1; |
341 | fdf9b3e8 | bellard | |
342 | 6f06939b | aurel32 | tmp1 = arg1 - arg0; |
343 | 6f06939b | aurel32 | tmp0 = arg1; |
344 | 6f06939b | aurel32 | arg1 = tmp1 - (env->sr & SR_T); |
345 | fdf9b3e8 | bellard | if (tmp0 < tmp1)
|
346 | fdf9b3e8 | bellard | env->sr |= SR_T; |
347 | fdf9b3e8 | bellard | else
|
348 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
349 | 6f06939b | aurel32 | if (tmp1 < arg1)
|
350 | fdf9b3e8 | bellard | env->sr |= SR_T; |
351 | 6f06939b | aurel32 | return arg1;
|
352 | fdf9b3e8 | bellard | } |
353 | fdf9b3e8 | bellard | |
354 | 6f06939b | aurel32 | uint32_t helper_subv(uint32_t arg0, uint32_t arg1) |
355 | fdf9b3e8 | bellard | { |
356 | fdf9b3e8 | bellard | int32_t dest, src, ans; |
357 | fdf9b3e8 | bellard | |
358 | 6f06939b | aurel32 | if ((int32_t) arg1 >= 0) |
359 | fdf9b3e8 | bellard | dest = 0;
|
360 | fdf9b3e8 | bellard | else
|
361 | fdf9b3e8 | bellard | dest = 1;
|
362 | 6f06939b | aurel32 | if ((int32_t) arg0 >= 0) |
363 | fdf9b3e8 | bellard | src = 0;
|
364 | fdf9b3e8 | bellard | else
|
365 | fdf9b3e8 | bellard | src = 1;
|
366 | fdf9b3e8 | bellard | src += dest; |
367 | 6f06939b | aurel32 | arg1 -= arg0; |
368 | 6f06939b | aurel32 | if ((int32_t) arg1 >= 0) |
369 | fdf9b3e8 | bellard | ans = 0;
|
370 | fdf9b3e8 | bellard | else
|
371 | fdf9b3e8 | bellard | ans = 1;
|
372 | fdf9b3e8 | bellard | ans += dest; |
373 | fdf9b3e8 | bellard | if (src == 1) { |
374 | fdf9b3e8 | bellard | if (ans == 1) |
375 | fdf9b3e8 | bellard | env->sr |= SR_T; |
376 | fdf9b3e8 | bellard | else
|
377 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
378 | fdf9b3e8 | bellard | } else
|
379 | fdf9b3e8 | bellard | env->sr &= ~SR_T; |
380 | 6f06939b | aurel32 | return arg1;
|
381 | fdf9b3e8 | bellard | } |
382 | fdf9b3e8 | bellard | |
383 | cc4ba6a9 | aurel32 | static inline void set_t(void) |
384 | cc4ba6a9 | aurel32 | { |
385 | cc4ba6a9 | aurel32 | env->sr |= SR_T; |
386 | cc4ba6a9 | aurel32 | } |
387 | cc4ba6a9 | aurel32 | |
388 | cc4ba6a9 | aurel32 | static inline void clr_t(void) |
389 | cc4ba6a9 | aurel32 | { |
390 | cc4ba6a9 | aurel32 | env->sr &= ~SR_T; |
391 | cc4ba6a9 | aurel32 | } |
392 | cc4ba6a9 | aurel32 | |
393 | 390af821 | aurel32 | void helper_ld_fpscr(uint32_t val)
|
394 | 390af821 | aurel32 | { |
395 | 390af821 | aurel32 | env->fpscr = val & 0x003fffff;
|
396 | 390af821 | aurel32 | if (val & 0x01) |
397 | 390af821 | aurel32 | set_float_rounding_mode(float_round_to_zero, &env->fp_status); |
398 | 390af821 | aurel32 | else
|
399 | 390af821 | aurel32 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
400 | 390af821 | aurel32 | } |
401 | cc4ba6a9 | aurel32 | |
402 | cc4ba6a9 | aurel32 | uint32_t helper_fabs_FT(uint32_t t0) |
403 | cc4ba6a9 | aurel32 | { |
404 | 9850d1e8 | aurel32 | CPU_FloatU f; |
405 | 9850d1e8 | aurel32 | f.l = t0; |
406 | 9850d1e8 | aurel32 | f.f = float32_abs(f.f); |
407 | 9850d1e8 | aurel32 | return f.l;
|
408 | cc4ba6a9 | aurel32 | } |
409 | cc4ba6a9 | aurel32 | |
410 | cc4ba6a9 | aurel32 | uint64_t helper_fabs_DT(uint64_t t0) |
411 | cc4ba6a9 | aurel32 | { |
412 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
413 | 9850d1e8 | aurel32 | d.ll = t0; |
414 | 9850d1e8 | aurel32 | d.d = float64_abs(d.d); |
415 | 9850d1e8 | aurel32 | return d.ll;
|
416 | cc4ba6a9 | aurel32 | } |
417 | cc4ba6a9 | aurel32 | |
418 | cc4ba6a9 | aurel32 | uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1) |
419 | cc4ba6a9 | aurel32 | { |
420 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
421 | 9850d1e8 | aurel32 | f0.l = t0; |
422 | 9850d1e8 | aurel32 | f1.l = t1; |
423 | 9850d1e8 | aurel32 | f0.f = float32_add(f0.f, f1.f, &env->fp_status); |
424 | 9850d1e8 | aurel32 | return f0.l;
|
425 | cc4ba6a9 | aurel32 | } |
426 | cc4ba6a9 | aurel32 | |
427 | cc4ba6a9 | aurel32 | uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1) |
428 | cc4ba6a9 | aurel32 | { |
429 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
430 | 9850d1e8 | aurel32 | d0.ll = t0; |
431 | 9850d1e8 | aurel32 | d1.ll = t1; |
432 | 9850d1e8 | aurel32 | d0.d = float64_add(d0.d, d1.d, &env->fp_status); |
433 | 9850d1e8 | aurel32 | return d0.ll;
|
434 | cc4ba6a9 | aurel32 | } |
435 | cc4ba6a9 | aurel32 | |
436 | cc4ba6a9 | aurel32 | void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
|
437 | cc4ba6a9 | aurel32 | { |
438 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
439 | 9850d1e8 | aurel32 | f0.l = t0; |
440 | 9850d1e8 | aurel32 | f1.l = t1; |
441 | 9850d1e8 | aurel32 | |
442 | 9850d1e8 | aurel32 | if (float32_compare(f0.f, f1.f, &env->fp_status) == 0) |
443 | cc4ba6a9 | aurel32 | set_t(); |
444 | cc4ba6a9 | aurel32 | else
|
445 | cc4ba6a9 | aurel32 | clr_t(); |
446 | cc4ba6a9 | aurel32 | } |
447 | cc4ba6a9 | aurel32 | |
448 | cc4ba6a9 | aurel32 | void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
|
449 | cc4ba6a9 | aurel32 | { |
450 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
451 | 9850d1e8 | aurel32 | d0.ll = t0; |
452 | 9850d1e8 | aurel32 | d1.ll = t1; |
453 | 9850d1e8 | aurel32 | |
454 | 9850d1e8 | aurel32 | if (float64_compare(d0.d, d1.d, &env->fp_status) == 0) |
455 | cc4ba6a9 | aurel32 | set_t(); |
456 | cc4ba6a9 | aurel32 | else
|
457 | cc4ba6a9 | aurel32 | clr_t(); |
458 | cc4ba6a9 | aurel32 | } |
459 | cc4ba6a9 | aurel32 | |
460 | cc4ba6a9 | aurel32 | void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
|
461 | cc4ba6a9 | aurel32 | { |
462 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
463 | 9850d1e8 | aurel32 | f0.l = t0; |
464 | 9850d1e8 | aurel32 | f1.l = t1; |
465 | 9850d1e8 | aurel32 | |
466 | 9850d1e8 | aurel32 | if (float32_compare(f0.f, f1.f, &env->fp_status) == 1) |
467 | cc4ba6a9 | aurel32 | set_t(); |
468 | cc4ba6a9 | aurel32 | else
|
469 | cc4ba6a9 | aurel32 | clr_t(); |
470 | cc4ba6a9 | aurel32 | } |
471 | cc4ba6a9 | aurel32 | |
472 | cc4ba6a9 | aurel32 | void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
|
473 | cc4ba6a9 | aurel32 | { |
474 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
475 | 9850d1e8 | aurel32 | d0.ll = t0; |
476 | 9850d1e8 | aurel32 | d1.ll = t1; |
477 | 9850d1e8 | aurel32 | |
478 | 9850d1e8 | aurel32 | if (float64_compare(d0.d, d1.d, &env->fp_status) == 1) |
479 | cc4ba6a9 | aurel32 | set_t(); |
480 | cc4ba6a9 | aurel32 | else
|
481 | cc4ba6a9 | aurel32 | clr_t(); |
482 | cc4ba6a9 | aurel32 | } |
483 | cc4ba6a9 | aurel32 | |
484 | cc4ba6a9 | aurel32 | uint64_t helper_fcnvsd_FT_DT(uint32_t t0) |
485 | cc4ba6a9 | aurel32 | { |
486 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
487 | 9850d1e8 | aurel32 | CPU_FloatU f; |
488 | 9850d1e8 | aurel32 | f.l = t0; |
489 | 9850d1e8 | aurel32 | d.d = float32_to_float64(f.f, &env->fp_status); |
490 | 9850d1e8 | aurel32 | return d.ll;
|
491 | cc4ba6a9 | aurel32 | } |
492 | cc4ba6a9 | aurel32 | |
493 | cc4ba6a9 | aurel32 | uint32_t helper_fcnvds_DT_FT(uint64_t t0) |
494 | cc4ba6a9 | aurel32 | { |
495 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
496 | 9850d1e8 | aurel32 | CPU_FloatU f; |
497 | 9850d1e8 | aurel32 | d.ll = t0; |
498 | 9850d1e8 | aurel32 | f.f = float64_to_float32(d.d, &env->fp_status); |
499 | 9850d1e8 | aurel32 | return f.l;
|
500 | cc4ba6a9 | aurel32 | } |
501 | cc4ba6a9 | aurel32 | |
502 | cc4ba6a9 | aurel32 | uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1) |
503 | cc4ba6a9 | aurel32 | { |
504 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
505 | 9850d1e8 | aurel32 | f0.l = t0; |
506 | 9850d1e8 | aurel32 | f1.l = t1; |
507 | 9850d1e8 | aurel32 | f0.f = float32_div(f0.f, f1.f, &env->fp_status); |
508 | 9850d1e8 | aurel32 | return f0.l;
|
509 | cc4ba6a9 | aurel32 | } |
510 | cc4ba6a9 | aurel32 | |
511 | cc4ba6a9 | aurel32 | uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1) |
512 | cc4ba6a9 | aurel32 | { |
513 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
514 | 9850d1e8 | aurel32 | d0.ll = t0; |
515 | 9850d1e8 | aurel32 | d1.ll = t1; |
516 | 9850d1e8 | aurel32 | d0.d = float64_div(d0.d, d1.d, &env->fp_status); |
517 | 9850d1e8 | aurel32 | return d0.ll;
|
518 | cc4ba6a9 | aurel32 | } |
519 | cc4ba6a9 | aurel32 | |
520 | cc4ba6a9 | aurel32 | uint32_t helper_float_FT(uint32_t t0) |
521 | cc4ba6a9 | aurel32 | { |
522 | 9850d1e8 | aurel32 | CPU_FloatU f; |
523 | 9850d1e8 | aurel32 | f.f = int32_to_float32(t0, &env->fp_status); |
524 | 9850d1e8 | aurel32 | return f.l;
|
525 | cc4ba6a9 | aurel32 | } |
526 | cc4ba6a9 | aurel32 | |
527 | cc4ba6a9 | aurel32 | uint64_t helper_float_DT(uint32_t t0) |
528 | cc4ba6a9 | aurel32 | { |
529 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
530 | 9850d1e8 | aurel32 | d.d = int32_to_float64(t0, &env->fp_status); |
531 | 9850d1e8 | aurel32 | return d.ll;
|
532 | cc4ba6a9 | aurel32 | } |
533 | cc4ba6a9 | aurel32 | |
534 | 5b7141a1 | aurel32 | uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2) |
535 | 5b7141a1 | aurel32 | { |
536 | 5b7141a1 | aurel32 | CPU_FloatU f0, f1, f2; |
537 | 5b7141a1 | aurel32 | f0.l = t0; |
538 | 5b7141a1 | aurel32 | f1.l = t1; |
539 | 5b7141a1 | aurel32 | f2.l = t2; |
540 | 5b7141a1 | aurel32 | f0.f = float32_mul(f0.f, f1.f, &env->fp_status); |
541 | 5b7141a1 | aurel32 | f0.f = float32_add(f0.f, f2.f, &env->fp_status); |
542 | 5b7141a1 | aurel32 | return f0.l;
|
543 | 5b7141a1 | aurel32 | } |
544 | 5b7141a1 | aurel32 | |
545 | cc4ba6a9 | aurel32 | uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1) |
546 | cc4ba6a9 | aurel32 | { |
547 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
548 | 9850d1e8 | aurel32 | f0.l = t0; |
549 | 9850d1e8 | aurel32 | f1.l = t1; |
550 | 9850d1e8 | aurel32 | f0.f = float32_mul(f0.f, f1.f, &env->fp_status); |
551 | 9850d1e8 | aurel32 | return f0.l;
|
552 | cc4ba6a9 | aurel32 | } |
553 | cc4ba6a9 | aurel32 | |
554 | cc4ba6a9 | aurel32 | uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1) |
555 | cc4ba6a9 | aurel32 | { |
556 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
557 | 9850d1e8 | aurel32 | d0.ll = t0; |
558 | 9850d1e8 | aurel32 | d1.ll = t1; |
559 | 9850d1e8 | aurel32 | d0.d = float64_mul(d0.d, d1.d, &env->fp_status); |
560 | 9850d1e8 | aurel32 | return d0.ll;
|
561 | cc4ba6a9 | aurel32 | } |
562 | cc4ba6a9 | aurel32 | |
563 | 7fdf924f | aurel32 | uint32_t helper_fneg_T(uint32_t t0) |
564 | 7fdf924f | aurel32 | { |
565 | 9850d1e8 | aurel32 | CPU_FloatU f; |
566 | 9850d1e8 | aurel32 | f.l = t0; |
567 | 9850d1e8 | aurel32 | f.f = float32_chs(f.f); |
568 | 9850d1e8 | aurel32 | return f.l;
|
569 | 7fdf924f | aurel32 | } |
570 | 7fdf924f | aurel32 | |
571 | cc4ba6a9 | aurel32 | uint32_t helper_fsqrt_FT(uint32_t t0) |
572 | cc4ba6a9 | aurel32 | { |
573 | 9850d1e8 | aurel32 | CPU_FloatU f; |
574 | 9850d1e8 | aurel32 | f.l = t0; |
575 | 9850d1e8 | aurel32 | f.f = float32_sqrt(f.f, &env->fp_status); |
576 | 9850d1e8 | aurel32 | return f.l;
|
577 | cc4ba6a9 | aurel32 | } |
578 | cc4ba6a9 | aurel32 | |
579 | cc4ba6a9 | aurel32 | uint64_t helper_fsqrt_DT(uint64_t t0) |
580 | cc4ba6a9 | aurel32 | { |
581 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
582 | 9850d1e8 | aurel32 | d.ll = t0; |
583 | 9850d1e8 | aurel32 | d.d = float64_sqrt(d.d, &env->fp_status); |
584 | 9850d1e8 | aurel32 | return d.ll;
|
585 | cc4ba6a9 | aurel32 | } |
586 | cc4ba6a9 | aurel32 | |
587 | cc4ba6a9 | aurel32 | uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1) |
588 | cc4ba6a9 | aurel32 | { |
589 | 9850d1e8 | aurel32 | CPU_FloatU f0, f1; |
590 | 9850d1e8 | aurel32 | f0.l = t0; |
591 | 9850d1e8 | aurel32 | f1.l = t1; |
592 | 9850d1e8 | aurel32 | f0.f = float32_sub(f0.f, f1.f, &env->fp_status); |
593 | 9850d1e8 | aurel32 | return f0.l;
|
594 | cc4ba6a9 | aurel32 | } |
595 | cc4ba6a9 | aurel32 | |
596 | cc4ba6a9 | aurel32 | uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1) |
597 | cc4ba6a9 | aurel32 | { |
598 | 9850d1e8 | aurel32 | CPU_DoubleU d0, d1; |
599 | 9850d1e8 | aurel32 | d0.ll = t0; |
600 | 9850d1e8 | aurel32 | d1.ll = t1; |
601 | 9850d1e8 | aurel32 | d0.d = float64_sub(d0.d, d1.d, &env->fp_status); |
602 | 9850d1e8 | aurel32 | return d0.ll;
|
603 | cc4ba6a9 | aurel32 | } |
604 | cc4ba6a9 | aurel32 | |
605 | cc4ba6a9 | aurel32 | uint32_t helper_ftrc_FT(uint32_t t0) |
606 | cc4ba6a9 | aurel32 | { |
607 | 9850d1e8 | aurel32 | CPU_FloatU f; |
608 | 9850d1e8 | aurel32 | f.l = t0; |
609 | 9850d1e8 | aurel32 | return float32_to_int32_round_to_zero(f.f, &env->fp_status);
|
610 | cc4ba6a9 | aurel32 | } |
611 | cc4ba6a9 | aurel32 | |
612 | cc4ba6a9 | aurel32 | uint32_t helper_ftrc_DT(uint64_t t0) |
613 | cc4ba6a9 | aurel32 | { |
614 | 9850d1e8 | aurel32 | CPU_DoubleU d; |
615 | 9850d1e8 | aurel32 | d.ll = t0; |
616 | 9850d1e8 | aurel32 | return float64_to_int32_round_to_zero(d.d, &env->fp_status);
|
617 | cc4ba6a9 | aurel32 | } |