Statistics
| Branch: | Revision:

root / target-arm / op.c @ 5899f386

History | View | Annotate | Download (20 kB)

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_T1_im(void)
105
{
106
    T1 = PARAM1;
107
}
108

    
109
void OPPROTO op_mov_CF_T1(void)
110
{
111
    env->CF = ((uint32_t)T1) >> 31;
112
}
113

    
114
void OPPROTO op_movl_T2_im(void)
115
{
116
    T2 = PARAM1;
117
}
118

    
119
void OPPROTO op_addl_T1_im(void)
120
{
121
    T1 += PARAM1;
122
}
123

    
124
void OPPROTO op_addl_T1_T2(void)
125
{
126
    T1 += T2;
127
}
128

    
129
void OPPROTO op_subl_T1_T2(void)
130
{
131
    T1 -= T2;
132
}
133

    
134
void OPPROTO op_addl_T0_T1(void)
135
{
136
    T0 += T1;
137
}
138

    
139
void OPPROTO op_addl_T0_T1_cc(void)
140
{
141
    unsigned int src1;
142
    src1 = T0;
143
    T0 += T1;
144
    env->NZF = T0;
145
    env->CF = T0 < src1;
146
    env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
147
}
148

    
149
void OPPROTO op_adcl_T0_T1(void)
150
{
151
    T0 += T1 + env->CF;
152
}
153

    
154
void OPPROTO op_adcl_T0_T1_cc(void)
155
{
156
    unsigned int src1;
157
    src1 = T0;
158
    if (!env->CF) {
159
        T0 += T1;
160
        env->CF = T0 < src1;
161
    } else {
162
        T0 += T1 + 1;
163
        env->CF = T0 <= src1;
164
    }
165
    env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
166
    env->NZF = T0;
167
    FORCE_RET();
168
}
169

    
170
#define OPSUB(sub, sbc, res, T0, T1)            \
171
                                                \
172
void OPPROTO op_ ## sub ## l_T0_T1(void)        \
173
{                                               \
174
    res = T0 - T1;                              \
175
}                                               \
176
                                                \
177
void OPPROTO op_ ## sub ## l_T0_T1_cc(void)     \
178
{                                               \
179
    unsigned int src1;                          \
180
    src1 = T0;                                  \
181
    T0 -= T1;                                   \
182
    env->NZF = T0;                              \
183
    env->CF = src1 >= T1;                       \
184
    env->VF = (src1 ^ T1) & (src1 ^ T0);        \
185
    res = T0;                                   \
186
}                                               \
187
                                                \
188
void OPPROTO op_ ## sbc ## l_T0_T1(void)        \
189
{                                               \
190
    res = T0 - T1 + env->CF - 1;                \
191
}                                               \
192
                                                \
193
void OPPROTO op_ ## sbc ## l_T0_T1_cc(void)     \
194
{                                               \
195
    unsigned int src1;                          \
196
    src1 = T0;                                  \
197
    if (!env->CF) {                             \
198
        T0 = T0 - T1 - 1;                       \
199
        env->CF = src1 > T1;                    \
200
    } else {                                    \
201
        T0 = T0 - T1;                           \
202
        env->CF = src1 >= T1;                   \
203
    }                                           \
204
    env->VF = (src1 ^ T1) & (src1 ^ T0);        \
205
    env->NZF = T0;                              \
206
    res = T0;                                   \
207
    FORCE_RET();                                \
208
}
209

    
210
OPSUB(sub, sbc, T0, T0, T1)
211

    
212
OPSUB(rsb, rsc, T0, T1, T0)
213

    
214
void OPPROTO op_andl_T0_T1(void)
215
{
216
    T0 &= T1;
217
}
218

    
219
void OPPROTO op_xorl_T0_T1(void)
220
{
221
    T0 ^= T1;
222
}
223

    
224
void OPPROTO op_orl_T0_T1(void)
225
{
226
    T0 |= T1;
227
}
228

    
229
void OPPROTO op_bicl_T0_T1(void)
230
{
231
    T0 &= ~T1;
232
}
233

    
234
void OPPROTO op_notl_T1(void)
235
{
236
    T1 = ~T1;
237
}
238

    
239
void OPPROTO op_logic_T0_cc(void)
240
{
241
    env->NZF = T0;
242
}
243

    
244
void OPPROTO op_logic_T1_cc(void)
245
{
246
    env->NZF = T1;
247
}
248

    
249
#define EIP (env->regs[15])
250

    
251
void OPPROTO op_test_eq(void)
252
{
253
    if (env->NZF == 0)
254
        GOTO_LABEL_PARAM(1);;
255
    FORCE_RET();
256
}
257

    
258
void OPPROTO op_test_ne(void)
259
{
260
    if (env->NZF != 0)
261
        GOTO_LABEL_PARAM(1);;
262
    FORCE_RET();
263
}
264

    
265
void OPPROTO op_test_cs(void)
266
{
267
    if (env->CF != 0)
268
        GOTO_LABEL_PARAM(1);
269
    FORCE_RET();
270
}
271

    
272
void OPPROTO op_test_cc(void)
273
{
274
    if (env->CF == 0)
275
        GOTO_LABEL_PARAM(1);
276
    FORCE_RET();
277
}
278

    
279
void OPPROTO op_test_mi(void)
280
{
281
    if ((env->NZF & 0x80000000) != 0)
282
        GOTO_LABEL_PARAM(1);
283
    FORCE_RET();
284
}
285

    
286
void OPPROTO op_test_pl(void)
287
{
288
    if ((env->NZF & 0x80000000) == 0)
289
        GOTO_LABEL_PARAM(1);
290
    FORCE_RET();
291
}
292

    
293
void OPPROTO op_test_vs(void)
294
{
295
    if ((env->VF & 0x80000000) != 0)
296
        GOTO_LABEL_PARAM(1);
297
    FORCE_RET();
298
}
299

    
300
void OPPROTO op_test_vc(void)
301
{
302
    if ((env->VF & 0x80000000) == 0)
303
        GOTO_LABEL_PARAM(1);
304
    FORCE_RET();
305
}
306

    
307
void OPPROTO op_test_hi(void)
308
{
309
    if (env->CF != 0 && env->NZF != 0)
310
        GOTO_LABEL_PARAM(1);
311
    FORCE_RET();
312
}
313

    
314
void OPPROTO op_test_ls(void)
315
{
316
    if (env->CF == 0 || env->NZF == 0)
317
        GOTO_LABEL_PARAM(1);
318
    FORCE_RET();
319
}
320

    
321
void OPPROTO op_test_ge(void)
322
{
323
    if (((env->VF ^ env->NZF) & 0x80000000) == 0)
324
        GOTO_LABEL_PARAM(1);
325
    FORCE_RET();
326
}
327

    
328
void OPPROTO op_test_lt(void)
329
{
330
    if (((env->VF ^ env->NZF) & 0x80000000) != 0)
331
        GOTO_LABEL_PARAM(1);
332
    FORCE_RET();
333
}
334

    
335
void OPPROTO op_test_gt(void)
336
{
337
    if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0)
338
        GOTO_LABEL_PARAM(1);
339
    FORCE_RET();
340
}
341

    
342
void OPPROTO op_test_le(void)
343
{
344
    if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0)
345
        GOTO_LABEL_PARAM(1);
346
    FORCE_RET();
347
}
348

    
349
void OPPROTO op_jmp0(void)
350
{
351
    JUMP_TB(op_jmp0, PARAM1, 0, PARAM2);
352
}
353

    
354
void OPPROTO op_jmp1(void)
355
{
356
    JUMP_TB(op_jmp1, PARAM1, 1, PARAM2);
357
}
358

    
359
void OPPROTO op_exit_tb(void)
360
{
361
    EXIT_TB();
362
}
363

    
364
void OPPROTO op_movl_T0_psr(void)
365
{
366
    T0 = compute_cpsr();
367
}
368

    
369
/* NOTE: N = 1 and Z = 1 cannot be stored currently */
370
void OPPROTO op_movl_psr_T0(void)
371
{
372
    unsigned int psr;
373
    psr = T0;
374
    env->CF = (psr >> 29) & 1;
375
    env->NZF = (psr & 0xc0000000) ^ 0x40000000;
376
    env->VF = (psr << 3) & 0x80000000;
377
    /* for user mode we do not update other state info */
378
}
379

    
380
void OPPROTO op_mul_T0_T1(void)
381
{
382
    T0 = T0 * T1;
383
}
384

    
385
/* 64 bit unsigned mul */
386
void OPPROTO op_mull_T0_T1(void)
387
{
388
    uint64_t res;
389
    res = (uint64_t)T0 * (uint64_t)T1;
390
    T1 = res >> 32;
391
    T0 = res;
392
}
393

    
394
/* 64 bit signed mul */
395
void OPPROTO op_imull_T0_T1(void)
396
{
397
    uint64_t res;
398
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
399
    T1 = res >> 32;
400
    T0 = res;
401
}
402

    
403
/* 48 bit signed mul, top 32 bits */
404
void OPPROTO op_imulw_T0_T1(void)
405
{
406
  uint64_t res;
407
  res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
408
  T0 = res >> 16;
409
}
410

    
411
void OPPROTO op_addq_T0_T1(void)
412
{
413
    uint64_t res;
414
    res = ((uint64_t)T1 << 32) | T0;
415
    res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
416
    T1 = res >> 32;
417
    T0 = res;
418
}
419

    
420
void OPPROTO op_addq_lo_T0_T1(void)
421
{
422
    uint64_t res;
423
    res = ((uint64_t)T1 << 32) | T0;
424
    res += (uint64_t)(env->regs[PARAM1]);
425
    T1 = res >> 32;
426
    T0 = res;
427
}
428

    
429
void OPPROTO op_logicq_cc(void)
430
{
431
    env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
432
}
433

    
434
/* memory access */
435

    
436
void OPPROTO op_ldub_T0_T1(void)
437
{
438
    T0 = ldub((void *)T1);
439
}
440

    
441
void OPPROTO op_ldsb_T0_T1(void)
442
{
443
    T0 = ldsb((void *)T1);
444
}
445

    
446
void OPPROTO op_lduw_T0_T1(void)
447
{
448
    T0 = lduw((void *)T1);
449
}
450

    
451
void OPPROTO op_ldsw_T0_T1(void)
452
{
453
    T0 = ldsw((void *)T1);
454
}
455

    
456
void OPPROTO op_ldl_T0_T1(void)
457
{
458
    T0 = ldl((void *)T1);
459
}
460

    
461
void OPPROTO op_stb_T0_T1(void)
462
{
463
    stb((void *)T1, T0);
464
}
465

    
466
void OPPROTO op_stw_T0_T1(void)
467
{
468
    stw((void *)T1, T0);
469
}
470

    
471
void OPPROTO op_stl_T0_T1(void)
472
{
473
    stl((void *)T1, T0);
474
}
475

    
476
void OPPROTO op_swpb_T0_T1(void)
477
{
478
    int tmp;
479

    
480
    cpu_lock();
481
    tmp = ldub((void *)T1);
482
    stb((void *)T1, T0);
483
    T0 = tmp;
484
    cpu_unlock();
485
}
486

    
487
void OPPROTO op_swpl_T0_T1(void)
488
{
489
    int tmp;
490

    
491
    cpu_lock();
492
    tmp = ldl((void *)T1);
493
    stl((void *)T1, T0);
494
    T0 = tmp;
495
    cpu_unlock();
496
}
497

    
498
/* shifts */
499

    
500
/* T1 based */
501

    
502
void OPPROTO op_shll_T1_im(void)
503
{
504
    T1 = T1 << PARAM1;
505
}
506

    
507
void OPPROTO op_shrl_T1_im(void)
508
{
509
    T1 = (uint32_t)T1 >> PARAM1;
510
}
511

    
512
void OPPROTO op_shrl_T1_0(void)
513
{
514
    T1 = 0;
515
}
516

    
517
void OPPROTO op_sarl_T1_im(void)
518
{
519
    T1 = (int32_t)T1 >> PARAM1;
520
}
521

    
522
void OPPROTO op_sarl_T1_0(void)
523
{
524
    T1 = (int32_t)T1 >> 31;
525
}
526

    
527
void OPPROTO op_rorl_T1_im(void)
528
{
529
    int shift;
530
    shift = PARAM1;
531
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
532
}
533

    
534
void OPPROTO op_rrxl_T1(void)
535
{
536
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
537
}
538

    
539
/* T1 based, set C flag */
540
void OPPROTO op_shll_T1_im_cc(void)
541
{
542
    env->CF = (T1 >> (32 - PARAM1)) & 1;
543
    T1 = T1 << PARAM1;
544
}
545

    
546
void OPPROTO op_shrl_T1_im_cc(void)
547
{
548
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
549
    T1 = (uint32_t)T1 >> PARAM1;
550
}
551

    
552
void OPPROTO op_shrl_T1_0_cc(void)
553
{
554
    env->CF = (T1 >> 31) & 1;
555
    T1 = 0;
556
}
557

    
558
void OPPROTO op_sarl_T1_im_cc(void)
559
{
560
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
561
    T1 = (int32_t)T1 >> PARAM1;
562
}
563

    
564
void OPPROTO op_sarl_T1_0_cc(void)
565
{
566
    env->CF = (T1 >> 31) & 1;
567
    T1 = (int32_t)T1 >> 31;
568
}
569

    
570
void OPPROTO op_rorl_T1_im_cc(void)
571
{
572
    int shift;
573
    shift = PARAM1;
574
    env->CF = (T1 >> (shift - 1)) & 1;
575
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
576
}
577

    
578
void OPPROTO op_rrxl_T1_cc(void)
579
{
580
    uint32_t c;
581
    c = T1 & 1;
582
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
583
    env->CF = c;
584
}
585

    
586
/* T2 based */
587
void OPPROTO op_shll_T2_im(void)
588
{
589
    T2 = T2 << PARAM1;
590
}
591

    
592
void OPPROTO op_shrl_T2_im(void)
593
{
594
    T2 = (uint32_t)T2 >> PARAM1;
595
}
596

    
597
void OPPROTO op_shrl_T2_0(void)
598
{
599
    T2 = 0;
600
}
601

    
602
void OPPROTO op_sarl_T2_im(void)
603
{
604
    T2 = (int32_t)T2 >> PARAM1;
605
}
606

    
607
void OPPROTO op_sarl_T2_0(void)
608
{
609
    T2 = (int32_t)T2 >> 31;
610
}
611

    
612
void OPPROTO op_rorl_T2_im(void)
613
{
614
    int shift;
615
    shift = PARAM1;
616
    T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
617
}
618

    
619
void OPPROTO op_rrxl_T2(void)
620
{
621
    T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31);
622
}
623

    
624
/* T1 based, use T0 as shift count */
625

    
626
void OPPROTO op_shll_T1_T0(void)
627
{
628
    int shift;
629
    shift = T0 & 0xff;
630
    if (shift >= 32)
631
        T1 = 0;
632
    else
633
        T1 = T1 << shift;
634
    FORCE_RET();
635
}
636

    
637
void OPPROTO op_shrl_T1_T0(void)
638
{
639
    int shift;
640
    shift = T0 & 0xff;
641
    if (shift >= 32)
642
        T1 = 0;
643
    else
644
        T1 = (uint32_t)T1 >> shift;
645
    FORCE_RET();
646
}
647

    
648
void OPPROTO op_sarl_T1_T0(void)
649
{
650
    int shift;
651
    shift = T0 & 0xff;
652
    if (shift >= 32)
653
        shift = 31;
654
    T1 = (int32_t)T1 >> shift;
655
}
656

    
657
void OPPROTO op_rorl_T1_T0(void)
658
{
659
    int shift;
660
    shift = T0 & 0x1f;
661
    if (shift) {
662
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
663
    }
664
    FORCE_RET();
665
}
666

    
667
/* T1 based, use T0 as shift count and compute CF */
668

    
669
void OPPROTO op_shll_T1_T0_cc(void)
670
{
671
    int shift;
672
    shift = T0 & 0xff;
673
    if (shift >= 32) {
674
        if (shift == 32)
675
            env->CF = T1 & 1;
676
        else
677
            env->CF = 0;
678
        T1 = 0;
679
    } else if (shift != 0) {
680
        env->CF = (T1 >> (32 - shift)) & 1;
681
        T1 = T1 << shift;
682
    }
683
    FORCE_RET();
684
}
685

    
686
void OPPROTO op_shrl_T1_T0_cc(void)
687
{
688
    int shift;
689
    shift = T0 & 0xff;
690
    if (shift >= 32) {
691
        if (shift == 32)
692
            env->CF = (T1 >> 31) & 1;
693
        else
694
            env->CF = 0;
695
        T1 = 0;
696
    } else if (shift != 0) {
697
        env->CF = (T1 >> (shift - 1)) & 1;
698
        T1 = (uint32_t)T1 >> shift;
699
    }
700
    FORCE_RET();
701
}
702

    
703
void OPPROTO op_sarl_T1_T0_cc(void)
704
{
705
    int shift;
706
    shift = T0 & 0xff;
707
    if (shift >= 32) {
708
        env->CF = (T1 >> 31) & 1;
709
        T1 = (int32_t)T1 >> 31;
710
    } else {
711
        env->CF = (T1 >> (shift - 1)) & 1;
712
        T1 = (int32_t)T1 >> shift;
713
    }
714
    FORCE_RET();
715
}
716

    
717
void OPPROTO op_rorl_T1_T0_cc(void)
718
{
719
    int shift1, shift;
720
    shift1 = T0 & 0xff;
721
    shift = shift1 & 0x1f;
722
    if (shift == 0) {
723
        if (shift1 != 0)
724
            env->CF = (T1 >> 31) & 1;
725
    } else {
726
        env->CF = (T1 >> (shift - 1)) & 1;
727
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
728
    }
729
    FORCE_RET();
730
}
731

    
732
/* misc */
733
void OPPROTO op_clz_T0(void)
734
{
735
    int count;
736
    for (count = 32; T0 > 0; count--)
737
        T0 = T0 >> 1;
738
    T0 = count;
739
    FORCE_RET();
740
}
741

    
742
void OPPROTO op_sarl_T0_im(void)
743
{
744
    T0 = (int32_t)T0 >> PARAM1;
745
}
746

    
747
/* 16->32 Sign extend */
748
void OPPROTO op_sxl_T0(void)
749
{
750
  T0 = (int16_t)T0;
751
}
752

    
753
void OPPROTO op_sxl_T1(void)
754
{
755
  T1 = (int16_t)T1;
756
}
757

    
758
#define SIGNBIT (uint32_t)0x80000000
759
/* saturating arithmetic  */
760
void OPPROTO op_addl_T0_T1_setq(void)
761
{
762
  uint32_t res;
763

    
764
  res = T0 + T1;
765
  if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT))
766
      env->QF = 1;
767

    
768
  T0 = res;
769
  FORCE_RET();
770
}
771

    
772
void OPPROTO op_addl_T0_T1_saturate(void)
773
{
774
  uint32_t res;
775

    
776
  res = T0 + T1;
777
  if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) {
778
      env->QF = 1;
779
      if (T0 & SIGNBIT)
780
          T0 = 0x80000000;
781
      else
782
          T0 = 0x7fffffff;
783
  }
784
  else
785
    T0 = res;
786
  
787
  FORCE_RET();
788
}
789

    
790
void OPPROTO op_subl_T0_T1_saturate(void)
791
{
792
  uint32_t res;
793

    
794
  res = T0 - T1;
795
  if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) {
796
      env->QF = 1;
797
      if (T0 & SIGNBIT)
798
          T0 = 0x8000000;
799
      else
800
          T0 = 0x7fffffff;
801
  }
802
  else
803
    T0 = res;
804
  
805
  FORCE_RET();
806
}
807

    
808
/* thumb shift by immediate */
809
void OPPROTO op_shll_T0_im_thumb(void)
810
{
811
    int shift;
812
    shift = PARAM1;
813
    if (shift != 0) {
814
        env->CF = (T1 >> (32 - shift)) & 1;
815
        T0 = T0 << shift;
816
    }
817
    env->NZF = T0;
818
    FORCE_RET();
819
}
820

    
821
void OPPROTO op_shrl_T0_im_thumb(void)
822
{
823
    int shift;
824

    
825
    shift = PARAM1;
826
    if (shift == 0) {
827
        env->CF = ((uint32_t)shift) >> 31;
828
        T0 = 0;
829
    } else {
830
        env->CF = (T0 >> (shift - 1)) & 1;
831
        T0 = T0 >> shift;
832
    }
833
    env->NZF = T0;
834
    FORCE_RET();
835
}
836

    
837
void OPPROTO op_sarl_T0_im_thumb(void)
838
{
839
    int shift;
840

    
841
    shift = PARAM1;
842
    if (shift == 0) {
843
        T0 = ((int32_t)T0) >> 31;
844
        env->CF = T0 & 1;
845
    } else {
846
        env->CF = (T0 >> (shift - 1)) & 1;
847
        T0 = ((int32_t)T0) >> shift;
848
    }
849
    env->NZF = T0;
850
    FORCE_RET();
851
}
852

    
853
/* exceptions */
854

    
855
void OPPROTO op_swi(void)
856
{
857
    env->exception_index = EXCP_SWI;
858
    cpu_loop_exit();
859
}
860

    
861
void OPPROTO op_undef_insn(void)
862
{
863
    env->exception_index = EXCP_UDEF;
864
    cpu_loop_exit();
865
}
866

    
867
void OPPROTO op_debug(void)
868
{
869
    env->exception_index = EXCP_DEBUG;
870
    cpu_loop_exit();
871
}
872

    
873
/* VFP support.  We follow the convention used for VFP instrunctions:
874
   Single precition routines have a "s" suffix, double precision a
875
   "d" suffix.  */
876

    
877
#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void)
878

    
879
#define VFP_BINOP(name) \
880
VFP_OP(name, s)             \
881
{                           \
882
    FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status);    \
883
}                           \
884
VFP_OP(name, d)             \
885
{                           \
886
    FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status);    \
887
}
888
VFP_BINOP(add)
889
VFP_BINOP(sub)
890
VFP_BINOP(mul)
891
VFP_BINOP(div)
892
#undef VFP_BINOP
893

    
894
#define VFP_HELPER(name)  \
895
VFP_OP(name, s)           \
896
{                         \
897
    do_vfp_##name##s();    \
898
}                         \
899
VFP_OP(name, d)           \
900
{                         \
901
    do_vfp_##name##d();    \
902
}
903
VFP_HELPER(abs)
904
VFP_HELPER(sqrt)
905
VFP_HELPER(cmp)
906
VFP_HELPER(cmpe)
907
#undef VFP_HELPER
908

    
909
/* XXX: Will this do the right thing for NANs.  Should invert the signbit
910
   without looking at the rest of the value.  */
911
VFP_OP(neg, s)
912
{
913
    FT0s = float32_chs(FT0s);
914
}
915

    
916
VFP_OP(neg, d)
917
{
918
    FT0d = float64_chs(FT0d);
919
}
920

    
921
VFP_OP(F1_ld0, s)
922
{
923
    union {
924
        uint32_t i;
925
        float32 s;
926
    } v;
927
    v.i = 0;
928
    FT1s = v.s;
929
}
930

    
931
VFP_OP(F1_ld0, d)
932
{
933
    union {
934
        uint64_t i;
935
        float64 d;
936
    } v;
937
    v.i = 0;
938
    FT1d = v.d;
939
}
940

    
941
/* Helper routines to perform bitwise copies between float and int.  */
942
static inline float32 vfp_itos(uint32_t i)
943
{
944
    union {
945
        uint32_t i;
946
        float32 s;
947
    } v;
948

    
949
    v.i = i;
950
    return v.s;
951
}
952

    
953
static inline uint32_t vfp_stoi(float32 s)
954
{
955
    union {
956
        uint32_t i;
957
        float32 s;
958
    } v;
959

    
960
    v.s = s;
961
    return v.i;
962
}
963

    
964
/* Integer to float conversion.  */
965
VFP_OP(uito, s)
966
{
967
    FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
968
}
969

    
970
VFP_OP(uito, d)
971
{
972
    FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
973
}
974

    
975
VFP_OP(sito, s)
976
{
977
    FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
978
}
979

    
980
VFP_OP(sito, d)
981
{
982
    FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
983
}
984

    
985
/* Float to integer conversion.  */
986
VFP_OP(toui, s)
987
{
988
    FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status));
989
}
990

    
991
VFP_OP(toui, d)
992
{
993
    FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status));
994
}
995

    
996
VFP_OP(tosi, s)
997
{
998
    FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status));
999
}
1000

    
1001
VFP_OP(tosi, d)
1002
{
1003
    FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status));
1004
}
1005

    
1006
/* TODO: Set rounding mode properly.  */
1007
VFP_OP(touiz, s)
1008
{
1009
    FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status));
1010
}
1011

    
1012
VFP_OP(touiz, d)
1013
{
1014
    FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status));
1015
}
1016

    
1017
VFP_OP(tosiz, s)
1018
{
1019
    FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status));
1020
}
1021

    
1022
VFP_OP(tosiz, d)
1023
{
1024
    FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status));
1025
}
1026

    
1027
/* floating point conversion */
1028
VFP_OP(fcvtd, s)
1029
{
1030
    FT0d = float32_to_float64(FT0s, &env->vfp.fp_status);
1031
}
1032

    
1033
VFP_OP(fcvts, d)
1034
{
1035
    FT0s = float64_to_float32(FT0d, &env->vfp.fp_status);
1036
}
1037

    
1038
/* Get and Put values from registers.  */
1039
VFP_OP(getreg_F0, d)
1040
{
1041
  FT0d = *(float64 *)((char *) env + PARAM1);
1042
}
1043

    
1044
VFP_OP(getreg_F0, s)
1045
{
1046
  FT0s = *(float32 *)((char *) env + PARAM1);
1047
}
1048

    
1049
VFP_OP(getreg_F1, d)
1050
{
1051
  FT1d = *(float64 *)((char *) env + PARAM1);
1052
}
1053

    
1054
VFP_OP(getreg_F1, s)
1055
{
1056
  FT1s = *(float32 *)((char *) env + PARAM1);
1057
}
1058

    
1059
VFP_OP(setreg_F0, d)
1060
{
1061
  *(float64 *)((char *) env + PARAM1) = FT0d;
1062
}
1063

    
1064
VFP_OP(setreg_F0, s)
1065
{
1066
  *(float32 *)((char *) env + PARAM1) = FT0s;
1067
}
1068

    
1069
void OPPROTO op_vfp_movl_T0_fpscr(void)
1070
{
1071
    do_vfp_get_fpscr ();
1072
}
1073

    
1074
void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
1075
{
1076
    T0 = env->vfp.fpscr & (0xf << 28);
1077
}
1078

    
1079
void OPPROTO op_vfp_movl_fpscr_T0(void)
1080
{
1081
    do_vfp_set_fpscr();
1082
}
1083

    
1084
/* Move between FT0s to T0  */
1085
void OPPROTO op_vfp_mrs(void)
1086
{
1087
    T0 = vfp_stoi(FT0s);
1088
}
1089

    
1090
void OPPROTO op_vfp_msr(void)
1091
{
1092
    FT0s = vfp_itos(T0);
1093
}
1094

    
1095
/* Move between FT0d and {T0,T1} */
1096
void OPPROTO op_vfp_mrrd(void)
1097
{
1098
    CPU_DoubleU u;
1099
    
1100
    u.d = FT0d;
1101
    T0 = u.l.lower;
1102
    T1 = u.l.upper;
1103
}
1104

    
1105
void OPPROTO op_vfp_mdrr(void)
1106
{
1107
    CPU_DoubleU u;
1108
    
1109
    u.l.lower = T0;
1110
    u.l.upper = T1;
1111
    FT0d = u.d;
1112
}
1113

    
1114
/* Floating point load/store.  Address is in T1 */
1115
void OPPROTO op_vfp_lds(void)
1116
{
1117
    FT0s = ldfl((void *)T1);
1118
}
1119

    
1120
void OPPROTO op_vfp_ldd(void)
1121
{
1122
    FT0d = ldfq((void *)T1);
1123
}
1124

    
1125
void OPPROTO op_vfp_sts(void)
1126
{
1127
    stfl((void *)T1, FT0s);
1128
}
1129

    
1130
void OPPROTO op_vfp_std(void)
1131
{
1132
    stfq((void *)T1, FT0d);
1133
}