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
->trapnr
= 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)
197 /* Apply the ccs shift. */
198 ccs
= env
->pregs
[PR_CCS
];
199 ccs
= (ccs
& 0xc0000000) | (ccs
>> 10);
200 env
->pregs
[PR_CCS
] = ccs
;
204 void OPPROTO
op_setf (void)
206 env
->pregs
[PR_CCS
] |= PARAM1
;
210 void OPPROTO
op_clrf (void)
212 env
->pregs
[PR_CCS
] &= ~PARAM1
;
216 void OPPROTO
op_movl_debug1_T0 (void)
222 void OPPROTO
op_movl_debug2_T0 (void)
228 void OPPROTO
op_movl_debug3_T0 (void)
233 void OPPROTO
op_movl_debug1_T1 (void)
239 void OPPROTO
op_movl_debug2_T1 (void)
245 void OPPROTO
op_movl_debug3_T1 (void)
250 void OPPROTO
op_movl_debug3_im (void)
252 env
->debug3
= PARAM1
;
255 void OPPROTO
op_movl_T0_flags (void)
257 T0
= env
->pregs
[PR_CCS
];
260 void OPPROTO
op_movl_flags_T0 (void)
262 env
->pregs
[PR_CCS
] = T0
;
266 void OPPROTO
op_movl_sreg_T0 (void)
268 env
->sregs
[env
->pregs
[PR_SRS
]][PARAM1
] = T0
;
272 void OPPROTO
op_movl_tlb_lo_T0 (void)
275 srs
= env
->pregs
[PR_SRS
];
276 if (srs
== 1 || srs
== 2)
282 idx
= set
= env
->sregs
[SFR_RW_MM_TLB_SEL
];
287 /* We've just made a write to tlb_lo. */
288 lo
= env
->sregs
[SFR_RW_MM_TLB_LO
];
289 hi
= env
->sregs
[SFR_RW_MM_TLB_HI
];
290 env
->tlbsets
[srs
- 1][set
][idx
].lo
= lo
;
291 env
->tlbsets
[srs
- 1][set
][idx
].hi
= hi
;
297 void OPPROTO
op_movl_T0_sreg (void)
299 T0
= env
->sregs
[env
->pregs
[PR_SRS
]][PARAM1
];
303 void OPPROTO
op_update_cc (void)
306 env
->cc_dest
= PARAM2
;
307 env
->cc_src
= PARAM3
;
311 void OPPROTO
op_update_cc_op (void)
317 void OPPROTO
op_update_cc_mask (void)
319 env
->cc_mask
= PARAM1
;
323 void OPPROTO
op_update_cc_dest_T0 (void)
329 void OPPROTO
op_update_cc_result_T0 (void)
335 void OPPROTO
op_update_cc_size_im (void)
337 env
->cc_size
= PARAM1
;
341 void OPPROTO
op_update_cc_src_T1 (void)
346 void OPPROTO
op_update_cc_x (void)
348 env
->cc_x_live
= PARAM1
;
353 /* FIXME: is this allowed? */
354 extern inline void evaluate_flags_writeback(uint32_t flags
)
358 /* Extended arithmetics, leave the z flag alone. */
359 env
->debug3
= env
->pregs
[PR_CCS
];
364 x
= env
->pregs
[PR_CCS
] & X_FLAG
;
366 if ((x
|| env
->cc_op
== CC_OP_ADDC
)
368 env
->cc_mask
&= ~Z_FLAG
;
370 /* all insn clear the x-flag except setf or clrf. */
371 env
->pregs
[PR_CCS
] &= ~(env
->cc_mask
| X_FLAG
);
372 flags
&= env
->cc_mask
;
373 env
->pregs
[PR_CCS
] |= flags
;
377 void OPPROTO
op_evaluate_flags_muls(void)
383 /* were gonna have to redo the muls. */
390 res
= env
->cc_result
;
393 /* cast into signed values to make GCC sign extend. */
396 dneg
= ((int32_t)res
) < 0;
404 if ((dneg
&& mof
!= -1)
405 || (!dneg
&& mof
!= 0))
407 evaluate_flags_writeback(flags
);
411 void OPPROTO
op_evaluate_flags_mulu(void)
417 /* were gonna have to redo the muls. */
418 uint64_t tmp
, t0
,t1
;
423 res
= env
->cc_result
;
426 /* cast into signed values to make GCC sign extend. */
439 evaluate_flags_writeback(flags
);
443 void OPPROTO
op_evaluate_flags_mcp(void)
452 res
= env
->cc_result
;
454 if ((res
& 0x80000000L
) != 0L)
457 if (((src
& 0x80000000L
) == 0L)
458 && ((dst
& 0x80000000L
) == 0L))
462 else if (((src
& 0x80000000L
) != 0L) &&
463 ((dst
& 0x80000000L
) != 0L))
472 if (((src
& 0x80000000L
) != 0L)
473 && ((dst
& 0x80000000L
) != 0L))
475 if ((dst
& 0x80000000L
) != 0L
476 || (src
& 0x80000000L
) != 0L)
480 evaluate_flags_writeback(flags
);
484 void OPPROTO
op_evaluate_flags_alu_4(void)
493 res
= env
->cc_result
;
495 if ((res
& 0x80000000L
) != 0L)
498 if (((src
& 0x80000000L
) == 0L)
499 && ((dst
& 0x80000000L
) == 0L))
503 else if (((src
& 0x80000000L
) != 0L) &&
504 ((dst
& 0x80000000L
) != 0L))
513 if (((src
& 0x80000000L
) != 0L)
514 && ((dst
& 0x80000000L
) != 0L))
516 if ((dst
& 0x80000000L
) != 0L
517 || (src
& 0x80000000L
) != 0L)
521 if (env
->cc_op
== CC_OP_SUB
522 || env
->cc_op
== CC_OP_CMP
) {
525 evaluate_flags_writeback(flags
);
529 void OPPROTO
op_evaluate_flags_move_4 (void)
536 res
= env
->cc_result
;
538 if ((int32_t)res
< 0)
543 evaluate_flags_writeback(flags
);
546 void OPPROTO
op_evaluate_flags_move_2 (void)
553 res
= env
->cc_result
;
555 if ((int16_t)res
< 0L)
560 evaluate_flags_writeback(flags
);
564 /* TODO: This is expensive. We could split things up and only evaluate part of
565 CCR on a need to know basis. For now, we simply re-evaluate everything. */
566 void OPPROTO
op_evaluate_flags (void)
575 res
= env
->cc_result
;
578 /* Now, evaluate the flags. This stuff is based on
579 Per Zander's CRISv10 simulator. */
580 switch (env
->cc_size
)
583 if ((res
& 0x80L
) != 0L)
586 if (((src
& 0x80L
) == 0L)
587 && ((dst
& 0x80L
) == 0L))
591 else if (((src
& 0x80L
) != 0L)
592 && ((dst
& 0x80L
) != 0L))
599 if ((res
& 0xFFL
) == 0L)
603 if (((src
& 0x80L
) != 0L)
604 && ((dst
& 0x80L
) != 0L))
608 if ((dst
& 0x80L
) != 0L
609 || (src
& 0x80L
) != 0L)
616 if ((res
& 0x8000L
) != 0L)
619 if (((src
& 0x8000L
) == 0L)
620 && ((dst
& 0x8000L
) == 0L))
624 else if (((src
& 0x8000L
) != 0L)
625 && ((dst
& 0x8000L
) != 0L))
632 if ((res
& 0xFFFFL
) == 0L)
636 if (((src
& 0x8000L
) != 0L)
637 && ((dst
& 0x8000L
) != 0L))
641 if ((dst
& 0x8000L
) != 0L
642 || (src
& 0x8000L
) != 0L)
649 if ((res
& 0x80000000L
) != 0L)
652 if (((src
& 0x80000000L
) == 0L)
653 && ((dst
& 0x80000000L
) == 0L))
657 else if (((src
& 0x80000000L
) != 0L) &&
658 ((dst
& 0x80000000L
) != 0L))
667 if (((src
& 0x80000000L
) != 0L)
668 && ((dst
& 0x80000000L
) != 0L))
670 if ((dst
& 0x80000000L
) != 0L
671 || (src
& 0x80000000L
) != 0L)
679 if (env
->cc_op
== CC_OP_SUB
680 || env
->cc_op
== CC_OP_CMP
) {
683 evaluate_flags_writeback(flags
);
687 void OPPROTO
op_extb_T0_T0 (void)
692 void OPPROTO
op_extb_T1_T0 (void)
697 void OPPROTO
op_extb_T1_T1 (void)
702 void OPPROTO
op_zextb_T0_T0 (void)
707 void OPPROTO
op_zextb_T1_T0 (void)
712 void OPPROTO
op_zextb_T1_T1 (void)
717 void OPPROTO
op_extw_T0_T0 (void)
722 void OPPROTO
op_extw_T1_T0 (void)
727 void OPPROTO
op_extw_T1_T1 (void)
733 void OPPROTO
op_zextw_T0_T0 (void)
738 void OPPROTO
op_zextw_T1_T0 (void)
744 void OPPROTO
op_zextw_T1_T1 (void)
750 void OPPROTO
op_movl_T0_im (void)
755 void OPPROTO
op_movl_T1_im (void)
761 void OPPROTO
op_addl_T0_im (void)
767 void OPPROTO
op_addl_T1_im (void)
773 void OPPROTO
op_subl_T0_im (void)
779 void OPPROTO
op_addxl_T0_C (void)
781 if (env
->pregs
[PR_CCS
] & X_FLAG
)
782 T0
+= !!(env
->pregs
[PR_CCS
] & C_FLAG
);
785 void OPPROTO
op_subxl_T0_C (void)
787 if (env
->pregs
[PR_CCS
] & X_FLAG
)
788 T0
-= !!(env
->pregs
[PR_CCS
] & C_FLAG
);
791 void OPPROTO
op_addl_T0_C (void)
793 T0
+= !!(env
->pregs
[PR_CCS
] & C_FLAG
);
796 void OPPROTO
op_addl_T0_R (void)
798 T0
+= !!(env
->pregs
[PR_CCS
] & R_FLAG
);
802 void OPPROTO
op_clr_R (void)
804 env
->pregs
[PR_CCS
] &= ~R_FLAG
;
809 void OPPROTO
op_andl_T0_im (void)
815 void OPPROTO
op_andl_T1_im (void)
821 void OPPROTO
op_movl_T0_T1 (void)
827 void OPPROTO
op_swp_T0_T1 (void)
835 void OPPROTO
op_movl_T1_T0 (void)
841 void OPPROTO
op_movl_pc_T0 (void)
847 void OPPROTO
op_movl_T0_0 (void)
853 void OPPROTO
op_addl_T0_T1 (void)
859 void OPPROTO
op_subl_T0_T1 (void)
865 void OPPROTO
op_absl_T1_T1 (void)
869 T1
= st
< 0 ? -st
: st
;
873 void OPPROTO
op_muls_T0_T1 (void)
877 /* cast into signed values to make GCC sign extend these babies. */
882 T0
= tmp
& 0xffffffff;
883 env
->pregs
[PR_MOF
] = tmp
>> 32;
887 void OPPROTO
op_mulu_T0_T1 (void)
889 uint64_t tmp
, t0
,t1
;
894 T0
= tmp
& 0xffffffff;
895 env
->pregs
[PR_MOF
] = tmp
>> 32;
899 void OPPROTO
op_dstep_T0_T1 (void)
907 void OPPROTO
op_orl_T0_T1 (void)
913 void OPPROTO
op_andl_T0_T1 (void)
919 void OPPROTO
op_xorl_T0_T1 (void)
925 void OPPROTO
op_lsll_T0_T1 (void)
935 void OPPROTO
op_lsll_T0_im (void)
941 void OPPROTO
op_lsrl_T0_T1 (void)
951 /* Rely on GCC emitting an arithmetic shift for signed right shifts. */
952 void OPPROTO
op_asrl_T0_T1 (void)
956 T0
= T0
& 0x80000000 ? -1 : 0;
958 T0
= (int32_t)T0
>> s
;
962 void OPPROTO
op_btst_T0_T1 (void)
964 /* FIXME: clean this up. */
967 The N flag is set according to the selected bit in the dest reg.
968 The Z flag is set if the selected bit and all bits to the right are
970 The X flag is cleared.
971 Other flags are left untouched.
972 The destination reg is not affected.*/
973 unsigned int fz
, sbit
, bset
, mask
, masked_t0
;
976 bset
= !!(T0
& (1 << sbit
));
977 mask
= sbit
== 31 ? -1 : (1 << (sbit
+ 1)) - 1;
978 masked_t0
= T0
& mask
;
979 fz
= !(masked_t0
| bset
);
981 /* Clear the X, N and Z flags. */
982 T0
= env
->pregs
[PR_CCS
] & ~(X_FLAG
| N_FLAG
| Z_FLAG
);
983 /* Set the N and Z flags accordingly. */
984 T0
|= (bset
<< 3) | (fz
<< 2);
988 void OPPROTO
op_bound_T0_T1 (void)
995 void OPPROTO
op_lz_T0_T1 (void)
1001 void OPPROTO
op_negl_T0_T1 (void)
1007 void OPPROTO
op_negl_T1_T1 (void)
1013 void OPPROTO
op_not_T0_T0 (void)
1018 void OPPROTO
op_not_T1_T1 (void)
1024 void OPPROTO
op_swapw_T0_T0 (void)
1026 T0
= (T0
<< 16) | ((T0
>> 16));
1030 void OPPROTO
op_swapb_T0_T0 (void)
1032 T0
= ((T0
<< 8) & 0xff00ff00) | ((T0
>> 8) & 0x00ff00ff);
1036 void OPPROTO
op_swapr_T0_T0 (void)
1038 T0
= (((T0
<< 7) & 0x80808080) |
1039 ((T0
<< 5) & 0x40404040) |
1040 ((T0
<< 3) & 0x20202020) |
1041 ((T0
<< 1) & 0x10101010) |
1042 ((T0
>> 1) & 0x08080808) |
1043 ((T0
>> 3) & 0x04040404) |
1044 ((T0
>> 5) & 0x02020202) |
1045 ((T0
>> 7) & 0x01010101));
1049 void OPPROTO
op_tst_cc_eq (void) {
1050 uint32_t flags
= env
->pregs
[PR_CCS
];
1053 z_set
= !!(flags
& Z_FLAG
);
1058 void OPPROTO
op_tst_cc_eq_fast (void) {
1059 T0
= !(env
->cc_result
);
1063 void OPPROTO
op_tst_cc_ne (void) {
1064 uint32_t flags
= env
->pregs
[PR_CCS
];
1067 z_set
= !!(flags
& Z_FLAG
);
1071 void OPPROTO
op_tst_cc_ne_fast (void) {
1072 T0
= !!(env
->cc_result
);
1076 void OPPROTO
op_tst_cc_cc (void) {
1077 uint32_t flags
= env
->pregs
[PR_CCS
];
1080 c_set
= !!(flags
& C_FLAG
);
1084 void OPPROTO
op_tst_cc_cs (void) {
1085 uint32_t flags
= env
->pregs
[PR_CCS
];
1088 c_set
= !!(flags
& C_FLAG
);
1093 void OPPROTO
op_tst_cc_vc (void) {
1094 uint32_t flags
= env
->pregs
[PR_CCS
];
1097 v_set
= !!(flags
& V_FLAG
);
1101 void OPPROTO
op_tst_cc_vs (void) {
1102 uint32_t flags
= env
->pregs
[PR_CCS
];
1105 v_set
= !!(flags
& V_FLAG
);
1109 void OPPROTO
op_tst_cc_pl (void) {
1110 uint32_t flags
= env
->pregs
[PR_CCS
];
1113 n_set
= !!(flags
& N_FLAG
);
1117 void OPPROTO
op_tst_cc_pl_fast (void) {
1118 T0
= ((int32_t)env
->cc_result
) >= 0;
1122 void OPPROTO
op_tst_cc_mi (void) {
1123 uint32_t flags
= env
->pregs
[PR_CCS
];
1126 n_set
= !!(flags
& N_FLAG
);
1130 void OPPROTO
op_tst_cc_mi_fast (void) {
1131 T0
= ((int32_t)env
->cc_result
) < 0;
1135 void OPPROTO
op_tst_cc_ls (void) {
1136 uint32_t flags
= env
->pregs
[PR_CCS
];
1140 c_set
= !!(flags
& C_FLAG
);
1141 z_set
= !!(flags
& Z_FLAG
);
1142 T0
= c_set
|| z_set
;
1145 void OPPROTO
op_tst_cc_hi (void) {
1146 uint32_t flags
= env
->pregs
[PR_CCS
];
1150 z_set
= !!(flags
& Z_FLAG
);
1151 c_set
= !!(flags
& C_FLAG
);
1152 T0
= !c_set
&& !z_set
;
1157 void OPPROTO
op_tst_cc_ge (void) {
1158 uint32_t flags
= env
->pregs
[PR_CCS
];
1162 n_set
= !!(flags
& N_FLAG
);
1163 v_set
= !!(flags
& V_FLAG
);
1164 T0
= (n_set
&& v_set
) || (!n_set
&& !v_set
);
1168 void OPPROTO
op_tst_cc_ge_fast (void) {
1169 T0
= ((int32_t)env
->cc_src
< (int32_t)env
->cc_dest
);
1173 void OPPROTO
op_tst_cc_lt (void) {
1174 uint32_t flags
= env
->pregs
[PR_CCS
];
1178 n_set
= !!(flags
& N_FLAG
);
1179 v_set
= !!(flags
& V_FLAG
);
1180 T0
= (n_set
&& !v_set
) || (!n_set
&& v_set
);
1184 void OPPROTO
op_tst_cc_gt (void) {
1185 uint32_t flags
= env
->pregs
[PR_CCS
];
1190 n_set
= !!(flags
& N_FLAG
);
1191 v_set
= !!(flags
& V_FLAG
);
1192 z_set
= !!(flags
& Z_FLAG
);
1193 T0
= (n_set
&& v_set
&& !z_set
)
1194 || (!n_set
&& !v_set
&& !z_set
);
1198 void OPPROTO
op_tst_cc_le (void) {
1199 uint32_t flags
= env
->pregs
[PR_CCS
];
1204 n_set
= !!(flags
& N_FLAG
);
1205 v_set
= !!(flags
& V_FLAG
);
1206 z_set
= !!(flags
& Z_FLAG
);
1207 T0
= z_set
|| (n_set
&& !v_set
) || (!n_set
&& v_set
);
1211 void OPPROTO
op_tst_cc_p (void) {
1212 uint32_t flags
= env
->pregs
[PR_CCS
];
1215 p_set
= !!(flags
& P_FLAG
);
1220 /* Evaluate the if the branch should be taken or not. Needs to be done in
1221 the original sequence. The acutal branch is rescheduled to right after the
1223 void OPPROTO
op_evaluate_bcc (void)
1229 /* this one is used on every alu op, optimize it!. */
1230 void OPPROTO
op_goto_if_not_x (void)
1232 if (env
->pregs
[PR_CCS
] & X_FLAG
)
1233 GOTO_LABEL_PARAM(1);
1237 void OPPROTO
op_cc_jmp (void)
1246 void OPPROTO
op_cc_ngoto (void)
1249 GOTO_LABEL_PARAM(1);
1253 void OPPROTO
op_movl_btarget_T0 (void)
1259 void OPPROTO
op_jmp1 (void)
1261 env
->pc
= env
->btarget
;
1265 /* Load and store */
1266 #define MEMSUFFIX _raw
1269 #if !defined(CONFIG_USER_ONLY)
1270 #define MEMSUFFIX _user
1274 #define MEMSUFFIX _kernel