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_exit_tb (void)
159 void OPPROTO
op_goto_tb0 (void)
161 GOTO_TB(op_goto_tb0
, PARAM1
, 0);
165 void OPPROTO
op_goto_tb1 (void)
167 GOTO_TB(op_goto_tb1
, PARAM1
, 1);
171 void OPPROTO
op_break_im(void)
173 env
->trapnr
= PARAM1
;
174 env
->exception_index
= EXCP_BREAK
;
178 void OPPROTO
op_debug(void)
180 env
->exception_index
= EXCP_DEBUG
;
184 void OPPROTO
op_exec_insn(void)
186 env
->stats
.exec_insns
++;
189 void OPPROTO
op_exec_load(void)
191 env
->stats
.exec_loads
++;
194 void OPPROTO
op_exec_store(void)
196 env
->stats
.exec_stores
++;
200 void OPPROTO
op_ccs_lshift (void)
204 /* Apply the ccs shift. */
205 ccs
= env
->pregs
[SR_CCS
];
206 ccs
= (ccs
& 0xc0000000) | ((ccs
<< 12) >> 2);
207 env
->pregs
[SR_CCS
] = ccs
;
209 void OPPROTO
op_ccs_rshift (void)
213 /* Apply the ccs shift. */
214 ccs
= env
->pregs
[SR_CCS
];
215 ccs
= (ccs
& 0xc0000000) | (ccs
>> 10);
216 env
->pregs
[SR_CCS
] = ccs
;
219 void OPPROTO
op_setf (void)
221 env
->pregs
[SR_CCS
] |= PARAM1
;
225 void OPPROTO
op_clrf (void)
227 env
->pregs
[SR_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
[SR_CCS
];
275 void OPPROTO
op_movl_flags_T0 (void)
277 env
->pregs
[SR_CCS
] = T0
;
281 void OPPROTO
op_movl_sreg_T0 (void)
283 env
->sregs
[env
->pregs
[SR_SRS
]][PARAM1
] = T0
;
287 void OPPROTO
op_movl_tlb_lo_T0 (void)
290 srs
= env
->pregs
[SR_SRS
];
291 if (srs
== 1 || srs
== 2)
297 idx
= set
= env
->sregs
[SFR_RW_MM_TLB_SEL
];
302 /* We've just made a write to tlb_lo. */
303 lo
= env
->sregs
[SFR_RW_MM_TLB_LO
];
304 hi
= env
->sregs
[SFR_RW_MM_TLB_HI
];
305 env
->tlbsets
[srs
- 1][set
][idx
].lo
= lo
;
306 env
->tlbsets
[srs
- 1][set
][idx
].hi
= hi
;
312 void OPPROTO
op_movl_T0_sreg (void)
314 T0
= env
->sregs
[env
->pregs
[SR_SRS
]][PARAM1
];
318 void OPPROTO
op_update_cc (void)
321 env
->cc_dest
= PARAM2
;
322 env
->cc_src
= PARAM3
;
326 void OPPROTO
op_update_cc_op (void)
332 void OPPROTO
op_update_cc_mask (void)
334 env
->cc_mask
= PARAM1
;
338 void OPPROTO
op_update_cc_dest_T0 (void)
344 void OPPROTO
op_update_cc_result_T0 (void)
350 void OPPROTO
op_update_cc_size_im (void)
352 env
->cc_size
= PARAM1
;
356 void OPPROTO
op_update_cc_src_T1 (void)
361 void OPPROTO
op_update_cc_x (void)
363 env
->cc_x_live
= PARAM1
;
368 /* FIXME: is this allowed? */
369 extern inline void evaluate_flags_writeback(uint32_t flags
)
373 /* Extended arithmetics, leave the z flag alone. */
374 env
->debug3
= env
->pregs
[SR_CCS
];
379 x
= env
->pregs
[SR_CCS
] & X_FLAG
;
381 if ((x
|| env
->cc_op
== CC_OP_ADDC
)
383 env
->cc_mask
&= ~Z_FLAG
;
385 /* all insn clear the x-flag except setf or clrf. */
386 env
->pregs
[SR_CCS
] &= ~(env
->cc_mask
| X_FLAG
);
387 flags
&= env
->cc_mask
;
388 env
->pregs
[SR_CCS
] |= flags
;
392 void OPPROTO
op_evaluate_flags_muls(void)
398 /* were gonna have to redo the muls. */
405 res
= env
->cc_result
;
408 /* cast into signed values to make GCC sign extend. */
411 dneg
= ((int32_t)res
) < 0;
419 if ((dneg
&& mof
!= -1)
420 || (!dneg
&& mof
!= 0))
422 evaluate_flags_writeback(flags
);
426 void OPPROTO
op_evaluate_flags_mulu(void)
432 /* were gonna have to redo the muls. */
433 uint64_t tmp
, t0
,t1
;
438 res
= env
->cc_result
;
441 /* cast into signed values to make GCC sign extend. */
454 evaluate_flags_writeback(flags
);
458 void OPPROTO
op_evaluate_flags_mcp(void)
467 res
= env
->cc_result
;
469 if ((res
& 0x80000000L
) != 0L)
472 if (((src
& 0x80000000L
) == 0L)
473 && ((dst
& 0x80000000L
) == 0L))
477 else if (((src
& 0x80000000L
) != 0L) &&
478 ((dst
& 0x80000000L
) != 0L))
487 if (((src
& 0x80000000L
) != 0L)
488 && ((dst
& 0x80000000L
) != 0L))
490 if ((dst
& 0x80000000L
) != 0L
491 || (src
& 0x80000000L
) != 0L)
495 evaluate_flags_writeback(flags
);
499 void OPPROTO
op_evaluate_flags_alu_4(void)
508 res
= env
->cc_result
;
510 if ((res
& 0x80000000L
) != 0L)
513 if (((src
& 0x80000000L
) == 0L)
514 && ((dst
& 0x80000000L
) == 0L))
518 else if (((src
& 0x80000000L
) != 0L) &&
519 ((dst
& 0x80000000L
) != 0L))
528 if (((src
& 0x80000000L
) != 0L)
529 && ((dst
& 0x80000000L
) != 0L))
531 if ((dst
& 0x80000000L
) != 0L
532 || (src
& 0x80000000L
) != 0L)
536 if (env
->cc_op
== CC_OP_SUB
537 || env
->cc_op
== CC_OP_CMP
) {
540 evaluate_flags_writeback(flags
);
544 void OPPROTO
op_evaluate_flags_move_4 (void)
551 res
= env
->cc_result
;
553 if ((int32_t)res
< 0)
558 evaluate_flags_writeback(flags
);
561 void OPPROTO
op_evaluate_flags_move_2 (void)
568 res
= env
->cc_result
;
570 if ((int16_t)res
< 0L)
575 evaluate_flags_writeback(flags
);
579 /* TODO: This is expensive. We could split things up and only evaluate part of
580 CCR on a need to know basis. For now, we simply re-evaluate everything. */
581 void OPPROTO
op_evaluate_flags (void)
590 res
= env
->cc_result
;
593 /* Now, evaluate the flags. This stuff is based on
594 Per Zander's CRISv10 simulator. */
595 switch (env
->cc_size
)
598 if ((res
& 0x80L
) != 0L)
601 if (((src
& 0x80L
) == 0L)
602 && ((dst
& 0x80L
) == 0L))
606 else if (((src
& 0x80L
) != 0L)
607 && ((dst
& 0x80L
) != 0L))
614 if ((res
& 0xFFL
) == 0L)
618 if (((src
& 0x80L
) != 0L)
619 && ((dst
& 0x80L
) != 0L))
623 if ((dst
& 0x80L
) != 0L
624 || (src
& 0x80L
) != 0L)
631 if ((res
& 0x8000L
) != 0L)
634 if (((src
& 0x8000L
) == 0L)
635 && ((dst
& 0x8000L
) == 0L))
639 else if (((src
& 0x8000L
) != 0L)
640 && ((dst
& 0x8000L
) != 0L))
647 if ((res
& 0xFFFFL
) == 0L)
651 if (((src
& 0x8000L
) != 0L)
652 && ((dst
& 0x8000L
) != 0L))
656 if ((dst
& 0x8000L
) != 0L
657 || (src
& 0x8000L
) != 0L)
664 if ((res
& 0x80000000L
) != 0L)
667 if (((src
& 0x80000000L
) == 0L)
668 && ((dst
& 0x80000000L
) == 0L))
672 else if (((src
& 0x80000000L
) != 0L) &&
673 ((dst
& 0x80000000L
) != 0L))
682 if (((src
& 0x80000000L
) != 0L)
683 && ((dst
& 0x80000000L
) != 0L))
685 if ((dst
& 0x80000000L
) != 0L
686 || (src
& 0x80000000L
) != 0L)
694 if (env
->cc_op
== CC_OP_SUB
695 || env
->cc_op
== CC_OP_CMP
) {
698 evaluate_flags_writeback(flags
);
702 void OPPROTO
op_extb_T0_T0 (void)
707 void OPPROTO
op_extb_T1_T0 (void)
712 void OPPROTO
op_extb_T1_T1 (void)
717 void OPPROTO
op_zextb_T0_T0 (void)
722 void OPPROTO
op_zextb_T1_T0 (void)
727 void OPPROTO
op_zextb_T1_T1 (void)
732 void OPPROTO
op_extw_T0_T0 (void)
737 void OPPROTO
op_extw_T1_T0 (void)
742 void OPPROTO
op_extw_T1_T1 (void)
748 void OPPROTO
op_zextw_T0_T0 (void)
753 void OPPROTO
op_zextw_T1_T0 (void)
759 void OPPROTO
op_zextw_T1_T1 (void)
765 void OPPROTO
op_movl_T0_im (void)
770 void OPPROTO
op_movl_T1_im (void)
776 void OPPROTO
op_addl_T0_im (void)
782 void OPPROTO
op_addl_T1_im (void)
788 void OPPROTO
op_subl_T0_im (void)
794 void OPPROTO
op_addxl_T0_C (void)
796 if (env
->pregs
[SR_CCS
] & X_FLAG
)
797 T0
+= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
800 void OPPROTO
op_subxl_T0_C (void)
802 if (env
->pregs
[SR_CCS
] & X_FLAG
)
803 T0
-= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
806 void OPPROTO
op_addl_T0_C (void)
808 T0
+= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
811 void OPPROTO
op_addl_T0_R (void)
813 T0
+= !!(env
->pregs
[SR_CCS
] & R_FLAG
);
817 void OPPROTO
op_clr_R (void)
819 env
->pregs
[SR_CCS
] &= ~R_FLAG
;
824 void OPPROTO
op_andl_T0_im (void)
830 void OPPROTO
op_andl_T1_im (void)
836 void OPPROTO
op_movl_T0_T1 (void)
842 void OPPROTO
op_swp_T0_T1 (void)
850 void OPPROTO
op_movl_T1_T0 (void)
856 void OPPROTO
op_movl_pc_T0 (void)
862 void OPPROTO
op_movl_T0_0 (void)
868 void OPPROTO
op_addl_T0_T1 (void)
874 void OPPROTO
op_subl_T0_T1 (void)
880 void OPPROTO
op_absl_T1_T1 (void)
884 T1
= st
< 0 ? -st
: st
;
888 void OPPROTO
op_muls_T0_T1 (void)
892 /* cast into signed values to make GCC sign extend these babies. */
897 T0
= tmp
& 0xffffffff;
898 env
->pregs
[REG_MOF
] = tmp
>> 32;
902 void OPPROTO
op_mulu_T0_T1 (void)
904 uint64_t tmp
, t0
,t1
;
909 T0
= tmp
& 0xffffffff;
910 env
->pregs
[REG_MOF
] = tmp
>> 32;
914 void OPPROTO
op_dstep_T0_T1 (void)
922 void OPPROTO
op_orl_T0_T1 (void)
928 void OPPROTO
op_andl_T0_T1 (void)
934 void OPPROTO
op_xorl_T0_T1 (void)
940 void OPPROTO
op_lsll_T0_T1 (void)
950 void OPPROTO
op_lsll_T0_im (void)
956 void OPPROTO
op_lsrl_T0_T1 (void)
966 /* Rely on GCC emitting an arithmetic shift for signed right shifts. */
967 void OPPROTO
op_asrl_T0_T1 (void)
971 T0
= T0
& 0x80000000 ? -1 : 0;
973 T0
= (int32_t)T0
>> s
;
977 void OPPROTO
op_btst_T0_T1 (void)
979 /* FIXME: clean this up. */
982 The N flag is set according to the selected bit in the dest reg.
983 The Z flag is set if the selected bit and all bits to the right are
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
);
993 /* Set the N and Z flags accordingly. */
994 T0
= (bset
<< 3) | (fz
<< 2);
998 void OPPROTO
op_bound_T0_T1 (void)
1005 void OPPROTO
op_lz_T0_T1 (void)
1011 void OPPROTO
op_negl_T0_T1 (void)
1017 void OPPROTO
op_negl_T1_T1 (void)
1023 void OPPROTO
op_not_T0_T0 (void)
1028 void OPPROTO
op_not_T1_T1 (void)
1034 void OPPROTO
op_swapw_T0_T0 (void)
1036 T0
= (T0
<< 16) | ((T0
>> 16));
1040 void OPPROTO
op_swapb_T0_T0 (void)
1042 T0
= ((T0
<< 8) & 0xff00ff00) | ((T0
>> 8) & 0x00ff00ff);
1046 void OPPROTO
op_swapr_T0_T0 (void)
1048 T0
= (((T0
<< 7) & 0x80808080) |
1049 ((T0
<< 5) & 0x40404040) |
1050 ((T0
<< 3) & 0x20202020) |
1051 ((T0
<< 1) & 0x10101010) |
1052 ((T0
>> 1) & 0x08080808) |
1053 ((T0
>> 3) & 0x04040404) |
1054 ((T0
>> 5) & 0x02020202) |
1055 ((T0
>> 7) & 0x01010101));
1059 void OPPROTO
op_tst_cc_eq (void) {
1060 uint32_t flags
= env
->pregs
[SR_CCS
];
1063 z_set
= !!(flags
& Z_FLAG
);
1068 void OPPROTO
op_tst_cc_eq_fast (void) {
1069 T0
= !(env
->cc_result
);
1073 void OPPROTO
op_tst_cc_ne (void) {
1074 uint32_t flags
= env
->pregs
[SR_CCS
];
1077 z_set
= !!(flags
& Z_FLAG
);
1081 void OPPROTO
op_tst_cc_ne_fast (void) {
1082 T0
= !!(env
->cc_result
);
1086 void OPPROTO
op_tst_cc_cc (void) {
1087 uint32_t flags
= env
->pregs
[SR_CCS
];
1090 c_set
= !!(flags
& C_FLAG
);
1094 void OPPROTO
op_tst_cc_cs (void) {
1095 uint32_t flags
= env
->pregs
[SR_CCS
];
1098 c_set
= !!(flags
& C_FLAG
);
1103 void OPPROTO
op_tst_cc_vc (void) {
1104 uint32_t flags
= env
->pregs
[SR_CCS
];
1107 v_set
= !!(flags
& V_FLAG
);
1111 void OPPROTO
op_tst_cc_vs (void) {
1112 uint32_t flags
= env
->pregs
[SR_CCS
];
1115 v_set
= !!(flags
& V_FLAG
);
1119 void OPPROTO
op_tst_cc_pl (void) {
1120 uint32_t flags
= env
->pregs
[SR_CCS
];
1123 n_set
= !!(flags
& N_FLAG
);
1127 void OPPROTO
op_tst_cc_pl_fast (void) {
1128 T0
= ((int32_t)env
->cc_result
) >= 0;
1132 void OPPROTO
op_tst_cc_mi (void) {
1133 uint32_t flags
= env
->pregs
[SR_CCS
];
1136 n_set
= !!(flags
& N_FLAG
);
1140 void OPPROTO
op_tst_cc_mi_fast (void) {
1141 T0
= ((int32_t)env
->cc_result
) < 0;
1145 void OPPROTO
op_tst_cc_ls (void) {
1146 uint32_t flags
= env
->pregs
[SR_CCS
];
1150 c_set
= !!(flags
& C_FLAG
);
1151 z_set
= !!(flags
& Z_FLAG
);
1152 T0
= c_set
|| z_set
;
1155 void OPPROTO
op_tst_cc_hi (void) {
1156 uint32_t flags
= env
->pregs
[SR_CCS
];
1160 z_set
= !!(flags
& Z_FLAG
);
1161 c_set
= !!(flags
& C_FLAG
);
1162 T0
= !c_set
&& !z_set
;
1167 void OPPROTO
op_tst_cc_ge (void) {
1168 uint32_t flags
= env
->pregs
[SR_CCS
];
1172 n_set
= !!(flags
& N_FLAG
);
1173 v_set
= !!(flags
& V_FLAG
);
1174 T0
= (n_set
&& v_set
) || (!n_set
&& !v_set
);
1178 void OPPROTO
op_tst_cc_ge_fast (void) {
1179 T0
= ((int32_t)env
->cc_src
< (int32_t)env
->cc_dest
);
1183 void OPPROTO
op_tst_cc_lt (void) {
1184 uint32_t flags
= env
->pregs
[SR_CCS
];
1188 n_set
= !!(flags
& N_FLAG
);
1189 v_set
= !!(flags
& V_FLAG
);
1190 T0
= (n_set
&& !v_set
) || (!n_set
&& v_set
);
1194 void OPPROTO
op_tst_cc_gt (void) {
1195 uint32_t flags
= env
->pregs
[SR_CCS
];
1200 n_set
= !!(flags
& N_FLAG
);
1201 v_set
= !!(flags
& V_FLAG
);
1202 z_set
= !!(flags
& Z_FLAG
);
1203 T0
= (n_set
&& v_set
&& !z_set
)
1204 || (!n_set
&& !v_set
&& !z_set
);
1208 void OPPROTO
op_tst_cc_le (void) {
1209 uint32_t flags
= env
->pregs
[SR_CCS
];
1214 n_set
= !!(flags
& N_FLAG
);
1215 v_set
= !!(flags
& V_FLAG
);
1216 z_set
= !!(flags
& Z_FLAG
);
1217 T0
= z_set
|| (n_set
&& !v_set
) || (!n_set
&& v_set
);
1221 void OPPROTO
op_tst_cc_p (void) {
1222 uint32_t flags
= env
->pregs
[SR_CCS
];
1225 p_set
= !!(flags
& P_FLAG
);
1230 /* Evaluate the if the branch should be taken or not. Needs to be done in
1231 the original sequence. The acutal branch is rescheduled to right after the
1233 void OPPROTO
op_evaluate_bcc (void)
1239 /* this one is used on every alu op, optimize it!. */
1240 void OPPROTO
op_goto_if_not_x (void)
1242 if (env
->pregs
[SR_CCS
] & X_FLAG
)
1243 GOTO_LABEL_PARAM(1);
1247 void OPPROTO
op_cc_jmp (void)
1256 void OPPROTO
op_cc_ngoto (void)
1259 GOTO_LABEL_PARAM(1);
1263 void OPPROTO
op_movl_btarget_T0 (void)
1269 void OPPROTO
op_jmp (void)
1271 env
->pc
= env
->btarget
;
1275 /* Load and store */
1276 #define MEMSUFFIX _raw
1279 #if !defined(CONFIG_USER_ONLY)
1280 #define MEMSUFFIX _user
1284 #define MEMSUFFIX _kernel