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