2 * CRIS emulation micro-operations for qemu.
4 * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
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
21 #include "host-utils.h"
24 #define REG (env->regs[0])
25 #include "op_template.h"
28 #define REG (env->regs[1])
29 #include "op_template.h"
32 #define REG (env->regs[2])
33 #include "op_template.h"
36 #define REG (env->regs[3])
37 #include "op_template.h"
40 #define REG (env->regs[4])
41 #include "op_template.h"
44 #define REG (env->regs[5])
45 #include "op_template.h"
48 #define REG (env->regs[6])
49 #include "op_template.h"
52 #define REG (env->regs[7])
53 #include "op_template.h"
56 #define REG (env->regs[8])
57 #include "op_template.h"
60 #define REG (env->regs[9])
61 #include "op_template.h"
64 #define REG (env->regs[10])
65 #include "op_template.h"
68 #define REG (env->regs[11])
69 #include "op_template.h"
72 #define REG (env->regs[12])
73 #include "op_template.h"
76 #define REG (env->regs[13])
77 #include "op_template.h"
80 #define REG (env->regs[14])
81 #include "op_template.h"
84 #define REG (env->regs[15])
85 #include "op_template.h"
89 #define REG (env->pregs[0])
90 #include "op_template.h"
93 #define REG (env->pregs[1])
94 #include "op_template.h"
97 #define REG (env->pregs[2])
98 #include "op_template.h"
101 #define REG (env->pregs[3])
102 #include "op_template.h"
105 #define REG (env->pregs[4])
106 #include "op_template.h"
109 #define REG (env->pregs[5])
110 #include "op_template.h"
113 #define REG (env->pregs[6])
114 #include "op_template.h"
117 #define REG (env->pregs[7])
118 #include "op_template.h"
121 #define REG (env->pregs[8])
122 #include "op_template.h"
125 #define REG (env->pregs[9])
126 #include "op_template.h"
129 #define REG (env->pregs[10])
130 #include "op_template.h"
133 #define REG (env->pregs[11])
134 #include "op_template.h"
137 #define REG (env->pregs[12])
138 #include "op_template.h"
141 #define REG (env->pregs[13])
142 #include "op_template.h"
145 #define REG (env->pregs[14])
146 #include "op_template.h"
149 #define REG (env->pregs[15])
150 #include "op_template.h"
154 void OPPROTO
op_break_im(void)
156 env
->trap_vector
= PARAM1
;
157 env
->exception_index
= EXCP_BREAK
;
161 void OPPROTO
op_debug(void)
163 env
->exception_index
= EXCP_DEBUG
;
167 void OPPROTO
op_exec_insn(void)
169 env
->stats
.exec_insns
++;
172 void OPPROTO
op_exec_load(void)
174 env
->stats
.exec_loads
++;
177 void OPPROTO
op_exec_store(void)
179 env
->stats
.exec_stores
++;
183 void OPPROTO
op_ccs_lshift (void)
187 /* Apply the ccs shift. */
188 ccs
= env
->pregs
[PR_CCS
];
189 ccs
= (ccs
& 0xc0000000) | ((ccs
<< 12) >> 2);
190 env
->pregs
[PR_CCS
] = ccs
;
193 void OPPROTO
op_ccs_rshift (void)
195 register uint32_t ccs
;
197 /* Apply the ccs shift. */
198 ccs
= env
->pregs
[PR_CCS
];
199 ccs
= (ccs
& 0xc0000000) | ((ccs
& 0x0fffffff) >> 10);
202 /* Enter user mode. */
203 env
->ksp
= env
->regs
[R_SP
];
204 env
->regs
[R_SP
] = env
->pregs
[PR_USP
];
207 env
->pregs
[PR_CCS
] = ccs
;
212 void OPPROTO
op_setf (void)
214 if (!(env
->pregs
[PR_CCS
] & U_FLAG
) && (PARAM1
& U_FLAG
))
216 /* Enter user mode. */
217 env
->ksp
= env
->regs
[R_SP
];
218 env
->regs
[R_SP
] = env
->pregs
[PR_USP
];
221 env
->pregs
[PR_CCS
] |= PARAM1
;
225 void OPPROTO
op_clrf (void)
227 env
->pregs
[PR_CCS
] &= ~PARAM1
;
231 void OPPROTO
op_movl_debug1_T0 (void)
237 void OPPROTO
op_movl_debug2_T0 (void)
243 void OPPROTO
op_movl_debug3_T0 (void)
248 void OPPROTO
op_movl_debug1_T1 (void)
254 void OPPROTO
op_movl_debug2_T1 (void)
260 void OPPROTO
op_movl_debug3_T1 (void)
265 void OPPROTO
op_movl_debug3_im (void)
267 env
->debug3
= PARAM1
;
270 void OPPROTO
op_movl_T0_flags (void)
272 T0
= env
->pregs
[PR_CCS
];
275 void OPPROTO
op_movl_flags_T0 (void)
277 env
->pregs
[PR_CCS
] = T0
;
281 void OPPROTO
op_movl_sreg_T0 (void)
284 srs
= env
->pregs
[PR_SRS
];
287 env
->sregs
[srs
][PARAM1
] = T0
;
291 void OPPROTO
op_movl_tlb_hi_T0 (void)
294 srs
= env
->pregs
[PR_SRS
];
295 if (srs
== 1 || srs
== 2)
297 /* Writes to tlb-hi write to mm_cause as a side effect. */
298 env
->sregs
[SFR_RW_MM_TLB_HI
] = T0
;
299 env
->sregs
[SFR_R_MM_CAUSE
] = T0
;
304 void OPPROTO
op_movl_tlb_lo_T0 (void)
308 env
->pregs
[PR_SRS
] &= 3;
309 srs
= env
->pregs
[PR_SRS
];
311 if (srs
== 1 || srs
== 2)
317 idx
= set
= env
->sregs
[SFR_RW_MM_TLB_SEL
];
322 /* We've just made a write to tlb_lo. */
323 lo
= env
->sregs
[SFR_RW_MM_TLB_LO
];
324 /* Writes are done via r_mm_cause. */
325 hi
= env
->sregs
[SFR_R_MM_CAUSE
];
326 env
->tlbsets
[srs
- 1][set
][idx
].lo
= lo
;
327 env
->tlbsets
[srs
- 1][set
][idx
].hi
= hi
;
332 void OPPROTO
op_movl_T0_sreg (void)
335 env
->pregs
[PR_SRS
] &= 3;
336 srs
= env
->pregs
[PR_SRS
];
338 if (srs
== 1 || srs
== 2)
344 idx
= set
= env
->sregs
[SFR_RW_MM_TLB_SEL
];
349 /* Update the mirror regs. */
350 hi
= env
->tlbsets
[srs
- 1][set
][idx
].hi
;
351 lo
= env
->tlbsets
[srs
- 1][set
][idx
].lo
;
352 env
->sregs
[SFR_RW_MM_TLB_HI
] = hi
;
353 env
->sregs
[SFR_RW_MM_TLB_LO
] = lo
;
355 T0
= env
->sregs
[srs
][PARAM1
];
359 void OPPROTO
op_update_cc (void)
362 env
->cc_dest
= PARAM2
;
363 env
->cc_src
= PARAM3
;
367 void OPPROTO
op_update_cc_op (void)
373 void OPPROTO
op_update_cc_mask (void)
375 env
->cc_mask
= PARAM1
;
379 void OPPROTO
op_update_cc_dest_T0 (void)
385 void OPPROTO
op_update_cc_result_T0 (void)
391 void OPPROTO
op_update_cc_size_im (void)
393 env
->cc_size
= PARAM1
;
397 void OPPROTO
op_update_cc_src_T1 (void)
402 void OPPROTO
op_update_cc_x (void)
404 env
->cc_x_live
= PARAM1
;
409 void OPPROTO
op_extb_T0_T0 (void)
414 void OPPROTO
op_extb_T1_T0 (void)
419 void OPPROTO
op_extb_T1_T1 (void)
424 void OPPROTO
op_zextb_T0_T0 (void)
429 void OPPROTO
op_zextb_T1_T0 (void)
434 void OPPROTO
op_zextb_T1_T1 (void)
439 void OPPROTO
op_extw_T0_T0 (void)
444 void OPPROTO
op_extw_T1_T0 (void)
449 void OPPROTO
op_extw_T1_T1 (void)
455 void OPPROTO
op_zextw_T0_T0 (void)
460 void OPPROTO
op_zextw_T1_T0 (void)
466 void OPPROTO
op_zextw_T1_T1 (void)
472 void OPPROTO
op_movl_T0_im (void)
477 void OPPROTO
op_movl_T1_im (void)
483 void OPPROTO
op_addl_T0_im (void)
489 void OPPROTO
op_addl_T1_im (void)
495 void OPPROTO
op_subl_T0_im (void)
501 void OPPROTO
op_addxl_T0_C (void)
503 if (env
->pregs
[PR_CCS
] & X_FLAG
)
504 T0
+= !!(env
->pregs
[PR_CCS
] & C_FLAG
);
507 void OPPROTO
op_subxl_T0_C (void)
509 if (env
->pregs
[PR_CCS
] & X_FLAG
)
510 T0
-= !!(env
->pregs
[PR_CCS
] & C_FLAG
);
513 void OPPROTO
op_addl_T0_C (void)
515 T0
+= !!(env
->pregs
[PR_CCS
] & C_FLAG
);
518 void OPPROTO
op_addl_T0_R (void)
520 T0
+= !!(env
->pregs
[PR_CCS
] & R_FLAG
);
524 void OPPROTO
op_clr_R (void)
526 env
->pregs
[PR_CCS
] &= ~R_FLAG
;
531 void OPPROTO
op_andl_T0_im (void)
537 void OPPROTO
op_andl_T1_im (void)
543 void OPPROTO
op_movl_T0_T1 (void)
549 void OPPROTO
op_swp_T0_T1 (void)
557 void OPPROTO
op_movl_T1_T0 (void)
563 void OPPROTO
op_movl_pc_T0 (void)
569 void OPPROTO
op_movl_T0_0 (void)
575 void OPPROTO
op_addl_T0_T1 (void)
581 void OPPROTO
op_subl_T0_T1 (void)
587 void OPPROTO
op_absl_T1_T1 (void)
591 T1
= st
< 0 ? -st
: st
;
595 void OPPROTO
op_muls_T0_T1 (void)
599 /* cast into signed values to make GCC sign extend these babies. */
604 T0
= tmp
& 0xffffffff;
605 env
->pregs
[PR_MOF
] = tmp
>> 32;
609 void OPPROTO
op_mulu_T0_T1 (void)
611 uint64_t tmp
, t0
,t1
;
616 T0
= tmp
& 0xffffffff;
617 env
->pregs
[PR_MOF
] = tmp
>> 32;
621 void OPPROTO
op_dstep_T0_T1 (void)
629 void OPPROTO
op_orl_T0_T1 (void)
635 void OPPROTO
op_andl_T0_T1 (void)
641 void OPPROTO
op_xorl_T0_T1 (void)
647 void OPPROTO
op_lsll_T0_T1 (void)
657 void OPPROTO
op_lsll_T0_im (void)
663 void OPPROTO
op_lsrl_T0_T1 (void)
673 /* Rely on GCC emitting an arithmetic shift for signed right shifts. */
674 void OPPROTO
op_asrl_T0_T1 (void)
678 T0
= T0
& 0x80000000 ? -1 : 0;
680 T0
= (int32_t)T0
>> s
;
684 void OPPROTO
op_btst_T0_T1 (void)
686 /* FIXME: clean this up. */
689 The N flag is set according to the selected bit in the dest reg.
690 The Z flag is set if the selected bit and all bits to the right are
692 The X flag is cleared.
693 Other flags are left untouched.
694 The destination reg is not affected.*/
695 unsigned int fz
, sbit
, bset
, mask
, masked_t0
;
698 bset
= !!(T0
& (1 << sbit
));
699 mask
= sbit
== 31 ? -1 : (1 << (sbit
+ 1)) - 1;
700 masked_t0
= T0
& mask
;
701 fz
= !(masked_t0
| bset
);
703 /* Clear the X, N and Z flags. */
704 T0
= env
->pregs
[PR_CCS
] & ~(X_FLAG
| N_FLAG
| Z_FLAG
);
705 /* Set the N and Z flags accordingly. */
706 T0
|= (bset
<< 3) | (fz
<< 2);
710 void OPPROTO
op_bound_T0_T1 (void)
717 void OPPROTO
op_lz_T0_T1 (void)
723 void OPPROTO
op_negl_T0_T1 (void)
729 void OPPROTO
op_negl_T1_T1 (void)
735 void OPPROTO
op_not_T0_T0 (void)
740 void OPPROTO
op_not_T1_T1 (void)
746 void OPPROTO
op_swapw_T0_T0 (void)
748 T0
= (T0
<< 16) | ((T0
>> 16));
752 void OPPROTO
op_swapb_T0_T0 (void)
754 T0
= ((T0
<< 8) & 0xff00ff00) | ((T0
>> 8) & 0x00ff00ff);
758 void OPPROTO
op_swapr_T0_T0 (void)
760 T0
= (((T0
<< 7) & 0x80808080) |
761 ((T0
<< 5) & 0x40404040) |
762 ((T0
<< 3) & 0x20202020) |
763 ((T0
<< 1) & 0x10101010) |
764 ((T0
>> 1) & 0x08080808) |
765 ((T0
>> 3) & 0x04040404) |
766 ((T0
>> 5) & 0x02020202) |
767 ((T0
>> 7) & 0x01010101));
771 void OPPROTO
op_tst_cc_eq (void) {
772 uint32_t flags
= env
->pregs
[PR_CCS
];
775 z_set
= !!(flags
& Z_FLAG
);
780 void OPPROTO
op_tst_cc_eq_fast (void) {
781 T0
= !(env
->cc_result
);
785 void OPPROTO
op_tst_cc_ne (void) {
786 uint32_t flags
= env
->pregs
[PR_CCS
];
789 z_set
= !!(flags
& Z_FLAG
);
793 void OPPROTO
op_tst_cc_ne_fast (void) {
794 T0
= !!(env
->cc_result
);
798 void OPPROTO
op_tst_cc_cc (void) {
799 uint32_t flags
= env
->pregs
[PR_CCS
];
802 c_set
= !!(flags
& C_FLAG
);
806 void OPPROTO
op_tst_cc_cs (void) {
807 uint32_t flags
= env
->pregs
[PR_CCS
];
810 c_set
= !!(flags
& C_FLAG
);
815 void OPPROTO
op_tst_cc_vc (void) {
816 uint32_t flags
= env
->pregs
[PR_CCS
];
819 v_set
= !!(flags
& V_FLAG
);
823 void OPPROTO
op_tst_cc_vs (void) {
824 uint32_t flags
= env
->pregs
[PR_CCS
];
827 v_set
= !!(flags
& V_FLAG
);
831 void OPPROTO
op_tst_cc_pl (void) {
832 uint32_t flags
= env
->pregs
[PR_CCS
];
835 n_set
= !!(flags
& N_FLAG
);
839 void OPPROTO
op_tst_cc_pl_fast (void) {
840 T0
= ((int32_t)env
->cc_result
) >= 0;
844 void OPPROTO
op_tst_cc_mi (void) {
845 uint32_t flags
= env
->pregs
[PR_CCS
];
848 n_set
= !!(flags
& N_FLAG
);
852 void OPPROTO
op_tst_cc_mi_fast (void) {
853 T0
= ((int32_t)env
->cc_result
) < 0;
857 void OPPROTO
op_tst_cc_ls (void) {
858 uint32_t flags
= env
->pregs
[PR_CCS
];
862 c_set
= !!(flags
& C_FLAG
);
863 z_set
= !!(flags
& Z_FLAG
);
867 void OPPROTO
op_tst_cc_hi (void) {
868 uint32_t flags
= env
->pregs
[PR_CCS
];
872 z_set
= !!(flags
& Z_FLAG
);
873 c_set
= !!(flags
& C_FLAG
);
874 T0
= !c_set
&& !z_set
;
879 void OPPROTO
op_tst_cc_ge (void) {
880 uint32_t flags
= env
->pregs
[PR_CCS
];
884 n_set
= !!(flags
& N_FLAG
);
885 v_set
= !!(flags
& V_FLAG
);
886 T0
= (n_set
&& v_set
) || (!n_set
&& !v_set
);
890 void OPPROTO
op_tst_cc_ge_fast (void) {
891 T0
= ((int32_t)env
->cc_src
< (int32_t)env
->cc_dest
);
895 void OPPROTO
op_tst_cc_lt (void) {
896 uint32_t flags
= env
->pregs
[PR_CCS
];
900 n_set
= !!(flags
& N_FLAG
);
901 v_set
= !!(flags
& V_FLAG
);
902 T0
= (n_set
&& !v_set
) || (!n_set
&& v_set
);
906 void OPPROTO
op_tst_cc_gt (void) {
907 uint32_t flags
= env
->pregs
[PR_CCS
];
912 n_set
= !!(flags
& N_FLAG
);
913 v_set
= !!(flags
& V_FLAG
);
914 z_set
= !!(flags
& Z_FLAG
);
915 T0
= (n_set
&& v_set
&& !z_set
)
916 || (!n_set
&& !v_set
&& !z_set
);
920 void OPPROTO
op_tst_cc_le (void) {
921 uint32_t flags
= env
->pregs
[PR_CCS
];
926 n_set
= !!(flags
& N_FLAG
);
927 v_set
= !!(flags
& V_FLAG
);
928 z_set
= !!(flags
& Z_FLAG
);
929 T0
= z_set
|| (n_set
&& !v_set
) || (!n_set
&& v_set
);
933 void OPPROTO
op_tst_cc_p (void) {
934 uint32_t flags
= env
->pregs
[PR_CCS
];
937 p_set
= !!(flags
& P_FLAG
);
942 /* Evaluate the if the branch should be taken or not. Needs to be done in
943 the original sequence. The acutal branch is rescheduled to right after the
945 void OPPROTO
op_evaluate_bcc (void)
951 /* this one is used on every alu op, optimize it!. */
952 void OPPROTO
op_goto_if_not_x (void)
954 if (env
->pregs
[PR_CCS
] & X_FLAG
)
959 void OPPROTO
op_cc_jmp (void)
968 void OPPROTO
op_cc_ngoto (void)
975 void OPPROTO
op_movl_btarget_T0 (void)
981 void OPPROTO
op_jmp1 (void)
983 env
->pc
= env
->btarget
;