]> git.proxmox.com Git - mirror_qemu.git/blame - target-sh4/op_helper.c
Some cleanups after dyngen removal
[mirror_qemu.git] / target-sh4 / op_helper.c
CommitLineData
fdf9b3e8
FB
1/*
2 * SH4 emulation
5fafdf24 3 *
fdf9b3e8
FB
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"
a7812ae4 22#include "helper.h"
fdf9b3e8 23
fdf9b3e8
FB
24#ifndef CONFIG_USER_ONLY
25
26#define MMUSUFFIX _mmu
fdf9b3e8
FB
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
6ebbf390 40void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
fdf9b3e8
FB
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;
6ebbf390 51 ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
fdf9b3e8
FB
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 }
e6afc2f4 63 cpu_loop_exit();
fdf9b3e8
FB
64 }
65 env = saved_env;
66}
67
68#endif
69
ea2b542a
AJ
70void 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
e6afc2f4
AJ
80void helper_raise_illegal_instruction(void)
81{
82 env->exception_index = 0x180;
83 cpu_loop_exit();
84}
85
86void helper_raise_slot_illegal_instruction(void)
87{
88 env->exception_index = 0x1a0;
89 cpu_loop_exit();
90}
91
92void helper_debug(void)
93{
94 env->exception_index = EXCP_DEBUG;
95 cpu_loop_exit();
96}
97
f24f381b 98void helper_sleep(uint32_t next_pc)
e6afc2f4
AJ
99{
100 env->halted = 1;
101 env->exception_index = EXCP_HLT;
f24f381b 102 env->pc = next_pc;
e6afc2f4
AJ
103 cpu_loop_exit();
104}
105
106void helper_trapa(uint32_t tra)
107{
108 env->tra = tra << 2;
109 env->exception_index = 0x160;
110 cpu_loop_exit();
111}
112
6f06939b 113uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
114{
115 uint32_t tmp0, tmp1;
116
6f06939b
AJ
117 tmp1 = arg0 + arg1;
118 tmp0 = arg1;
119 arg1 = tmp1 + (env->sr & 1);
fdf9b3e8
FB
120 if (tmp0 > tmp1)
121 env->sr |= SR_T;
122 else
123 env->sr &= ~SR_T;
6f06939b 124 if (tmp1 > arg1)
fdf9b3e8 125 env->sr |= SR_T;
6f06939b 126 return arg1;
fdf9b3e8
FB
127}
128
6f06939b 129uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
130{
131 uint32_t dest, src, ans;
132
6f06939b 133 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
134 dest = 0;
135 else
136 dest = 1;
6f06939b 137 if ((int32_t) arg0 >= 0)
fdf9b3e8
FB
138 src = 0;
139 else
140 src = 1;
141 src += dest;
6f06939b
AJ
142 arg1 += arg0;
143 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
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;
6f06939b 155 return arg1;
fdf9b3e8
FB
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
69d6275b 168uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
169{
170 uint32_t tmp0, tmp2;
171 uint8_t old_q, tmp1 = 0xff;
172
69d6275b 173 //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
fdf9b3e8 174 old_q = Q;
69d6275b 175 if ((0x80000000 & arg1) != 0)
fdf9b3e8
FB
176 SETQ;
177 else
178 CLRQ;
69d6275b
AJ
179 tmp2 = arg0;
180 arg1 <<= 1;
181 arg1 |= T;
fdf9b3e8
FB
182 switch (old_q) {
183 case 0:
184 switch (M) {
185 case 0:
69d6275b
AJ
186 tmp0 = arg1;
187 arg1 -= tmp2;
188 tmp1 = arg1 > tmp0;
fdf9b3e8
FB
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:
69d6275b
AJ
205 tmp0 = arg1;
206 arg1 += tmp2;
207 tmp1 = arg1 < tmp0;
fdf9b3e8
FB
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:
69d6275b
AJ
228 tmp0 = arg1;
229 arg1 += tmp2;
230 tmp1 = arg1 < tmp0;
fdf9b3e8
FB
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:
69d6275b
AJ
247 tmp0 = arg1;
248 arg1 -= tmp2;
249 tmp1 = arg1 > tmp0;
fdf9b3e8
FB
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;
69d6275b
AJ
272 //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
273 return arg1;
fdf9b3e8
FB
274}
275
6f06939b 276void helper_macl(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
277{
278 int64_t res;
279
280 res = ((uint64_t) env->mach << 32) | env->macl;
6f06939b 281 res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
fdf9b3e8
FB
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
6f06939b 292void helper_macw(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
293{
294 int64_t res;
295
296 res = ((uint64_t) env->mach << 32) | env->macl;
6f06939b 297 res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
fdf9b3e8
FB
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
6f06939b 311uint32_t helper_negc(uint32_t arg)
fdf9b3e8
FB
312{
313 uint32_t temp;
314
6f06939b
AJ
315 temp = -arg;
316 arg = temp - (env->sr & SR_T);
fdf9b3e8
FB
317 if (0 < temp)
318 env->sr |= SR_T;
319 else
320 env->sr &= ~SR_T;
6f06939b 321 if (temp < arg)
fdf9b3e8 322 env->sr |= SR_T;
6f06939b 323 return arg;
fdf9b3e8
FB
324}
325
6f06939b 326uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
327{
328 uint32_t tmp0, tmp1;
329
6f06939b
AJ
330 tmp1 = arg1 - arg0;
331 tmp0 = arg1;
332 arg1 = tmp1 - (env->sr & SR_T);
fdf9b3e8
FB
333 if (tmp0 < tmp1)
334 env->sr |= SR_T;
335 else
336 env->sr &= ~SR_T;
6f06939b 337 if (tmp1 < arg1)
fdf9b3e8 338 env->sr |= SR_T;
6f06939b 339 return arg1;
fdf9b3e8
FB
340}
341
6f06939b 342uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
fdf9b3e8
FB
343{
344 int32_t dest, src, ans;
345
6f06939b 346 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
347 dest = 0;
348 else
349 dest = 1;
6f06939b 350 if ((int32_t) arg0 >= 0)
fdf9b3e8
FB
351 src = 0;
352 else
353 src = 1;
354 src += dest;
6f06939b
AJ
355 arg1 -= arg0;
356 if ((int32_t) arg1 >= 0)
fdf9b3e8
FB
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;
6f06939b 368 return arg1;
fdf9b3e8
FB
369}
370
cc4ba6a9
AJ
371static inline void set_t(void)
372{
373 env->sr |= SR_T;
374}
375
376static inline void clr_t(void)
377{
378 env->sr &= ~SR_T;
379}
380
390af821
AJ
381void 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}
cc4ba6a9
AJ
389
390uint32_t helper_fabs_FT(uint32_t t0)
391{
9850d1e8
AJ
392 CPU_FloatU f;
393 f.l = t0;
394 f.f = float32_abs(f.f);
395 return f.l;
cc4ba6a9
AJ
396}
397
398uint64_t helper_fabs_DT(uint64_t t0)
399{
9850d1e8
AJ
400 CPU_DoubleU d;
401 d.ll = t0;
402 d.d = float64_abs(d.d);
403 return d.ll;
cc4ba6a9
AJ
404}
405
406uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
407{
9850d1e8
AJ
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;
cc4ba6a9
AJ
413}
414
415uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
416{
9850d1e8
AJ
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;
cc4ba6a9
AJ
422}
423
424void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
425{
9850d1e8
AJ
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)
cc4ba6a9
AJ
431 set_t();
432 else
433 clr_t();
434}
435
436void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
437{
9850d1e8
AJ
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)
cc4ba6a9
AJ
443 set_t();
444 else
445 clr_t();
446}
447
448void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
449{
9850d1e8
AJ
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)
cc4ba6a9
AJ
455 set_t();
456 else
457 clr_t();
458}
459
460void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
461{
9850d1e8
AJ
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)
cc4ba6a9
AJ
467 set_t();
468 else
469 clr_t();
470}
471
472uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
473{
9850d1e8
AJ
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;
cc4ba6a9
AJ
479}
480
481uint32_t helper_fcnvds_DT_FT(uint64_t t0)
482{
9850d1e8
AJ
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;
cc4ba6a9
AJ
488}
489
490uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
491{
9850d1e8
AJ
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;
cc4ba6a9
AJ
497}
498
499uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
500{
9850d1e8
AJ
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;
cc4ba6a9
AJ
506}
507
508uint32_t helper_float_FT(uint32_t t0)
509{
9850d1e8
AJ
510 CPU_FloatU f;
511 f.f = int32_to_float32(t0, &env->fp_status);
512 return f.l;
cc4ba6a9
AJ
513}
514
515uint64_t helper_float_DT(uint32_t t0)
516{
9850d1e8
AJ
517 CPU_DoubleU d;
518 d.d = int32_to_float64(t0, &env->fp_status);
519 return d.ll;
cc4ba6a9
AJ
520}
521
522uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
523{
9850d1e8
AJ
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;
cc4ba6a9
AJ
529}
530
531uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
532{
9850d1e8
AJ
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;
cc4ba6a9
AJ
538}
539
7fdf924f
AJ
540uint32_t helper_fneg_T(uint32_t t0)
541{
9850d1e8
AJ
542 CPU_FloatU f;
543 f.l = t0;
544 f.f = float32_chs(f.f);
545 return f.l;
7fdf924f
AJ
546}
547
cc4ba6a9
AJ
548uint32_t helper_fsqrt_FT(uint32_t t0)
549{
9850d1e8
AJ
550 CPU_FloatU f;
551 f.l = t0;
552 f.f = float32_sqrt(f.f, &env->fp_status);
553 return f.l;
cc4ba6a9
AJ
554}
555
556uint64_t helper_fsqrt_DT(uint64_t t0)
557{
9850d1e8
AJ
558 CPU_DoubleU d;
559 d.ll = t0;
560 d.d = float64_sqrt(d.d, &env->fp_status);
561 return d.ll;
cc4ba6a9
AJ
562}
563
564uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
565{
9850d1e8
AJ
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;
cc4ba6a9
AJ
571}
572
573uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
574{
9850d1e8
AJ
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;
cc4ba6a9
AJ
580}
581
582uint32_t helper_ftrc_FT(uint32_t t0)
583{
9850d1e8
AJ
584 CPU_FloatU f;
585 f.l = t0;
586 return float32_to_int32_round_to_zero(f.f, &env->fp_status);
cc4ba6a9
AJ
587}
588
589uint32_t helper_ftrc_DT(uint64_t t0)
590{
9850d1e8
AJ
591 CPU_DoubleU d;
592 d.ll = t0;
593 return float64_to_int32_round_to_zero(d.d, &env->fp_status);
cc4ba6a9 594}