CFI: Fix AMD erase support
[qemu/malc.git] / target-cris / op.c
blobd44185c4d4568460c390a308db9c45ad6ac40d52
1 /*
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
20 #include "exec.h"
21 #include "host-utils.h"
23 #define REGNAME r0
24 #define REG (env->regs[0])
25 #include "op_template.h"
27 #define REGNAME r1
28 #define REG (env->regs[1])
29 #include "op_template.h"
31 #define REGNAME r2
32 #define REG (env->regs[2])
33 #include "op_template.h"
35 #define REGNAME r3
36 #define REG (env->regs[3])
37 #include "op_template.h"
39 #define REGNAME r4
40 #define REG (env->regs[4])
41 #include "op_template.h"
43 #define REGNAME r5
44 #define REG (env->regs[5])
45 #include "op_template.h"
47 #define REGNAME r6
48 #define REG (env->regs[6])
49 #include "op_template.h"
51 #define REGNAME r7
52 #define REG (env->regs[7])
53 #include "op_template.h"
55 #define REGNAME r8
56 #define REG (env->regs[8])
57 #include "op_template.h"
59 #define REGNAME r9
60 #define REG (env->regs[9])
61 #include "op_template.h"
63 #define REGNAME r10
64 #define REG (env->regs[10])
65 #include "op_template.h"
67 #define REGNAME r11
68 #define REG (env->regs[11])
69 #include "op_template.h"
71 #define REGNAME r12
72 #define REG (env->regs[12])
73 #include "op_template.h"
75 #define REGNAME r13
76 #define REG (env->regs[13])
77 #include "op_template.h"
79 #define REGNAME r14
80 #define REG (env->regs[14])
81 #include "op_template.h"
83 #define REGNAME r15
84 #define REG (env->regs[15])
85 #include "op_template.h"
88 #define REGNAME p0
89 #define REG (env->pregs[0])
90 #include "op_template.h"
92 #define REGNAME p1
93 #define REG (env->pregs[1])
94 #include "op_template.h"
96 #define REGNAME p2
97 #define REG (env->pregs[2])
98 #include "op_template.h"
100 #define REGNAME p3
101 #define REG (env->pregs[3])
102 #include "op_template.h"
104 #define REGNAME p4
105 #define REG (env->pregs[4])
106 #include "op_template.h"
108 #define REGNAME p5
109 #define REG (env->pregs[5])
110 #include "op_template.h"
112 #define REGNAME p6
113 #define REG (env->pregs[6])
114 #include "op_template.h"
116 #define REGNAME p7
117 #define REG (env->pregs[7])
118 #include "op_template.h"
120 #define REGNAME p8
121 #define REG (env->pregs[8])
122 #include "op_template.h"
124 #define REGNAME p9
125 #define REG (env->pregs[9])
126 #include "op_template.h"
128 #define REGNAME p10
129 #define REG (env->pregs[10])
130 #include "op_template.h"
132 #define REGNAME p11
133 #define REG (env->pregs[11])
134 #include "op_template.h"
136 #define REGNAME p12
137 #define REG (env->pregs[12])
138 #include "op_template.h"
140 #define REGNAME p13
141 #define REG (env->pregs[13])
142 #include "op_template.h"
144 #define REGNAME p14
145 #define REG (env->pregs[14])
146 #include "op_template.h"
148 #define REGNAME p15
149 #define REG (env->pregs[15])
150 #include "op_template.h"
152 /* Microcode. */
154 void OPPROTO op_break_im(void)
156 env->trap_vector = PARAM1;
157 env->exception_index = EXCP_BREAK;
158 cpu_loop_exit();
161 void OPPROTO op_debug(void)
163 env->exception_index = EXCP_DEBUG;
164 cpu_loop_exit();
167 void OPPROTO op_exec_insn(void)
169 env->stats.exec_insns++;
170 RETURN();
172 void OPPROTO op_exec_load(void)
174 env->stats.exec_loads++;
175 RETURN();
177 void OPPROTO op_exec_store(void)
179 env->stats.exec_stores++;
180 RETURN();
183 void OPPROTO op_ccs_lshift (void)
185 uint32_t ccs;
187 /* Apply the ccs shift. */
188 ccs = env->pregs[PR_CCS];
189 ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2);
190 env->pregs[PR_CCS] = ccs;
191 RETURN();
193 void OPPROTO op_ccs_rshift (void)
195 uint32_t ccs;
197 /* Apply the ccs shift. */
198 ccs = env->pregs[PR_CCS];
199 ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10);
200 env->pregs[PR_CCS] = ccs;
201 RETURN();
204 void OPPROTO op_setf (void)
206 env->pregs[PR_CCS] |= PARAM1;
207 RETURN();
210 void OPPROTO op_clrf (void)
212 env->pregs[PR_CCS] &= ~PARAM1;
213 RETURN();
216 void OPPROTO op_movl_debug1_T0 (void)
218 env->debug1 = T0;
219 RETURN();
222 void OPPROTO op_movl_debug2_T0 (void)
224 env->debug2 = T0;
225 RETURN();
228 void OPPROTO op_movl_debug3_T0 (void)
230 env->debug3 = T0;
231 RETURN();
233 void OPPROTO op_movl_debug1_T1 (void)
235 env->debug1 = T1;
236 RETURN();
239 void OPPROTO op_movl_debug2_T1 (void)
241 env->debug2 = T1;
242 RETURN();
245 void OPPROTO op_movl_debug3_T1 (void)
247 env->debug3 = T1;
248 RETURN();
250 void OPPROTO op_movl_debug3_im (void)
252 env->debug3 = PARAM1;
253 RETURN();
255 void OPPROTO op_movl_T0_flags (void)
257 T0 = env->pregs[PR_CCS];
258 RETURN();
260 void OPPROTO op_movl_flags_T0 (void)
262 env->pregs[PR_CCS] = T0;
263 RETURN();
266 void OPPROTO op_movl_sreg_T0 (void)
268 env->sregs[env->pregs[PR_SRS]][PARAM1] = T0;
269 RETURN();
272 void OPPROTO op_movl_tlb_hi_T0 (void)
274 uint32_t srs;
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;
282 RETURN();
285 void OPPROTO op_movl_tlb_lo_T0 (void)
287 uint32_t srs;
288 srs = env->pregs[PR_SRS];
289 if (srs == 1 || srs == 2)
291 uint32_t set;
292 uint32_t idx;
293 uint32_t lo, hi;
295 idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
296 set >>= 4;
297 set &= 3;
299 idx &= 15;
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;
307 RETURN();
310 void OPPROTO op_movl_T0_sreg (void)
312 T0 = env->sregs[env->pregs[PR_SRS]][PARAM1];
313 RETURN();
316 void OPPROTO op_update_cc (void)
318 env->cc_op = PARAM1;
319 env->cc_dest = PARAM2;
320 env->cc_src = PARAM3;
321 RETURN();
324 void OPPROTO op_update_cc_op (void)
326 env->cc_op = PARAM1;
327 RETURN();
330 void OPPROTO op_update_cc_mask (void)
332 env->cc_mask = PARAM1;
333 RETURN();
336 void OPPROTO op_update_cc_dest_T0 (void)
338 env->cc_dest = T0;
339 RETURN();
342 void OPPROTO op_update_cc_result_T0 (void)
344 env->cc_result = T0;
345 RETURN();
348 void OPPROTO op_update_cc_size_im (void)
350 env->cc_size = PARAM1;
351 RETURN();
354 void OPPROTO op_update_cc_src_T1 (void)
356 env->cc_src = T1;
357 RETURN();
359 void OPPROTO op_update_cc_x (void)
361 env->cc_x_live = PARAM1;
362 env->cc_x = PARAM2;
363 RETURN();
366 /* FIXME: is this allowed? */
367 extern inline void evaluate_flags_writeback(uint32_t flags)
369 int x;
371 /* Extended arithmetics, leave the z flag alone. */
372 env->debug3 = env->pregs[PR_CCS];
374 if (env->cc_x_live)
375 x = env->cc_x;
376 else
377 x = env->pregs[PR_CCS] & X_FLAG;
379 if ((x || env->cc_op == CC_OP_ADDC)
380 && flags & Z_FLAG)
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;
387 RETURN();
390 void OPPROTO op_evaluate_flags_muls(void)
392 uint32_t src;
393 uint32_t dst;
394 uint32_t res;
395 uint32_t flags = 0;
396 /* were gonna have to redo the muls. */
397 int64_t tmp, t0 ,t1;
398 int32_t mof;
399 int dneg;
401 src = env->cc_src;
402 dst = env->cc_dest;
403 res = env->cc_result;
406 /* cast into signed values to make GCC sign extend. */
407 t0 = (int32_t)src;
408 t1 = (int32_t)dst;
409 dneg = ((int32_t)res) < 0;
411 tmp = t0 * t1;
412 mof = tmp >> 32;
413 if (tmp == 0)
414 flags |= Z_FLAG;
415 else if (tmp < 0)
416 flags |= N_FLAG;
417 if ((dneg && mof != -1)
418 || (!dneg && mof != 0))
419 flags |= V_FLAG;
420 evaluate_flags_writeback(flags);
421 RETURN();
424 void OPPROTO op_evaluate_flags_mulu(void)
426 uint32_t src;
427 uint32_t dst;
428 uint32_t res;
429 uint32_t flags = 0;
430 /* were gonna have to redo the muls. */
431 uint64_t tmp, t0 ,t1;
432 uint32_t mof;
434 src = env->cc_src;
435 dst = env->cc_dest;
436 res = env->cc_result;
439 /* cast into signed values to make GCC sign extend. */
440 t0 = src;
441 t1 = dst;
443 tmp = t0 * t1;
444 mof = tmp >> 32;
445 if (tmp == 0)
446 flags |= Z_FLAG;
447 else if (tmp >> 63)
448 flags |= N_FLAG;
449 if (mof)
450 flags |= V_FLAG;
452 evaluate_flags_writeback(flags);
453 RETURN();
456 void OPPROTO op_evaluate_flags_mcp(void)
458 uint32_t src;
459 uint32_t dst;
460 uint32_t res;
461 uint32_t flags = 0;
463 src = env->cc_src;
464 dst = env->cc_dest;
465 res = env->cc_result;
467 if ((res & 0x80000000L) != 0L)
469 flags |= N_FLAG;
470 if (((src & 0x80000000L) == 0L)
471 && ((dst & 0x80000000L) == 0L))
473 flags |= V_FLAG;
475 else if (((src & 0x80000000L) != 0L) &&
476 ((dst & 0x80000000L) != 0L))
478 flags |= R_FLAG;
481 else
483 if (res == 0L)
484 flags |= Z_FLAG;
485 if (((src & 0x80000000L) != 0L)
486 && ((dst & 0x80000000L) != 0L))
487 flags |= V_FLAG;
488 if ((dst & 0x80000000L) != 0L
489 || (src & 0x80000000L) != 0L)
490 flags |= R_FLAG;
493 evaluate_flags_writeback(flags);
494 RETURN();
497 void OPPROTO op_evaluate_flags_alu_4(void)
499 uint32_t src;
500 uint32_t dst;
501 uint32_t res;
502 uint32_t flags = 0;
504 src = env->cc_src;
505 dst = env->cc_dest;
506 res = env->cc_result;
508 if ((res & 0x80000000L) != 0L)
510 flags |= N_FLAG;
511 if (((src & 0x80000000L) == 0L)
512 && ((dst & 0x80000000L) == 0L))
514 flags |= V_FLAG;
516 else if (((src & 0x80000000L) != 0L) &&
517 ((dst & 0x80000000L) != 0L))
519 flags |= C_FLAG;
522 else
524 if (res == 0L)
525 flags |= Z_FLAG;
526 if (((src & 0x80000000L) != 0L)
527 && ((dst & 0x80000000L) != 0L))
528 flags |= V_FLAG;
529 if ((dst & 0x80000000L) != 0L
530 || (src & 0x80000000L) != 0L)
531 flags |= C_FLAG;
534 if (env->cc_op == CC_OP_SUB
535 || env->cc_op == CC_OP_CMP) {
536 flags ^= C_FLAG;
538 evaluate_flags_writeback(flags);
539 RETURN();
542 void OPPROTO op_evaluate_flags_move_4 (void)
544 uint32_t src;
545 uint32_t res;
546 uint32_t flags = 0;
548 src = env->cc_src;
549 res = env->cc_result;
551 if ((int32_t)res < 0)
552 flags |= N_FLAG;
553 else if (res == 0L)
554 flags |= Z_FLAG;
556 evaluate_flags_writeback(flags);
557 RETURN();
559 void OPPROTO op_evaluate_flags_move_2 (void)
561 uint32_t src;
562 uint32_t flags = 0;
563 uint16_t res;
565 src = env->cc_src;
566 res = env->cc_result;
568 if ((int16_t)res < 0L)
569 flags |= N_FLAG;
570 else if (res == 0)
571 flags |= Z_FLAG;
573 evaluate_flags_writeback(flags);
574 RETURN();
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)
581 uint32_t src;
582 uint32_t dst;
583 uint32_t res;
584 uint32_t flags = 0;
586 src = env->cc_src;
587 dst = env->cc_dest;
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)
595 case 1:
596 if ((res & 0x80L) != 0L)
598 flags |= N_FLAG;
599 if (((src & 0x80L) == 0L)
600 && ((dst & 0x80L) == 0L))
602 flags |= V_FLAG;
604 else if (((src & 0x80L) != 0L)
605 && ((dst & 0x80L) != 0L))
607 flags |= C_FLAG;
610 else
612 if ((res & 0xFFL) == 0L)
614 flags |= Z_FLAG;
616 if (((src & 0x80L) != 0L)
617 && ((dst & 0x80L) != 0L))
619 flags |= V_FLAG;
621 if ((dst & 0x80L) != 0L
622 || (src & 0x80L) != 0L)
624 flags |= C_FLAG;
627 break;
628 case 2:
629 if ((res & 0x8000L) != 0L)
631 flags |= N_FLAG;
632 if (((src & 0x8000L) == 0L)
633 && ((dst & 0x8000L) == 0L))
635 flags |= V_FLAG;
637 else if (((src & 0x8000L) != 0L)
638 && ((dst & 0x8000L) != 0L))
640 flags |= C_FLAG;
643 else
645 if ((res & 0xFFFFL) == 0L)
647 flags |= Z_FLAG;
649 if (((src & 0x8000L) != 0L)
650 && ((dst & 0x8000L) != 0L))
652 flags |= V_FLAG;
654 if ((dst & 0x8000L) != 0L
655 || (src & 0x8000L) != 0L)
657 flags |= C_FLAG;
660 break;
661 case 4:
662 if ((res & 0x80000000L) != 0L)
664 flags |= N_FLAG;
665 if (((src & 0x80000000L) == 0L)
666 && ((dst & 0x80000000L) == 0L))
668 flags |= V_FLAG;
670 else if (((src & 0x80000000L) != 0L) &&
671 ((dst & 0x80000000L) != 0L))
673 flags |= C_FLAG;
676 else
678 if (res == 0L)
679 flags |= Z_FLAG;
680 if (((src & 0x80000000L) != 0L)
681 && ((dst & 0x80000000L) != 0L))
682 flags |= V_FLAG;
683 if ((dst & 0x80000000L) != 0L
684 || (src & 0x80000000L) != 0L)
685 flags |= C_FLAG;
687 break;
688 default:
689 break;
692 if (env->cc_op == CC_OP_SUB
693 || env->cc_op == CC_OP_CMP) {
694 flags ^= C_FLAG;
696 evaluate_flags_writeback(flags);
697 RETURN();
700 void OPPROTO op_extb_T0_T0 (void)
702 T0 = ((int8_t)T0);
703 RETURN();
705 void OPPROTO op_extb_T1_T0 (void)
707 T1 = ((int8_t)T0);
708 RETURN();
710 void OPPROTO op_extb_T1_T1 (void)
712 T1 = ((int8_t)T1);
713 RETURN();
715 void OPPROTO op_zextb_T0_T0 (void)
717 T0 = ((uint8_t)T0);
718 RETURN();
720 void OPPROTO op_zextb_T1_T0 (void)
722 T1 = ((uint8_t)T0);
723 RETURN();
725 void OPPROTO op_zextb_T1_T1 (void)
727 T1 = ((uint8_t)T1);
728 RETURN();
730 void OPPROTO op_extw_T0_T0 (void)
732 T0 = ((int16_t)T0);
733 RETURN();
735 void OPPROTO op_extw_T1_T0 (void)
737 T1 = ((int16_t)T0);
738 RETURN();
740 void OPPROTO op_extw_T1_T1 (void)
742 T1 = ((int16_t)T1);
743 RETURN();
746 void OPPROTO op_zextw_T0_T0 (void)
748 T0 = ((uint16_t)T0);
749 RETURN();
751 void OPPROTO op_zextw_T1_T0 (void)
753 T1 = ((uint16_t)T0);
754 RETURN();
757 void OPPROTO op_zextw_T1_T1 (void)
759 T1 = ((uint16_t)T1);
760 RETURN();
763 void OPPROTO op_movl_T0_im (void)
765 T0 = PARAM1;
766 RETURN();
768 void OPPROTO op_movl_T1_im (void)
770 T1 = PARAM1;
771 RETURN();
774 void OPPROTO op_addl_T0_im (void)
776 T0 += PARAM1;
777 RETURN();
780 void OPPROTO op_addl_T1_im (void)
782 T1 += PARAM1;
783 RETURN();
786 void OPPROTO op_subl_T0_im (void)
788 T0 -= PARAM1;
789 RETURN();
792 void OPPROTO op_addxl_T0_C (void)
794 if (env->pregs[PR_CCS] & X_FLAG)
795 T0 += !!(env->pregs[PR_CCS] & C_FLAG);
796 RETURN();
798 void OPPROTO op_subxl_T0_C (void)
800 if (env->pregs[PR_CCS] & X_FLAG)
801 T0 -= !!(env->pregs[PR_CCS] & C_FLAG);
802 RETURN();
804 void OPPROTO op_addl_T0_C (void)
806 T0 += !!(env->pregs[PR_CCS] & C_FLAG);
807 RETURN();
809 void OPPROTO op_addl_T0_R (void)
811 T0 += !!(env->pregs[PR_CCS] & R_FLAG);
812 RETURN();
815 void OPPROTO op_clr_R (void)
817 env->pregs[PR_CCS] &= ~R_FLAG;
818 RETURN();
822 void OPPROTO op_andl_T0_im (void)
824 T0 &= PARAM1;
825 RETURN();
828 void OPPROTO op_andl_T1_im (void)
830 T1 &= PARAM1;
831 RETURN();
834 void OPPROTO op_movl_T0_T1 (void)
836 T0 = T1;
837 RETURN();
840 void OPPROTO op_swp_T0_T1 (void)
842 T0 ^= T1;
843 T1 ^= T0;
844 T0 ^= T1;
845 RETURN();
848 void OPPROTO op_movl_T1_T0 (void)
850 T1 = T0;
851 RETURN();
854 void OPPROTO op_movl_pc_T0 (void)
856 env->pc = T0;
857 RETURN();
860 void OPPROTO op_movl_T0_0 (void)
862 T0 = 0;
863 RETURN();
866 void OPPROTO op_addl_T0_T1 (void)
868 T0 += T1;
869 RETURN();
872 void OPPROTO op_subl_T0_T1 (void)
874 T0 -= T1;
875 RETURN();
878 void OPPROTO op_absl_T1_T1 (void)
880 int32_t st = T1;
882 T1 = st < 0 ? -st : st;
883 RETURN();
886 void OPPROTO op_muls_T0_T1 (void)
888 int64_t tmp, t0 ,t1;
890 /* cast into signed values to make GCC sign extend these babies. */
891 t0 = (int32_t)T0;
892 t1 = (int32_t)T1;
894 tmp = t0 * t1;
895 T0 = tmp & 0xffffffff;
896 env->pregs[PR_MOF] = tmp >> 32;
897 RETURN();
900 void OPPROTO op_mulu_T0_T1 (void)
902 uint64_t tmp, t0 ,t1;
903 t0 = T0;
904 t1 = T1;
906 tmp = t0 * t1;
907 T0 = tmp & 0xffffffff;
908 env->pregs[PR_MOF] = tmp >> 32;
909 RETURN();
912 void OPPROTO op_dstep_T0_T1 (void)
914 T0 <<= 1;
915 if (T0 >= T1)
916 T0 -= T1;
917 RETURN();
920 void OPPROTO op_orl_T0_T1 (void)
922 T0 |= T1;
923 RETURN();
926 void OPPROTO op_andl_T0_T1 (void)
928 T0 &= T1;
929 RETURN();
932 void OPPROTO op_xorl_T0_T1 (void)
934 T0 ^= T1;
935 RETURN();
938 void OPPROTO op_lsll_T0_T1 (void)
940 int s = T1;
941 if (s > 31)
942 T0 = 0;
943 else
944 T0 <<= s;
945 RETURN();
948 void OPPROTO op_lsll_T0_im (void)
950 T0 <<= PARAM1;
951 RETURN();
954 void OPPROTO op_lsrl_T0_T1 (void)
956 int s = T1;
957 if (s > 31)
958 T0 = 0;
959 else
960 T0 >>= s;
961 RETURN();
964 /* Rely on GCC emitting an arithmetic shift for signed right shifts. */
965 void OPPROTO op_asrl_T0_T1 (void)
967 int s = T1;
968 if (s > 31)
969 T0 = T0 & 0x80000000 ? -1 : 0;
970 else
971 T0 = (int32_t)T0 >> s;
972 RETURN();
975 void OPPROTO op_btst_T0_T1 (void)
977 /* FIXME: clean this up. */
979 /* des ref:
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
982 zero.
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;
988 sbit = T1 & 31;
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);
998 RETURN();
1001 void OPPROTO op_bound_T0_T1 (void)
1003 if (T0 > T1)
1004 T0 = T1;
1005 RETURN();
1008 void OPPROTO op_lz_T0_T1 (void)
1010 T0 = clz32(T1);
1011 RETURN();
1014 void OPPROTO op_negl_T0_T1 (void)
1016 T0 = -T1;
1017 RETURN();
1020 void OPPROTO op_negl_T1_T1 (void)
1022 T1 = -T1;
1023 RETURN();
1026 void OPPROTO op_not_T0_T0 (void)
1028 T0 = ~(T0);
1029 RETURN();
1031 void OPPROTO op_not_T1_T1 (void)
1033 T1 = ~(T1);
1034 RETURN();
1037 void OPPROTO op_swapw_T0_T0 (void)
1039 T0 = (T0 << 16) | ((T0 >> 16));
1040 RETURN();
1043 void OPPROTO op_swapb_T0_T0 (void)
1045 T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff);
1046 RETURN();
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));
1059 RETURN();
1062 void OPPROTO op_tst_cc_eq (void) {
1063 uint32_t flags = env->pregs[PR_CCS];
1064 int z_set;
1066 z_set = !!(flags & Z_FLAG);
1067 T0 = z_set;
1068 RETURN();
1071 void OPPROTO op_tst_cc_eq_fast (void) {
1072 T0 = !(env->cc_result);
1073 RETURN();
1076 void OPPROTO op_tst_cc_ne (void) {
1077 uint32_t flags = env->pregs[PR_CCS];
1078 int z_set;
1080 z_set = !!(flags & Z_FLAG);
1081 T0 = !z_set;
1082 RETURN();
1084 void OPPROTO op_tst_cc_ne_fast (void) {
1085 T0 = !!(env->cc_result);
1086 RETURN();
1089 void OPPROTO op_tst_cc_cc (void) {
1090 uint32_t flags = env->pregs[PR_CCS];
1091 int c_set;
1093 c_set = !!(flags & C_FLAG);
1094 T0 = !c_set;
1095 RETURN();
1097 void OPPROTO op_tst_cc_cs (void) {
1098 uint32_t flags = env->pregs[PR_CCS];
1099 int c_set;
1101 c_set = !!(flags & C_FLAG);
1102 T0 = c_set;
1103 RETURN();
1106 void OPPROTO op_tst_cc_vc (void) {
1107 uint32_t flags = env->pregs[PR_CCS];
1108 int v_set;
1110 v_set = !!(flags & V_FLAG);
1111 T0 = !v_set;
1112 RETURN();
1114 void OPPROTO op_tst_cc_vs (void) {
1115 uint32_t flags = env->pregs[PR_CCS];
1116 int v_set;
1118 v_set = !!(flags & V_FLAG);
1119 T0 = v_set;
1120 RETURN();
1122 void OPPROTO op_tst_cc_pl (void) {
1123 uint32_t flags = env->pregs[PR_CCS];
1124 int n_set;
1126 n_set = !!(flags & N_FLAG);
1127 T0 = !n_set;
1128 RETURN();
1130 void OPPROTO op_tst_cc_pl_fast (void) {
1131 T0 = ((int32_t)env->cc_result) >= 0;
1132 RETURN();
1135 void OPPROTO op_tst_cc_mi (void) {
1136 uint32_t flags = env->pregs[PR_CCS];
1137 int n_set;
1139 n_set = !!(flags & N_FLAG);
1140 T0 = n_set;
1141 RETURN();
1143 void OPPROTO op_tst_cc_mi_fast (void) {
1144 T0 = ((int32_t)env->cc_result) < 0;
1145 RETURN();
1148 void OPPROTO op_tst_cc_ls (void) {
1149 uint32_t flags = env->pregs[PR_CCS];
1150 int c_set;
1151 int z_set;
1153 c_set = !!(flags & C_FLAG);
1154 z_set = !!(flags & Z_FLAG);
1155 T0 = c_set || z_set;
1156 RETURN();
1158 void OPPROTO op_tst_cc_hi (void) {
1159 uint32_t flags = env->pregs[PR_CCS];
1160 int z_set;
1161 int c_set;
1163 z_set = !!(flags & Z_FLAG);
1164 c_set = !!(flags & C_FLAG);
1165 T0 = !c_set && !z_set;
1166 RETURN();
1170 void OPPROTO op_tst_cc_ge (void) {
1171 uint32_t flags = env->pregs[PR_CCS];
1172 int n_set;
1173 int v_set;
1175 n_set = !!(flags & N_FLAG);
1176 v_set = !!(flags & V_FLAG);
1177 T0 = (n_set && v_set) || (!n_set && !v_set);
1178 RETURN();
1181 void OPPROTO op_tst_cc_ge_fast (void) {
1182 T0 = ((int32_t)env->cc_src < (int32_t)env->cc_dest);
1183 RETURN();
1186 void OPPROTO op_tst_cc_lt (void) {
1187 uint32_t flags = env->pregs[PR_CCS];
1188 int n_set;
1189 int v_set;
1191 n_set = !!(flags & N_FLAG);
1192 v_set = !!(flags & V_FLAG);
1193 T0 = (n_set && !v_set) || (!n_set && v_set);
1194 RETURN();
1197 void OPPROTO op_tst_cc_gt (void) {
1198 uint32_t flags = env->pregs[PR_CCS];
1199 int n_set;
1200 int v_set;
1201 int z_set;
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);
1208 RETURN();
1211 void OPPROTO op_tst_cc_le (void) {
1212 uint32_t flags = env->pregs[PR_CCS];
1213 int n_set;
1214 int v_set;
1215 int z_set;
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);
1221 RETURN();
1224 void OPPROTO op_tst_cc_p (void) {
1225 uint32_t flags = env->pregs[PR_CCS];
1226 int p_set;
1228 p_set = !!(flags & P_FLAG);
1229 T0 = p_set;
1230 RETURN();
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
1235 delay-slot. */
1236 void OPPROTO op_evaluate_bcc (void)
1238 env->btaken = T0;
1239 RETURN();
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);
1247 RETURN();
1250 void OPPROTO op_cc_jmp (void)
1252 if (env->btaken)
1253 env->pc = PARAM1;
1254 else
1255 env->pc = PARAM2;
1256 RETURN();
1259 void OPPROTO op_cc_ngoto (void)
1261 if (!env->btaken)
1262 GOTO_LABEL_PARAM(1);
1263 RETURN();
1266 void OPPROTO op_movl_btarget_T0 (void)
1268 env->btarget = T0;
1269 RETURN();
1272 void OPPROTO op_jmp1 (void)
1274 env->pc = env->btarget;
1275 RETURN();
1278 /* Load and store */
1279 #define MEMSUFFIX _raw
1280 #include "op_mem.c"
1281 #undef MEMSUFFIX
1282 #if !defined(CONFIG_USER_ONLY)
1283 #define MEMSUFFIX _user
1284 #include "op_mem.c"
1285 #undef MEMSUFFIX
1287 #define MEMSUFFIX _kernel
1288 #include "op_mem.c"
1289 #undef MEMSUFFIX
1290 #endif