]> git.proxmox.com Git - qemu.git/blob - target-cris/op.c
aeb80de4a36baf1b0a5321c7ed832ed17ab28ad5
[qemu.git] / target-cris / op.c
1 /*
2 * CRIS emulation micro-operations for qemu.
3 *
4 * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
5 *
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.
10 *
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.
15 *
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
19 */
20 #include "exec.h"
21 #include "host-utils.h"
22
23 #define REGNAME r0
24 #define REG (env->regs[0])
25 #include "op_template.h"
26
27 #define REGNAME r1
28 #define REG (env->regs[1])
29 #include "op_template.h"
30
31 #define REGNAME r2
32 #define REG (env->regs[2])
33 #include "op_template.h"
34
35 #define REGNAME r3
36 #define REG (env->regs[3])
37 #include "op_template.h"
38
39 #define REGNAME r4
40 #define REG (env->regs[4])
41 #include "op_template.h"
42
43 #define REGNAME r5
44 #define REG (env->regs[5])
45 #include "op_template.h"
46
47 #define REGNAME r6
48 #define REG (env->regs[6])
49 #include "op_template.h"
50
51 #define REGNAME r7
52 #define REG (env->regs[7])
53 #include "op_template.h"
54
55 #define REGNAME r8
56 #define REG (env->regs[8])
57 #include "op_template.h"
58
59 #define REGNAME r9
60 #define REG (env->regs[9])
61 #include "op_template.h"
62
63 #define REGNAME r10
64 #define REG (env->regs[10])
65 #include "op_template.h"
66
67 #define REGNAME r11
68 #define REG (env->regs[11])
69 #include "op_template.h"
70
71 #define REGNAME r12
72 #define REG (env->regs[12])
73 #include "op_template.h"
74
75 #define REGNAME r13
76 #define REG (env->regs[13])
77 #include "op_template.h"
78
79 #define REGNAME r14
80 #define REG (env->regs[14])
81 #include "op_template.h"
82
83 #define REGNAME r15
84 #define REG (env->regs[15])
85 #include "op_template.h"
86
87
88 #define REGNAME p0
89 #define REG (env->pregs[0])
90 #include "op_template.h"
91
92 #define REGNAME p1
93 #define REG (env->pregs[1])
94 #include "op_template.h"
95
96 #define REGNAME p2
97 #define REG (env->pregs[2])
98 #include "op_template.h"
99
100 #define REGNAME p3
101 #define REG (env->pregs[3])
102 #include "op_template.h"
103
104 #define REGNAME p4
105 #define REG (env->pregs[4])
106 #include "op_template.h"
107
108 #define REGNAME p5
109 #define REG (env->pregs[5])
110 #include "op_template.h"
111
112 #define REGNAME p6
113 #define REG (env->pregs[6])
114 #include "op_template.h"
115
116 #define REGNAME p7
117 #define REG (env->pregs[7])
118 #include "op_template.h"
119
120 #define REGNAME p8
121 #define REG (env->pregs[8])
122 #include "op_template.h"
123
124 #define REGNAME p9
125 #define REG (env->pregs[9])
126 #include "op_template.h"
127
128 #define REGNAME p10
129 #define REG (env->pregs[10])
130 #include "op_template.h"
131
132 #define REGNAME p11
133 #define REG (env->pregs[11])
134 #include "op_template.h"
135
136 #define REGNAME p12
137 #define REG (env->pregs[12])
138 #include "op_template.h"
139
140 #define REGNAME p13
141 #define REG (env->pregs[13])
142 #include "op_template.h"
143
144 #define REGNAME p14
145 #define REG (env->pregs[14])
146 #include "op_template.h"
147
148 #define REGNAME p15
149 #define REG (env->pregs[15])
150 #include "op_template.h"
151
152 /* Microcode. */
153
154 void OPPROTO op_break_im(void)
155 {
156 env->trapnr = PARAM1;
157 env->exception_index = EXCP_BREAK;
158 cpu_loop_exit();
159 }
160
161 void OPPROTO op_debug(void)
162 {
163 env->exception_index = EXCP_DEBUG;
164 cpu_loop_exit();
165 }
166
167 void OPPROTO op_exec_insn(void)
168 {
169 env->stats.exec_insns++;
170 RETURN();
171 }
172 void OPPROTO op_exec_load(void)
173 {
174 env->stats.exec_loads++;
175 RETURN();
176 }
177 void OPPROTO op_exec_store(void)
178 {
179 env->stats.exec_stores++;
180 RETURN();
181 }
182
183 void OPPROTO op_ccs_lshift (void)
184 {
185 uint32_t ccs;
186
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();
192 }
193 void OPPROTO op_ccs_rshift (void)
194 {
195 uint32_t ccs;
196
197 /* Apply the ccs shift. */
198 ccs = env->pregs[PR_CCS];
199 ccs = (ccs & 0xc0000000) | (ccs >> 10);
200 env->pregs[PR_CCS] = ccs;
201 RETURN();
202 }
203
204 void OPPROTO op_setf (void)
205 {
206 env->pregs[PR_CCS] |= PARAM1;
207 RETURN();
208 }
209
210 void OPPROTO op_clrf (void)
211 {
212 env->pregs[PR_CCS] &= ~PARAM1;
213 RETURN();
214 }
215
216 void OPPROTO op_movl_debug1_T0 (void)
217 {
218 env->debug1 = T0;
219 RETURN();
220 }
221
222 void OPPROTO op_movl_debug2_T0 (void)
223 {
224 env->debug2 = T0;
225 RETURN();
226 }
227
228 void OPPROTO op_movl_debug3_T0 (void)
229 {
230 env->debug3 = T0;
231 RETURN();
232 }
233 void OPPROTO op_movl_debug1_T1 (void)
234 {
235 env->debug1 = T1;
236 RETURN();
237 }
238
239 void OPPROTO op_movl_debug2_T1 (void)
240 {
241 env->debug2 = T1;
242 RETURN();
243 }
244
245 void OPPROTO op_movl_debug3_T1 (void)
246 {
247 env->debug3 = T1;
248 RETURN();
249 }
250 void OPPROTO op_movl_debug3_im (void)
251 {
252 env->debug3 = PARAM1;
253 RETURN();
254 }
255 void OPPROTO op_movl_T0_flags (void)
256 {
257 T0 = env->pregs[PR_CCS];
258 RETURN();
259 }
260 void OPPROTO op_movl_flags_T0 (void)
261 {
262 env->pregs[PR_CCS] = T0;
263 RETURN();
264 }
265
266 void OPPROTO op_movl_sreg_T0 (void)
267 {
268 env->sregs[env->pregs[PR_SRS]][PARAM1] = T0;
269 RETURN();
270 }
271
272 void OPPROTO op_movl_tlb_lo_T0 (void)
273 {
274 int srs;
275 srs = env->pregs[PR_SRS];
276 if (srs == 1 || srs == 2)
277 {
278 int set;
279 int idx;
280 uint32_t lo, hi;
281
282 idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
283 set >>= 4;
284 set &= 3;
285
286 idx &= 31;
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;
292 }
293
294 RETURN();
295 }
296
297 void OPPROTO op_movl_T0_sreg (void)
298 {
299 T0 = env->sregs[env->pregs[PR_SRS]][PARAM1];
300 RETURN();
301 }
302
303 void OPPROTO op_update_cc (void)
304 {
305 env->cc_op = PARAM1;
306 env->cc_dest = PARAM2;
307 env->cc_src = PARAM3;
308 RETURN();
309 }
310
311 void OPPROTO op_update_cc_op (void)
312 {
313 env->cc_op = PARAM1;
314 RETURN();
315 }
316
317 void OPPROTO op_update_cc_mask (void)
318 {
319 env->cc_mask = PARAM1;
320 RETURN();
321 }
322
323 void OPPROTO op_update_cc_dest_T0 (void)
324 {
325 env->cc_dest = T0;
326 RETURN();
327 }
328
329 void OPPROTO op_update_cc_result_T0 (void)
330 {
331 env->cc_result = T0;
332 RETURN();
333 }
334
335 void OPPROTO op_update_cc_size_im (void)
336 {
337 env->cc_size = PARAM1;
338 RETURN();
339 }
340
341 void OPPROTO op_update_cc_src_T1 (void)
342 {
343 env->cc_src = T1;
344 RETURN();
345 }
346 void OPPROTO op_update_cc_x (void)
347 {
348 env->cc_x_live = PARAM1;
349 env->cc_x = PARAM2;
350 RETURN();
351 }
352
353 /* FIXME: is this allowed? */
354 extern inline void evaluate_flags_writeback(uint32_t flags)
355 {
356 int x;
357
358 /* Extended arithmetics, leave the z flag alone. */
359 env->debug3 = env->pregs[PR_CCS];
360
361 if (env->cc_x_live)
362 x = env->cc_x;
363 else
364 x = env->pregs[PR_CCS] & X_FLAG;
365
366 if ((x || env->cc_op == CC_OP_ADDC)
367 && flags & Z_FLAG)
368 env->cc_mask &= ~Z_FLAG;
369
370 /* all insn clear the x-flag except setf or clrf. */
371 env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG);
372 flags &= env->cc_mask;
373 env->pregs[PR_CCS] |= flags;
374 RETURN();
375 }
376
377 void OPPROTO op_evaluate_flags_muls(void)
378 {
379 uint32_t src;
380 uint32_t dst;
381 uint32_t res;
382 uint32_t flags = 0;
383 /* were gonna have to redo the muls. */
384 int64_t tmp, t0 ,t1;
385 int32_t mof;
386 int dneg;
387
388 src = env->cc_src;
389 dst = env->cc_dest;
390 res = env->cc_result;
391
392
393 /* cast into signed values to make GCC sign extend. */
394 t0 = (int32_t)src;
395 t1 = (int32_t)dst;
396 dneg = ((int32_t)res) < 0;
397
398 tmp = t0 * t1;
399 mof = tmp >> 32;
400 if (tmp == 0)
401 flags |= Z_FLAG;
402 else if (tmp < 0)
403 flags |= N_FLAG;
404 if ((dneg && mof != -1)
405 || (!dneg && mof != 0))
406 flags |= V_FLAG;
407 evaluate_flags_writeback(flags);
408 RETURN();
409 }
410
411 void OPPROTO op_evaluate_flags_mulu(void)
412 {
413 uint32_t src;
414 uint32_t dst;
415 uint32_t res;
416 uint32_t flags = 0;
417 /* were gonna have to redo the muls. */
418 uint64_t tmp, t0 ,t1;
419 uint32_t mof;
420
421 src = env->cc_src;
422 dst = env->cc_dest;
423 res = env->cc_result;
424
425
426 /* cast into signed values to make GCC sign extend. */
427 t0 = src;
428 t1 = dst;
429
430 tmp = t0 * t1;
431 mof = tmp >> 32;
432 if (tmp == 0)
433 flags |= Z_FLAG;
434 else if (tmp >> 63)
435 flags |= N_FLAG;
436 if (mof)
437 flags |= V_FLAG;
438
439 evaluate_flags_writeback(flags);
440 RETURN();
441 }
442
443 void OPPROTO op_evaluate_flags_mcp(void)
444 {
445 uint32_t src;
446 uint32_t dst;
447 uint32_t res;
448 uint32_t flags = 0;
449
450 src = env->cc_src;
451 dst = env->cc_dest;
452 res = env->cc_result;
453
454 if ((res & 0x80000000L) != 0L)
455 {
456 flags |= N_FLAG;
457 if (((src & 0x80000000L) == 0L)
458 && ((dst & 0x80000000L) == 0L))
459 {
460 flags |= V_FLAG;
461 }
462 else if (((src & 0x80000000L) != 0L) &&
463 ((dst & 0x80000000L) != 0L))
464 {
465 flags |= R_FLAG;
466 }
467 }
468 else
469 {
470 if (res == 0L)
471 flags |= Z_FLAG;
472 if (((src & 0x80000000L) != 0L)
473 && ((dst & 0x80000000L) != 0L))
474 flags |= V_FLAG;
475 if ((dst & 0x80000000L) != 0L
476 || (src & 0x80000000L) != 0L)
477 flags |= R_FLAG;
478 }
479
480 evaluate_flags_writeback(flags);
481 RETURN();
482 }
483
484 void OPPROTO op_evaluate_flags_alu_4(void)
485 {
486 uint32_t src;
487 uint32_t dst;
488 uint32_t res;
489 uint32_t flags = 0;
490
491 src = env->cc_src;
492 dst = env->cc_dest;
493 res = env->cc_result;
494
495 if ((res & 0x80000000L) != 0L)
496 {
497 flags |= N_FLAG;
498 if (((src & 0x80000000L) == 0L)
499 && ((dst & 0x80000000L) == 0L))
500 {
501 flags |= V_FLAG;
502 }
503 else if (((src & 0x80000000L) != 0L) &&
504 ((dst & 0x80000000L) != 0L))
505 {
506 flags |= C_FLAG;
507 }
508 }
509 else
510 {
511 if (res == 0L)
512 flags |= Z_FLAG;
513 if (((src & 0x80000000L) != 0L)
514 && ((dst & 0x80000000L) != 0L))
515 flags |= V_FLAG;
516 if ((dst & 0x80000000L) != 0L
517 || (src & 0x80000000L) != 0L)
518 flags |= C_FLAG;
519 }
520
521 if (env->cc_op == CC_OP_SUB
522 || env->cc_op == CC_OP_CMP) {
523 flags ^= C_FLAG;
524 }
525 evaluate_flags_writeback(flags);
526 RETURN();
527 }
528
529 void OPPROTO op_evaluate_flags_move_4 (void)
530 {
531 uint32_t src;
532 uint32_t res;
533 uint32_t flags = 0;
534
535 src = env->cc_src;
536 res = env->cc_result;
537
538 if ((int32_t)res < 0)
539 flags |= N_FLAG;
540 else if (res == 0L)
541 flags |= Z_FLAG;
542
543 evaluate_flags_writeback(flags);
544 RETURN();
545 }
546 void OPPROTO op_evaluate_flags_move_2 (void)
547 {
548 uint32_t src;
549 uint32_t flags = 0;
550 uint16_t res;
551
552 src = env->cc_src;
553 res = env->cc_result;
554
555 if ((int16_t)res < 0L)
556 flags |= N_FLAG;
557 else if (res == 0)
558 flags |= Z_FLAG;
559
560 evaluate_flags_writeback(flags);
561 RETURN();
562 }
563
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)
567 {
568 uint32_t src;
569 uint32_t dst;
570 uint32_t res;
571 uint32_t flags = 0;
572
573 src = env->cc_src;
574 dst = env->cc_dest;
575 res = env->cc_result;
576
577
578 /* Now, evaluate the flags. This stuff is based on
579 Per Zander's CRISv10 simulator. */
580 switch (env->cc_size)
581 {
582 case 1:
583 if ((res & 0x80L) != 0L)
584 {
585 flags |= N_FLAG;
586 if (((src & 0x80L) == 0L)
587 && ((dst & 0x80L) == 0L))
588 {
589 flags |= V_FLAG;
590 }
591 else if (((src & 0x80L) != 0L)
592 && ((dst & 0x80L) != 0L))
593 {
594 flags |= C_FLAG;
595 }
596 }
597 else
598 {
599 if ((res & 0xFFL) == 0L)
600 {
601 flags |= Z_FLAG;
602 }
603 if (((src & 0x80L) != 0L)
604 && ((dst & 0x80L) != 0L))
605 {
606 flags |= V_FLAG;
607 }
608 if ((dst & 0x80L) != 0L
609 || (src & 0x80L) != 0L)
610 {
611 flags |= C_FLAG;
612 }
613 }
614 break;
615 case 2:
616 if ((res & 0x8000L) != 0L)
617 {
618 flags |= N_FLAG;
619 if (((src & 0x8000L) == 0L)
620 && ((dst & 0x8000L) == 0L))
621 {
622 flags |= V_FLAG;
623 }
624 else if (((src & 0x8000L) != 0L)
625 && ((dst & 0x8000L) != 0L))
626 {
627 flags |= C_FLAG;
628 }
629 }
630 else
631 {
632 if ((res & 0xFFFFL) == 0L)
633 {
634 flags |= Z_FLAG;
635 }
636 if (((src & 0x8000L) != 0L)
637 && ((dst & 0x8000L) != 0L))
638 {
639 flags |= V_FLAG;
640 }
641 if ((dst & 0x8000L) != 0L
642 || (src & 0x8000L) != 0L)
643 {
644 flags |= C_FLAG;
645 }
646 }
647 break;
648 case 4:
649 if ((res & 0x80000000L) != 0L)
650 {
651 flags |= N_FLAG;
652 if (((src & 0x80000000L) == 0L)
653 && ((dst & 0x80000000L) == 0L))
654 {
655 flags |= V_FLAG;
656 }
657 else if (((src & 0x80000000L) != 0L) &&
658 ((dst & 0x80000000L) != 0L))
659 {
660 flags |= C_FLAG;
661 }
662 }
663 else
664 {
665 if (res == 0L)
666 flags |= Z_FLAG;
667 if (((src & 0x80000000L) != 0L)
668 && ((dst & 0x80000000L) != 0L))
669 flags |= V_FLAG;
670 if ((dst & 0x80000000L) != 0L
671 || (src & 0x80000000L) != 0L)
672 flags |= C_FLAG;
673 }
674 break;
675 default:
676 break;
677 }
678
679 if (env->cc_op == CC_OP_SUB
680 || env->cc_op == CC_OP_CMP) {
681 flags ^= C_FLAG;
682 }
683 evaluate_flags_writeback(flags);
684 RETURN();
685 }
686
687 void OPPROTO op_extb_T0_T0 (void)
688 {
689 T0 = ((int8_t)T0);
690 RETURN();
691 }
692 void OPPROTO op_extb_T1_T0 (void)
693 {
694 T1 = ((int8_t)T0);
695 RETURN();
696 }
697 void OPPROTO op_extb_T1_T1 (void)
698 {
699 T1 = ((int8_t)T1);
700 RETURN();
701 }
702 void OPPROTO op_zextb_T0_T0 (void)
703 {
704 T0 = ((uint8_t)T0);
705 RETURN();
706 }
707 void OPPROTO op_zextb_T1_T0 (void)
708 {
709 T1 = ((uint8_t)T0);
710 RETURN();
711 }
712 void OPPROTO op_zextb_T1_T1 (void)
713 {
714 T1 = ((uint8_t)T1);
715 RETURN();
716 }
717 void OPPROTO op_extw_T0_T0 (void)
718 {
719 T0 = ((int16_t)T0);
720 RETURN();
721 }
722 void OPPROTO op_extw_T1_T0 (void)
723 {
724 T1 = ((int16_t)T0);
725 RETURN();
726 }
727 void OPPROTO op_extw_T1_T1 (void)
728 {
729 T1 = ((int16_t)T1);
730 RETURN();
731 }
732
733 void OPPROTO op_zextw_T0_T0 (void)
734 {
735 T0 = ((uint16_t)T0);
736 RETURN();
737 }
738 void OPPROTO op_zextw_T1_T0 (void)
739 {
740 T1 = ((uint16_t)T0);
741 RETURN();
742 }
743
744 void OPPROTO op_zextw_T1_T1 (void)
745 {
746 T1 = ((uint16_t)T1);
747 RETURN();
748 }
749
750 void OPPROTO op_movl_T0_im (void)
751 {
752 T0 = PARAM1;
753 RETURN();
754 }
755 void OPPROTO op_movl_T1_im (void)
756 {
757 T1 = PARAM1;
758 RETURN();
759 }
760
761 void OPPROTO op_addl_T0_im (void)
762 {
763 T0 += PARAM1;
764 RETURN();
765 }
766
767 void OPPROTO op_addl_T1_im (void)
768 {
769 T1 += PARAM1;
770 RETURN();
771
772 }
773 void OPPROTO op_subl_T0_im (void)
774 {
775 T0 -= PARAM1;
776 RETURN();
777 }
778
779 void OPPROTO op_addxl_T0_C (void)
780 {
781 if (env->pregs[PR_CCS] & X_FLAG)
782 T0 += !!(env->pregs[PR_CCS] & C_FLAG);
783 RETURN();
784 }
785 void OPPROTO op_subxl_T0_C (void)
786 {
787 if (env->pregs[PR_CCS] & X_FLAG)
788 T0 -= !!(env->pregs[PR_CCS] & C_FLAG);
789 RETURN();
790 }
791 void OPPROTO op_addl_T0_C (void)
792 {
793 T0 += !!(env->pregs[PR_CCS] & C_FLAG);
794 RETURN();
795 }
796 void OPPROTO op_addl_T0_R (void)
797 {
798 T0 += !!(env->pregs[PR_CCS] & R_FLAG);
799 RETURN();
800 }
801
802 void OPPROTO op_clr_R (void)
803 {
804 env->pregs[PR_CCS] &= ~R_FLAG;
805 RETURN();
806 }
807
808
809 void OPPROTO op_andl_T0_im (void)
810 {
811 T0 &= PARAM1;
812 RETURN();
813 }
814
815 void OPPROTO op_andl_T1_im (void)
816 {
817 T1 &= PARAM1;
818 RETURN();
819 }
820
821 void OPPROTO op_movl_T0_T1 (void)
822 {
823 T0 = T1;
824 RETURN();
825 }
826
827 void OPPROTO op_swp_T0_T1 (void)
828 {
829 T0 ^= T1;
830 T1 ^= T0;
831 T0 ^= T1;
832 RETURN();
833 }
834
835 void OPPROTO op_movl_T1_T0 (void)
836 {
837 T1 = T0;
838 RETURN();
839 }
840
841 void OPPROTO op_movl_pc_T0 (void)
842 {
843 env->pc = T0;
844 RETURN();
845 }
846
847 void OPPROTO op_movl_T0_0 (void)
848 {
849 T0 = 0;
850 RETURN();
851 }
852
853 void OPPROTO op_addl_T0_T1 (void)
854 {
855 T0 += T1;
856 RETURN();
857 }
858
859 void OPPROTO op_subl_T0_T1 (void)
860 {
861 T0 -= T1;
862 RETURN();
863 }
864
865 void OPPROTO op_absl_T1_T1 (void)
866 {
867 int32_t st = T1;
868
869 T1 = st < 0 ? -st : st;
870 RETURN();
871 }
872
873 void OPPROTO op_muls_T0_T1 (void)
874 {
875 int64_t tmp, t0 ,t1;
876
877 /* cast into signed values to make GCC sign extend these babies. */
878 t0 = (int32_t)T0;
879 t1 = (int32_t)T1;
880
881 tmp = t0 * t1;
882 T0 = tmp & 0xffffffff;
883 env->pregs[PR_MOF] = tmp >> 32;
884 RETURN();
885 }
886
887 void OPPROTO op_mulu_T0_T1 (void)
888 {
889 uint64_t tmp, t0 ,t1;
890 t0 = T0;
891 t1 = T1;
892
893 tmp = t0 * t1;
894 T0 = tmp & 0xffffffff;
895 env->pregs[PR_MOF] = tmp >> 32;
896 RETURN();
897 }
898
899 void OPPROTO op_dstep_T0_T1 (void)
900 {
901 T0 <<= 1;
902 if (T0 >= T1)
903 T0 -= T1;
904 RETURN();
905 }
906
907 void OPPROTO op_orl_T0_T1 (void)
908 {
909 T0 |= T1;
910 RETURN();
911 }
912
913 void OPPROTO op_andl_T0_T1 (void)
914 {
915 T0 &= T1;
916 RETURN();
917 }
918
919 void OPPROTO op_xorl_T0_T1 (void)
920 {
921 T0 ^= T1;
922 RETURN();
923 }
924
925 void OPPROTO op_lsll_T0_T1 (void)
926 {
927 int s = T1;
928 if (s > 31)
929 T0 = 0;
930 else
931 T0 <<= s;
932 RETURN();
933 }
934
935 void OPPROTO op_lsll_T0_im (void)
936 {
937 T0 <<= PARAM1;
938 RETURN();
939 }
940
941 void OPPROTO op_lsrl_T0_T1 (void)
942 {
943 int s = T1;
944 if (s > 31)
945 T0 = 0;
946 else
947 T0 >>= s;
948 RETURN();
949 }
950
951 /* Rely on GCC emitting an arithmetic shift for signed right shifts. */
952 void OPPROTO op_asrl_T0_T1 (void)
953 {
954 int s = T1;
955 if (s > 31)
956 T0 = T0 & 0x80000000 ? -1 : 0;
957 else
958 T0 = (int32_t)T0 >> s;
959 RETURN();
960 }
961
962 void OPPROTO op_btst_T0_T1 (void)
963 {
964 /* FIXME: clean this up. */
965
966 /* des ref:
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
969 zero.
970 The X flag is cleared.
971 Other flags are left untouched.
972 The destination reg is not affected.*/
973 unsigned int fz, sbit, bset, mask, masked_t0;
974
975 sbit = T1 & 31;
976 bset = !!(T0 & (1 << sbit));
977 mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1;
978 masked_t0 = T0 & mask;
979 fz = !(masked_t0 | bset);
980
981 /* Clear the X, N and Z flags. */
982 T0 = env->pregs[PR_CCS] & ~(X_FLAG | N_FLAG | Z_FLAG);
983 /* Set the N and Z flags accordingly. */
984 T0 |= (bset << 3) | (fz << 2);
985 RETURN();
986 }
987
988 void OPPROTO op_bound_T0_T1 (void)
989 {
990 if (T0 > T1)
991 T0 = T1;
992 RETURN();
993 }
994
995 void OPPROTO op_lz_T0_T1 (void)
996 {
997 T0 = clz32(T1);
998 RETURN();
999 }
1000
1001 void OPPROTO op_negl_T0_T1 (void)
1002 {
1003 T0 = -T1;
1004 RETURN();
1005 }
1006
1007 void OPPROTO op_negl_T1_T1 (void)
1008 {
1009 T1 = -T1;
1010 RETURN();
1011 }
1012
1013 void OPPROTO op_not_T0_T0 (void)
1014 {
1015 T0 = ~(T0);
1016 RETURN();
1017 }
1018 void OPPROTO op_not_T1_T1 (void)
1019 {
1020 T1 = ~(T1);
1021 RETURN();
1022 }
1023
1024 void OPPROTO op_swapw_T0_T0 (void)
1025 {
1026 T0 = (T0 << 16) | ((T0 >> 16));
1027 RETURN();
1028 }
1029
1030 void OPPROTO op_swapb_T0_T0 (void)
1031 {
1032 T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff);
1033 RETURN();
1034 }
1035
1036 void OPPROTO op_swapr_T0_T0 (void)
1037 {
1038 T0 = (((T0 << 7) & 0x80808080) |
1039 ((T0 << 5) & 0x40404040) |
1040 ((T0 << 3) & 0x20202020) |
1041 ((T0 << 1) & 0x10101010) |
1042 ((T0 >> 1) & 0x08080808) |
1043 ((T0 >> 3) & 0x04040404) |
1044 ((T0 >> 5) & 0x02020202) |
1045 ((T0 >> 7) & 0x01010101));
1046 RETURN();
1047 }
1048
1049 void OPPROTO op_tst_cc_eq (void) {
1050 uint32_t flags = env->pregs[PR_CCS];
1051 int z_set;
1052
1053 z_set = !!(flags & Z_FLAG);
1054 T0 = z_set;
1055 RETURN();
1056 }
1057
1058 void OPPROTO op_tst_cc_eq_fast (void) {
1059 T0 = !(env->cc_result);
1060 RETURN();
1061 }
1062
1063 void OPPROTO op_tst_cc_ne (void) {
1064 uint32_t flags = env->pregs[PR_CCS];
1065 int z_set;
1066
1067 z_set = !!(flags & Z_FLAG);
1068 T0 = !z_set;
1069 RETURN();
1070 }
1071 void OPPROTO op_tst_cc_ne_fast (void) {
1072 T0 = !!(env->cc_result);
1073 RETURN();
1074 }
1075
1076 void OPPROTO op_tst_cc_cc (void) {
1077 uint32_t flags = env->pregs[PR_CCS];
1078 int c_set;
1079
1080 c_set = !!(flags & C_FLAG);
1081 T0 = !c_set;
1082 RETURN();
1083 }
1084 void OPPROTO op_tst_cc_cs (void) {
1085 uint32_t flags = env->pregs[PR_CCS];
1086 int c_set;
1087
1088 c_set = !!(flags & C_FLAG);
1089 T0 = c_set;
1090 RETURN();
1091 }
1092
1093 void OPPROTO op_tst_cc_vc (void) {
1094 uint32_t flags = env->pregs[PR_CCS];
1095 int v_set;
1096
1097 v_set = !!(flags & V_FLAG);
1098 T0 = !v_set;
1099 RETURN();
1100 }
1101 void OPPROTO op_tst_cc_vs (void) {
1102 uint32_t flags = env->pregs[PR_CCS];
1103 int v_set;
1104
1105 v_set = !!(flags & V_FLAG);
1106 T0 = v_set;
1107 RETURN();
1108 }
1109 void OPPROTO op_tst_cc_pl (void) {
1110 uint32_t flags = env->pregs[PR_CCS];
1111 int n_set;
1112
1113 n_set = !!(flags & N_FLAG);
1114 T0 = !n_set;
1115 RETURN();
1116 }
1117 void OPPROTO op_tst_cc_pl_fast (void) {
1118 T0 = ((int32_t)env->cc_result) >= 0;
1119 RETURN();
1120 }
1121
1122 void OPPROTO op_tst_cc_mi (void) {
1123 uint32_t flags = env->pregs[PR_CCS];
1124 int n_set;
1125
1126 n_set = !!(flags & N_FLAG);
1127 T0 = n_set;
1128 RETURN();
1129 }
1130 void OPPROTO op_tst_cc_mi_fast (void) {
1131 T0 = ((int32_t)env->cc_result) < 0;
1132 RETURN();
1133 }
1134
1135 void OPPROTO op_tst_cc_ls (void) {
1136 uint32_t flags = env->pregs[PR_CCS];
1137 int c_set;
1138 int z_set;
1139
1140 c_set = !!(flags & C_FLAG);
1141 z_set = !!(flags & Z_FLAG);
1142 T0 = c_set || z_set;
1143 RETURN();
1144 }
1145 void OPPROTO op_tst_cc_hi (void) {
1146 uint32_t flags = env->pregs[PR_CCS];
1147 int z_set;
1148 int c_set;
1149
1150 z_set = !!(flags & Z_FLAG);
1151 c_set = !!(flags & C_FLAG);
1152 T0 = !c_set && !z_set;
1153 RETURN();
1154
1155 }
1156
1157 void OPPROTO op_tst_cc_ge (void) {
1158 uint32_t flags = env->pregs[PR_CCS];
1159 int n_set;
1160 int v_set;
1161
1162 n_set = !!(flags & N_FLAG);
1163 v_set = !!(flags & V_FLAG);
1164 T0 = (n_set && v_set) || (!n_set && !v_set);
1165 RETURN();
1166 }
1167
1168 void OPPROTO op_tst_cc_ge_fast (void) {
1169 T0 = ((int32_t)env->cc_src < (int32_t)env->cc_dest);
1170 RETURN();
1171 }
1172
1173 void OPPROTO op_tst_cc_lt (void) {
1174 uint32_t flags = env->pregs[PR_CCS];
1175 int n_set;
1176 int v_set;
1177
1178 n_set = !!(flags & N_FLAG);
1179 v_set = !!(flags & V_FLAG);
1180 T0 = (n_set && !v_set) || (!n_set && v_set);
1181 RETURN();
1182 }
1183
1184 void OPPROTO op_tst_cc_gt (void) {
1185 uint32_t flags = env->pregs[PR_CCS];
1186 int n_set;
1187 int v_set;
1188 int z_set;
1189
1190 n_set = !!(flags & N_FLAG);
1191 v_set = !!(flags & V_FLAG);
1192 z_set = !!(flags & Z_FLAG);
1193 T0 = (n_set && v_set && !z_set)
1194 || (!n_set && !v_set && !z_set);
1195 RETURN();
1196 }
1197
1198 void OPPROTO op_tst_cc_le (void) {
1199 uint32_t flags = env->pregs[PR_CCS];
1200 int n_set;
1201 int v_set;
1202 int z_set;
1203
1204 n_set = !!(flags & N_FLAG);
1205 v_set = !!(flags & V_FLAG);
1206 z_set = !!(flags & Z_FLAG);
1207 T0 = z_set || (n_set && !v_set) || (!n_set && v_set);
1208 RETURN();
1209 }
1210
1211 void OPPROTO op_tst_cc_p (void) {
1212 uint32_t flags = env->pregs[PR_CCS];
1213 int p_set;
1214
1215 p_set = !!(flags & P_FLAG);
1216 T0 = p_set;
1217 RETURN();
1218 }
1219
1220 /* Evaluate the if the branch should be taken or not. Needs to be done in
1221 the original sequence. The acutal branch is rescheduled to right after the
1222 delay-slot. */
1223 void OPPROTO op_evaluate_bcc (void)
1224 {
1225 env->btaken = T0;
1226 RETURN();
1227 }
1228
1229 /* this one is used on every alu op, optimize it!. */
1230 void OPPROTO op_goto_if_not_x (void)
1231 {
1232 if (env->pregs[PR_CCS] & X_FLAG)
1233 GOTO_LABEL_PARAM(1);
1234 RETURN();
1235 }
1236
1237 void OPPROTO op_cc_jmp (void)
1238 {
1239 if (env->btaken)
1240 env->pc = PARAM1;
1241 else
1242 env->pc = PARAM2;
1243 RETURN();
1244 }
1245
1246 void OPPROTO op_cc_ngoto (void)
1247 {
1248 if (!env->btaken)
1249 GOTO_LABEL_PARAM(1);
1250 RETURN();
1251 }
1252
1253 void OPPROTO op_movl_btarget_T0 (void)
1254 {
1255 env->btarget = T0;
1256 RETURN();
1257 }
1258
1259 void OPPROTO op_jmp1 (void)
1260 {
1261 env->pc = env->btarget;
1262 RETURN();
1263 }
1264
1265 /* Load and store */
1266 #define MEMSUFFIX _raw
1267 #include "op_mem.c"
1268 #undef MEMSUFFIX
1269 #if !defined(CONFIG_USER_ONLY)
1270 #define MEMSUFFIX _user
1271 #include "op_mem.c"
1272 #undef MEMSUFFIX
1273
1274 #define MEMSUFFIX _kernel
1275 #include "op_mem.c"
1276 #undef MEMSUFFIX
1277 #endif