Statistics
| Branch: | Revision:

root / target-arm / op.c @ 18c9b560

History | View | Annotate | Download (21.6 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_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 of 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_cp_T0(void)
1152
{
1153
    helper_set_cp(env, PARAM1, T0);
1154
    FORCE_RET();
1155
}
1156

    
1157
void OPPROTO op_movl_T0_cp(void)
1158
{
1159
    T0 = helper_get_cp(env, PARAM1);
1160
    FORCE_RET();
1161
}
1162

    
1163
void OPPROTO op_movl_cp15_T0(void)
1164
{
1165
    helper_set_cp15(env, PARAM1, T0);
1166
    FORCE_RET();
1167
}
1168

    
1169
void OPPROTO op_movl_T0_cp15(void)
1170
{
1171
    T0 = helper_get_cp15(env, PARAM1);
1172
    FORCE_RET();
1173
}
1174

    
1175
/* Access to user mode registers from privileged modes.  */
1176
void OPPROTO op_movl_T0_user(void)
1177
{
1178
    int regno = PARAM1;
1179
    if (regno == 13) {
1180
        T0 = env->banked_r13[0];
1181
    } else if (regno == 14) {
1182
        T0 = env->banked_r14[0];
1183
    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
1184
        T0 = env->usr_regs[regno - 8];
1185
    } else {
1186
        T0 = env->regs[regno];
1187
    }
1188
    FORCE_RET();
1189
}
1190

    
1191

    
1192
void OPPROTO op_movl_user_T0(void)
1193
{
1194
    int regno = PARAM1;
1195
    if (regno == 13) {
1196
        env->banked_r13[0] = T0;
1197
    } else if (regno == 14) {
1198
        env->banked_r14[0] = T0;
1199
    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
1200
        env->usr_regs[regno - 8] = T0;
1201
    } else {
1202
        env->regs[regno] = T0;
1203
    }
1204
    FORCE_RET();
1205
}
1206

    
1207
void OPPROTO op_movl_T2_T0(void)
1208
{
1209
    T2 = T0;
1210
}
1211

    
1212
void OPPROTO op_movl_T0_T2(void)
1213
{
1214
    T0 = T2;
1215
}
1216

    
1217
/* iwMMXt support */
1218
#include "op_iwmmxt.c"