Clarify -soundhw documentation as to avoid hda confusion
[qemu/mini2440.git] / target-sh4 / op_helper.c
blobf3e73004a790313096f9718910d52aace7dc5a48
1 /*
2 * SH4 emulation
4 * Copyright (c) 2005 Samuel Tardieu
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.
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.
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
20 #include <assert.h>
21 #include "exec.h"
22 #include "helper.h"
24 #ifndef CONFIG_USER_ONLY
26 #define MMUSUFFIX _mmu
28 #define SHIFT 0
29 #include "softmmu_template.h"
31 #define SHIFT 1
32 #include "softmmu_template.h"
34 #define SHIFT 2
35 #include "softmmu_template.h"
37 #define SHIFT 3
38 #include "softmmu_template.h"
40 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
42 TranslationBlock *tb;
43 CPUState *saved_env;
44 unsigned long pc;
45 int ret;
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);
63 cpu_loop_exit();
65 env = saved_env;
68 #endif
70 void helper_ldtlb(void)
72 #ifdef CONFIG_USER_ONLY
73 /* XXXXX */
74 assert(0);
75 #else
76 cpu_load_tlb(env);
77 #endif
80 void helper_raise_illegal_instruction(void)
82 env->exception_index = 0x180;
83 cpu_loop_exit();
86 void helper_raise_slot_illegal_instruction(void)
88 env->exception_index = 0x1a0;
89 cpu_loop_exit();
92 void helper_debug(void)
94 env->exception_index = EXCP_DEBUG;
95 cpu_loop_exit();
98 void helper_sleep(uint32_t next_pc)
100 env->halted = 1;
101 env->exception_index = EXCP_HLT;
102 env->pc = next_pc;
103 cpu_loop_exit();
106 void helper_trapa(uint32_t tra)
108 env->tra = tra << 2;
109 env->exception_index = 0x160;
110 cpu_loop_exit();
113 uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
115 uint32_t tmp0, tmp1;
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;
129 uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
131 uint32_t dest, src, ans;
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;
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
168 uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
170 uint32_t tmp0, tmp2;
171 uint8_t old_q, tmp1 = 0xff;
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;
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;
222 break;
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;
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;
264 break;
266 break;
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;
276 void helper_macl(uint32_t arg0, uint32_t arg1)
278 int64_t res;
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;
292 void helper_macw(uint32_t arg0, uint32_t arg1)
294 int64_t res;
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;
311 uint32_t helper_negc(uint32_t arg)
313 uint32_t temp;
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;
326 uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
328 uint32_t tmp0, tmp1;
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;
342 uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
344 int32_t dest, src, ans;
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;
371 static inline void set_t(void)
373 env->sr |= SR_T;
376 static inline void clr_t(void)
378 env->sr &= ~SR_T;
381 void helper_ld_fpscr(uint32_t val)
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);
390 uint32_t helper_fabs_FT(uint32_t t0)
392 CPU_FloatU f;
393 f.l = t0;
394 f.f = float32_abs(f.f);
395 return f.l;
398 uint64_t helper_fabs_DT(uint64_t t0)
400 CPU_DoubleU d;
401 d.ll = t0;
402 d.d = float64_abs(d.d);
403 return d.ll;
406 uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
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;
415 uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
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;
424 void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
426 CPU_FloatU f0, f1;
427 f0.l = t0;
428 f1.l = t1;
430 if (float32_compare(f0.f, f1.f, &env->fp_status) == 0)
431 set_t();
432 else
433 clr_t();
436 void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
438 CPU_DoubleU d0, d1;
439 d0.ll = t0;
440 d1.ll = t1;
442 if (float64_compare(d0.d, d1.d, &env->fp_status) == 0)
443 set_t();
444 else
445 clr_t();
448 void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
450 CPU_FloatU f0, f1;
451 f0.l = t0;
452 f1.l = t1;
454 if (float32_compare(f0.f, f1.f, &env->fp_status) == 1)
455 set_t();
456 else
457 clr_t();
460 void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
462 CPU_DoubleU d0, d1;
463 d0.ll = t0;
464 d1.ll = t1;
466 if (float64_compare(d0.d, d1.d, &env->fp_status) == 1)
467 set_t();
468 else
469 clr_t();
472 uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
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;
481 uint32_t helper_fcnvds_DT_FT(uint64_t t0)
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;
490 uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
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;
499 uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
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;
508 uint32_t helper_float_FT(uint32_t t0)
510 CPU_FloatU f;
511 f.f = int32_to_float32(t0, &env->fp_status);
512 return f.l;
515 uint64_t helper_float_DT(uint32_t t0)
517 CPU_DoubleU d;
518 d.d = int32_to_float64(t0, &env->fp_status);
519 return d.ll;
522 uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
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;
531 uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
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;
540 uint32_t helper_fneg_T(uint32_t t0)
542 CPU_FloatU f;
543 f.l = t0;
544 f.f = float32_chs(f.f);
545 return f.l;
548 uint32_t helper_fsqrt_FT(uint32_t t0)
550 CPU_FloatU f;
551 f.l = t0;
552 f.f = float32_sqrt(f.f, &env->fp_status);
553 return f.l;
556 uint64_t helper_fsqrt_DT(uint64_t t0)
558 CPU_DoubleU d;
559 d.ll = t0;
560 d.d = float64_sqrt(d.d, &env->fp_status);
561 return d.ll;
564 uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
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;
573 uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
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;
582 uint32_t helper_ftrc_FT(uint32_t t0)
584 CPU_FloatU f;
585 f.l = t0;
586 return float32_to_int32_round_to_zero(f.f, &env->fp_status);
589 uint32_t helper_ftrc_DT(uint64_t t0)
591 CPU_DoubleU d;
592 d.ll = t0;
593 return float64_to_int32_round_to_zero(d.d, &env->fp_status);