Fix userland ELF loader for zero sized BSS.
[qemu] / target-arm / op.c
1 /*
2  *  ARM micro operations
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *  Copyright (c) 2005 CodeSourcery, LLC
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #include "exec.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 #define SET_REG(x) REG = x & ~(uint32_t)1
86 #include "op_template.h"
87
88 void OPPROTO op_bx_T0(void)
89 {
90   env->regs[15] = T0 & ~(uint32_t)1;
91   env->thumb = (T0 & 1) != 0;
92 }
93
94 void OPPROTO op_movl_T0_0(void)
95 {
96     T0 = 0;
97 }
98
99 void OPPROTO op_movl_T0_im(void)
100 {
101     T0 = PARAM1;
102 }
103
104 void OPPROTO op_movl_T0_T1(void)
105 {
106     T0 = T1;
107 }
108
109 void OPPROTO op_movl_T1_im(void)
110 {
111     T1 = PARAM1;
112 }
113
114 void OPPROTO op_mov_CF_T1(void)
115 {
116     env->CF = ((uint32_t)T1) >> 31;
117 }
118
119 void OPPROTO op_movl_T2_im(void)
120 {
121     T2 = PARAM1;
122 }
123
124 void OPPROTO op_addl_T1_im(void)
125 {
126     T1 += PARAM1;
127 }
128
129 void OPPROTO op_addl_T1_T2(void)
130 {
131     T1 += T2;
132 }
133
134 void OPPROTO op_subl_T1_T2(void)
135 {
136     T1 -= T2;
137 }
138
139 void OPPROTO op_addl_T0_T1(void)
140 {
141     T0 += T1;
142 }
143
144 void OPPROTO op_addl_T0_T1_cc(void)
145 {
146     unsigned int src1;
147     src1 = T0;
148     T0 += T1;
149     env->NZF = T0;
150     env->CF = T0 < src1;
151     env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
152 }
153
154 void OPPROTO op_adcl_T0_T1(void)
155 {
156     T0 += T1 + env->CF;
157 }
158
159 void OPPROTO op_adcl_T0_T1_cc(void)
160 {
161     unsigned int src1;
162     src1 = T0;
163     if (!env->CF) {
164         T0 += T1;
165         env->CF = T0 < src1;
166     } else {
167         T0 += T1 + 1;
168         env->CF = T0 <= src1;
169     }
170     env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
171     env->NZF = T0;
172     FORCE_RET();
173 }
174
175 #define OPSUB(sub, sbc, res, T0, T1)            \
176                                                 \
177 void OPPROTO op_ ## sub ## l_T0_T1(void)        \
178 {                                               \
179     res = T0 - T1;                              \
180 }                                               \
181                                                 \
182 void OPPROTO op_ ## sub ## l_T0_T1_cc(void)     \
183 {                                               \
184     unsigned int src1;                          \
185     src1 = T0;                                  \
186     T0 -= T1;                                   \
187     env->NZF = T0;                              \
188     env->CF = src1 >= T1;                       \
189     env->VF = (src1 ^ T1) & (src1 ^ T0);        \
190     res = T0;                                   \
191 }                                               \
192                                                 \
193 void OPPROTO op_ ## sbc ## l_T0_T1(void)        \
194 {                                               \
195     res = T0 - T1 + env->CF - 1;                \
196 }                                               \
197                                                 \
198 void OPPROTO op_ ## sbc ## l_T0_T1_cc(void)     \
199 {                                               \
200     unsigned int src1;                          \
201     src1 = T0;                                  \
202     if (!env->CF) {                             \
203         T0 = T0 - T1 - 1;                       \
204         env->CF = src1 > T1;                    \
205     } else {                                    \
206         T0 = T0 - T1;                           \
207         env->CF = src1 >= T1;                   \
208     }                                           \
209     env->VF = (src1 ^ T1) & (src1 ^ T0);        \
210     env->NZF = T0;                              \
211     res = T0;                                   \
212     FORCE_RET();                                \
213 }
214
215 OPSUB(sub, sbc, T0, T0, T1)
216
217 OPSUB(rsb, rsc, T0, T1, T0)
218
219 void OPPROTO op_andl_T0_T1(void)
220 {
221     T0 &= T1;
222 }
223
224 void OPPROTO op_xorl_T0_T1(void)
225 {
226     T0 ^= T1;
227 }
228
229 void OPPROTO op_orl_T0_T1(void)
230 {
231     T0 |= T1;
232 }
233
234 void OPPROTO op_bicl_T0_T1(void)
235 {
236     T0 &= ~T1;
237 }
238
239 void OPPROTO op_notl_T1(void)
240 {
241     T1 = ~T1;
242 }
243
244 void OPPROTO op_logic_T0_cc(void)
245 {
246     env->NZF = T0;
247 }
248
249 void OPPROTO op_logic_T1_cc(void)
250 {
251     env->NZF = T1;
252 }
253
254 #define EIP (env->regs[15])
255
256 void OPPROTO op_test_eq(void)
257 {
258     if (env->NZF == 0)
259         GOTO_LABEL_PARAM(1);;
260     FORCE_RET();
261 }
262
263 void OPPROTO op_test_ne(void)
264 {
265     if (env->NZF != 0)
266         GOTO_LABEL_PARAM(1);;
267     FORCE_RET();
268 }
269
270 void OPPROTO op_test_cs(void)
271 {
272     if (env->CF != 0)
273         GOTO_LABEL_PARAM(1);
274     FORCE_RET();
275 }
276
277 void OPPROTO op_test_cc(void)
278 {
279     if (env->CF == 0)
280         GOTO_LABEL_PARAM(1);
281     FORCE_RET();
282 }
283
284 void OPPROTO op_test_mi(void)
285 {
286     if ((env->NZF & 0x80000000) != 0)
287         GOTO_LABEL_PARAM(1);
288     FORCE_RET();
289 }
290
291 void OPPROTO op_test_pl(void)
292 {
293     if ((env->NZF & 0x80000000) == 0)
294         GOTO_LABEL_PARAM(1);
295     FORCE_RET();
296 }
297
298 void OPPROTO op_test_vs(void)
299 {
300     if ((env->VF & 0x80000000) != 0)
301         GOTO_LABEL_PARAM(1);
302     FORCE_RET();
303 }
304
305 void OPPROTO op_test_vc(void)
306 {
307     if ((env->VF & 0x80000000) == 0)
308         GOTO_LABEL_PARAM(1);
309     FORCE_RET();
310 }
311
312 void OPPROTO op_test_hi(void)
313 {
314     if (env->CF != 0 && env->NZF != 0)
315         GOTO_LABEL_PARAM(1);
316     FORCE_RET();
317 }
318
319 void OPPROTO op_test_ls(void)
320 {
321     if (env->CF == 0 || env->NZF == 0)
322         GOTO_LABEL_PARAM(1);
323     FORCE_RET();
324 }
325
326 void OPPROTO op_test_ge(void)
327 {
328     if (((env->VF ^ env->NZF) & 0x80000000) == 0)
329         GOTO_LABEL_PARAM(1);
330     FORCE_RET();
331 }
332
333 void OPPROTO op_test_lt(void)
334 {
335     if (((env->VF ^ env->NZF) & 0x80000000) != 0)
336         GOTO_LABEL_PARAM(1);
337     FORCE_RET();
338 }
339
340 void OPPROTO op_test_gt(void)
341 {
342     if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0)
343         GOTO_LABEL_PARAM(1);
344     FORCE_RET();
345 }
346
347 void OPPROTO op_test_le(void)
348 {
349     if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0)
350         GOTO_LABEL_PARAM(1);
351     FORCE_RET();
352 }
353
354 void OPPROTO op_goto_tb0(void)
355 {
356     GOTO_TB(op_goto_tb0, PARAM1, 0);
357 }
358
359 void OPPROTO op_goto_tb1(void)
360 {
361     GOTO_TB(op_goto_tb1, PARAM1, 1);
362 }
363
364 void OPPROTO op_exit_tb(void)
365 {
366     EXIT_TB();
367 }
368
369 void OPPROTO op_movl_T0_cpsr(void)
370 {
371     T0 = cpsr_read(env);
372     FORCE_RET();
373 }
374
375 void OPPROTO op_movl_T0_spsr(void)
376 {
377     T0 = env->spsr;
378 }
379
380 void OPPROTO op_movl_spsr_T0(void)
381 {
382     uint32_t mask = PARAM1;
383     env->spsr = (env->spsr & ~mask) | (T0 & mask);
384 }
385
386 void OPPROTO op_movl_cpsr_T0(void)
387 {
388     cpsr_write(env, T0, PARAM1);
389     FORCE_RET();
390 }
391
392 void OPPROTO op_mul_T0_T1(void)
393 {
394     T0 = T0 * T1;
395 }
396
397 /* 64 bit unsigned mul */
398 void OPPROTO op_mull_T0_T1(void)
399 {
400     uint64_t res;
401     res = (uint64_t)T0 * (uint64_t)T1;
402     T1 = res >> 32;
403     T0 = res;
404 }
405
406 /* 64 bit signed mul */
407 void OPPROTO op_imull_T0_T1(void)
408 {
409     uint64_t res;
410     res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
411     T1 = res >> 32;
412     T0 = res;
413 }
414
415 /* 48 bit signed mul, top 32 bits */
416 void OPPROTO op_imulw_T0_T1(void)
417 {
418   uint64_t res;
419   res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
420   T0 = res >> 16;
421 }
422
423 void OPPROTO op_addq_T0_T1(void)
424 {
425     uint64_t res;
426     res = ((uint64_t)T1 << 32) | T0;
427     res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
428     T1 = res >> 32;
429     T0 = res;
430 }
431
432 void OPPROTO op_addq_lo_T0_T1(void)
433 {
434     uint64_t res;
435     res = ((uint64_t)T1 << 32) | T0;
436     res += (uint64_t)(env->regs[PARAM1]);
437     T1 = res >> 32;
438     T0 = res;
439 }
440
441 void OPPROTO op_logicq_cc(void)
442 {
443     env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
444 }
445
446 /* memory access */
447
448 #define MEMSUFFIX _raw
449 #include "op_mem.h"
450
451 #if !defined(CONFIG_USER_ONLY)
452 #define MEMSUFFIX _user
453 #include "op_mem.h"
454 #define MEMSUFFIX _kernel
455 #include "op_mem.h"
456 #endif
457
458 /* shifts */
459
460 /* T1 based */
461
462 void OPPROTO op_shll_T1_im(void)
463 {
464     T1 = T1 << PARAM1;
465 }
466
467 void OPPROTO op_shrl_T1_im(void)
468 {
469     T1 = (uint32_t)T1 >> PARAM1;
470 }
471
472 void OPPROTO op_shrl_T1_0(void)
473 {
474     T1 = 0;
475 }
476
477 void OPPROTO op_sarl_T1_im(void)
478 {
479     T1 = (int32_t)T1 >> PARAM1;
480 }
481
482 void OPPROTO op_sarl_T1_0(void)
483 {
484     T1 = (int32_t)T1 >> 31;
485 }
486
487 void OPPROTO op_rorl_T1_im(void)
488 {
489     int shift;
490     shift = PARAM1;
491     T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
492 }
493
494 void OPPROTO op_rrxl_T1(void)
495 {
496     T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
497 }
498
499 /* T1 based, set C flag */
500 void OPPROTO op_shll_T1_im_cc(void)
501 {
502     env->CF = (T1 >> (32 - PARAM1)) & 1;
503     T1 = T1 << PARAM1;
504 }
505
506 void OPPROTO op_shrl_T1_im_cc(void)
507 {
508     env->CF = (T1 >> (PARAM1 - 1)) & 1;
509     T1 = (uint32_t)T1 >> PARAM1;
510 }
511
512 void OPPROTO op_shrl_T1_0_cc(void)
513 {
514     env->CF = (T1 >> 31) & 1;
515     T1 = 0;
516 }
517
518 void OPPROTO op_sarl_T1_im_cc(void)
519 {
520     env->CF = (T1 >> (PARAM1 - 1)) & 1;
521     T1 = (int32_t)T1 >> PARAM1;
522 }
523
524 void OPPROTO op_sarl_T1_0_cc(void)
525 {
526     env->CF = (T1 >> 31) & 1;
527     T1 = (int32_t)T1 >> 31;
528 }
529
530 void OPPROTO op_rorl_T1_im_cc(void)
531 {
532     int shift;
533     shift = PARAM1;
534     env->CF = (T1 >> (shift - 1)) & 1;
535     T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
536 }
537
538 void OPPROTO op_rrxl_T1_cc(void)
539 {
540     uint32_t c;
541     c = T1 & 1;
542     T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
543     env->CF = c;
544 }
545
546 /* T2 based */
547 void OPPROTO op_shll_T2_im(void)
548 {
549     T2 = T2 << PARAM1;
550 }
551
552 void OPPROTO op_shrl_T2_im(void)
553 {
554     T2 = (uint32_t)T2 >> PARAM1;
555 }
556
557 void OPPROTO op_shrl_T2_0(void)
558 {
559     T2 = 0;
560 }
561
562 void OPPROTO op_sarl_T2_im(void)
563 {
564     T2 = (int32_t)T2 >> PARAM1;
565 }
566
567 void OPPROTO op_sarl_T2_0(void)
568 {
569     T2 = (int32_t)T2 >> 31;
570 }
571
572 void OPPROTO op_rorl_T2_im(void)
573 {
574     int shift;
575     shift = PARAM1;
576     T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
577 }
578
579 void OPPROTO op_rrxl_T2(void)
580 {
581     T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31);
582 }
583
584 /* T1 based, use T0 as shift count */
585
586 void OPPROTO op_shll_T1_T0(void)
587 {
588     int shift;
589     shift = T0 & 0xff;
590     if (shift >= 32)
591         T1 = 0;
592     else
593         T1 = T1 << shift;
594     FORCE_RET();
595 }
596
597 void OPPROTO op_shrl_T1_T0(void)
598 {
599     int shift;
600     shift = T0 & 0xff;
601     if (shift >= 32)
602         T1 = 0;
603     else
604         T1 = (uint32_t)T1 >> shift;
605     FORCE_RET();
606 }
607
608 void OPPROTO op_sarl_T1_T0(void)
609 {
610     int shift;
611     shift = T0 & 0xff;
612     if (shift >= 32)
613         shift = 31;
614     T1 = (int32_t)T1 >> shift;
615 }
616
617 void OPPROTO op_rorl_T1_T0(void)
618 {
619     int shift;
620     shift = T0 & 0x1f;
621     if (shift) {
622         T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
623     }
624     FORCE_RET();
625 }
626
627 /* T1 based, use T0 as shift count and compute CF */
628
629 void OPPROTO op_shll_T1_T0_cc(void)
630 {
631     int shift;
632     shift = T0 & 0xff;
633     if (shift >= 32) {
634         if (shift == 32)
635             env->CF = T1 & 1;
636         else
637             env->CF = 0;
638         T1 = 0;
639     } else if (shift != 0) {
640         env->CF = (T1 >> (32 - shift)) & 1;
641         T1 = T1 << shift;
642     }
643     FORCE_RET();
644 }
645
646 void OPPROTO op_shrl_T1_T0_cc(void)
647 {
648     int shift;
649     shift = T0 & 0xff;
650     if (shift >= 32) {
651         if (shift == 32)
652             env->CF = (T1 >> 31) & 1;
653         else
654             env->CF = 0;
655         T1 = 0;
656     } else if (shift != 0) {
657         env->CF = (T1 >> (shift - 1)) & 1;
658         T1 = (uint32_t)T1 >> shift;
659     }
660     FORCE_RET();
661 }
662
663 void OPPROTO op_sarl_T1_T0_cc(void)
664 {
665     int shift;
666     shift = T0 & 0xff;
667     if (shift >= 32) {
668         env->CF = (T1 >> 31) & 1;
669         T1 = (int32_t)T1 >> 31;
670     } else {
671         env->CF = (T1 >> (shift - 1)) & 1;
672         T1 = (int32_t)T1 >> shift;
673     }
674     FORCE_RET();
675 }
676
677 void OPPROTO op_rorl_T1_T0_cc(void)
678 {
679     int shift1, shift;
680     shift1 = T0 & 0xff;
681     shift = shift1 & 0x1f;
682     if (shift == 0) {
683         if (shift1 != 0)
684             env->CF = (T1 >> 31) & 1;
685     } else {
686         env->CF = (T1 >> (shift - 1)) & 1;
687         T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
688     }
689     FORCE_RET();
690 }
691
692 /* misc */
693 void OPPROTO op_clz_T0(void)
694 {
695     int count;
696     for (count = 32; T0 > 0; count--)
697         T0 = T0 >> 1;
698     T0 = count;
699     FORCE_RET();
700 }
701
702 void OPPROTO op_sarl_T0_im(void)
703 {
704     T0 = (int32_t)T0 >> PARAM1;
705 }
706
707 /* Sign/zero extend */
708 void OPPROTO op_sxth_T0(void)
709 {
710   T0 = (int16_t)T0;
711 }
712
713 void OPPROTO op_sxth_T1(void)
714 {
715   T1 = (int16_t)T1;
716 }
717
718 void OPPROTO op_sxtb_T1(void)
719 {
720     T1 = (int8_t)T1;
721 }
722
723 void OPPROTO op_uxtb_T1(void)
724 {
725     T1 = (uint8_t)T1;
726 }
727
728 void OPPROTO op_uxth_T1(void)
729 {
730     T1 = (uint16_t)T1;
731 }
732
733 void OPPROTO op_sxtb16_T1(void)
734 {
735     uint32_t res;
736     res = (uint16_t)(int8_t)T1;
737     res |= (uint32_t)(int8_t)(T1 >> 16) << 16;
738     T1 = res;
739 }
740
741 void OPPROTO op_uxtb16_T1(void)
742 {
743     uint32_t res;
744     res = (uint16_t)(uint8_t)T1;
745     res |= (uint32_t)(uint8_t)(T1 >> 16) << 16;
746     T1 = res;
747 }
748
749 #define SIGNBIT (uint32_t)0x80000000
750 /* saturating arithmetic  */
751 void OPPROTO op_addl_T0_T1_setq(void)
752 {
753   uint32_t res;
754
755   res = T0 + T1;
756   if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT))
757       env->QF = 1;
758
759   T0 = res;
760   FORCE_RET();
761 }
762
763 void OPPROTO op_addl_T0_T1_saturate(void)
764 {
765   uint32_t res;
766
767   res = T0 + T1;
768   if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) {
769       env->QF = 1;
770       if (T0 & SIGNBIT)
771           T0 = 0x80000000;
772       else
773           T0 = 0x7fffffff;
774   }
775   else
776     T0 = res;
777   
778   FORCE_RET();
779 }
780
781 void OPPROTO op_subl_T0_T1_saturate(void)
782 {
783   uint32_t res;
784
785   res = T0 - T1;
786   if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) {
787       env->QF = 1;
788       if (T0 & SIGNBIT)
789           T0 = 0x80000000;
790       else
791           T0 = 0x7fffffff;
792   }
793   else
794     T0 = res;
795   
796   FORCE_RET();
797 }
798
799 void OPPROTO op_double_T1_saturate(void)
800 {
801   int32_t val;
802
803   val = T1;
804   if (val >= 0x40000000) {
805       T1 = 0x7fffffff;
806       env->QF = 1;
807   } else if (val <= (int32_t)0xc0000000) {
808       T1 = 0x80000000;
809       env->QF = 1;
810   } else {
811       T1 = val << 1;
812   }
813   FORCE_RET();
814 }
815
816 /* thumb shift by immediate */
817 void OPPROTO op_shll_T0_im_thumb(void)
818 {
819     int shift;
820     shift = PARAM1;
821     if (shift != 0) {
822         env->CF = (T1 >> (32 - shift)) & 1;
823         T0 = T0 << shift;
824     }
825     env->NZF = T0;
826     FORCE_RET();
827 }
828
829 void OPPROTO op_shrl_T0_im_thumb(void)
830 {
831     int shift;
832
833     shift = PARAM1;
834     if (shift == 0) {
835         env->CF = ((uint32_t)shift) >> 31;
836         T0 = 0;
837     } else {
838         env->CF = (T0 >> (shift - 1)) & 1;
839         T0 = T0 >> shift;
840     }
841     env->NZF = T0;
842     FORCE_RET();
843 }
844
845 void OPPROTO op_sarl_T0_im_thumb(void)
846 {
847     int shift;
848
849     shift = PARAM1;
850     if (shift == 0) {
851         T0 = ((int32_t)T0) >> 31;
852         env->CF = T0 & 1;
853     } else {
854         env->CF = (T0 >> (shift - 1)) & 1;
855         T0 = ((int32_t)T0) >> shift;
856     }
857     env->NZF = T0;
858     FORCE_RET();
859 }
860
861 /* exceptions */
862
863 void OPPROTO op_swi(void)
864 {
865     env->exception_index = EXCP_SWI;
866     cpu_loop_exit();
867 }
868
869 void OPPROTO op_undef_insn(void)
870 {
871     env->exception_index = EXCP_UDEF;
872     cpu_loop_exit();
873 }
874
875 void OPPROTO op_debug(void)
876 {
877     env->exception_index = EXCP_DEBUG;
878     cpu_loop_exit();
879 }
880
881 void OPPROTO op_wfi(void)
882 {
883     env->exception_index = EXCP_HLT;
884     env->halted = 1;
885     cpu_loop_exit();
886 }
887
888 void OPPROTO op_bkpt(void)
889 {
890     env->exception_index = EXCP_BKPT;
891     cpu_loop_exit();
892 }
893
894 /* VFP support.  We follow the convention used for VFP instrunctions:
895    Single precition routines have a "s" suffix, double precision a
896    "d" suffix.  */
897
898 #define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void)
899
900 #define VFP_BINOP(name) \
901 VFP_OP(name, s)             \
902 {                           \
903     FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status);    \
904 }                           \
905 VFP_OP(name, d)             \
906 {                           \
907     FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status);    \
908 }
909 VFP_BINOP(add)
910 VFP_BINOP(sub)
911 VFP_BINOP(mul)
912 VFP_BINOP(div)
913 #undef VFP_BINOP
914
915 #define VFP_HELPER(name)  \
916 VFP_OP(name, s)           \
917 {                         \
918     do_vfp_##name##s();    \
919 }                         \
920 VFP_OP(name, d)           \
921 {                         \
922     do_vfp_##name##d();    \
923 }
924 VFP_HELPER(abs)
925 VFP_HELPER(sqrt)
926 VFP_HELPER(cmp)
927 VFP_HELPER(cmpe)
928 #undef VFP_HELPER
929
930 /* XXX: Will this do the right thing for NANs.  Should invert the signbit
931    without looking at the rest of the value.  */
932 VFP_OP(neg, s)
933 {
934     FT0s = float32_chs(FT0s);
935 }
936
937 VFP_OP(neg, d)
938 {
939     FT0d = float64_chs(FT0d);
940 }
941
942 VFP_OP(F1_ld0, s)
943 {
944     union {
945         uint32_t i;
946         float32 s;
947     } v;
948     v.i = 0;
949     FT1s = v.s;
950 }
951
952 VFP_OP(F1_ld0, d)
953 {
954     union {
955         uint64_t i;
956         float64 d;
957     } v;
958     v.i = 0;
959     FT1d = v.d;
960 }
961
962 /* Helper routines to perform bitwise copies between float and int.  */
963 static inline float32 vfp_itos(uint32_t i)
964 {
965     union {
966         uint32_t i;
967         float32 s;
968     } v;
969
970     v.i = i;
971     return v.s;
972 }
973
974 static inline uint32_t vfp_stoi(float32 s)
975 {
976     union {
977         uint32_t i;
978         float32 s;
979     } v;
980
981     v.s = s;
982     return v.i;
983 }
984
985 /* Integer to float conversion.  */
986 VFP_OP(uito, s)
987 {
988     FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
989 }
990
991 VFP_OP(uito, d)
992 {
993     FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
994 }
995
996 VFP_OP(sito, s)
997 {
998     FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
999 }
1000
1001 VFP_OP(sito, d)
1002 {
1003     FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
1004 }
1005
1006 /* Float to integer conversion.  */
1007 VFP_OP(toui, s)
1008 {
1009     FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status));
1010 }
1011
1012 VFP_OP(toui, d)
1013 {
1014     FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status));
1015 }
1016
1017 VFP_OP(tosi, s)
1018 {
1019     FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status));
1020 }
1021
1022 VFP_OP(tosi, d)
1023 {
1024     FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status));
1025 }
1026
1027 /* TODO: Set rounding mode properly.  */
1028 VFP_OP(touiz, s)
1029 {
1030     FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status));
1031 }
1032
1033 VFP_OP(touiz, d)
1034 {
1035     FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status));
1036 }
1037
1038 VFP_OP(tosiz, s)
1039 {
1040     FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status));
1041 }
1042
1043 VFP_OP(tosiz, d)
1044 {
1045     FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status));
1046 }
1047
1048 /* floating point conversion */
1049 VFP_OP(fcvtd, s)
1050 {
1051     FT0d = float32_to_float64(FT0s, &env->vfp.fp_status);
1052 }
1053
1054 VFP_OP(fcvts, d)
1055 {
1056     FT0s = float64_to_float32(FT0d, &env->vfp.fp_status);
1057 }
1058
1059 /* Get and Put values from registers.  */
1060 VFP_OP(getreg_F0, d)
1061 {
1062   FT0d = *(float64 *)((char *) env + PARAM1);
1063 }
1064
1065 VFP_OP(getreg_F0, s)
1066 {
1067   FT0s = *(float32 *)((char *) env + PARAM1);
1068 }
1069
1070 VFP_OP(getreg_F1, d)
1071 {
1072   FT1d = *(float64 *)((char *) env + PARAM1);
1073 }
1074
1075 VFP_OP(getreg_F1, s)
1076 {
1077   FT1s = *(float32 *)((char *) env + PARAM1);
1078 }
1079
1080 VFP_OP(setreg_F0, d)
1081 {
1082   *(float64 *)((char *) env + PARAM1) = FT0d;
1083 }
1084
1085 VFP_OP(setreg_F0, s)
1086 {
1087   *(float32 *)((char *) env + PARAM1) = FT0s;
1088 }
1089
1090 void OPPROTO op_vfp_movl_T0_fpscr(void)
1091 {
1092     do_vfp_get_fpscr ();
1093 }
1094
1095 void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
1096 {
1097     T0 = env->vfp.xregs[ARM_VFP_FPSCR] & (0xf << 28);
1098 }
1099
1100 void OPPROTO op_vfp_movl_fpscr_T0(void)
1101 {
1102     do_vfp_set_fpscr();
1103 }
1104
1105 void OPPROTO op_vfp_movl_T0_xreg(void)
1106 {
1107     T0 = env->vfp.xregs[PARAM1];
1108 }
1109
1110 void OPPROTO op_vfp_movl_xreg_T0(void)
1111 {
1112     env->vfp.xregs[PARAM1] = T0;
1113 }
1114
1115 /* Move between FT0s to T0  */
1116 void OPPROTO op_vfp_mrs(void)
1117 {
1118     T0 = vfp_stoi(FT0s);
1119 }
1120
1121 void OPPROTO op_vfp_msr(void)
1122 {
1123     FT0s = vfp_itos(T0);
1124 }
1125
1126 /* Move between FT0d and {T0,T1} */
1127 void OPPROTO op_vfp_mrrd(void)
1128 {
1129     CPU_DoubleU u;
1130     
1131     u.d = FT0d;
1132     T0 = u.l.lower;
1133     T1 = u.l.upper;
1134 }
1135
1136 void OPPROTO op_vfp_mdrr(void)
1137 {
1138     CPU_DoubleU u;
1139     
1140     u.l.lower = T0;
1141     u.l.upper = T1;
1142     FT0d = u.d;
1143 }
1144
1145 /* Copy the most significant bit to T0 to all bits of T1.  */
1146 void OPPROTO op_signbit_T1_T0(void)
1147 {
1148     T1 = (int32_t)T0 >> 31;
1149 }
1150
1151 void OPPROTO op_movl_cp15_T0(void)
1152 {
1153     helper_set_cp15(env, PARAM1, T0);
1154     FORCE_RET();
1155 }
1156
1157 void OPPROTO op_movl_T0_cp15(void)
1158 {
1159     T0 = helper_get_cp15(env, PARAM1);
1160     FORCE_RET();
1161 }
1162
1163 /* Access to user mode registers from privileged modes.  */
1164 void OPPROTO op_movl_T0_user(void)
1165 {
1166     int regno = PARAM1;
1167     if (regno == 13) {
1168         T0 = env->banked_r13[0];
1169     } else if (regno == 14) {
1170         T0 = env->banked_r14[0];
1171     } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
1172         T0 = env->usr_regs[regno - 8];
1173     } else {
1174         T0 = env->regs[regno];
1175     }
1176     FORCE_RET();
1177 }
1178
1179
1180 void OPPROTO op_movl_user_T0(void)
1181 {
1182     int regno = PARAM1;
1183     if (regno == 13) {
1184         env->banked_r13[0] = T0;
1185     } else if (regno == 14) {
1186         env->banked_r14[0] = T0;
1187     } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
1188         env->usr_regs[regno - 8] = T0;
1189     } else {
1190         env->regs[regno] = T0;
1191     }
1192     FORCE_RET();
1193 }
1194
1195 void OPPROTO op_movl_T2_T0(void)
1196 {
1197     T2 = T0;
1198 }
1199
1200 void OPPROTO op_movl_T0_T2(void)
1201 {
1202     T0 = T2;
1203 }