CRIS MMU emulation, by Edgar E. Iglesias.
[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
22 #define REGNAME r0
23 #define REG (env->regs[0])
24 #include "op_template.h"
25
26 #define REGNAME r1
27 #define REG (env->regs[1])
28 #include "op_template.h"
29
30 #define REGNAME r2
31 #define REG (env->regs[2])
32 #include "op_template.h"
33
34 #define REGNAME r3
35 #define REG (env->regs[3])
36 #include "op_template.h"
37
38 #define REGNAME r4
39 #define REG (env->regs[4])
40 #include "op_template.h"
41
42 #define REGNAME r5
43 #define REG (env->regs[5])
44 #include "op_template.h"
45
46 #define REGNAME r6
47 #define REG (env->regs[6])
48 #include "op_template.h"
49
50 #define REGNAME r7
51 #define REG (env->regs[7])
52 #include "op_template.h"
53
54 #define REGNAME r8
55 #define REG (env->regs[8])
56 #include "op_template.h"
57
58 #define REGNAME r9
59 #define REG (env->regs[9])
60 #include "op_template.h"
61
62 #define REGNAME r10
63 #define REG (env->regs[10])
64 #include "op_template.h"
65
66 #define REGNAME r11
67 #define REG (env->regs[11])
68 #include "op_template.h"
69
70 #define REGNAME r12
71 #define REG (env->regs[12])
72 #include "op_template.h"
73
74 #define REGNAME r13
75 #define REG (env->regs[13])
76 #include "op_template.h"
77
78 #define REGNAME r14
79 #define REG (env->regs[14])
80 #include "op_template.h"
81
82 #define REGNAME r15
83 #define REG (env->regs[15])
84 #include "op_template.h"
85
86
87 #define REGNAME p0
88 #define REG (env->pregs[0])
89 #include "op_template.h"
90
91 #define REGNAME p1
92 #define REG (env->pregs[1])
93 #include "op_template.h"
94
95 #define REGNAME p2
96 #define REG (env->pregs[2])
97 #include "op_template.h"
98
99 #define REGNAME p3
100 #define REG (env->pregs[3])
101 #include "op_template.h"
102
103 #define REGNAME p4
104 #define REG (env->pregs[4])
105 #include "op_template.h"
106
107 #define REGNAME p5
108 #define REG (env->pregs[5])
109 #include "op_template.h"
110
111 #define REGNAME p6
112 #define REG (env->pregs[6])
113 #include "op_template.h"
114
115 #define REGNAME p7
116 #define REG (env->pregs[7])
117 #include "op_template.h"
118
119 #define REGNAME p8
120 #define REG (env->pregs[8])
121 #include "op_template.h"
122
123 #define REGNAME p9
124 #define REG (env->pregs[9])
125 #include "op_template.h"
126
127 #define REGNAME p10
128 #define REG (env->pregs[10])
129 #include "op_template.h"
130
131 #define REGNAME p11
132 #define REG (env->pregs[11])
133 #include "op_template.h"
134
135 #define REGNAME p12
136 #define REG (env->pregs[12])
137 #include "op_template.h"
138
139 #define REGNAME p13
140 #define REG (env->pregs[13])
141 #include "op_template.h"
142
143 #define REGNAME p14
144 #define REG (env->pregs[14])
145 #include "op_template.h"
146
147 #define REGNAME p15
148 #define REG (env->pregs[15])
149 #include "op_template.h"
150
151 /* Microcode.  */
152
153 void OPPROTO op_exit_tb (void)
154 {
155         EXIT_TB();
156 }
157
158 void OPPROTO op_goto_tb0 (void)
159 {
160         GOTO_TB(op_goto_tb0, PARAM1, 0);
161         RETURN();
162 }
163
164 void OPPROTO op_goto_tb1 (void)
165 {
166         GOTO_TB(op_goto_tb1, PARAM1, 1);
167         RETURN();
168 }
169
170 void OPPROTO op_break_im(void)
171 {
172         env->trapnr = PARAM1;
173         env->exception_index = EXCP_BREAK;
174         cpu_loop_exit();
175 }
176
177 void OPPROTO op_debug(void)
178 {
179         env->exception_index = EXCP_DEBUG;
180         cpu_loop_exit();
181 }
182
183 void OPPROTO op_exec_insn(void)
184 {
185         env->stats.exec_insns++;
186         RETURN();
187 }
188 void OPPROTO op_exec_load(void)
189 {
190         env->stats.exec_loads++;
191         RETURN();
192 }
193 void OPPROTO op_exec_store(void)
194 {
195         env->stats.exec_stores++;
196         RETURN();
197 }
198
199 void OPPROTO op_ccs_lshift (void)
200 {
201         uint32_t ccs;
202
203         /* Apply the ccs shift.  */
204         ccs = env->pregs[SR_CCS];
205         ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2);
206         env->pregs[SR_CCS] = ccs;
207 }
208 void OPPROTO op_ccs_rshift (void)
209 {
210         uint32_t ccs;
211
212         /* Apply the ccs shift.  */
213         ccs = env->pregs[SR_CCS];
214         ccs = (ccs & 0xc0000000) | (ccs >> 10);
215         env->pregs[SR_CCS] = ccs;
216 }
217
218 void OPPROTO op_setf (void)
219 {
220         env->pregs[SR_CCS] |= PARAM1;
221         RETURN();
222 }
223
224 void OPPROTO op_clrf (void)
225 {
226         env->pregs[SR_CCS] &= ~PARAM1;
227         RETURN();
228 }
229
230 void OPPROTO op_movl_debug1_T0 (void)
231 {
232         env->debug1 = T0;
233         RETURN();
234 }
235
236 void OPPROTO op_movl_debug2_T0 (void)
237 {
238         env->debug2 = T0;
239         RETURN();
240 }
241
242 void OPPROTO op_movl_debug3_T0 (void)
243 {
244         env->debug3 = T0;
245         RETURN();
246 }
247 void OPPROTO op_movl_debug1_T1 (void)
248 {
249         env->debug1 = T1;
250         RETURN();
251 }
252
253 void OPPROTO op_movl_debug2_T1 (void)
254 {
255         env->debug2 = T1;
256         RETURN();
257 }
258
259 void OPPROTO op_movl_debug3_T1 (void)
260 {
261         env->debug3 = T1;
262         RETURN();
263 }
264 void OPPROTO op_movl_debug3_im (void)
265 {
266         env->debug3 = PARAM1;
267         RETURN();
268 }
269 void OPPROTO op_movl_T0_flags (void)
270 {
271         T0 = env->pregs[SR_CCS];
272         RETURN();
273 }
274 void OPPROTO op_movl_flags_T0 (void)
275 {
276         env->pregs[SR_CCS] = T0;
277         RETURN();
278 }
279
280 void OPPROTO op_movl_sreg_T0 (void)
281 {
282         env->sregs[env->pregs[SR_SRS]][PARAM1] = T0;
283         RETURN();
284 }
285
286 void OPPROTO op_movl_tlb_lo_T0 (void)
287 {
288         int srs;
289         srs = env->pregs[SR_SRS];
290         if (srs == 1 || srs == 2)
291         {
292                 int set;
293                 int idx;
294                 uint32_t lo, hi;
295
296                 idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
297                 set >>= 4;
298                 set &= 3;
299
300                 idx &= 31;
301                 /* We've just made a write to tlb_lo.  */
302                 lo = env->sregs[SFR_RW_MM_TLB_LO];
303                 hi = env->sregs[SFR_RW_MM_TLB_HI];
304                 env->tlbsets[srs - 1][set][idx].lo = lo;
305                 env->tlbsets[srs - 1][set][idx].hi = hi;
306         }
307
308         RETURN();
309 }
310
311 void OPPROTO op_movl_T0_sreg (void)
312 {
313         T0 = env->sregs[env->pregs[SR_SRS]][PARAM1];
314         RETURN();
315 }
316
317 void OPPROTO op_update_cc (void)
318 {
319         env->cc_op = PARAM1;
320         env->cc_dest = PARAM2;
321         env->cc_src = PARAM3;
322         RETURN();
323 }
324
325 void OPPROTO op_update_cc_op (void)
326 {
327         env->cc_op = PARAM1;
328         RETURN();
329 }
330
331 void OPPROTO op_update_cc_mask (void)
332 {
333         env->cc_mask = PARAM1;
334         RETURN();
335 }
336
337 void OPPROTO op_update_cc_dest_T0 (void)
338 {
339         env->cc_dest = T0;
340         RETURN();
341 }
342
343 void OPPROTO op_update_cc_result_T0 (void)
344 {
345         env->cc_result = T0;
346         RETURN();
347 }
348
349 void OPPROTO op_update_cc_size_im (void)
350 {
351         env->cc_size = PARAM1;
352         RETURN();
353 }
354
355 void OPPROTO op_update_cc_src_T1 (void)
356 {
357         env->cc_src = T1;
358         RETURN();
359 }
360 void OPPROTO op_update_cc_x (void)
361 {
362         env->cc_x_live = PARAM1;
363         env->cc_x = PARAM2;
364         RETURN();
365 }
366
367 /* FIXME: is this allowed?  */
368 extern inline void evaluate_flags_writeback(uint32_t flags)
369 {
370         int x;
371
372         /* Extended arithmetics, leave the z flag alone.  */
373         env->debug3 = env->pregs[SR_CCS];
374
375         if (env->cc_x_live)
376                 x = env->cc_x;
377         else
378                 x = env->pregs[SR_CCS] & X_FLAG;
379
380         if ((x || env->cc_op == CC_OP_ADDC)
381             && flags & Z_FLAG)
382                 env->cc_mask &= ~Z_FLAG;
383
384         /* all insn clear the x-flag except setf or clrf.  */
385         env->pregs[SR_CCS] &= ~(env->cc_mask | X_FLAG);
386         flags &= env->cc_mask;
387         env->pregs[SR_CCS] |= flags;
388         RETURN();
389 }
390
391 void OPPROTO op_evaluate_flags_muls(void)
392 {
393         uint32_t src;
394         uint32_t dst;
395         uint32_t res;
396         uint32_t flags = 0;
397         /* were gonna have to redo the muls.  */
398         int64_t tmp, t0 ,t1;
399         int32_t mof;
400         int dneg;
401
402         src = env->cc_src;
403         dst = env->cc_dest;
404         res = env->cc_result;
405
406
407         /* cast into signed values to make GCC sign extend.  */
408         t0 = (int32_t)src;
409         t1 = (int32_t)dst;
410         dneg = ((int32_t)res) < 0;
411
412         tmp = t0 * t1;
413         mof = tmp >> 32;
414         if (tmp == 0)
415                 flags |= Z_FLAG;
416         else if (tmp < 0)
417                 flags |= N_FLAG;
418         if ((dneg && mof != -1)
419             || (!dneg && mof != 0))
420                 flags |= V_FLAG;
421         evaluate_flags_writeback(flags);
422         RETURN();
423 }
424
425 void OPPROTO op_evaluate_flags_mulu(void)
426 {
427         uint32_t src;
428         uint32_t dst;
429         uint32_t res;
430         uint32_t flags = 0;
431         /* were gonna have to redo the muls.  */
432         uint64_t tmp, t0 ,t1;
433         uint32_t mof;
434
435         src = env->cc_src;
436         dst = env->cc_dest;
437         res = env->cc_result;
438
439
440         /* cast into signed values to make GCC sign extend.  */
441         t0 = src;
442         t1 = dst;
443
444         tmp = t0 * t1;
445         mof = tmp >> 32;
446         if (tmp == 0)
447                 flags |= Z_FLAG;
448         else if (tmp >> 63)
449                 flags |= N_FLAG;
450         if (mof)
451                 flags |= V_FLAG;
452
453         evaluate_flags_writeback(flags);
454         RETURN();
455 }
456
457 void OPPROTO op_evaluate_flags_mcp(void)
458 {
459         uint32_t src;
460         uint32_t dst;
461         uint32_t res;
462         uint32_t flags = 0;
463
464         src = env->cc_src;
465         dst = env->cc_dest;
466         res = env->cc_result;
467
468         if ((res & 0x80000000L) != 0L)
469         {
470                 flags |= N_FLAG;
471                 if (((src & 0x80000000L) == 0L)
472                     && ((dst & 0x80000000L) == 0L))
473                 {
474                         flags |= V_FLAG;
475                 }
476                 else if (((src & 0x80000000L) != 0L) &&
477                          ((dst & 0x80000000L) != 0L))
478                 {
479                         flags |= R_FLAG;
480                 }
481         }
482         else
483         {
484                 if (res == 0L)
485                         flags |= Z_FLAG;
486                 if (((src & 0x80000000L) != 0L)
487                     && ((dst & 0x80000000L) != 0L))
488                         flags |= V_FLAG;
489                 if ((dst & 0x80000000L) != 0L
490                     || (src & 0x80000000L) != 0L)
491                         flags |= R_FLAG;
492         }
493
494         evaluate_flags_writeback(flags);
495         RETURN();
496 }
497
498 void OPPROTO op_evaluate_flags_alu_4(void)
499 {
500         uint32_t src;
501         uint32_t dst;
502         uint32_t res;
503         uint32_t flags = 0;
504
505         src = env->cc_src;
506         dst = env->cc_dest;
507         res = env->cc_result;
508
509         if ((res & 0x80000000L) != 0L)
510         {
511                 flags |= N_FLAG;
512                 if (((src & 0x80000000L) == 0L)
513                     && ((dst & 0x80000000L) == 0L))
514                 {
515                         flags |= V_FLAG;
516                 }
517                 else if (((src & 0x80000000L) != 0L) &&
518                          ((dst & 0x80000000L) != 0L))
519                 {
520                         flags |= C_FLAG;
521                 }
522         }
523         else
524         {
525                 if (res == 0L)
526                         flags |= Z_FLAG;
527                 if (((src & 0x80000000L) != 0L)
528                     && ((dst & 0x80000000L) != 0L))
529                         flags |= V_FLAG;
530                 if ((dst & 0x80000000L) != 0L
531                     || (src & 0x80000000L) != 0L)
532                         flags |= C_FLAG;
533         }
534
535         if (env->cc_op == CC_OP_SUB
536             || env->cc_op == CC_OP_CMP) {
537                 flags ^= C_FLAG;
538         }
539         evaluate_flags_writeback(flags);
540         RETURN();
541 }
542
543 void OPPROTO op_evaluate_flags_move_4 (void)
544 {
545         uint32_t src;
546         uint32_t res;
547         uint32_t flags = 0;
548
549         src = env->cc_src;
550         res = env->cc_result;
551
552         if ((int32_t)res < 0)
553                 flags |= N_FLAG;
554         else if (res == 0L)
555                 flags |= Z_FLAG;
556
557         evaluate_flags_writeback(flags);
558         RETURN();
559 }
560 void OPPROTO op_evaluate_flags_move_2 (void)
561 {
562         uint32_t src;
563         uint32_t flags = 0;
564         uint16_t res;
565
566         src = env->cc_src;
567         res = env->cc_result;
568
569         if ((int16_t)res < 0L)
570                 flags |= N_FLAG;
571         else if (res == 0)
572                 flags |= Z_FLAG;
573
574         evaluate_flags_writeback(flags);
575         RETURN();
576 }
577
578 /* TODO: This is expensive. We could split things up and only evaluate part of
579    CCR on a need to know basis. For now, we simply re-evaluate everything.  */
580 void OPPROTO op_evaluate_flags (void)
581 {
582         uint32_t src;
583         uint32_t dst;
584         uint32_t res;
585         uint32_t flags = 0;
586
587         src = env->cc_src;
588         dst = env->cc_dest;
589         res = env->cc_result;
590
591
592         /* Now, evaluate the flags. This stuff is based on
593            Per Zander's CRISv10 simulator.  */
594         switch (env->cc_size)
595         {
596                 case 1:
597                         if ((res & 0x80L) != 0L)
598                         {
599                                 flags |= N_FLAG;
600                                 if (((src & 0x80L) == 0L)
601                                     && ((dst & 0x80L) == 0L))
602                                 {
603                                         flags |= V_FLAG;
604                                 }
605                                 else if (((src & 0x80L) != 0L)
606                                          && ((dst & 0x80L) != 0L))
607                                 {
608                                         flags |= C_FLAG;
609                                 }
610                         }
611                         else
612                         {
613                                 if ((res & 0xFFL) == 0L)
614                                 {
615                                         flags |= Z_FLAG;
616                                 }
617                                 if (((src & 0x80L) != 0L)
618                                     && ((dst & 0x80L) != 0L))
619                                 {
620                                         flags |= V_FLAG;
621                                 }
622                                 if ((dst & 0x80L) != 0L
623                                     || (src & 0x80L) != 0L)
624                                 {
625                                         flags |= C_FLAG;
626                                 }
627                         }
628                         break;
629                 case 2:
630                         if ((res & 0x8000L) != 0L)
631                         {
632                                 flags |= N_FLAG;
633                                 if (((src & 0x8000L) == 0L)
634                                     && ((dst & 0x8000L) == 0L))
635                                 {
636                                         flags |= V_FLAG;
637                                 }
638                                 else if (((src & 0x8000L) != 0L)
639                                          && ((dst & 0x8000L) != 0L))
640                                 {
641                                         flags |= C_FLAG;
642                                 }
643                         }
644                         else
645                         {
646                                 if ((res & 0xFFFFL) == 0L)
647                                 {
648                                         flags |= Z_FLAG;
649                                 }
650                                 if (((src & 0x8000L) != 0L)
651                                     && ((dst & 0x8000L) != 0L))
652                                 {
653                                         flags |= V_FLAG;
654                                 }
655                                 if ((dst & 0x8000L) != 0L
656                                     || (src & 0x8000L) != 0L)
657                                 {
658                                         flags |= C_FLAG;
659                                 }
660                         }
661                         break;
662                 case 4:
663                         if ((res & 0x80000000L) != 0L)
664                         {
665                                 flags |= N_FLAG;
666                                 if (((src & 0x80000000L) == 0L)
667                                     && ((dst & 0x80000000L) == 0L))
668                                 {
669                                         flags |= V_FLAG;
670                                 }
671                                 else if (((src & 0x80000000L) != 0L) &&
672                                          ((dst & 0x80000000L) != 0L))
673                                 {
674                                         flags |= C_FLAG;
675                                 }
676                         }
677                         else
678                         {
679                                 if (res == 0L)
680                                         flags |= Z_FLAG;
681                                 if (((src & 0x80000000L) != 0L)
682                                     && ((dst & 0x80000000L) != 0L))
683                                         flags |= V_FLAG;
684                                 if ((dst & 0x80000000L) != 0L
685                                     || (src & 0x80000000L) != 0L)
686                                         flags |= C_FLAG;
687                         }
688                         break;
689                 default:
690                         break;
691         }
692
693         if (env->cc_op == CC_OP_SUB
694             || env->cc_op == CC_OP_CMP) {
695                 flags ^= C_FLAG;
696         }
697         evaluate_flags_writeback(flags);
698         RETURN();
699 }
700
701 void OPPROTO op_extb_T0_T0 (void)
702 {
703         T0 = ((int8_t)T0);
704         RETURN();
705 }
706 void OPPROTO op_extb_T1_T0 (void)
707 {
708         T1 = ((int8_t)T0);
709         RETURN();
710 }
711 void OPPROTO op_extb_T1_T1 (void)
712 {
713         T1 = ((int8_t)T1);
714         RETURN();
715 }
716 void OPPROTO op_zextb_T0_T0 (void)
717 {
718         T0 = ((uint8_t)T0);
719         RETURN();
720 }
721 void OPPROTO op_zextb_T1_T0 (void)
722 {
723         T1 = ((uint8_t)T0);
724         RETURN();
725 }
726 void OPPROTO op_zextb_T1_T1 (void)
727 {
728         T1 = ((uint8_t)T1);
729         RETURN();
730 }
731 void OPPROTO op_extw_T0_T0 (void)
732 {
733         T0 = ((int16_t)T0);
734         RETURN();
735 }
736 void OPPROTO op_extw_T1_T0 (void)
737 {
738         T1 = ((int16_t)T0);
739         RETURN();
740 }
741 void OPPROTO op_extw_T1_T1 (void)
742 {
743         T1 = ((int16_t)T1);
744         RETURN();
745 }
746
747 void OPPROTO op_zextw_T0_T0 (void)
748 {
749         T0 = ((uint16_t)T0);
750         RETURN();
751 }
752 void OPPROTO op_zextw_T1_T0 (void)
753 {
754         T1 = ((uint16_t)T0);
755         RETURN();
756 }
757
758 void OPPROTO op_zextw_T1_T1 (void)
759 {
760         T1 = ((uint16_t)T1);
761         RETURN();
762 }
763
764 void OPPROTO op_movl_T0_im (void)
765 {
766         T0 = PARAM1;
767         RETURN();
768 }
769 void OPPROTO op_movl_T1_im (void)
770 {
771         T1 = PARAM1;
772         RETURN();
773 }
774
775 void OPPROTO op_addl_T0_im (void)
776 {
777         T0 += PARAM1;
778         RETURN();
779 }
780
781 void OPPROTO op_addl_T1_im (void)
782 {
783         T1 += PARAM1;
784         RETURN();
785
786 }
787 void OPPROTO op_subl_T0_im (void)
788 {
789         T0 -= PARAM1;
790         RETURN();
791 }
792
793 void OPPROTO op_addxl_T0_C (void)
794 {
795         if (env->pregs[SR_CCS] & X_FLAG)
796                 T0 += !!(env->pregs[SR_CCS] & C_FLAG);
797         RETURN();
798 }
799 void OPPROTO op_subxl_T0_C (void)
800 {
801         if (env->pregs[SR_CCS] & X_FLAG)
802                 T0 -= !!(env->pregs[SR_CCS] & C_FLAG);
803         RETURN();
804 }
805 void OPPROTO op_addl_T0_C (void)
806 {
807         T0 += !!(env->pregs[SR_CCS] & C_FLAG);
808         RETURN();
809 }
810 void OPPROTO op_addl_T0_R (void)
811 {
812         T0 += !!(env->pregs[SR_CCS] & R_FLAG);
813         RETURN();
814 }
815
816 void OPPROTO op_clr_R (void)
817 {
818         env->pregs[SR_CCS] &= ~R_FLAG;
819         RETURN();
820 }
821
822
823 void OPPROTO op_andl_T0_im (void)
824 {
825         T0 &= PARAM1;
826         RETURN();
827 }
828
829 void OPPROTO op_andl_T1_im (void)
830 {
831         T1 &= PARAM1;
832         RETURN();
833 }
834
835 void OPPROTO op_movl_T0_T1 (void)
836 {
837         T0 = T1;
838         RETURN();
839 }
840
841 void OPPROTO op_swp_T0_T1 (void)
842 {
843         T0 ^= T1;
844         T1 ^= T0;
845         T0 ^= T1;
846         RETURN();
847 }
848
849 void OPPROTO op_movl_T1_T0 (void)
850 {
851         T1 = T0;
852         RETURN();
853 }
854
855 void OPPROTO op_movl_pc_T0 (void)
856 {
857         env->pc = T0;
858         RETURN();
859 }
860
861 void OPPROTO op_movl_T0_0 (void)
862 {
863         T0 = 0;
864         RETURN();
865 }
866
867 void OPPROTO op_addl_T0_T1 (void)
868 {
869         T0 += T1;
870         RETURN();
871 }
872
873 void OPPROTO op_subl_T0_T1 (void)
874 {
875         T0 -= T1;
876         RETURN();
877 }
878
879 void OPPROTO op_absl_T1_T1 (void)
880 {
881         int32_t st = T1;
882
883         T1 = st < 0 ? -st : st;
884         RETURN();
885 }
886
887 void OPPROTO op_muls_T0_T1 (void)
888 {
889         int64_t tmp, t0 ,t1;
890
891         /* cast into signed values to make GCC sign extend these babies.  */
892         t0 = (int32_t)T0;
893         t1 = (int32_t)T1;
894
895         tmp = t0 * t1;
896         T0 = tmp & 0xffffffff;
897         env->pregs[REG_MOF] = tmp >> 32;
898         RETURN();
899 }
900
901 void OPPROTO op_mulu_T0_T1 (void)
902 {
903         uint64_t tmp, t0 ,t1;
904         t0 = T0;
905         t1 = T1;
906
907         tmp = t0 * t1;
908         T0 = tmp & 0xffffffff;
909         env->pregs[REG_MOF] = tmp >> 32;
910         RETURN();
911 }
912
913 void OPPROTO op_dstep_T0_T1 (void)
914 {
915         T0 <<= 1;
916         if (T0 >= T1)
917                 T0 -= T1;
918         RETURN();
919 }
920
921 void OPPROTO op_orl_T0_T1 (void)
922 {
923         T0 |= T1;
924         RETURN();
925 }
926
927 void OPPROTO op_andl_T0_T1 (void)
928 {
929         T0 &= T1;
930         RETURN();
931 }
932
933 void OPPROTO op_xorl_T0_T1 (void)
934 {
935         T0 ^= T1;
936         RETURN();
937 }
938
939 void OPPROTO op_lsll_T0_T1 (void)
940 {
941         int s = T1;
942         if (s > 31)
943                 T0 = 0;
944         else
945                 T0 <<= s;
946         RETURN();
947 }
948
949 void OPPROTO op_lsll_T0_im (void)
950 {
951         T0 <<= PARAM1;
952         RETURN();
953 }
954
955 void OPPROTO op_lsrl_T0_T1 (void)
956 {
957         int s = T1;
958         if (s > 31)
959                 T0 = 0;
960         else
961                 T0 >>= s;
962         RETURN();
963 }
964
965 /* Rely on GCC emitting an arithmetic shift for signed right shifts.  */
966 void OPPROTO op_asrl_T0_T1 (void)
967 {
968         int s = T1;
969         if (s > 31)
970                 T0 = T0 & 0x80000000 ? -1 : 0;
971         else
972                 T0 = (int32_t)T0 >> s;
973         RETURN();
974 }
975
976 void OPPROTO op_btst_T0_T1 (void)
977 {
978         /* FIXME: clean this up.  */
979
980         /* des ref:
981            The N flag is set according to the selected bit in the dest reg.
982            The Z flag is set if the selected bit and all bits to the right are
983            zero.
984            The destination reg is not affected.*/
985         unsigned int fz, sbit, bset, mask, masked_t0;
986
987         sbit = T1 & 31;
988         bset = !!(T0 & (1 << sbit));
989         mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1;
990         masked_t0 = T0 & mask;
991         fz = !(masked_t0 | bset);
992         /* Set the N and Z flags accordingly.  */
993         T0 = (bset << 3) | (fz << 2);
994         RETURN();
995 }
996
997 void OPPROTO op_bound_T0_T1 (void)
998 {
999         if (T0 > T1)
1000                 T0 = T1;
1001         RETURN();
1002 }
1003
1004 void OPPROTO op_lz_T0_T1 (void)
1005 {
1006         if (T1 == 0)
1007                 T0 = 32;
1008         else
1009                 T0 = __builtin_clz(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