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