]>
git.proxmox.com Git - qemu.git/blob - target-cris/op.c
3ce9888bc07e2d2b590191427f9313fbb40c855c
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
23 #define REG (env->regs[0])
24 #include "op_template.h"
27 #define REG (env->regs[1])
28 #include "op_template.h"
31 #define REG (env->regs[2])
32 #include "op_template.h"
35 #define REG (env->regs[3])
36 #include "op_template.h"
39 #define REG (env->regs[4])
40 #include "op_template.h"
43 #define REG (env->regs[5])
44 #include "op_template.h"
47 #define REG (env->regs[6])
48 #include "op_template.h"
51 #define REG (env->regs[7])
52 #include "op_template.h"
55 #define REG (env->regs[8])
56 #include "op_template.h"
59 #define REG (env->regs[9])
60 #include "op_template.h"
63 #define REG (env->regs[10])
64 #include "op_template.h"
67 #define REG (env->regs[11])
68 #include "op_template.h"
71 #define REG (env->regs[12])
72 #include "op_template.h"
75 #define REG (env->regs[13])
76 #include "op_template.h"
79 #define REG (env->regs[14])
80 #include "op_template.h"
83 #define REG (env->regs[15])
84 #include "op_template.h"
88 #define REG (env->pregs[0])
89 #include "op_template.h"
92 #define REG (env->pregs[1])
93 #include "op_template.h"
96 #define REG (env->pregs[2])
97 #include "op_template.h"
100 #define REG (env->pregs[3])
101 #include "op_template.h"
104 #define REG (env->pregs[4])
105 #include "op_template.h"
108 #define REG (env->pregs[5])
109 #include "op_template.h"
112 #define REG (env->pregs[6])
113 #include "op_template.h"
116 #define REG (env->pregs[7])
117 #include "op_template.h"
120 #define REG (env->pregs[8])
121 #include "op_template.h"
124 #define REG (env->pregs[9])
125 #include "op_template.h"
128 #define REG (env->pregs[10])
129 #include "op_template.h"
132 #define REG (env->pregs[11])
133 #include "op_template.h"
136 #define REG (env->pregs[12])
137 #include "op_template.h"
140 #define REG (env->pregs[13])
141 #include "op_template.h"
144 #define REG (env->pregs[14])
145 #include "op_template.h"
148 #define REG (env->pregs[15])
149 #include "op_template.h"
153 void OPPROTO
op_exit_tb (void)
158 void OPPROTO
op_goto_tb0 (void)
160 GOTO_TB(op_goto_tb0
, PARAM1
, 0);
164 void OPPROTO
op_goto_tb1 (void)
166 GOTO_TB(op_goto_tb1
, PARAM1
, 1);
170 void OPPROTO
op_break_im(void)
172 env
->trapnr
= PARAM1
;
173 env
->exception_index
= EXCP_BREAK
;
177 void OPPROTO
op_debug(void)
179 env
->exception_index
= EXCP_DEBUG
;
183 void OPPROTO
op_exec_insn(void)
185 env
->stats
.exec_insns
++;
188 void OPPROTO
op_exec_load(void)
190 env
->stats
.exec_loads
++;
193 void OPPROTO
op_exec_store(void)
195 env
->stats
.exec_stores
++;
199 void OPPROTO
op_ccs_lshift (void)
203 /* Apply the ccs shift. */
204 ccs
= env
->pregs
[SR_CCS
];
205 ccs
= (ccs
& 0xc0000000) | ((ccs
<< 12) >> 2);
206 env
->pregs
[SR_CCS
] = ccs
;
208 void OPPROTO
op_ccs_rshift (void)
212 /* Apply the ccs shift. */
213 ccs
= env
->pregs
[SR_CCS
];
214 ccs
= (ccs
& 0xc0000000) | (ccs
>> 10);
215 env
->pregs
[SR_CCS
] = ccs
;
218 void OPPROTO
op_setf (void)
220 env
->pregs
[SR_CCS
] |= PARAM1
;
224 void OPPROTO
op_clrf (void)
226 env
->pregs
[SR_CCS
] &= ~PARAM1
;
230 void OPPROTO
op_movl_debug1_T0 (void)
236 void OPPROTO
op_movl_debug2_T0 (void)
242 void OPPROTO
op_movl_debug3_T0 (void)
247 void OPPROTO
op_movl_debug1_T1 (void)
253 void OPPROTO
op_movl_debug2_T1 (void)
259 void OPPROTO
op_movl_debug3_T1 (void)
264 void OPPROTO
op_movl_debug3_im (void)
266 env
->debug3
= PARAM1
;
269 void OPPROTO
op_movl_T0_flags (void)
271 T0
= env
->pregs
[SR_CCS
];
274 void OPPROTO
op_movl_flags_T0 (void)
276 env
->pregs
[SR_CCS
] = T0
;
280 void OPPROTO
op_movl_sreg_T0 (void)
282 env
->sregs
[env
->pregs
[SR_SRS
]][PARAM1
] = T0
;
286 void OPPROTO
op_movl_tlb_lo_T0 (void)
289 srs
= env
->pregs
[SR_SRS
];
290 if (srs
== 1 || srs
== 2)
296 idx
= set
= env
->sregs
[SFR_RW_MM_TLB_SEL
];
301 /* We've just made a write to tlb_lo. */
302 lo
= env
->sregs
[SFR_RW_MM_TLB_LO
];
303 hi
= env
->sregs
[SFR_RW_MM_TLB_HI
];
304 env
->tlbsets
[srs
- 1][set
][idx
].lo
= lo
;
305 env
->tlbsets
[srs
- 1][set
][idx
].hi
= hi
;
311 void OPPROTO
op_movl_T0_sreg (void)
313 T0
= env
->sregs
[env
->pregs
[SR_SRS
]][PARAM1
];
317 void OPPROTO
op_update_cc (void)
320 env
->cc_dest
= PARAM2
;
321 env
->cc_src
= PARAM3
;
325 void OPPROTO
op_update_cc_op (void)
331 void OPPROTO
op_update_cc_mask (void)
333 env
->cc_mask
= PARAM1
;
337 void OPPROTO
op_update_cc_dest_T0 (void)
343 void OPPROTO
op_update_cc_result_T0 (void)
349 void OPPROTO
op_update_cc_size_im (void)
351 env
->cc_size
= PARAM1
;
355 void OPPROTO
op_update_cc_src_T1 (void)
360 void OPPROTO
op_update_cc_x (void)
362 env
->cc_x_live
= PARAM1
;
367 /* FIXME: is this allowed? */
368 extern inline void evaluate_flags_writeback(uint32_t flags
)
372 /* Extended arithmetics, leave the z flag alone. */
373 env
->debug3
= env
->pregs
[SR_CCS
];
378 x
= env
->pregs
[SR_CCS
] & X_FLAG
;
380 if ((x
|| env
->cc_op
== CC_OP_ADDC
)
382 env
->cc_mask
&= ~Z_FLAG
;
384 /* all insn clear the x-flag except setf or clrf. */
385 env
->pregs
[SR_CCS
] &= ~(env
->cc_mask
| X_FLAG
);
386 flags
&= env
->cc_mask
;
387 env
->pregs
[SR_CCS
] |= flags
;
391 void OPPROTO
op_evaluate_flags_muls(void)
397 /* were gonna have to redo the muls. */
404 res
= env
->cc_result
;
407 /* cast into signed values to make GCC sign extend. */
410 dneg
= ((int32_t)res
) < 0;
418 if ((dneg
&& mof
!= -1)
419 || (!dneg
&& mof
!= 0))
421 evaluate_flags_writeback(flags
);
425 void OPPROTO
op_evaluate_flags_mulu(void)
431 /* were gonna have to redo the muls. */
432 uint64_t tmp
, t0
,t1
;
437 res
= env
->cc_result
;
440 /* cast into signed values to make GCC sign extend. */
453 evaluate_flags_writeback(flags
);
457 void OPPROTO
op_evaluate_flags_mcp(void)
466 res
= env
->cc_result
;
468 if ((res
& 0x80000000L
) != 0L)
471 if (((src
& 0x80000000L
) == 0L)
472 && ((dst
& 0x80000000L
) == 0L))
476 else if (((src
& 0x80000000L
) != 0L) &&
477 ((dst
& 0x80000000L
) != 0L))
486 if (((src
& 0x80000000L
) != 0L)
487 && ((dst
& 0x80000000L
) != 0L))
489 if ((dst
& 0x80000000L
) != 0L
490 || (src
& 0x80000000L
) != 0L)
494 evaluate_flags_writeback(flags
);
498 void OPPROTO
op_evaluate_flags_alu_4(void)
507 res
= env
->cc_result
;
509 if ((res
& 0x80000000L
) != 0L)
512 if (((src
& 0x80000000L
) == 0L)
513 && ((dst
& 0x80000000L
) == 0L))
517 else if (((src
& 0x80000000L
) != 0L) &&
518 ((dst
& 0x80000000L
) != 0L))
527 if (((src
& 0x80000000L
) != 0L)
528 && ((dst
& 0x80000000L
) != 0L))
530 if ((dst
& 0x80000000L
) != 0L
531 || (src
& 0x80000000L
) != 0L)
535 if (env
->cc_op
== CC_OP_SUB
536 || env
->cc_op
== CC_OP_CMP
) {
539 evaluate_flags_writeback(flags
);
543 void OPPROTO
op_evaluate_flags_move_4 (void)
550 res
= env
->cc_result
;
552 if ((int32_t)res
< 0)
557 evaluate_flags_writeback(flags
);
560 void OPPROTO
op_evaluate_flags_move_2 (void)
567 res
= env
->cc_result
;
569 if ((int16_t)res
< 0L)
574 evaluate_flags_writeback(flags
);
578 /* TODO: This is expensive. We could split things up and only evaluate part of
579 CCR on a need to know basis. For now, we simply re-evaluate everything. */
580 void OPPROTO
op_evaluate_flags (void)
589 res
= env
->cc_result
;
592 /* Now, evaluate the flags. This stuff is based on
593 Per Zander's CRISv10 simulator. */
594 switch (env
->cc_size
)
597 if ((res
& 0x80L
) != 0L)
600 if (((src
& 0x80L
) == 0L)
601 && ((dst
& 0x80L
) == 0L))
605 else if (((src
& 0x80L
) != 0L)
606 && ((dst
& 0x80L
) != 0L))
613 if ((res
& 0xFFL
) == 0L)
617 if (((src
& 0x80L
) != 0L)
618 && ((dst
& 0x80L
) != 0L))
622 if ((dst
& 0x80L
) != 0L
623 || (src
& 0x80L
) != 0L)
630 if ((res
& 0x8000L
) != 0L)
633 if (((src
& 0x8000L
) == 0L)
634 && ((dst
& 0x8000L
) == 0L))
638 else if (((src
& 0x8000L
) != 0L)
639 && ((dst
& 0x8000L
) != 0L))
646 if ((res
& 0xFFFFL
) == 0L)
650 if (((src
& 0x8000L
) != 0L)
651 && ((dst
& 0x8000L
) != 0L))
655 if ((dst
& 0x8000L
) != 0L
656 || (src
& 0x8000L
) != 0L)
663 if ((res
& 0x80000000L
) != 0L)
666 if (((src
& 0x80000000L
) == 0L)
667 && ((dst
& 0x80000000L
) == 0L))
671 else if (((src
& 0x80000000L
) != 0L) &&
672 ((dst
& 0x80000000L
) != 0L))
681 if (((src
& 0x80000000L
) != 0L)
682 && ((dst
& 0x80000000L
) != 0L))
684 if ((dst
& 0x80000000L
) != 0L
685 || (src
& 0x80000000L
) != 0L)
693 if (env
->cc_op
== CC_OP_SUB
694 || env
->cc_op
== CC_OP_CMP
) {
697 evaluate_flags_writeback(flags
);
701 void OPPROTO
op_extb_T0_T0 (void)
706 void OPPROTO
op_extb_T1_T0 (void)
711 void OPPROTO
op_extb_T1_T1 (void)
716 void OPPROTO
op_zextb_T0_T0 (void)
721 void OPPROTO
op_zextb_T1_T0 (void)
726 void OPPROTO
op_zextb_T1_T1 (void)
731 void OPPROTO
op_extw_T0_T0 (void)
736 void OPPROTO
op_extw_T1_T0 (void)
741 void OPPROTO
op_extw_T1_T1 (void)
747 void OPPROTO
op_zextw_T0_T0 (void)
752 void OPPROTO
op_zextw_T1_T0 (void)
758 void OPPROTO
op_zextw_T1_T1 (void)
764 void OPPROTO
op_movl_T0_im (void)
769 void OPPROTO
op_movl_T1_im (void)
775 void OPPROTO
op_addl_T0_im (void)
781 void OPPROTO
op_addl_T1_im (void)
787 void OPPROTO
op_subl_T0_im (void)
793 void OPPROTO
op_addxl_T0_C (void)
795 if (env
->pregs
[SR_CCS
] & X_FLAG
)
796 T0
+= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
799 void OPPROTO
op_subxl_T0_C (void)
801 if (env
->pregs
[SR_CCS
] & X_FLAG
)
802 T0
-= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
805 void OPPROTO
op_addl_T0_C (void)
807 T0
+= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
810 void OPPROTO
op_addl_T0_R (void)
812 T0
+= !!(env
->pregs
[SR_CCS
] & R_FLAG
);
816 void OPPROTO
op_clr_R (void)
818 env
->pregs
[SR_CCS
] &= ~R_FLAG
;
823 void OPPROTO
op_andl_T0_im (void)
829 void OPPROTO
op_andl_T1_im (void)
835 void OPPROTO
op_movl_T0_T1 (void)
841 void OPPROTO
op_swp_T0_T1 (void)
849 void OPPROTO
op_movl_T1_T0 (void)
855 void OPPROTO
op_movl_pc_T0 (void)
861 void OPPROTO
op_movl_T0_0 (void)
867 void OPPROTO
op_addl_T0_T1 (void)
873 void OPPROTO
op_subl_T0_T1 (void)
879 void OPPROTO
op_absl_T1_T1 (void)
883 T1
= st
< 0 ? -st
: st
;
887 void OPPROTO
op_muls_T0_T1 (void)
891 /* cast into signed values to make GCC sign extend these babies. */
896 T0
= tmp
& 0xffffffff;
897 env
->pregs
[REG_MOF
] = tmp
>> 32;
901 void OPPROTO
op_mulu_T0_T1 (void)
903 uint64_t tmp
, t0
,t1
;
908 T0
= tmp
& 0xffffffff;
909 env
->pregs
[REG_MOF
] = tmp
>> 32;
913 void OPPROTO
op_dstep_T0_T1 (void)
921 void OPPROTO
op_orl_T0_T1 (void)
927 void OPPROTO
op_andl_T0_T1 (void)
933 void OPPROTO
op_xorl_T0_T1 (void)
939 void OPPROTO
op_lsll_T0_T1 (void)
949 void OPPROTO
op_lsll_T0_im (void)
955 void OPPROTO
op_lsrl_T0_T1 (void)
965 /* Rely on GCC emitting an arithmetic shift for signed right shifts. */
966 void OPPROTO
op_asrl_T0_T1 (void)
970 T0
= T0
& 0x80000000 ? -1 : 0;
972 T0
= (int32_t)T0
>> s
;
976 void OPPROTO
op_btst_T0_T1 (void)
978 /* FIXME: clean this up. */
981 The N flag is set according to the selected bit in the dest reg.
982 The Z flag is set if the selected bit and all bits to the right are
984 The destination reg is not affected.*/
985 unsigned int fz
, sbit
, bset
, mask
, masked_t0
;
988 bset
= !!(T0
& (1 << sbit
));
989 mask
= sbit
== 31 ? -1 : (1 << (sbit
+ 1)) - 1;
990 masked_t0
= T0
& mask
;
991 fz
= !(masked_t0
| bset
);
992 /* Set the N and Z flags accordingly. */
993 T0
= (bset
<< 3) | (fz
<< 2);
997 void OPPROTO
op_bound_T0_T1 (void)
1004 void OPPROTO
op_lz_T0_T1 (void)
1009 T0
= __builtin_clz(T1
);
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