Device hot-remove
[qemu-kvm/fedora.git] / target-sh4 / op.c
blob955610a90ab6b414a5dde39300e4934a91e790b9
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 "exec.h"
22 static inline void set_t(void)
24 env->sr |= SR_T;
27 static inline void clr_t(void)
29 env->sr &= ~SR_T;
32 static inline void cond_t(int cond)
34 if (cond)
35 set_t();
36 else
37 clr_t();
40 void OPPROTO op_movl_imm_T0(void)
42 T0 = (uint32_t) PARAM1;
43 RETURN();
46 void OPPROTO op_movl_imm_T1(void)
48 T0 = (uint32_t) PARAM1;
49 RETURN();
52 void OPPROTO op_movl_imm_T2(void)
54 T0 = (uint32_t) PARAM1;
55 RETURN();
58 void OPPROTO op_cmp_eq_imm_T0(void)
60 cond_t((int32_t) T0 == (int32_t) PARAM1);
61 RETURN();
64 void OPPROTO op_cmd_eq_T0_T1(void)
66 cond_t(T0 == T1);
67 RETURN();
70 void OPPROTO op_cmd_hs_T0_T1(void)
72 cond_t((uint32_t) T0 <= (uint32_t) T1);
73 RETURN();
76 void OPPROTO op_cmd_ge_T0_T1(void)
78 cond_t((int32_t) T0 <= (int32_t) T1);
79 RETURN();
82 void OPPROTO op_cmd_hi_T0_T1(void)
84 cond_t((uint32_t) T0 < (uint32_t) T1);
85 RETURN();
88 void OPPROTO op_cmd_gt_T0_T1(void)
90 cond_t((int32_t) T0 < (int32_t) T1);
91 RETURN();
94 void OPPROTO op_not_T0(void)
96 T0 = ~T0;
97 RETURN();
100 void OPPROTO op_bf_s(void)
102 env->delayed_pc = PARAM1;
103 if (!(env->sr & SR_T)) {
104 env->flags |= DELAY_SLOT_TRUE;
106 RETURN();
109 void OPPROTO op_bt_s(void)
111 env->delayed_pc = PARAM1;
112 if (env->sr & SR_T) {
113 env->flags |= DELAY_SLOT_TRUE;
115 RETURN();
118 void OPPROTO op_store_flags(void)
120 env->flags &= DELAY_SLOT_TRUE;
121 env->flags |= PARAM1;
122 RETURN();
125 void OPPROTO op_bra(void)
127 env->delayed_pc = PARAM1;
128 RETURN();
131 void OPPROTO op_braf_T0(void)
133 env->delayed_pc = PARAM1 + T0;
134 RETURN();
137 void OPPROTO op_bsr(void)
139 env->pr = PARAM1;
140 env->delayed_pc = PARAM2;
141 RETURN();
144 void OPPROTO op_bsrf_T0(void)
146 env->pr = PARAM1;
147 env->delayed_pc = PARAM1 + T0;
148 RETURN();
151 void OPPROTO op_jsr_T0(void)
153 env->pr = PARAM1;
154 env->delayed_pc = T0;
155 RETURN();
158 void OPPROTO op_rts(void)
160 env->delayed_pc = env->pr;
161 RETURN();
164 void OPPROTO op_addl_imm_T0(void)
166 T0 += PARAM1;
167 RETURN();
170 void OPPROTO op_addl_imm_T1(void)
172 T1 += PARAM1;
173 RETURN();
176 void OPPROTO op_clrmac(void)
178 env->mach = env->macl = 0;
179 RETURN();
182 void OPPROTO op_clrs(void)
184 env->sr &= ~SR_S;
185 RETURN();
188 void OPPROTO op_clrt(void)
190 env->sr &= ~SR_T;
191 RETURN();
194 void OPPROTO op_sets(void)
196 env->sr |= SR_S;
197 RETURN();
200 void OPPROTO op_sett(void)
202 env->sr |= SR_T;
203 RETURN();
206 void OPPROTO op_frchg(void)
208 env->fpscr ^= FPSCR_FR;
209 RETURN();
212 void OPPROTO op_fschg(void)
214 env->fpscr ^= FPSCR_SZ;
215 RETURN();
218 void OPPROTO op_rte(void)
220 env->sr = env->ssr;
221 env->delayed_pc = env->spc;
222 RETURN();
225 void OPPROTO op_swapb_T0(void)
227 T0 = (T0 & 0xffff0000) | ((T0 & 0xff) << 8) | ((T0 >> 8) & 0xff);
228 RETURN();
231 void OPPROTO op_swapw_T0(void)
233 T0 = ((T0 & 0xffff) << 16) | ((T0 >> 16) & 0xffff);
234 RETURN();
237 void OPPROTO op_xtrct_T0_T1(void)
239 T1 = ((T0 & 0xffff) << 16) | ((T1 >> 16) & 0xffff);
240 RETURN();
243 void OPPROTO op_addc_T0_T1(void)
245 helper_addc_T0_T1();
246 RETURN();
249 void OPPROTO op_addv_T0_T1(void)
251 helper_addv_T0_T1();
252 RETURN();
255 void OPPROTO op_cmp_eq_T0_T1(void)
257 cond_t(T1 == T0);
258 RETURN();
261 void OPPROTO op_cmp_ge_T0_T1(void)
263 cond_t((int32_t) T1 >= (int32_t) T0);
264 RETURN();
267 void OPPROTO op_cmp_gt_T0_T1(void)
269 cond_t((int32_t) T1 > (int32_t) T0);
270 RETURN();
273 void OPPROTO op_cmp_hi_T0_T1(void)
275 cond_t((uint32_t) T1 > (uint32_t) T0);
276 RETURN();
279 void OPPROTO op_cmp_hs_T0_T1(void)
281 cond_t((uint32_t) T1 >= (uint32_t) T0);
282 RETURN();
285 void OPPROTO op_cmp_str_T0_T1(void)
287 cond_t((T0 & 0x000000ff) == (T1 & 0x000000ff) ||
288 (T0 & 0x0000ff00) == (T1 & 0x0000ff00) ||
289 (T0 & 0x00ff0000) == (T1 & 0x00ff0000) ||
290 (T0 & 0xff000000) == (T1 & 0xff000000));
291 RETURN();
294 void OPPROTO op_tst_T0_T1(void)
296 cond_t((T1 & T0) == 0);
297 RETURN();
300 void OPPROTO op_div0s_T0_T1(void)
302 if (T1 & 0x80000000)
303 env->sr |= SR_Q;
304 else
305 env->sr &= ~SR_Q;
306 if (T0 & 0x80000000)
307 env->sr |= SR_M;
308 else
309 env->sr &= ~SR_M;
310 cond_t((T1 ^ T0) & 0x80000000);
311 RETURN();
314 void OPPROTO op_div0u(void)
316 env->sr &= ~(SR_M | SR_Q | SR_T);
317 RETURN();
320 void OPPROTO op_div1_T0_T1(void)
322 helper_div1_T0_T1();
323 RETURN();
326 void OPPROTO op_dmulsl_T0_T1(void)
328 helper_dmulsl_T0_T1();
329 RETURN();
332 void OPPROTO op_dmulul_T0_T1(void)
334 helper_dmulul_T0_T1();
335 RETURN();
338 void OPPROTO op_macl_T0_T1(void)
340 helper_macl_T0_T1();
341 RETURN();
344 void OPPROTO op_macw_T0_T1(void)
346 helper_macw_T0_T1();
347 RETURN();
350 void OPPROTO op_mull_T0_T1(void)
352 env->macl = (T0 * T1) & 0xffffffff;
353 RETURN();
356 void OPPROTO op_mulsw_T0_T1(void)
358 env->macl = (int32_t) T0 *(int32_t) T1;
359 RETURN();
362 void OPPROTO op_muluw_T0_T1(void)
364 env->macl = (uint32_t) T0 *(uint32_t) T1;
365 RETURN();
368 void OPPROTO op_neg_T0(void)
370 T0 = -T0;
371 RETURN();
374 void OPPROTO op_negc_T0(void)
376 helper_negc_T0();
377 RETURN();
380 void OPPROTO op_shad_T0_T1(void)
382 if ((T0 & 0x80000000) == 0)
383 T1 <<= (T0 & 0x1f);
384 else if ((T0 & 0x1f) == 0)
385 T1 = 0;
386 else
387 T1 = ((int32_t) T1) >> ((~T0 & 0x1f) + 1);
388 RETURN();
391 void OPPROTO op_shld_T0_T1(void)
393 if ((T0 & 0x80000000) == 0)
394 T1 <<= (T0 & 0x1f);
395 else if ((T0 & 0x1f) == 0)
396 T1 = 0;
397 else
398 T1 = ((uint32_t) T1) >> ((~T0 & 0x1f) + 1);
399 RETURN();
402 void OPPROTO op_subc_T0_T1(void)
404 helper_subc_T0_T1();
405 RETURN();
408 void OPPROTO op_subv_T0_T1(void)
410 helper_subv_T0_T1();
411 RETURN();
414 void OPPROTO op_trapa(void)
416 env->tra = PARAM1 << 2;
417 env->exception_index = 0x160;
418 do_raise_exception();
419 RETURN();
422 void OPPROTO op_cmp_pl_T0(void)
424 cond_t((int32_t) T0 > 0);
425 RETURN();
428 void OPPROTO op_cmp_pz_T0(void)
430 cond_t((int32_t) T0 >= 0);
431 RETURN();
434 void OPPROTO op_jmp_T0(void)
436 env->delayed_pc = T0;
437 RETURN();
440 void OPPROTO op_movl_rN_rN(void)
442 env->gregs[PARAM2] = env->gregs[PARAM1];
443 RETURN();
446 void OPPROTO op_ldcl_rMplus_rN_bank(void)
448 env->gregs[PARAM2] = env->gregs[PARAM1];
449 env->gregs[PARAM1] += 4;
450 RETURN();
453 void OPPROTO op_ldc_T0_sr(void)
455 env->sr = T0 & 0x700083f3;
456 RETURN();
459 void OPPROTO op_stc_sr_T0(void)
461 T0 = env->sr;
462 RETURN();
465 #define LDSTOPS(target,load,store) \
466 void OPPROTO op_##load##_T0_##target (void) \
467 { env ->target = T0; RETURN(); \
469 void OPPROTO op_##store##_##target##_T0 (void) \
470 { T0 = env->target; RETURN(); \
473 LDSTOPS(gbr, ldc, stc)
474 LDSTOPS(vbr, ldc, stc)
475 LDSTOPS(ssr, ldc, stc)
476 LDSTOPS(spc, ldc, stc)
477 LDSTOPS(sgr, ldc, stc)
478 LDSTOPS(dbr, ldc, stc)
479 LDSTOPS(mach, lds, sts)
480 LDSTOPS(macl, lds, sts)
481 LDSTOPS(pr, lds, sts)
482 LDSTOPS(fpul, lds, sts)
484 void OPPROTO op_lds_T0_fpscr(void)
486 env->fpscr = T0 & 0x003fffff;
487 env->fp_status.float_rounding_mode = T0 & 0x01 ?
488 float_round_to_zero : float_round_nearest_even;
490 RETURN();
493 void OPPROTO op_sts_fpscr_T0(void)
495 T0 = env->fpscr & 0x003fffff;
496 RETURN();
499 void OPPROTO op_movt_rN(void)
501 env->gregs[PARAM1] = env->sr & SR_T;
502 RETURN();
505 void OPPROTO op_rotcl_Rn(void)
507 helper_rotcl(&env->gregs[PARAM1]);
508 RETURN();
511 void OPPROTO op_rotcr_Rn(void)
513 helper_rotcr(&env->gregs[PARAM1]);
514 RETURN();
517 void OPPROTO op_rotl_Rn(void)
519 cond_t(env->gregs[PARAM1] & 0x80000000);
520 env->gregs[PARAM1] = (env->gregs[PARAM1] << 1) | (env->sr & SR_T);
521 RETURN();
524 void OPPROTO op_rotr_Rn(void)
526 cond_t(env->gregs[PARAM1] & 1);
527 env->gregs[PARAM1] = (env->gregs[PARAM1] >> 1) |
528 ((env->sr & SR_T) ? 0x80000000 : 0);
529 RETURN();
532 void OPPROTO op_shal_Rn(void)
534 cond_t(env->gregs[PARAM1] & 0x80000000);
535 env->gregs[PARAM1] <<= 1;
536 RETURN();
539 void OPPROTO op_shar_Rn(void)
541 cond_t(env->gregs[PARAM1] & 1);
542 env->gregs[PARAM1] >>= 1;
543 RETURN();
546 void OPPROTO op_shlr_Rn(void)
548 cond_t(env->gregs[PARAM1] & 1);
549 env->gregs[PARAM1] >>= 1;
550 RETURN();
553 void OPPROTO op_shll2_Rn(void)
555 env->gregs[PARAM1] <<= 2;
556 RETURN();
559 void OPPROTO op_shll8_Rn(void)
561 env->gregs[PARAM1] <<= 8;
562 RETURN();
565 void OPPROTO op_shll16_Rn(void)
567 env->gregs[PARAM1] <<= 16;
568 RETURN();
571 void OPPROTO op_shlr2_Rn(void)
573 env->gregs[PARAM1] >>= 2;
574 RETURN();
577 void OPPROTO op_shlr8_Rn(void)
579 env->gregs[PARAM1] >>= 8;
580 RETURN();
583 void OPPROTO op_shlr16_Rn(void)
585 env->gregs[PARAM1] >>= 16;
586 RETURN();
589 void OPPROTO op_tasb_rN(void)
591 cond_t(*(int8_t *) env->gregs[PARAM1] == 0);
592 *(int8_t *) env->gregs[PARAM1] |= 0x80;
593 RETURN();
596 void OPPROTO op_movl_T0_rN(void)
598 env->gregs[PARAM1] = T0;
599 RETURN();
602 void OPPROTO op_movl_T1_rN(void)
604 env->gregs[PARAM1] = T1;
605 RETURN();
608 void OPPROTO op_movb_rN_T0(void)
610 T0 = (int32_t) (int8_t) (env->gregs[PARAM1] & 0xff);
611 RETURN();
614 void OPPROTO op_movub_rN_T0(void)
616 T0 = env->gregs[PARAM1] & 0xff;
617 RETURN();
620 void OPPROTO op_movw_rN_T0(void)
622 T0 = (int32_t) (int16_t) (env->gregs[PARAM1] & 0xffff);
623 RETURN();
626 void OPPROTO op_movuw_rN_T0(void)
628 T0 = env->gregs[PARAM1] & 0xffff;
629 RETURN();
632 void OPPROTO op_movl_rN_T0(void)
634 T0 = env->gregs[PARAM1];
635 RETURN();
638 void OPPROTO op_movb_rN_T1(void)
640 T1 = (int32_t) (int8_t) (env->gregs[PARAM1] & 0xff);
641 RETURN();
644 void OPPROTO op_movub_rN_T1(void)
646 T1 = env->gregs[PARAM1] & 0xff;
647 RETURN();
650 void OPPROTO op_movw_rN_T1(void)
652 T1 = (int32_t) (int16_t) (env->gregs[PARAM1] & 0xffff);
653 RETURN();
656 void OPPROTO op_movuw_rN_T1(void)
658 T1 = env->gregs[PARAM1] & 0xffff;
659 RETURN();
662 void OPPROTO op_movl_rN_T1(void)
664 T1 = env->gregs[PARAM1];
665 RETURN();
668 void OPPROTO op_movl_imm_rN(void)
670 env->gregs[PARAM2] = PARAM1;
671 RETURN();
674 void OPPROTO op_fmov_frN_FT0(void)
676 FT0 = env->fregs[PARAM1];
677 RETURN();
680 void OPPROTO op_fmov_drN_DT0(void)
682 CPU_DoubleU d;
684 d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
685 d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
686 DT0 = d.d;
687 RETURN();
690 void OPPROTO op_fmov_frN_FT1(void)
692 FT1 = env->fregs[PARAM1];
693 RETURN();
696 void OPPROTO op_fmov_drN_DT1(void)
698 CPU_DoubleU d;
700 d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
701 d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
702 DT1 = d.d;
703 RETURN();
706 void OPPROTO op_fmov_FT0_frN(void)
708 env->fregs[PARAM1] = FT0;
709 RETURN();
712 void OPPROTO op_fmov_DT0_drN(void)
714 CPU_DoubleU d;
716 d.d = DT0;
717 *(uint32_t *)&env->fregs[PARAM1] = d.l.upper;
718 *(uint32_t *)&env->fregs[PARAM1 + 1] = d.l.lower;
719 RETURN();
722 void OPPROTO op_fadd_FT(void)
724 FT0 = float32_add(FT0, FT1, &env->fp_status);
725 RETURN();
728 void OPPROTO op_fadd_DT(void)
730 DT0 = float64_add(DT0, DT1, &env->fp_status);
731 RETURN();
734 void OPPROTO op_fsub_FT(void)
736 FT0 = float32_sub(FT0, FT1, &env->fp_status);
737 RETURN();
740 void OPPROTO op_fsub_DT(void)
742 DT0 = float64_sub(DT0, DT1, &env->fp_status);
743 RETURN();
746 void OPPROTO op_fmul_FT(void)
748 FT0 = float32_mul(FT0, FT1, &env->fp_status);
749 RETURN();
752 void OPPROTO op_fmul_DT(void)
754 DT0 = float64_mul(DT0, DT1, &env->fp_status);
755 RETURN();
758 void OPPROTO op_fdiv_FT(void)
760 FT0 = float32_div(FT0, FT1, &env->fp_status);
761 RETURN();
764 void OPPROTO op_fdiv_DT(void)
766 DT0 = float64_div(DT0, DT1, &env->fp_status);
767 RETURN();
770 void OPPROTO op_float_FT(void)
772 FT0 = int32_to_float32(env->fpul, &env->fp_status);
773 RETURN();
776 void OPPROTO op_float_DT(void)
778 DT0 = int32_to_float64(env->fpul, &env->fp_status);
779 RETURN();
782 void OPPROTO op_ftrc_FT(void)
784 env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status);
785 RETURN();
788 void OPPROTO op_ftrc_DT(void)
790 env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status);
791 RETURN();
794 void OPPROTO op_fmov_T0_frN(void)
796 *(unsigned int *)&env->fregs[PARAM1] = T0;
797 RETURN();
800 void OPPROTO op_dec1_rN(void)
802 env->gregs[PARAM1] -= 1;
803 RETURN();
806 void OPPROTO op_dec2_rN(void)
808 env->gregs[PARAM1] -= 2;
809 RETURN();
812 void OPPROTO op_dec4_rN(void)
814 env->gregs[PARAM1] -= 4;
815 RETURN();
818 void OPPROTO op_dec8_rN(void)
820 env->gregs[PARAM1] -= 8;
821 RETURN();
824 void OPPROTO op_inc1_rN(void)
826 env->gregs[PARAM1] += 1;
827 RETURN();
830 void OPPROTO op_inc2_rN(void)
832 env->gregs[PARAM1] += 2;
833 RETURN();
836 void OPPROTO op_inc4_rN(void)
838 env->gregs[PARAM1] += 4;
839 RETURN();
842 void OPPROTO op_inc8_rN(void)
844 env->gregs[PARAM1] += 8;
845 RETURN();
848 void OPPROTO op_add_T0_rN(void)
850 env->gregs[PARAM1] += T0;
851 RETURN();
854 void OPPROTO op_sub_T0_rN(void)
856 env->gregs[PARAM1] -= T0;
857 RETURN();
860 void OPPROTO op_and_T0_rN(void)
862 env->gregs[PARAM1] &= T0;
863 RETURN();
866 void OPPROTO op_or_T0_rN(void)
868 env->gregs[PARAM1] |= T0;
869 RETURN();
872 void OPPROTO op_xor_T0_rN(void)
874 env->gregs[PARAM1] ^= T0;
875 RETURN();
878 void OPPROTO op_add_rN_T0(void)
880 T0 += env->gregs[PARAM1];
881 RETURN();
884 void OPPROTO op_add_rN_T1(void)
886 T1 += env->gregs[PARAM1];
887 RETURN();
890 void OPPROTO op_add_imm_rN(void)
892 env->gregs[PARAM2] += PARAM1;
893 RETURN();
896 void OPPROTO op_and_imm_rN(void)
898 env->gregs[PARAM2] &= PARAM1;
899 RETURN();
902 void OPPROTO op_or_imm_rN(void)
904 env->gregs[PARAM2] |= PARAM1;
905 RETURN();
908 void OPPROTO op_xor_imm_rN(void)
910 env->gregs[PARAM2] ^= PARAM1;
911 RETURN();
914 void OPPROTO op_dt_rN(void)
916 cond_t((--env->gregs[PARAM1]) == 0);
917 RETURN();
920 void OPPROTO op_tst_imm_rN(void)
922 cond_t((env->gregs[PARAM2] & PARAM1) == 0);
923 RETURN();
926 void OPPROTO op_movl_T0_T1(void)
928 T1 = T0;
929 RETURN();
932 void OPPROTO op_movl_fpul_FT0(void)
934 FT0 = *(float32 *)&env->fpul;
935 RETURN();
938 void OPPROTO op_movl_FT0_fpul(void)
940 *(float32 *)&env->fpul = FT0;
941 RETURN();
944 void OPPROTO op_movl_imm_PC(void)
946 env->pc = PARAM1;
947 RETURN();
950 void OPPROTO op_jT(void)
952 if (env->sr & SR_T)
953 GOTO_LABEL_PARAM(1);
954 RETURN();
957 void OPPROTO op_jdelayed(void)
959 if (env->flags & DELAY_SLOT_TRUE) {
960 env->flags &= ~DELAY_SLOT_TRUE;
961 GOTO_LABEL_PARAM(1);
963 RETURN();
966 void OPPROTO op_movl_delayed_pc_PC(void)
968 env->pc = env->delayed_pc;
969 RETURN();
972 void OPPROTO op_addl_GBR_T0(void)
974 T0 += env->gbr;
975 RETURN();
978 void OPPROTO op_and_imm_T0(void)
980 T0 &= PARAM1;
981 RETURN();
984 void OPPROTO op_or_imm_T0(void)
986 T0 |= PARAM1;
987 RETURN();
990 void OPPROTO op_xor_imm_T0(void)
992 T0 ^= PARAM1;
993 RETURN();
996 void OPPROTO op_tst_imm_T0(void)
998 cond_t((T0 & PARAM1) == 0);
999 RETURN();
1002 void OPPROTO op_raise_illegal_instruction(void)
1004 env->exception_index = 0x180;
1005 do_raise_exception();
1006 RETURN();
1009 void OPPROTO op_raise_slot_illegal_instruction(void)
1011 env->exception_index = 0x1a0;
1012 do_raise_exception();
1013 RETURN();
1016 void OPPROTO op_debug(void)
1018 env->exception_index = EXCP_DEBUG;
1019 cpu_loop_exit();
1022 /* Load and store */
1023 #define MEMSUFFIX _raw
1024 #include "op_mem.c"
1025 #undef MEMSUFFIX
1026 #if !defined(CONFIG_USER_ONLY)
1027 #define MEMSUFFIX _user
1028 #include "op_mem.c"
1029 #undef MEMSUFFIX
1031 #define MEMSUFFIX _kernel
1032 #include "op_mem.c"
1033 #undef MEMSUFFIX
1034 #endif