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