]>
git.proxmox.com Git - mirror_qemu.git/blob - target-cris/op.c
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
[SR_CCS
];
189 ccs
= (ccs
& 0xc0000000) | ((ccs
<< 12) >> 2);
190 env
->pregs
[SR_CCS
] = ccs
;
193 void OPPROTO
op_ccs_rshift (void)
197 /* Apply the ccs shift. */
198 ccs
= env
->pregs
[SR_CCS
];
199 ccs
= (ccs
& 0xc0000000) | (ccs
>> 10);
200 env
->pregs
[SR_CCS
] = ccs
;
204 void OPPROTO
op_setf (void)
206 env
->pregs
[SR_CCS
] |= PARAM1
;
210 void OPPROTO
op_clrf (void)
212 env
->pregs
[SR_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
[SR_CCS
];
260 void OPPROTO
op_movl_flags_T0 (void)
262 env
->pregs
[SR_CCS
] = T0
;
266 void OPPROTO
op_movl_sreg_T0 (void)
268 env
->sregs
[env
->pregs
[SR_SRS
]][PARAM1
] = T0
;
272 void OPPROTO
op_movl_tlb_lo_T0 (void)
275 srs
= env
->pregs
[SR_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
[SR_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
[SR_CCS
];
364 x
= env
->pregs
[SR_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
[SR_CCS
] &= ~(env
->cc_mask
| X_FLAG
);
372 flags
&= env
->cc_mask
;
373 env
->pregs
[SR_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
[SR_CCS
] & X_FLAG
)
782 T0
+= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
785 void OPPROTO
op_subxl_T0_C (void)
787 if (env
->pregs
[SR_CCS
] & X_FLAG
)
788 T0
-= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
791 void OPPROTO
op_addl_T0_C (void)
793 T0
+= !!(env
->pregs
[SR_CCS
] & C_FLAG
);
796 void OPPROTO
op_addl_T0_R (void)
798 T0
+= !!(env
->pregs
[SR_CCS
] & R_FLAG
);
802 void OPPROTO
op_clr_R (void)
804 env
->pregs
[SR_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
[REG_MOF
] = tmp
>> 32;
887 void OPPROTO
op_mulu_T0_T1 (void)
889 uint64_t tmp
, t0
,t1
;
894 T0
= tmp
& 0xffffffff;
895 env
->pregs
[REG_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 destination reg is not affected.*/
971 unsigned int fz
, sbit
, bset
, mask
, masked_t0
;
974 bset
= !!(T0
& (1 << sbit
));
975 mask
= sbit
== 31 ? -1 : (1 << (sbit
+ 1)) - 1;
976 masked_t0
= T0
& mask
;
977 fz
= !(masked_t0
| bset
);
978 /* Set the N and Z flags accordingly. */
979 T0
= (bset
<< 3) | (fz
<< 2);
983 void OPPROTO
op_bound_T0_T1 (void)
990 void OPPROTO
op_lz_T0_T1 (void)
996 void OPPROTO
op_negl_T0_T1 (void)
1002 void OPPROTO
op_negl_T1_T1 (void)
1008 void OPPROTO
op_not_T0_T0 (void)
1013 void OPPROTO
op_not_T1_T1 (void)
1019 void OPPROTO
op_swapw_T0_T0 (void)
1021 T0
= (T0
<< 16) | ((T0
>> 16));
1025 void OPPROTO
op_swapb_T0_T0 (void)
1027 T0
= ((T0
<< 8) & 0xff00ff00) | ((T0
>> 8) & 0x00ff00ff);
1031 void OPPROTO
op_swapr_T0_T0 (void)
1033 T0
= (((T0
<< 7) & 0x80808080) |
1034 ((T0
<< 5) & 0x40404040) |
1035 ((T0
<< 3) & 0x20202020) |
1036 ((T0
<< 1) & 0x10101010) |
1037 ((T0
>> 1) & 0x08080808) |
1038 ((T0
>> 3) & 0x04040404) |
1039 ((T0
>> 5) & 0x02020202) |
1040 ((T0
>> 7) & 0x01010101));
1044 void OPPROTO
op_tst_cc_eq (void) {
1045 uint32_t flags
= env
->pregs
[SR_CCS
];
1048 z_set
= !!(flags
& Z_FLAG
);
1053 void OPPROTO
op_tst_cc_eq_fast (void) {
1054 T0
= !(env
->cc_result
);
1058 void OPPROTO
op_tst_cc_ne (void) {
1059 uint32_t flags
= env
->pregs
[SR_CCS
];
1062 z_set
= !!(flags
& Z_FLAG
);
1066 void OPPROTO
op_tst_cc_ne_fast (void) {
1067 T0
= !!(env
->cc_result
);
1071 void OPPROTO
op_tst_cc_cc (void) {
1072 uint32_t flags
= env
->pregs
[SR_CCS
];
1075 c_set
= !!(flags
& C_FLAG
);
1079 void OPPROTO
op_tst_cc_cs (void) {
1080 uint32_t flags
= env
->pregs
[SR_CCS
];
1083 c_set
= !!(flags
& C_FLAG
);
1088 void OPPROTO
op_tst_cc_vc (void) {
1089 uint32_t flags
= env
->pregs
[SR_CCS
];
1092 v_set
= !!(flags
& V_FLAG
);
1096 void OPPROTO
op_tst_cc_vs (void) {
1097 uint32_t flags
= env
->pregs
[SR_CCS
];
1100 v_set
= !!(flags
& V_FLAG
);
1104 void OPPROTO
op_tst_cc_pl (void) {
1105 uint32_t flags
= env
->pregs
[SR_CCS
];
1108 n_set
= !!(flags
& N_FLAG
);
1112 void OPPROTO
op_tst_cc_pl_fast (void) {
1113 T0
= ((int32_t)env
->cc_result
) >= 0;
1117 void OPPROTO
op_tst_cc_mi (void) {
1118 uint32_t flags
= env
->pregs
[SR_CCS
];
1121 n_set
= !!(flags
& N_FLAG
);
1125 void OPPROTO
op_tst_cc_mi_fast (void) {
1126 T0
= ((int32_t)env
->cc_result
) < 0;
1130 void OPPROTO
op_tst_cc_ls (void) {
1131 uint32_t flags
= env
->pregs
[SR_CCS
];
1135 c_set
= !!(flags
& C_FLAG
);
1136 z_set
= !!(flags
& Z_FLAG
);
1137 T0
= c_set
|| z_set
;
1140 void OPPROTO
op_tst_cc_hi (void) {
1141 uint32_t flags
= env
->pregs
[SR_CCS
];
1145 z_set
= !!(flags
& Z_FLAG
);
1146 c_set
= !!(flags
& C_FLAG
);
1147 T0
= !c_set
&& !z_set
;
1152 void OPPROTO
op_tst_cc_ge (void) {
1153 uint32_t flags
= env
->pregs
[SR_CCS
];
1157 n_set
= !!(flags
& N_FLAG
);
1158 v_set
= !!(flags
& V_FLAG
);
1159 T0
= (n_set
&& v_set
) || (!n_set
&& !v_set
);
1163 void OPPROTO
op_tst_cc_ge_fast (void) {
1164 T0
= ((int32_t)env
->cc_src
< (int32_t)env
->cc_dest
);
1168 void OPPROTO
op_tst_cc_lt (void) {
1169 uint32_t flags
= env
->pregs
[SR_CCS
];
1173 n_set
= !!(flags
& N_FLAG
);
1174 v_set
= !!(flags
& V_FLAG
);
1175 T0
= (n_set
&& !v_set
) || (!n_set
&& v_set
);
1179 void OPPROTO
op_tst_cc_gt (void) {
1180 uint32_t flags
= env
->pregs
[SR_CCS
];
1185 n_set
= !!(flags
& N_FLAG
);
1186 v_set
= !!(flags
& V_FLAG
);
1187 z_set
= !!(flags
& Z_FLAG
);
1188 T0
= (n_set
&& v_set
&& !z_set
)
1189 || (!n_set
&& !v_set
&& !z_set
);
1193 void OPPROTO
op_tst_cc_le (void) {
1194 uint32_t flags
= env
->pregs
[SR_CCS
];
1199 n_set
= !!(flags
& N_FLAG
);
1200 v_set
= !!(flags
& V_FLAG
);
1201 z_set
= !!(flags
& Z_FLAG
);
1202 T0
= z_set
|| (n_set
&& !v_set
) || (!n_set
&& v_set
);
1206 void OPPROTO
op_tst_cc_p (void) {
1207 uint32_t flags
= env
->pregs
[SR_CCS
];
1210 p_set
= !!(flags
& P_FLAG
);
1215 /* Evaluate the if the branch should be taken or not. Needs to be done in
1216 the original sequence. The acutal branch is rescheduled to right after the
1218 void OPPROTO
op_evaluate_bcc (void)
1224 /* this one is used on every alu op, optimize it!. */
1225 void OPPROTO
op_goto_if_not_x (void)
1227 if (env
->pregs
[SR_CCS
] & X_FLAG
)
1228 GOTO_LABEL_PARAM(1);
1232 void OPPROTO
op_cc_jmp (void)
1241 void OPPROTO
op_cc_ngoto (void)
1244 GOTO_LABEL_PARAM(1);
1248 void OPPROTO
op_movl_btarget_T0 (void)
1254 void OPPROTO
op_jmp1 (void)
1256 env
->pc
= env
->btarget
;
1260 /* Load and store */
1261 #define MEMSUFFIX _raw
1264 #if !defined(CONFIG_USER_ONLY)
1265 #define MEMSUFFIX _user
1269 #define MEMSUFFIX _kernel