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)
197 /* Apply the ccs shift. */
198 ccs
= env
->pregs
[PR_CCS
];
199 ccs
= (ccs
& 0xc0000000) | ((ccs
& 0x0fffffff) >> 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_hi_T0 (void)
275 srs
= env
->pregs
[PR_SRS
];
276 if (srs
== 1 || srs
== 2)
278 /* Writes to tlb-hi write to mm_cause as a side effect. */
279 env
->sregs
[SFR_RW_MM_TLB_HI
] = T0
;
280 env
->sregs
[SFR_R_MM_CAUSE
] = T0
;
285 void OPPROTO
op_movl_tlb_lo_T0 (void)
288 srs
= env
->pregs
[PR_SRS
];
289 if (srs
== 1 || srs
== 2)
295 idx
= set
= env
->sregs
[SFR_RW_MM_TLB_SEL
];
300 /* We've just made a write to tlb_lo. */
301 lo
= env
->sregs
[SFR_RW_MM_TLB_LO
];
302 /* Writes are done via r_mm_cause. */
303 hi
= env
->sregs
[SFR_R_MM_CAUSE
];
304 env
->tlbsets
[srs
- 1][set
][idx
].lo
= lo
;
305 env
->tlbsets
[srs
- 1][set
][idx
].hi
= hi
;
310 void OPPROTO
op_movl_T0_sreg (void)
312 T0
= env
->sregs
[env
->pregs
[PR_SRS
]][PARAM1
];
316 void OPPROTO
op_update_cc (void)
319 env
->cc_dest
= PARAM2
;
320 env
->cc_src
= PARAM3
;
324 void OPPROTO
op_update_cc_op (void)
330 void OPPROTO
op_update_cc_mask (void)
332 env
->cc_mask
= PARAM1
;
336 void OPPROTO
op_update_cc_dest_T0 (void)
342 void OPPROTO
op_update_cc_result_T0 (void)
348 void OPPROTO
op_update_cc_size_im (void)
350 env
->cc_size
= PARAM1
;
354 void OPPROTO
op_update_cc_src_T1 (void)
359 void OPPROTO
op_update_cc_x (void)
361 env
->cc_x_live
= PARAM1
;
366 /* FIXME: is this allowed? */
367 extern inline void evaluate_flags_writeback(uint32_t flags
)
371 /* Extended arithmetics, leave the z flag alone. */
372 env
->debug3
= env
->pregs
[PR_CCS
];
377 x
= env
->pregs
[PR_CCS
] & X_FLAG
;
379 if ((x
|| env
->cc_op
== CC_OP_ADDC
)
381 env
->cc_mask
&= ~Z_FLAG
;
383 /* all insn clear the x-flag except setf or clrf. */
384 env
->pregs
[PR_CCS
] &= ~(env
->cc_mask
| X_FLAG
);
385 flags
&= env
->cc_mask
;
386 env
->pregs
[PR_CCS
] |= flags
;
390 void OPPROTO
op_evaluate_flags_muls(void)
396 /* were gonna have to redo the muls. */
403 res
= env
->cc_result
;
406 /* cast into signed values to make GCC sign extend. */
409 dneg
= ((int32_t)res
) < 0;
417 if ((dneg
&& mof
!= -1)
418 || (!dneg
&& mof
!= 0))
420 evaluate_flags_writeback(flags
);
424 void OPPROTO
op_evaluate_flags_mulu(void)
430 /* were gonna have to redo the muls. */
431 uint64_t tmp
, t0
,t1
;
436 res
= env
->cc_result
;
439 /* cast into signed values to make GCC sign extend. */
452 evaluate_flags_writeback(flags
);
456 void OPPROTO
op_evaluate_flags_mcp(void)
465 res
= env
->cc_result
;
467 if ((res
& 0x80000000L
) != 0L)
470 if (((src
& 0x80000000L
) == 0L)
471 && ((dst
& 0x80000000L
) == 0L))
475 else if (((src
& 0x80000000L
) != 0L) &&
476 ((dst
& 0x80000000L
) != 0L))
485 if (((src
& 0x80000000L
) != 0L)
486 && ((dst
& 0x80000000L
) != 0L))
488 if ((dst
& 0x80000000L
) != 0L
489 || (src
& 0x80000000L
) != 0L)
493 evaluate_flags_writeback(flags
);
497 void OPPROTO
op_evaluate_flags_alu_4(void)
506 res
= env
->cc_result
;
508 if ((res
& 0x80000000L
) != 0L)
511 if (((src
& 0x80000000L
) == 0L)
512 && ((dst
& 0x80000000L
) == 0L))
516 else if (((src
& 0x80000000L
) != 0L) &&
517 ((dst
& 0x80000000L
) != 0L))
526 if (((src
& 0x80000000L
) != 0L)
527 && ((dst
& 0x80000000L
) != 0L))
529 if ((dst
& 0x80000000L
) != 0L
530 || (src
& 0x80000000L
) != 0L)
534 if (env
->cc_op
== CC_OP_SUB
535 || env
->cc_op
== CC_OP_CMP
) {
538 evaluate_flags_writeback(flags
);
542 void OPPROTO
op_evaluate_flags_move_4 (void)
549 res
= env
->cc_result
;
551 if ((int32_t)res
< 0)
556 evaluate_flags_writeback(flags
);
559 void OPPROTO
op_evaluate_flags_move_2 (void)
566 res
= env
->cc_result
;
568 if ((int16_t)res
< 0L)
573 evaluate_flags_writeback(flags
);
577 /* TODO: This is expensive. We could split things up and only evaluate part of
578 CCR on a need to know basis. For now, we simply re-evaluate everything. */
579 void OPPROTO
op_evaluate_flags (void)
588 res
= env
->cc_result
;
591 /* Now, evaluate the flags. This stuff is based on
592 Per Zander's CRISv10 simulator. */
593 switch (env
->cc_size
)
596 if ((res
& 0x80L
) != 0L)
599 if (((src
& 0x80L
) == 0L)
600 && ((dst
& 0x80L
) == 0L))
604 else if (((src
& 0x80L
) != 0L)
605 && ((dst
& 0x80L
) != 0L))
612 if ((res
& 0xFFL
) == 0L)
616 if (((src
& 0x80L
) != 0L)
617 && ((dst
& 0x80L
) != 0L))
621 if ((dst
& 0x80L
) != 0L
622 || (src
& 0x80L
) != 0L)
629 if ((res
& 0x8000L
) != 0L)
632 if (((src
& 0x8000L
) == 0L)
633 && ((dst
& 0x8000L
) == 0L))
637 else if (((src
& 0x8000L
) != 0L)
638 && ((dst
& 0x8000L
) != 0L))
645 if ((res
& 0xFFFFL
) == 0L)
649 if (((src
& 0x8000L
) != 0L)
650 && ((dst
& 0x8000L
) != 0L))
654 if ((dst
& 0x8000L
) != 0L
655 || (src
& 0x8000L
) != 0L)
662 if ((res
& 0x80000000L
) != 0L)
665 if (((src
& 0x80000000L
) == 0L)
666 && ((dst
& 0x80000000L
) == 0L))
670 else if (((src
& 0x80000000L
) != 0L) &&
671 ((dst
& 0x80000000L
) != 0L))
680 if (((src
& 0x80000000L
) != 0L)
681 && ((dst
& 0x80000000L
) != 0L))
683 if ((dst
& 0x80000000L
) != 0L
684 || (src
& 0x80000000L
) != 0L)
692 if (env
->cc_op
== CC_OP_SUB
693 || env
->cc_op
== CC_OP_CMP
) {
696 evaluate_flags_writeback(flags
);
700 void OPPROTO
op_extb_T0_T0 (void)
705 void OPPROTO
op_extb_T1_T0 (void)
710 void OPPROTO
op_extb_T1_T1 (void)
715 void OPPROTO
op_zextb_T0_T0 (void)
720 void OPPROTO
op_zextb_T1_T0 (void)
725 void OPPROTO
op_zextb_T1_T1 (void)
730 void OPPROTO
op_extw_T0_T0 (void)
735 void OPPROTO
op_extw_T1_T0 (void)
740 void OPPROTO
op_extw_T1_T1 (void)
746 void OPPROTO
op_zextw_T0_T0 (void)
751 void OPPROTO
op_zextw_T1_T0 (void)
757 void OPPROTO
op_zextw_T1_T1 (void)
763 void OPPROTO
op_movl_T0_im (void)
768 void OPPROTO
op_movl_T1_im (void)
774 void OPPROTO
op_addl_T0_im (void)
780 void OPPROTO
op_addl_T1_im (void)
786 void OPPROTO
op_subl_T0_im (void)
792 void OPPROTO
op_addxl_T0_C (void)
794 if (env
->pregs
[PR_CCS
] & X_FLAG
)
795 T0
+= !!(env
->pregs
[PR_CCS
] & C_FLAG
);
798 void OPPROTO
op_subxl_T0_C (void)
800 if (env
->pregs
[PR_CCS
] & X_FLAG
)
801 T0
-= !!(env
->pregs
[PR_CCS
] & C_FLAG
);
804 void OPPROTO
op_addl_T0_C (void)
806 T0
+= !!(env
->pregs
[PR_CCS
] & C_FLAG
);
809 void OPPROTO
op_addl_T0_R (void)
811 T0
+= !!(env
->pregs
[PR_CCS
] & R_FLAG
);
815 void OPPROTO
op_clr_R (void)
817 env
->pregs
[PR_CCS
] &= ~R_FLAG
;
822 void OPPROTO
op_andl_T0_im (void)
828 void OPPROTO
op_andl_T1_im (void)
834 void OPPROTO
op_movl_T0_T1 (void)
840 void OPPROTO
op_swp_T0_T1 (void)
848 void OPPROTO
op_movl_T1_T0 (void)
854 void OPPROTO
op_movl_pc_T0 (void)
860 void OPPROTO
op_movl_T0_0 (void)
866 void OPPROTO
op_addl_T0_T1 (void)
872 void OPPROTO
op_subl_T0_T1 (void)
878 void OPPROTO
op_absl_T1_T1 (void)
882 T1
= st
< 0 ? -st
: st
;
886 void OPPROTO
op_muls_T0_T1 (void)
890 /* cast into signed values to make GCC sign extend these babies. */
895 T0
= tmp
& 0xffffffff;
896 env
->pregs
[PR_MOF
] = tmp
>> 32;
900 void OPPROTO
op_mulu_T0_T1 (void)
902 uint64_t tmp
, t0
,t1
;
907 T0
= tmp
& 0xffffffff;
908 env
->pregs
[PR_MOF
] = tmp
>> 32;
912 void OPPROTO
op_dstep_T0_T1 (void)
920 void OPPROTO
op_orl_T0_T1 (void)
926 void OPPROTO
op_andl_T0_T1 (void)
932 void OPPROTO
op_xorl_T0_T1 (void)
938 void OPPROTO
op_lsll_T0_T1 (void)
948 void OPPROTO
op_lsll_T0_im (void)
954 void OPPROTO
op_lsrl_T0_T1 (void)
964 /* Rely on GCC emitting an arithmetic shift for signed right shifts. */
965 void OPPROTO
op_asrl_T0_T1 (void)
969 T0
= T0
& 0x80000000 ? -1 : 0;
971 T0
= (int32_t)T0
>> s
;
975 void OPPROTO
op_btst_T0_T1 (void)
977 /* FIXME: clean this up. */
980 The N flag is set according to the selected bit in the dest reg.
981 The Z flag is set if the selected bit and all bits to the right are
983 The X flag is cleared.
984 Other flags are left untouched.
985 The destination reg is not affected.*/
986 unsigned int fz
, sbit
, bset
, mask
, masked_t0
;
989 bset
= !!(T0
& (1 << sbit
));
990 mask
= sbit
== 31 ? -1 : (1 << (sbit
+ 1)) - 1;
991 masked_t0
= T0
& mask
;
992 fz
= !(masked_t0
| bset
);
994 /* Clear the X, N and Z flags. */
995 T0
= env
->pregs
[PR_CCS
] & ~(X_FLAG
| N_FLAG
| Z_FLAG
);
996 /* Set the N and Z flags accordingly. */
997 T0
|= (bset
<< 3) | (fz
<< 2);
1001 void OPPROTO
op_bound_T0_T1 (void)
1008 void OPPROTO
op_lz_T0_T1 (void)
1014 void OPPROTO
op_negl_T0_T1 (void)
1020 void OPPROTO
op_negl_T1_T1 (void)
1026 void OPPROTO
op_not_T0_T0 (void)
1031 void OPPROTO
op_not_T1_T1 (void)
1037 void OPPROTO
op_swapw_T0_T0 (void)
1039 T0
= (T0
<< 16) | ((T0
>> 16));
1043 void OPPROTO
op_swapb_T0_T0 (void)
1045 T0
= ((T0
<< 8) & 0xff00ff00) | ((T0
>> 8) & 0x00ff00ff);
1049 void OPPROTO
op_swapr_T0_T0 (void)
1051 T0
= (((T0
<< 7) & 0x80808080) |
1052 ((T0
<< 5) & 0x40404040) |
1053 ((T0
<< 3) & 0x20202020) |
1054 ((T0
<< 1) & 0x10101010) |
1055 ((T0
>> 1) & 0x08080808) |
1056 ((T0
>> 3) & 0x04040404) |
1057 ((T0
>> 5) & 0x02020202) |
1058 ((T0
>> 7) & 0x01010101));
1062 void OPPROTO
op_tst_cc_eq (void) {
1063 uint32_t flags
= env
->pregs
[PR_CCS
];
1066 z_set
= !!(flags
& Z_FLAG
);
1071 void OPPROTO
op_tst_cc_eq_fast (void) {
1072 T0
= !(env
->cc_result
);
1076 void OPPROTO
op_tst_cc_ne (void) {
1077 uint32_t flags
= env
->pregs
[PR_CCS
];
1080 z_set
= !!(flags
& Z_FLAG
);
1084 void OPPROTO
op_tst_cc_ne_fast (void) {
1085 T0
= !!(env
->cc_result
);
1089 void OPPROTO
op_tst_cc_cc (void) {
1090 uint32_t flags
= env
->pregs
[PR_CCS
];
1093 c_set
= !!(flags
& C_FLAG
);
1097 void OPPROTO
op_tst_cc_cs (void) {
1098 uint32_t flags
= env
->pregs
[PR_CCS
];
1101 c_set
= !!(flags
& C_FLAG
);
1106 void OPPROTO
op_tst_cc_vc (void) {
1107 uint32_t flags
= env
->pregs
[PR_CCS
];
1110 v_set
= !!(flags
& V_FLAG
);
1114 void OPPROTO
op_tst_cc_vs (void) {
1115 uint32_t flags
= env
->pregs
[PR_CCS
];
1118 v_set
= !!(flags
& V_FLAG
);
1122 void OPPROTO
op_tst_cc_pl (void) {
1123 uint32_t flags
= env
->pregs
[PR_CCS
];
1126 n_set
= !!(flags
& N_FLAG
);
1130 void OPPROTO
op_tst_cc_pl_fast (void) {
1131 T0
= ((int32_t)env
->cc_result
) >= 0;
1135 void OPPROTO
op_tst_cc_mi (void) {
1136 uint32_t flags
= env
->pregs
[PR_CCS
];
1139 n_set
= !!(flags
& N_FLAG
);
1143 void OPPROTO
op_tst_cc_mi_fast (void) {
1144 T0
= ((int32_t)env
->cc_result
) < 0;
1148 void OPPROTO
op_tst_cc_ls (void) {
1149 uint32_t flags
= env
->pregs
[PR_CCS
];
1153 c_set
= !!(flags
& C_FLAG
);
1154 z_set
= !!(flags
& Z_FLAG
);
1155 T0
= c_set
|| z_set
;
1158 void OPPROTO
op_tst_cc_hi (void) {
1159 uint32_t flags
= env
->pregs
[PR_CCS
];
1163 z_set
= !!(flags
& Z_FLAG
);
1164 c_set
= !!(flags
& C_FLAG
);
1165 T0
= !c_set
&& !z_set
;
1170 void OPPROTO
op_tst_cc_ge (void) {
1171 uint32_t flags
= env
->pregs
[PR_CCS
];
1175 n_set
= !!(flags
& N_FLAG
);
1176 v_set
= !!(flags
& V_FLAG
);
1177 T0
= (n_set
&& v_set
) || (!n_set
&& !v_set
);
1181 void OPPROTO
op_tst_cc_ge_fast (void) {
1182 T0
= ((int32_t)env
->cc_src
< (int32_t)env
->cc_dest
);
1186 void OPPROTO
op_tst_cc_lt (void) {
1187 uint32_t flags
= env
->pregs
[PR_CCS
];
1191 n_set
= !!(flags
& N_FLAG
);
1192 v_set
= !!(flags
& V_FLAG
);
1193 T0
= (n_set
&& !v_set
) || (!n_set
&& v_set
);
1197 void OPPROTO
op_tst_cc_gt (void) {
1198 uint32_t flags
= env
->pregs
[PR_CCS
];
1203 n_set
= !!(flags
& N_FLAG
);
1204 v_set
= !!(flags
& V_FLAG
);
1205 z_set
= !!(flags
& Z_FLAG
);
1206 T0
= (n_set
&& v_set
&& !z_set
)
1207 || (!n_set
&& !v_set
&& !z_set
);
1211 void OPPROTO
op_tst_cc_le (void) {
1212 uint32_t flags
= env
->pregs
[PR_CCS
];
1217 n_set
= !!(flags
& N_FLAG
);
1218 v_set
= !!(flags
& V_FLAG
);
1219 z_set
= !!(flags
& Z_FLAG
);
1220 T0
= z_set
|| (n_set
&& !v_set
) || (!n_set
&& v_set
);
1224 void OPPROTO
op_tst_cc_p (void) {
1225 uint32_t flags
= env
->pregs
[PR_CCS
];
1228 p_set
= !!(flags
& P_FLAG
);
1233 /* Evaluate the if the branch should be taken or not. Needs to be done in
1234 the original sequence. The acutal branch is rescheduled to right after the
1236 void OPPROTO
op_evaluate_bcc (void)
1242 /* this one is used on every alu op, optimize it!. */
1243 void OPPROTO
op_goto_if_not_x (void)
1245 if (env
->pregs
[PR_CCS
] & X_FLAG
)
1246 GOTO_LABEL_PARAM(1);
1250 void OPPROTO
op_cc_jmp (void)
1259 void OPPROTO
op_cc_ngoto (void)
1262 GOTO_LABEL_PARAM(1);
1266 void OPPROTO
op_movl_btarget_T0 (void)
1272 void OPPROTO
op_jmp1 (void)
1274 env
->pc
= env
->btarget
;
1278 /* Load and store */
1279 #define MEMSUFFIX _raw
1282 #if !defined(CONFIG_USER_ONLY)
1283 #define MEMSUFFIX _user
1287 #define MEMSUFFIX _kernel