]>
git.proxmox.com Git - qemu.git/blob - target-cris/op.c
3c50574e769e5508bb7da55f33a8478c8a80a84a
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
;
210 void OPPROTO
op_ccs_rshift (void)
214 /* Apply the ccs shift. */
215 ccs
= env
->pregs
[SR_CCS
];
216 ccs
= (ccs
& 0xc0000000) | (ccs
>> 10);
217 env
->pregs
[SR_CCS
] = ccs
;
221 void OPPROTO
op_setf (void)
223 env
->pregs
[SR_CCS
] |= PARAM1
;
227 void OPPROTO
op_clrf (void)
229 env
->pregs
[SR_CCS
] &= ~PARAM1
;
233 void OPPROTO
op_movl_debug1_T0 (void)
239 void OPPROTO
op_movl_debug2_T0 (void)
245 void OPPROTO
op_movl_debug3_T0 (void)
250 void OPPROTO
op_movl_debug1_T1 (void)
256 void OPPROTO
op_movl_debug2_T1 (void)
262 void OPPROTO
op_movl_debug3_T1 (void)
267 void OPPROTO
op_movl_debug3_im (void)
269 env
->debug3
= PARAM1
;
272 void OPPROTO
op_movl_T0_flags (void)
274 T0
= env
->pregs
[SR_CCS
];
277 void OPPROTO
op_movl_flags_T0 (void)
279 env
->pregs
[SR_CCS
] = T0
;
283 void OPPROTO
op_movl_sreg_T0 (void)
285 env
->sregs
[env
->pregs
[SR_SRS
]][PARAM1
] = T0
;
289 void OPPROTO
op_movl_tlb_lo_T0 (void)
292 srs
= env
->pregs
[SR_SRS
];
293 if (srs
== 1 || srs
== 2)
299 idx
= set
= env
->sregs
[SFR_RW_MM_TLB_SEL
];
304 /* We've just made a write to tlb_lo. */
305 lo
= env
->sregs
[SFR_RW_MM_TLB_LO
];
306 hi
= env
->sregs
[SFR_RW_MM_TLB_HI
];
307 env
->tlbsets
[srs
- 1][set
][idx
].lo
= lo
;
308 env
->tlbsets
[srs
- 1][set
][idx
].hi
= hi
;
314 void OPPROTO
op_movl_T0_sreg (void)
316 T0
= env
->sregs
[env
->pregs
[SR_SRS
]][PARAM1
];
320 void OPPROTO
op_update_cc (void)
323 env
->cc_dest
= PARAM2
;
324 env
->cc_src
= PARAM3
;
328 void OPPROTO
op_update_cc_op (void)
334 void OPPROTO
op_update_cc_mask (void)
336 env
->cc_mask
= PARAM1
;
340 void OPPROTO
op_update_cc_dest_T0 (void)
346 void OPPROTO
op_update_cc_result_T0 (void)
352 void OPPROTO
op_update_cc_size_im (void)
354 env
->cc_size
= PARAM1
;
358 void OPPROTO
op_update_cc_src_T1 (void)
363 void OPPROTO
op_update_cc_x (void)
365 env
->cc_x_live
= PARAM1
;
370 /* FIXME: is this allowed? */
371 extern inline void evaluate_flags_writeback(uint32_t flags
)
375 /* Extended arithmetics, leave the z flag alone. */
376 env
->debug3
= env
->pregs
[SR_CCS
];
381 x
= env
->pregs
[SR_CCS
] & X_FLAG
;
383 if ((x
|| env
->cc_op
== CC_OP_ADDC
)
385 env
->cc_mask
&= ~Z_FLAG
;
387 /* all insn clear the x-flag except setf or clrf. */
388 env
->pregs
[SR_CCS
] &= ~(env
->cc_mask
| X_FLAG
);
389 flags
&= env
->cc_mask
;
390 env
->pregs
[SR_CCS
] |= flags
;
394 void OPPROTO
op_evaluate_flags_muls(void)
400 /* were gonna have to redo the muls. */
407 res
= env
->cc_result
;
410 /* cast into signed values to make GCC sign extend. */
413 dneg
= ((int32_t)res
) < 0;
421 if ((dneg
&& mof
!= -1)
422 || (!dneg
&& mof
!= 0))
424 evaluate_flags_writeback(flags
);
428 void OPPROTO
op_evaluate_flags_mulu(void)
434 /* were gonna have to redo the muls. */
435 uint64_t tmp
, t0
,t1
;
440 res
= env
->cc_result
;
443 /* cast into signed values to make GCC sign extend. */
456 evaluate_flags_writeback(flags
);
460 void OPPROTO
op_evaluate_flags_mcp(void)
469 res
= env
->cc_result
;
471 if ((res
& 0x80000000L
) != 0L)
474 if (((src
& 0x80000000L
) == 0L)
475 && ((dst
& 0x80000000L
) == 0L))
479 else if (((src
& 0x80000000L
) != 0L) &&
480 ((dst
& 0x80000000L
) != 0L))
489 if (((src
& 0x80000000L
) != 0L)
490 && ((dst
& 0x80000000L
) != 0L))
492 if ((dst
& 0x80000000L
) != 0L
493 || (src
& 0x80000000L
) != 0L)
497 evaluate_flags_writeback(flags
);
501 void OPPROTO
op_evaluate_flags_alu_4(void)
510 res
= env
->cc_result
;
512 if ((res
& 0x80000000L
) != 0L)
515 if (((src
& 0x80000000L
) == 0L)
516 && ((dst
& 0x80000000L
) == 0L))
520 else if (((src
& 0x80000000L
) != 0L) &&
521 ((dst
& 0x80000000L
) != 0L))
530 if (((src
& 0x80000000L
) != 0L)
531 && ((dst
& 0x80000000L
) != 0L))
533 if ((dst
& 0x80000000L
) != 0L
534 || (src
& 0x80000000L
) != 0L)
538 if (env
->cc_op
== CC_OP_SUB
539 || env
->cc_op
== CC_OP_CMP
) {
542 evaluate_flags_writeback(flags
);
546 void OPPROTO
op_evaluate_flags_move_4 (void)
553 res
= env
->cc_result
;
555 if ((int32_t)res
< 0)
560 evaluate_flags_writeback(flags
);
563 void OPPROTO
op_evaluate_flags_move_2 (void)
570 res
= env
->cc_result
;
572 if ((int16_t)res
< 0L)
577 evaluate_flags_writeback(flags
);
581 /* TODO: This is expensive. We could split things up and only evaluate part of
582 CCR on a need to know basis. For now, we simply re-evaluate everything. */
583 void OPPROTO
op_evaluate_flags (void)
592 res
= env
->cc_result
;
595 /* Now, evaluate the flags. This stuff is based on
596 Per Zander's CRISv10 simulator. */
597 switch (env
->cc_size
)
600 if ((res
& 0x80L
) != 0L)
603 if (((src
& 0x80L
) == 0L)
604 && ((dst
& 0x80L
) == 0L))
608 else if (((src
& 0x80L
) != 0L)
609 && ((dst
& 0x80L
) != 0L))
616 if ((res
& 0xFFL
) == 0L)
620 if (((src
& 0x80L
) != 0L)
621 && ((dst
& 0x80L
) != 0L))
625 if ((dst
& 0x80L
) != 0L
626 || (src
& 0x80L
) != 0L)
633 if ((res
& 0x8000L
) != 0L)
636 if (((src
& 0x8000L
) == 0L)
637 && ((dst
& 0x8000L
) == 0L))
641 else if (((src
& 0x8000L
) != 0L)
642 && ((dst
& 0x8000L
) != 0L))
649 if ((res
& 0xFFFFL
) == 0L)
653 if (((src
& 0x8000L
) != 0L)
654 && ((dst
& 0x8000L
) != 0L))
658 if ((dst
& 0x8000L
) != 0L
659 || (src
& 0x8000L
) != 0L)
666 if ((res
& 0x80000000L
) != 0L)
669 if (((src
& 0x80000000L
) == 0L)
670 && ((dst
& 0x80000000L
) == 0L))
674 else if (((src
& 0x80000000L
) != 0L) &&
675 ((dst
& 0x80000000L
) != 0L))
684 if (((src
& 0x80000000L
) != 0L)
685 && ((dst
& 0x80000000L
) != 0L))
687 if ((dst
& 0x80000000L
) != 0L
688 || (src
& 0x80000000L
) != 0L)
696 if (env
->cc_op
== CC_OP_SUB
697 || env
->cc_op
== CC_OP_CMP
) {
700 evaluate_flags_writeback(flags
);
704 void OPPROTO
op_extb_T0_T0 (void)
709 void OPPROTO
op_extb_T1_T0 (void)
714 void OPPROTO
op_extb_T1_T1 (void)
719 void OPPROTO
op_zextb_T0_T0 (void)
724 void OPPROTO
op_zextb_T1_T0 (void)
729 void OPPROTO
op_zextb_T1_T1 (void)
734 void OPPROTO
op_extw_T0_T0 (void)
739 void OPPROTO
op_extw_T1_T0 (void)
744 void OPPROTO
op_extw_T1_T1 (void)
750 void OPPROTO
op_zextw_T0_T0 (void)
755 void OPPROTO
op_zextw_T1_T0 (void)
761 void OPPROTO
op_zextw_T1_T1 (void)
767 void OPPROTO
op_movl_T0_im (void)
772 void OPPROTO
op_movl_T1_im (void)
778 void OPPROTO
op_addl_T0_im (void)
784 void OPPROTO
op_addl_T1_im (void)
790 void OPPROTO
op_subl_T0_im (void)
796 void OPPROTO
op_addxl_T0_C (void)
798 if (env
->pregs
[SR_CCS
] & X_FLAG
)
799 T0
+= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
802 void OPPROTO
op_subxl_T0_C (void)
804 if (env
->pregs
[SR_CCS
] & X_FLAG
)
805 T0
-= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
808 void OPPROTO
op_addl_T0_C (void)
810 T0
+= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
813 void OPPROTO
op_addl_T0_R (void)
815 T0
+= !!(env
->pregs
[SR_CCS
] & R_FLAG
);
819 void OPPROTO
op_clr_R (void)
821 env
->pregs
[SR_CCS
] &= ~R_FLAG
;
826 void OPPROTO
op_andl_T0_im (void)
832 void OPPROTO
op_andl_T1_im (void)
838 void OPPROTO
op_movl_T0_T1 (void)
844 void OPPROTO
op_swp_T0_T1 (void)
852 void OPPROTO
op_movl_T1_T0 (void)
858 void OPPROTO
op_movl_pc_T0 (void)
864 void OPPROTO
op_movl_T0_0 (void)
870 void OPPROTO
op_addl_T0_T1 (void)
876 void OPPROTO
op_subl_T0_T1 (void)
882 void OPPROTO
op_absl_T1_T1 (void)
886 T1
= st
< 0 ? -st
: st
;
890 void OPPROTO
op_muls_T0_T1 (void)
894 /* cast into signed values to make GCC sign extend these babies. */
899 T0
= tmp
& 0xffffffff;
900 env
->pregs
[REG_MOF
] = tmp
>> 32;
904 void OPPROTO
op_mulu_T0_T1 (void)
906 uint64_t tmp
, t0
,t1
;
911 T0
= tmp
& 0xffffffff;
912 env
->pregs
[REG_MOF
] = tmp
>> 32;
916 void OPPROTO
op_dstep_T0_T1 (void)
924 void OPPROTO
op_orl_T0_T1 (void)
930 void OPPROTO
op_andl_T0_T1 (void)
936 void OPPROTO
op_xorl_T0_T1 (void)
942 void OPPROTO
op_lsll_T0_T1 (void)
952 void OPPROTO
op_lsll_T0_im (void)
958 void OPPROTO
op_lsrl_T0_T1 (void)
968 /* Rely on GCC emitting an arithmetic shift for signed right shifts. */
969 void OPPROTO
op_asrl_T0_T1 (void)
973 T0
= T0
& 0x80000000 ? -1 : 0;
975 T0
= (int32_t)T0
>> s
;
979 void OPPROTO
op_btst_T0_T1 (void)
981 /* FIXME: clean this up. */
984 The N flag is set according to the selected bit in the dest reg.
985 The Z flag is set if the selected bit and all bits to the right are
987 The destination reg is not affected.*/
988 unsigned int fz
, sbit
, bset
, mask
, masked_t0
;
991 bset
= !!(T0
& (1 << sbit
));
992 mask
= sbit
== 31 ? -1 : (1 << (sbit
+ 1)) - 1;
993 masked_t0
= T0
& mask
;
994 fz
= !(masked_t0
| bset
);
995 /* Set the N and Z flags accordingly. */
996 T0
= (bset
<< 3) | (fz
<< 2);
1000 void OPPROTO
op_bound_T0_T1 (void)
1007 void OPPROTO
op_lz_T0_T1 (void)
1013 void OPPROTO
op_negl_T0_T1 (void)
1019 void OPPROTO
op_negl_T1_T1 (void)
1025 void OPPROTO
op_not_T0_T0 (void)
1030 void OPPROTO
op_not_T1_T1 (void)
1036 void OPPROTO
op_swapw_T0_T0 (void)
1038 T0
= (T0
<< 16) | ((T0
>> 16));
1042 void OPPROTO
op_swapb_T0_T0 (void)
1044 T0
= ((T0
<< 8) & 0xff00ff00) | ((T0
>> 8) & 0x00ff00ff);
1048 void OPPROTO
op_swapr_T0_T0 (void)
1050 T0
= (((T0
<< 7) & 0x80808080) |
1051 ((T0
<< 5) & 0x40404040) |
1052 ((T0
<< 3) & 0x20202020) |
1053 ((T0
<< 1) & 0x10101010) |
1054 ((T0
>> 1) & 0x08080808) |
1055 ((T0
>> 3) & 0x04040404) |
1056 ((T0
>> 5) & 0x02020202) |
1057 ((T0
>> 7) & 0x01010101));
1061 void OPPROTO
op_tst_cc_eq (void) {
1062 uint32_t flags
= env
->pregs
[SR_CCS
];
1065 z_set
= !!(flags
& Z_FLAG
);
1070 void OPPROTO
op_tst_cc_eq_fast (void) {
1071 T0
= !(env
->cc_result
);
1075 void OPPROTO
op_tst_cc_ne (void) {
1076 uint32_t flags
= env
->pregs
[SR_CCS
];
1079 z_set
= !!(flags
& Z_FLAG
);
1083 void OPPROTO
op_tst_cc_ne_fast (void) {
1084 T0
= !!(env
->cc_result
);
1088 void OPPROTO
op_tst_cc_cc (void) {
1089 uint32_t flags
= env
->pregs
[SR_CCS
];
1092 c_set
= !!(flags
& C_FLAG
);
1096 void OPPROTO
op_tst_cc_cs (void) {
1097 uint32_t flags
= env
->pregs
[SR_CCS
];
1100 c_set
= !!(flags
& C_FLAG
);
1105 void OPPROTO
op_tst_cc_vc (void) {
1106 uint32_t flags
= env
->pregs
[SR_CCS
];
1109 v_set
= !!(flags
& V_FLAG
);
1113 void OPPROTO
op_tst_cc_vs (void) {
1114 uint32_t flags
= env
->pregs
[SR_CCS
];
1117 v_set
= !!(flags
& V_FLAG
);
1121 void OPPROTO
op_tst_cc_pl (void) {
1122 uint32_t flags
= env
->pregs
[SR_CCS
];
1125 n_set
= !!(flags
& N_FLAG
);
1129 void OPPROTO
op_tst_cc_pl_fast (void) {
1130 T0
= ((int32_t)env
->cc_result
) >= 0;
1134 void OPPROTO
op_tst_cc_mi (void) {
1135 uint32_t flags
= env
->pregs
[SR_CCS
];
1138 n_set
= !!(flags
& N_FLAG
);
1142 void OPPROTO
op_tst_cc_mi_fast (void) {
1143 T0
= ((int32_t)env
->cc_result
) < 0;
1147 void OPPROTO
op_tst_cc_ls (void) {
1148 uint32_t flags
= env
->pregs
[SR_CCS
];
1152 c_set
= !!(flags
& C_FLAG
);
1153 z_set
= !!(flags
& Z_FLAG
);
1154 T0
= c_set
|| z_set
;
1157 void OPPROTO
op_tst_cc_hi (void) {
1158 uint32_t flags
= env
->pregs
[SR_CCS
];
1162 z_set
= !!(flags
& Z_FLAG
);
1163 c_set
= !!(flags
& C_FLAG
);
1164 T0
= !c_set
&& !z_set
;
1169 void OPPROTO
op_tst_cc_ge (void) {
1170 uint32_t flags
= env
->pregs
[SR_CCS
];
1174 n_set
= !!(flags
& N_FLAG
);
1175 v_set
= !!(flags
& V_FLAG
);
1176 T0
= (n_set
&& v_set
) || (!n_set
&& !v_set
);
1180 void OPPROTO
op_tst_cc_ge_fast (void) {
1181 T0
= ((int32_t)env
->cc_src
< (int32_t)env
->cc_dest
);
1185 void OPPROTO
op_tst_cc_lt (void) {
1186 uint32_t flags
= env
->pregs
[SR_CCS
];
1190 n_set
= !!(flags
& N_FLAG
);
1191 v_set
= !!(flags
& V_FLAG
);
1192 T0
= (n_set
&& !v_set
) || (!n_set
&& v_set
);
1196 void OPPROTO
op_tst_cc_gt (void) {
1197 uint32_t flags
= env
->pregs
[SR_CCS
];
1202 n_set
= !!(flags
& N_FLAG
);
1203 v_set
= !!(flags
& V_FLAG
);
1204 z_set
= !!(flags
& Z_FLAG
);
1205 T0
= (n_set
&& v_set
&& !z_set
)
1206 || (!n_set
&& !v_set
&& !z_set
);
1210 void OPPROTO
op_tst_cc_le (void) {
1211 uint32_t flags
= env
->pregs
[SR_CCS
];
1216 n_set
= !!(flags
& N_FLAG
);
1217 v_set
= !!(flags
& V_FLAG
);
1218 z_set
= !!(flags
& Z_FLAG
);
1219 T0
= z_set
|| (n_set
&& !v_set
) || (!n_set
&& v_set
);
1223 void OPPROTO
op_tst_cc_p (void) {
1224 uint32_t flags
= env
->pregs
[SR_CCS
];
1227 p_set
= !!(flags
& P_FLAG
);
1232 /* Evaluate the if the branch should be taken or not. Needs to be done in
1233 the original sequence. The acutal branch is rescheduled to right after the
1235 void OPPROTO
op_evaluate_bcc (void)
1241 /* this one is used on every alu op, optimize it!. */
1242 void OPPROTO
op_goto_if_not_x (void)
1244 if (env
->pregs
[SR_CCS
] & X_FLAG
)
1245 GOTO_LABEL_PARAM(1);
1249 void OPPROTO
op_cc_jmp (void)
1258 void OPPROTO
op_cc_ngoto (void)
1261 GOTO_LABEL_PARAM(1);
1265 void OPPROTO
op_movl_btarget_T0 (void)
1271 void OPPROTO
op_jmp (void)
1273 env
->pc
= env
->btarget
;
1277 /* Load and store */
1278 #define MEMSUFFIX _raw
1281 #if !defined(CONFIG_USER_ONLY)
1282 #define MEMSUFFIX _user
1286 #define MEMSUFFIX _kernel