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