3c50574e769e5508bb7da55f33a8478c8a80a84a
[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         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