Statistics
| Branch: | Revision:

root / target-arm / op.c @ 9ee6e8bb

History | View | Annotate | Download (35.4 kB)

1
/*
2
 *  ARM micro operations
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005-2007 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_T0(void)
235
{
236
    T0 = ~T0;
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_test_T0(void)
355
{
356
    if (T0)
357
        GOTO_LABEL_PARAM(1);
358
    FORCE_RET();
359
}
360
void OPPROTO op_testn_T0(void)
361
{
362
    if (!T0)
363
        GOTO_LABEL_PARAM(1);
364
    FORCE_RET();
365
}
366

    
367
void OPPROTO op_goto_tb0(void)
368
{
369
    GOTO_TB(op_goto_tb0, PARAM1, 0);
370
}
371

    
372
void OPPROTO op_goto_tb1(void)
373
{
374
    GOTO_TB(op_goto_tb1, PARAM1, 1);
375
}
376

    
377
void OPPROTO op_exit_tb(void)
378
{
379
    EXIT_TB();
380
}
381

    
382
void OPPROTO op_movl_T0_cpsr(void)
383
{
384
    /* Execution state bits always read as zero.  */
385
    T0 = cpsr_read(env) & ~CPSR_EXEC;
386
    FORCE_RET();
387
}
388

    
389
void OPPROTO op_movl_T0_spsr(void)
390
{
391
    T0 = env->spsr;
392
}
393

    
394
void OPPROTO op_movl_spsr_T0(void)
395
{
396
    uint32_t mask = PARAM1;
397
    env->spsr = (env->spsr & ~mask) | (T0 & mask);
398
}
399

    
400
void OPPROTO op_movl_cpsr_T0(void)
401
{
402
    cpsr_write(env, T0, PARAM1);
403
    FORCE_RET();
404
}
405

    
406
void OPPROTO op_mul_T0_T1(void)
407
{
408
    T0 = T0 * T1;
409
}
410

    
411
/* 64 bit unsigned mul */
412
void OPPROTO op_mull_T0_T1(void)
413
{
414
    uint64_t res;
415
    res = (uint64_t)T0 * (uint64_t)T1;
416
    T1 = res >> 32;
417
    T0 = res;
418
}
419

    
420
/* 64 bit signed mul */
421
void OPPROTO op_imull_T0_T1(void)
422
{
423
    uint64_t res;
424
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
425
    T1 = res >> 32;
426
    T0 = res;
427
}
428

    
429
/* 48 bit signed mul, top 32 bits */
430
void OPPROTO op_imulw_T0_T1(void)
431
{
432
  uint64_t res;
433
  res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
434
  T0 = res >> 16;
435
}
436

    
437
void OPPROTO op_addq_T0_T1(void)
438
{
439
    uint64_t res;
440
    res = ((uint64_t)T1 << 32) | T0;
441
    res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
442
    T1 = res >> 32;
443
    T0 = res;
444
}
445

    
446
void OPPROTO op_addq_lo_T0_T1(void)
447
{
448
    uint64_t res;
449
    res = ((uint64_t)T1 << 32) | T0;
450
    res += (uint64_t)(env->regs[PARAM1]);
451
    T1 = res >> 32;
452
    T0 = res;
453
}
454

    
455
/* Dual 16-bit accumulate.  */
456
void OPPROTO op_addq_T0_T1_dual(void)
457
{
458
  uint64_t res;
459
  res = ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
460
  res += (int32_t)T0;
461
  res += (int32_t)T1;
462
  env->regs[PARAM1] = (uint32_t)res;
463
  env->regs[PARAM2] = res >> 32;
464
}
465

    
466
/* Dual 16-bit subtract accumulate.  */
467
void OPPROTO op_subq_T0_T1_dual(void)
468
{
469
  uint64_t res;
470
  res = ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
471
  res += (int32_t)T0;
472
  res -= (int32_t)T1;
473
  env->regs[PARAM1] = (uint32_t)res;
474
  env->regs[PARAM2] = res >> 32;
475
}
476

    
477
void OPPROTO op_logicq_cc(void)
478
{
479
    env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
480
}
481

    
482
/* memory access */
483

    
484
#define MEMSUFFIX _raw
485
#include "op_mem.h"
486

    
487
#if !defined(CONFIG_USER_ONLY)
488
#define MEMSUFFIX _user
489
#include "op_mem.h"
490
#define MEMSUFFIX _kernel
491
#include "op_mem.h"
492
#endif
493

    
494
void OPPROTO op_clrex(void)
495
{
496
    cpu_lock();
497
    helper_clrex(env);
498
    cpu_unlock();
499
}
500

    
501
/* shifts */
502

    
503
/* Used by NEON.  */
504
void OPPROTO op_shll_T0_im(void)
505
{
506
    T1 = T1 << PARAM1;
507
}
508

    
509
/* T1 based */
510

    
511
void OPPROTO op_shll_T1_im(void)
512
{
513
    T1 = T1 << PARAM1;
514
}
515

    
516
void OPPROTO op_shrl_T1_im(void)
517
{
518
    T1 = (uint32_t)T1 >> PARAM1;
519
}
520

    
521
void OPPROTO op_shrl_T1_0(void)
522
{
523
    T1 = 0;
524
}
525

    
526
void OPPROTO op_sarl_T1_im(void)
527
{
528
    T1 = (int32_t)T1 >> PARAM1;
529
}
530

    
531
void OPPROTO op_sarl_T1_0(void)
532
{
533
    T1 = (int32_t)T1 >> 31;
534
}
535

    
536
void OPPROTO op_rorl_T1_im(void)
537
{
538
    int shift;
539
    shift = PARAM1;
540
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
541
}
542

    
543
void OPPROTO op_rrxl_T1(void)
544
{
545
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
546
}
547

    
548
/* T1 based, set C flag */
549
void OPPROTO op_shll_T1_im_cc(void)
550
{
551
    env->CF = (T1 >> (32 - PARAM1)) & 1;
552
    T1 = T1 << PARAM1;
553
}
554

    
555
void OPPROTO op_shrl_T1_im_cc(void)
556
{
557
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
558
    T1 = (uint32_t)T1 >> PARAM1;
559
}
560

    
561
void OPPROTO op_shrl_T1_0_cc(void)
562
{
563
    env->CF = (T1 >> 31) & 1;
564
    T1 = 0;
565
}
566

    
567
void OPPROTO op_sarl_T1_im_cc(void)
568
{
569
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
570
    T1 = (int32_t)T1 >> PARAM1;
571
}
572

    
573
void OPPROTO op_sarl_T1_0_cc(void)
574
{
575
    env->CF = (T1 >> 31) & 1;
576
    T1 = (int32_t)T1 >> 31;
577
}
578

    
579
void OPPROTO op_rorl_T1_im_cc(void)
580
{
581
    int shift;
582
    shift = PARAM1;
583
    env->CF = (T1 >> (shift - 1)) & 1;
584
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
585
}
586

    
587
void OPPROTO op_rrxl_T1_cc(void)
588
{
589
    uint32_t c;
590
    c = T1 & 1;
591
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
592
    env->CF = c;
593
}
594

    
595
/* T2 based */
596
void OPPROTO op_shll_T2_im(void)
597
{
598
    T2 = T2 << PARAM1;
599
}
600

    
601
void OPPROTO op_shrl_T2_im(void)
602
{
603
    T2 = (uint32_t)T2 >> PARAM1;
604
}
605

    
606
void OPPROTO op_shrl_T2_0(void)
607
{
608
    T2 = 0;
609
}
610

    
611
void OPPROTO op_sarl_T2_im(void)
612
{
613
    T2 = (int32_t)T2 >> PARAM1;
614
}
615

    
616
void OPPROTO op_sarl_T2_0(void)
617
{
618
    T2 = (int32_t)T2 >> 31;
619
}
620

    
621
void OPPROTO op_rorl_T2_im(void)
622
{
623
    int shift;
624
    shift = PARAM1;
625
    T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
626
}
627

    
628
void OPPROTO op_rrxl_T2(void)
629
{
630
    T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31);
631
}
632

    
633
/* T1 based, use T0 as shift count */
634

    
635
void OPPROTO op_shll_T1_T0(void)
636
{
637
    int shift;
638
    shift = T0 & 0xff;
639
    if (shift >= 32)
640
        T1 = 0;
641
    else
642
        T1 = T1 << shift;
643
    FORCE_RET();
644
}
645

    
646
void OPPROTO op_shrl_T1_T0(void)
647
{
648
    int shift;
649
    shift = T0 & 0xff;
650
    if (shift >= 32)
651
        T1 = 0;
652
    else
653
        T1 = (uint32_t)T1 >> shift;
654
    FORCE_RET();
655
}
656

    
657
void OPPROTO op_sarl_T1_T0(void)
658
{
659
    int shift;
660
    shift = T0 & 0xff;
661
    if (shift >= 32)
662
        shift = 31;
663
    T1 = (int32_t)T1 >> shift;
664
}
665

    
666
void OPPROTO op_rorl_T1_T0(void)
667
{
668
    int shift;
669
    shift = T0 & 0x1f;
670
    if (shift) {
671
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
672
    }
673
    FORCE_RET();
674
}
675

    
676
/* T1 based, use T0 as shift count and compute CF */
677

    
678
void OPPROTO op_shll_T1_T0_cc(void)
679
{
680
    int shift;
681
    shift = T0 & 0xff;
682
    if (shift >= 32) {
683
        if (shift == 32)
684
            env->CF = T1 & 1;
685
        else
686
            env->CF = 0;
687
        T1 = 0;
688
    } else if (shift != 0) {
689
        env->CF = (T1 >> (32 - shift)) & 1;
690
        T1 = T1 << shift;
691
    }
692
    FORCE_RET();
693
}
694

    
695
void OPPROTO op_shrl_T1_T0_cc(void)
696
{
697
    int shift;
698
    shift = T0 & 0xff;
699
    if (shift >= 32) {
700
        if (shift == 32)
701
            env->CF = (T1 >> 31) & 1;
702
        else
703
            env->CF = 0;
704
        T1 = 0;
705
    } else if (shift != 0) {
706
        env->CF = (T1 >> (shift - 1)) & 1;
707
        T1 = (uint32_t)T1 >> shift;
708
    }
709
    FORCE_RET();
710
}
711

    
712
void OPPROTO op_sarl_T1_T0_cc(void)
713
{
714
    int shift;
715
    shift = T0 & 0xff;
716
    if (shift >= 32) {
717
        env->CF = (T1 >> 31) & 1;
718
        T1 = (int32_t)T1 >> 31;
719
    } else if (shift != 0) {
720
        env->CF = (T1 >> (shift - 1)) & 1;
721
        T1 = (int32_t)T1 >> shift;
722
    }
723
    FORCE_RET();
724
}
725

    
726
void OPPROTO op_rorl_T1_T0_cc(void)
727
{
728
    int shift1, shift;
729
    shift1 = T0 & 0xff;
730
    shift = shift1 & 0x1f;
731
    if (shift == 0) {
732
        if (shift1 != 0)
733
            env->CF = (T1 >> 31) & 1;
734
    } else {
735
        env->CF = (T1 >> (shift - 1)) & 1;
736
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
737
    }
738
    FORCE_RET();
739
}
740

    
741
/* misc */
742
void OPPROTO op_clz_T0(void)
743
{
744
    int count;
745
    for (count = 32; T0 > 0; count--)
746
        T0 = T0 >> 1;
747
    T0 = count;
748
    FORCE_RET();
749
}
750

    
751
void OPPROTO op_sarl_T0_im(void)
752
{
753
    T0 = (int32_t)T0 >> PARAM1;
754
}
755

    
756
/* Sign/zero extend */
757
void OPPROTO op_sxth_T0(void)
758
{
759
  T0 = (int16_t)T0;
760
}
761

    
762
void OPPROTO op_sxth_T1(void)
763
{
764
  T1 = (int16_t)T1;
765
}
766

    
767
void OPPROTO op_sxtb_T1(void)
768
{
769
    T1 = (int8_t)T1;
770
}
771

    
772
void OPPROTO op_uxtb_T1(void)
773
{
774
    T1 = (uint8_t)T1;
775
}
776

    
777
void OPPROTO op_uxth_T1(void)
778
{
779
    T1 = (uint16_t)T1;
780
}
781

    
782
void OPPROTO op_sxtb16_T1(void)
783
{
784
    uint32_t res;
785
    res = (uint16_t)(int8_t)T1;
786
    res |= (uint32_t)(int8_t)(T1 >> 16) << 16;
787
    T1 = res;
788
}
789

    
790
void OPPROTO op_uxtb16_T1(void)
791
{
792
    uint32_t res;
793
    res = (uint16_t)(uint8_t)T1;
794
    res |= (uint32_t)(uint8_t)(T1 >> 16) << 16;
795
    T1 = res;
796
}
797

    
798
#define SIGNBIT (uint32_t)0x80000000
799
/* saturating arithmetic  */
800
void OPPROTO op_addl_T0_T1_setq(void)
801
{
802
  uint32_t res;
803

    
804
  res = T0 + T1;
805
  if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT))
806
      env->QF = 1;
807

    
808
  T0 = res;
809
  FORCE_RET();
810
}
811

    
812
void OPPROTO op_addl_T0_T1_saturate(void)
813
{
814
  uint32_t res;
815

    
816
  res = T0 + T1;
817
  if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) {
818
      env->QF = 1;
819
      if (T0 & SIGNBIT)
820
          T0 = 0x80000000;
821
      else
822
          T0 = 0x7fffffff;
823
  }
824
  else
825
    T0 = res;
826

    
827
  FORCE_RET();
828
}
829

    
830
void OPPROTO op_subl_T0_T1_saturate(void)
831
{
832
  uint32_t res;
833

    
834
  res = T0 - T1;
835
  if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) {
836
      env->QF = 1;
837
      if (T0 & SIGNBIT)
838
          T0 = 0x80000000;
839
      else
840
          T0 = 0x7fffffff;
841
  }
842
  else
843
    T0 = res;
844

    
845
  FORCE_RET();
846
}
847

    
848
void OPPROTO op_double_T1_saturate(void)
849
{
850
  int32_t val;
851

    
852
  val = T1;
853
  if (val >= 0x40000000) {
854
      T1 = 0x7fffffff;
855
      env->QF = 1;
856
  } else if (val <= (int32_t)0xc0000000) {
857
      T1 = 0x80000000;
858
      env->QF = 1;
859
  } else {
860
      T1 = val << 1;
861
  }
862
  FORCE_RET();
863
}
864

    
865
/* Unsigned saturating arithmetic for NEON.  */
866
void OPPROTO op_addl_T0_T1_usaturate(void)
867
{
868
  uint32_t res;
869

    
870
  res = T0 + T1;
871
  if (res < T0) {
872
      env->QF = 1;
873
      T0 = 0xffffffff;
874
  } else {
875
      T0 = res;
876
  }
877

    
878
  FORCE_RET();
879
}
880

    
881
void OPPROTO op_subl_T0_T1_usaturate(void)
882
{
883
  uint32_t res;
884

    
885
  res = T0 - T1;
886
  if (res > T0) {
887
      env->QF = 1;
888
      T0 = 0;
889
  } else {
890
      T0 = res;
891
  }
892

    
893
  FORCE_RET();
894
}
895

    
896
/* Thumb shift by immediate */
897
void OPPROTO op_shll_T0_im_thumb_cc(void)
898
{
899
    int shift;
900
    shift = PARAM1;
901
    if (shift != 0) {
902
        env->CF = (T0 >> (32 - shift)) & 1;
903
        T0 = T0 << shift;
904
    }
905
    env->NZF = T0;
906
    FORCE_RET();
907
}
908

    
909
void OPPROTO op_shll_T0_im_thumb(void)
910
{
911
    T0 = T0 << PARAM1;
912
    FORCE_RET();
913
}
914

    
915
void OPPROTO op_shrl_T0_im_thumb_cc(void)
916
{
917
    int shift;
918

    
919
    shift = PARAM1;
920
    if (shift == 0) {
921
        env->CF = ((uint32_t)T0) >> 31;
922
        T0 = 0;
923
    } else {
924
        env->CF = (T0 >> (shift - 1)) & 1;
925
        T0 = T0 >> shift;
926
    }
927
    env->NZF = T0;
928
    FORCE_RET();
929
}
930

    
931
void OPPROTO op_shrl_T0_im_thumb(void)
932
{
933
    int shift;
934

    
935
    shift = PARAM1;
936
    if (shift == 0) {
937
        T0 = 0;
938
    } else {
939
        T0 = T0 >> shift;
940
    }
941
    FORCE_RET();
942
}
943

    
944
void OPPROTO op_sarl_T0_im_thumb_cc(void)
945
{
946
    int shift;
947

    
948
    shift = PARAM1;
949
    if (shift == 0) {
950
        T0 = ((int32_t)T0) >> 31;
951
        env->CF = T0 & 1;
952
    } else {
953
        env->CF = (T0 >> (shift - 1)) & 1;
954
        T0 = ((int32_t)T0) >> shift;
955
    }
956
    env->NZF = T0;
957
    FORCE_RET();
958
}
959

    
960
void OPPROTO op_sarl_T0_im_thumb(void)
961
{
962
    int shift;
963

    
964
    shift = PARAM1;
965
    if (shift == 0) {
966
        env->CF = T0 & 1;
967
    } else {
968
        T0 = ((int32_t)T0) >> shift;
969
    }
970
    FORCE_RET();
971
}
972

    
973
/* exceptions */
974

    
975
void OPPROTO op_swi(void)
976
{
977
    env->exception_index = EXCP_SWI;
978
    cpu_loop_exit();
979
}
980

    
981
void OPPROTO op_undef_insn(void)
982
{
983
    env->exception_index = EXCP_UDEF;
984
    cpu_loop_exit();
985
}
986

    
987
void OPPROTO op_debug(void)
988
{
989
    env->exception_index = EXCP_DEBUG;
990
    cpu_loop_exit();
991
}
992

    
993
void OPPROTO op_wfi(void)
994
{
995
    env->exception_index = EXCP_HLT;
996
    env->halted = 1;
997
    cpu_loop_exit();
998
}
999

    
1000
void OPPROTO op_bkpt(void)
1001
{
1002
    env->exception_index = EXCP_BKPT;
1003
    cpu_loop_exit();
1004
}
1005

    
1006
void OPPROTO op_exception_exit(void)
1007
{
1008
    env->exception_index = EXCP_EXCEPTION_EXIT;
1009
    cpu_loop_exit();
1010
}
1011

    
1012
/* VFP support.  We follow the convention used for VFP instrunctions:
1013
   Single precition routines have a "s" suffix, double precision a
1014
   "d" suffix.  */
1015

    
1016
#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void)
1017

    
1018
#define VFP_BINOP(name) \
1019
VFP_OP(name, s)             \
1020
{                           \
1021
    FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status);    \
1022
}                           \
1023
VFP_OP(name, d)             \
1024
{                           \
1025
    FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status);    \
1026
}
1027
VFP_BINOP(add)
1028
VFP_BINOP(sub)
1029
VFP_BINOP(mul)
1030
VFP_BINOP(div)
1031
#undef VFP_BINOP
1032

    
1033
#define VFP_HELPER(name)  \
1034
VFP_OP(name, s)           \
1035
{                         \
1036
    do_vfp_##name##s();    \
1037
}                         \
1038
VFP_OP(name, d)           \
1039
{                         \
1040
    do_vfp_##name##d();    \
1041
}
1042
VFP_HELPER(abs)
1043
VFP_HELPER(sqrt)
1044
VFP_HELPER(cmp)
1045
VFP_HELPER(cmpe)
1046
#undef VFP_HELPER
1047

    
1048
/* XXX: Will this do the right thing for NANs.  Should invert the signbit
1049
   without looking at the rest of the value.  */
1050
VFP_OP(neg, s)
1051
{
1052
    FT0s = float32_chs(FT0s);
1053
}
1054

    
1055
VFP_OP(neg, d)
1056
{
1057
    FT0d = float64_chs(FT0d);
1058
}
1059

    
1060
VFP_OP(F1_ld0, s)
1061
{
1062
    union {
1063
        uint32_t i;
1064
        float32 s;
1065
    } v;
1066
    v.i = 0;
1067
    FT1s = v.s;
1068
}
1069

    
1070
VFP_OP(F1_ld0, d)
1071
{
1072
    union {
1073
        uint64_t i;
1074
        float64 d;
1075
    } v;
1076
    v.i = 0;
1077
    FT1d = v.d;
1078
}
1079

    
1080
/* Helper routines to perform bitwise copies between float and int.  */
1081
static inline float32 vfp_itos(uint32_t i)
1082
{
1083
    union {
1084
        uint32_t i;
1085
        float32 s;
1086
    } v;
1087

    
1088
    v.i = i;
1089
    return v.s;
1090
}
1091

    
1092
static inline uint32_t vfp_stoi(float32 s)
1093
{
1094
    union {
1095
        uint32_t i;
1096
        float32 s;
1097
    } v;
1098

    
1099
    v.s = s;
1100
    return v.i;
1101
}
1102

    
1103
static inline float64 vfp_itod(uint64_t i)
1104
{
1105
    union {
1106
        uint64_t i;
1107
        float64 d;
1108
    } v;
1109

    
1110
    v.i = i;
1111
    return v.d;
1112
}
1113

    
1114
static inline uint64_t vfp_dtoi(float64 d)
1115
{
1116
    union {
1117
        uint64_t i;
1118
        float64 d;
1119
    } v;
1120

    
1121
    v.d = d;
1122
    return v.i;
1123
}
1124

    
1125
/* Integer to float conversion.  */
1126
VFP_OP(uito, s)
1127
{
1128
    FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
1129
}
1130

    
1131
VFP_OP(uito, d)
1132
{
1133
    FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
1134
}
1135

    
1136
VFP_OP(sito, s)
1137
{
1138
    FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
1139
}
1140

    
1141
VFP_OP(sito, d)
1142
{
1143
    FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
1144
}
1145

    
1146
/* Float to integer conversion.  */
1147
VFP_OP(toui, s)
1148
{
1149
    FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status));
1150
}
1151

    
1152
VFP_OP(toui, d)
1153
{
1154
    FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status));
1155
}
1156

    
1157
VFP_OP(tosi, s)
1158
{
1159
    FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status));
1160
}
1161

    
1162
VFP_OP(tosi, d)
1163
{
1164
    FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status));
1165
}
1166

    
1167
/* TODO: Set rounding mode properly.  */
1168
VFP_OP(touiz, s)
1169
{
1170
    FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status));
1171
}
1172

    
1173
VFP_OP(touiz, d)
1174
{
1175
    FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status));
1176
}
1177

    
1178
VFP_OP(tosiz, s)
1179
{
1180
    FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status));
1181
}
1182

    
1183
VFP_OP(tosiz, d)
1184
{
1185
    FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status));
1186
}
1187

    
1188
/* floating point conversion */
1189
VFP_OP(fcvtd, s)
1190
{
1191
    FT0d = float32_to_float64(FT0s, &env->vfp.fp_status);
1192
}
1193

    
1194
VFP_OP(fcvts, d)
1195
{
1196
    FT0s = float64_to_float32(FT0d, &env->vfp.fp_status);
1197
}
1198

    
1199
/* VFP3 fixed point conversion.  */
1200
#define VFP_CONV_FIX(name, p, ftype, itype, sign) \
1201
VFP_OP(name##to, p) \
1202
{ \
1203
    ftype tmp; \
1204
    tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(FT0##p), \
1205
                                  &env->vfp.fp_status); \
1206
    FT0##p = ftype##_scalbn(tmp, PARAM1, &env->vfp.fp_status); \
1207
} \
1208
VFP_OP(to##name, p) \
1209
{ \
1210
    ftype tmp; \
1211
    tmp = ftype##_scalbn(FT0##p, PARAM1, &env->vfp.fp_status); \
1212
    FT0##p = vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \
1213
            &env->vfp.fp_status)); \
1214
}
1215

    
1216
VFP_CONV_FIX(sh, d, float64, int16, )
1217
VFP_CONV_FIX(sl, d, float64, int32, )
1218
VFP_CONV_FIX(uh, d, float64, uint16, u)
1219
VFP_CONV_FIX(ul, d, float64, uint32, u)
1220
VFP_CONV_FIX(sh, s, float32, int16, )
1221
VFP_CONV_FIX(sl, s, float32, int32, )
1222
VFP_CONV_FIX(uh, s, float32, uint16, u)
1223
VFP_CONV_FIX(ul, s, float32, uint32, u)
1224

    
1225
/* Get and Put values from registers.  */
1226
VFP_OP(getreg_F0, d)
1227
{
1228
  FT0d = *(float64 *)((char *) env + PARAM1);
1229
}
1230

    
1231
VFP_OP(getreg_F0, s)
1232
{
1233
  FT0s = *(float32 *)((char *) env + PARAM1);
1234
}
1235

    
1236
VFP_OP(getreg_F1, d)
1237
{
1238
  FT1d = *(float64 *)((char *) env + PARAM1);
1239
}
1240

    
1241
VFP_OP(getreg_F1, s)
1242
{
1243
  FT1s = *(float32 *)((char *) env + PARAM1);
1244
}
1245

    
1246
VFP_OP(setreg_F0, d)
1247
{
1248
  *(float64 *)((char *) env + PARAM1) = FT0d;
1249
}
1250

    
1251
VFP_OP(setreg_F0, s)
1252
{
1253
  *(float32 *)((char *) env + PARAM1) = FT0s;
1254
}
1255

    
1256
void OPPROTO op_vfp_movl_T0_fpscr(void)
1257
{
1258
    do_vfp_get_fpscr ();
1259
}
1260

    
1261
void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
1262
{
1263
    T0 = env->vfp.xregs[ARM_VFP_FPSCR] & (0xf << 28);
1264
}
1265

    
1266
void OPPROTO op_vfp_movl_fpscr_T0(void)
1267
{
1268
    do_vfp_set_fpscr();
1269
}
1270

    
1271
void OPPROTO op_vfp_movl_T0_xreg(void)
1272
{
1273
    T0 = env->vfp.xregs[PARAM1];
1274
}
1275

    
1276
void OPPROTO op_vfp_movl_xreg_T0(void)
1277
{
1278
    env->vfp.xregs[PARAM1] = T0;
1279
}
1280

    
1281
/* Move between FT0s to T0  */
1282
void OPPROTO op_vfp_mrs(void)
1283
{
1284
    T0 = vfp_stoi(FT0s);
1285
}
1286

    
1287
void OPPROTO op_vfp_msr(void)
1288
{
1289
    FT0s = vfp_itos(T0);
1290
}
1291

    
1292
/* Move between FT0d and {T0,T1} */
1293
void OPPROTO op_vfp_mrrd(void)
1294
{
1295
    CPU_DoubleU u;
1296

    
1297
    u.d = FT0d;
1298
    T0 = u.l.lower;
1299
    T1 = u.l.upper;
1300
}
1301

    
1302
void OPPROTO op_vfp_mdrr(void)
1303
{
1304
    CPU_DoubleU u;
1305

    
1306
    u.l.lower = T0;
1307
    u.l.upper = T1;
1308
    FT0d = u.d;
1309
}
1310

    
1311
/* Load immediate.  PARAM1 is the 32 most significant bits of the value.  */
1312
void OPPROTO op_vfp_fconstd(void)
1313
{
1314
    CPU_DoubleU u;
1315
    u.l.upper = PARAM1;
1316
    u.l.lower = 0;
1317
    FT0d = u.d;
1318
}
1319

    
1320
void OPPROTO op_vfp_fconsts(void)
1321
{
1322
    FT0s = vfp_itos(PARAM1);
1323
}
1324

    
1325
/* Copy the most significant bit of T0 to all bits of T1.  */
1326
void OPPROTO op_signbit_T1_T0(void)
1327
{
1328
    T1 = (int32_t)T0 >> 31;
1329
}
1330

    
1331
void OPPROTO op_movl_cp_T0(void)
1332
{
1333
    helper_set_cp(env, PARAM1, T0);
1334
    FORCE_RET();
1335
}
1336

    
1337
void OPPROTO op_movl_T0_cp(void)
1338
{
1339
    T0 = helper_get_cp(env, PARAM1);
1340
    FORCE_RET();
1341
}
1342

    
1343
void OPPROTO op_movl_cp15_T0(void)
1344
{
1345
    helper_set_cp15(env, PARAM1, T0);
1346
    FORCE_RET();
1347
}
1348

    
1349
void OPPROTO op_movl_T0_cp15(void)
1350
{
1351
    T0 = helper_get_cp15(env, PARAM1);
1352
    FORCE_RET();
1353
}
1354

    
1355
/* Access to user mode registers from privileged modes.  */
1356
void OPPROTO op_movl_T0_user(void)
1357
{
1358
    int regno = PARAM1;
1359
    if (regno == 13) {
1360
        T0 = env->banked_r13[0];
1361
    } else if (regno == 14) {
1362
        T0 = env->banked_r14[0];
1363
    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
1364
        T0 = env->usr_regs[regno - 8];
1365
    } else {
1366
        T0 = env->regs[regno];
1367
    }
1368
    FORCE_RET();
1369
}
1370

    
1371

    
1372
void OPPROTO op_movl_user_T0(void)
1373
{
1374
    int regno = PARAM1;
1375
    if (regno == 13) {
1376
        env->banked_r13[0] = T0;
1377
    } else if (regno == 14) {
1378
        env->banked_r14[0] = T0;
1379
    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
1380
        env->usr_regs[regno - 8] = T0;
1381
    } else {
1382
        env->regs[regno] = T0;
1383
    }
1384
    FORCE_RET();
1385
}
1386

    
1387
void OPPROTO op_movl_T0_T1(void)
1388
{
1389
    T0 = T1;
1390
}
1391

    
1392
void OPPROTO op_movl_T0_T2(void)
1393
{
1394
    T0 = T2;
1395
}
1396

    
1397
void OPPROTO op_movl_T1_T0(void)
1398
{
1399
    T1 = T0;
1400
}
1401

    
1402
void OPPROTO op_movl_T1_T2(void)
1403
{
1404
    T1 = T2;
1405
}
1406

    
1407
void OPPROTO op_movl_T2_T0(void)
1408
{
1409
    T2 = T0;
1410
}
1411

    
1412
/* ARMv6 Media instructions.  */
1413

    
1414
/* Note that signed overflow is undefined in C.  The following routines are
1415
   careful to use unsigned types where modulo arithmetic is required.
1416
   Failure to do so _will_ break on newer gcc.  */
1417

    
1418
/* Signed saturating arithmetic.  */
1419

    
1420
/* Perform 16-bit signed satruating addition.  */
1421
static inline uint16_t add16_sat(uint16_t a, uint16_t b)
1422
{
1423
    uint16_t res;
1424

    
1425
    res = a + b;
1426
    if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
1427
        if (a & 0x8000)
1428
            res = 0x8000;
1429
        else
1430
            res = 0x7fff;
1431
    }
1432
    return res;
1433
}
1434

    
1435
/* Perform 8-bit signed satruating addition.  */
1436
static inline uint8_t add8_sat(uint8_t a, uint8_t b)
1437
{
1438
    uint8_t res;
1439

    
1440
    res = a + b;
1441
    if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
1442
        if (a & 0x80)
1443
            res = 0x80;
1444
        else
1445
            res = 0x7f;
1446
    }
1447
    return res;
1448
}
1449

    
1450
/* Perform 16-bit signed satruating subtraction.  */
1451
static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
1452
{
1453
    uint16_t res;
1454

    
1455
    res = a - b;
1456
    if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
1457
        if (a & 0x8000)
1458
            res = 0x8000;
1459
        else
1460
            res = 0x7fff;
1461
    }
1462
    return res;
1463
}
1464

    
1465
/* Perform 8-bit signed satruating subtraction.  */
1466
static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
1467
{
1468
    uint8_t res;
1469

    
1470
    res = a - b;
1471
    if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
1472
        if (a & 0x80)
1473
            res = 0x80;
1474
        else
1475
            res = 0x7f;
1476
    }
1477
    return res;
1478
}
1479

    
1480
#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
1481
#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
1482
#define ADD8(a, b, n)  RESULT(add8_sat(a, b), n, 8);
1483
#define SUB8(a, b, n)  RESULT(sub8_sat(a, b), n, 8);
1484
#define PFX q
1485

    
1486
#include "op_addsub.h"
1487

    
1488
/* Unsigned saturating arithmetic.  */
1489
static inline uint16_t add16_usat(uint16_t a, uint8_t b)
1490
{
1491
    uint16_t res;
1492
    res = a + b;
1493
    if (res < a)
1494
        res = 0xffff;
1495
    return res;
1496
}
1497

    
1498
static inline uint16_t sub16_usat(uint16_t a, uint8_t b)
1499
{
1500
    if (a < b)
1501
        return a - b;
1502
    else
1503
        return 0;
1504
}
1505

    
1506
static inline uint8_t add8_usat(uint8_t a, uint8_t b)
1507
{
1508
    uint8_t res;
1509
    res = a + b;
1510
    if (res < a)
1511
        res = 0xff;
1512
    return res;
1513
}
1514

    
1515
static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
1516
{
1517
    if (a < b)
1518
        return a - b;
1519
    else
1520
        return 0;
1521
}
1522

    
1523
#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
1524
#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
1525
#define ADD8(a, b, n)  RESULT(add8_usat(a, b), n, 8);
1526
#define SUB8(a, b, n)  RESULT(sub8_usat(a, b), n, 8);
1527
#define PFX uq
1528

    
1529
#include "op_addsub.h"
1530

    
1531
/* Signed modulo arithmetic.  */
1532
#define SARITH16(a, b, n, op) do { \
1533
    int32_t sum; \
1534
    sum = (int16_t)((uint16_t)(a) op (uint16_t)(b)); \
1535
    RESULT(sum, n, 16); \
1536
    if (sum >= 0) \
1537
        ge |= 3 << (n * 2); \
1538
    } while(0)
1539

    
1540
#define SARITH8(a, b, n, op) do { \
1541
    int32_t sum; \
1542
    sum = (int8_t)((uint8_t)(a) op (uint8_t)(b)); \
1543
    RESULT(sum, n, 8); \
1544
    if (sum >= 0) \
1545
        ge |= 1 << n; \
1546
    } while(0)
1547

    
1548

    
1549
#define ADD16(a, b, n) SARITH16(a, b, n, +)
1550
#define SUB16(a, b, n) SARITH16(a, b, n, -)
1551
#define ADD8(a, b, n)  SARITH8(a, b, n, +)
1552
#define SUB8(a, b, n)  SARITH8(a, b, n, -)
1553
#define PFX s
1554
#define ARITH_GE
1555

    
1556
#include "op_addsub.h"
1557

    
1558
/* Unsigned modulo arithmetic.  */
1559
#define ADD16(a, b, n) do { \
1560
    uint32_t sum; \
1561
    sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
1562
    RESULT(sum, n, 16); \
1563
    if ((sum >> 16) == 0) \
1564
        ge |= 3 << (n * 2); \
1565
    } while(0)
1566

    
1567
#define ADD8(a, b, n) do { \
1568
    uint32_t sum; \
1569
    sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
1570
    RESULT(sum, n, 8); \
1571
    if ((sum >> 8) == 0) \
1572
        ge |= 3 << (n * 2); \
1573
    } while(0)
1574

    
1575
#define SUB16(a, b, n) do { \
1576
    uint32_t sum; \
1577
    sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
1578
    RESULT(sum, n, 16); \
1579
    if ((sum >> 16) == 0) \
1580
        ge |= 3 << (n * 2); \
1581
    } while(0)
1582

    
1583
#define SUB8(a, b, n) do { \
1584
    uint32_t sum; \
1585
    sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
1586
    RESULT(sum, n, 8); \
1587
    if ((sum >> 8) == 0) \
1588
        ge |= 3 << (n * 2); \
1589
    } while(0)
1590

    
1591
#define PFX u
1592
#define ARITH_GE
1593

    
1594
#include "op_addsub.h"
1595

    
1596
/* Halved signed arithmetic.  */
1597
#define ADD16(a, b, n) \
1598
  RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
1599
#define SUB16(a, b, n) \
1600
  RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
1601
#define ADD8(a, b, n) \
1602
  RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
1603
#define SUB8(a, b, n) \
1604
  RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
1605
#define PFX sh
1606

    
1607
#include "op_addsub.h"
1608

    
1609
/* Halved unsigned arithmetic.  */
1610
#define ADD16(a, b, n) \
1611
  RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
1612
#define SUB16(a, b, n) \
1613
  RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
1614
#define ADD8(a, b, n) \
1615
  RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
1616
#define SUB8(a, b, n) \
1617
  RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
1618
#define PFX uh
1619

    
1620
#include "op_addsub.h"
1621

    
1622
void OPPROTO op_pkhtb_T0_T1(void)
1623
{
1624
    T0 = (T0 & 0xffff0000) | (T1 & 0xffff);
1625
}
1626

    
1627
void OPPROTO op_pkhbt_T0_T1(void)
1628
{
1629
    T0 = (T0 & 0xffff) | (T1 & 0xffff0000);
1630
}
1631
void OPPROTO op_rev_T0(void)
1632
{
1633
    T0 =  ((T0 & 0xff000000) >> 24)
1634
        | ((T0 & 0x00ff0000) >> 8)
1635
        | ((T0 & 0x0000ff00) << 8)
1636
        | ((T0 & 0x000000ff) << 24);
1637
}
1638

    
1639
void OPPROTO op_revh_T0(void)
1640
{
1641
    T0 = (T0 >> 16) | (T0 << 16);
1642
}
1643

    
1644
void OPPROTO op_rev16_T0(void)
1645
{
1646
    T0 =  ((T0 & 0xff000000) >> 8)
1647
        | ((T0 & 0x00ff0000) << 8)
1648
        | ((T0 & 0x0000ff00) >> 8)
1649
        | ((T0 & 0x000000ff) << 8);
1650
}
1651

    
1652
void OPPROTO op_revsh_T0(void)
1653
{
1654
    T0 = (int16_t)(  ((T0 & 0x0000ff00) >> 8)
1655
                   | ((T0 & 0x000000ff) << 8));
1656
}
1657

    
1658
void OPPROTO op_rbit_T0(void)
1659
{
1660
    T0 =  ((T0 & 0xff000000) >> 24)
1661
        | ((T0 & 0x00ff0000) >> 8)
1662
        | ((T0 & 0x0000ff00) << 8)
1663
        | ((T0 & 0x000000ff) << 24);
1664
    T0 =  ((T0 & 0xf0f0f0f0) >> 4)
1665
        | ((T0 & 0x0f0f0f0f) << 4);
1666
    T0 =  ((T0 & 0x88888888) >> 3)
1667
        | ((T0 & 0x44444444) >> 1)
1668
        | ((T0 & 0x22222222) << 1)
1669
        | ((T0 & 0x11111111) << 3);
1670
}
1671

    
1672
/* Swap low and high halfwords.  */
1673
void OPPROTO op_swap_half_T1(void)
1674
{
1675
    T1 = (T1 >> 16) | (T1 << 16);
1676
    FORCE_RET();
1677
}
1678

    
1679
/* Dual 16-bit signed multiply.  */
1680
void OPPROTO op_mul_dual_T0_T1(void)
1681
{
1682
    int32_t low;
1683
    int32_t high;
1684
    low = (int32_t)(int16_t)T0 * (int32_t)(int16_t)T1;
1685
    high = (((int32_t)T0) >> 16) * (((int32_t)T1) >> 16);
1686
    T0 = low;
1687
    T1 = high;
1688
}
1689

    
1690
void OPPROTO op_sel_T0_T1(void)
1691
{
1692
    uint32_t mask;
1693
    uint32_t flags;
1694

    
1695
    flags = env->GE;
1696
    mask = 0;
1697
    if (flags & 1)
1698
        mask |= 0xff;
1699
    if (flags & 2)
1700
        mask |= 0xff00;
1701
    if (flags & 4)
1702
        mask |= 0xff0000;
1703
    if (flags & 8)
1704
        mask |= 0xff000000;
1705
    T0 = (T0 & mask) | (T1 & ~mask);
1706
    FORCE_RET();
1707
}
1708

    
1709
void OPPROTO op_roundqd_T0_T1(void)
1710
{
1711
    T0 = T1 + ((uint32_t)T0 >> 31);
1712
}
1713

    
1714
/* Signed saturation.  */
1715
static inline uint32_t do_ssat(int32_t val, int shift)
1716
{
1717
    int32_t top;
1718
    uint32_t mask;
1719

    
1720
    shift = PARAM1;
1721
    top = val >> shift;
1722
    mask = (1u << shift) - 1;
1723
    if (top > 0) {
1724
        env->QF = 1;
1725
        return mask;
1726
    } else if (top < -1) {
1727
        env->QF = 1;
1728
        return ~mask;
1729
    }
1730
    return val;
1731
}
1732

    
1733
/* Unsigned saturation.  */
1734
static inline uint32_t do_usat(int32_t val, int shift)
1735
{
1736
    uint32_t max;
1737

    
1738
    shift = PARAM1;
1739
    max = (1u << shift) - 1;
1740
    if (val < 0) {
1741
        env->QF = 1;
1742
        return 0;
1743
    } else if (val > max) {
1744
        env->QF = 1;
1745
        return max;
1746
    }
1747
    return val;
1748
}
1749

    
1750
/* Signed saturate.  */
1751
void OPPROTO op_ssat_T1(void)
1752
{
1753
    T0 = do_ssat(T0, PARAM1);
1754
    FORCE_RET();
1755
}
1756

    
1757
/* Dual halfword signed saturate.  */
1758
void OPPROTO op_ssat16_T1(void)
1759
{
1760
    uint32_t res;
1761

    
1762
    res = (uint16_t)do_ssat((int16_t)T0, PARAM1);
1763
    res |= do_ssat(((int32_t)T0) >> 16, PARAM1) << 16;
1764
    T0 = res;
1765
    FORCE_RET();
1766
}
1767

    
1768
/* Unsigned saturate.  */
1769
void OPPROTO op_usat_T1(void)
1770
{
1771
    T0 = do_usat(T0, PARAM1);
1772
    FORCE_RET();
1773
}
1774

    
1775
/* Dual halfword unsigned saturate.  */
1776
void OPPROTO op_usat16_T1(void)
1777
{
1778
    uint32_t res;
1779

    
1780
    res = (uint16_t)do_usat((int16_t)T0, PARAM1);
1781
    res |= do_usat(((int32_t)T0) >> 16, PARAM1) << 16;
1782
    T0 = res;
1783
    FORCE_RET();
1784
}
1785

    
1786
/* Dual 16-bit add.  */
1787
void OPPROTO op_add16_T1_T2(void)
1788
{
1789
    uint32_t mask;
1790
    mask = (T0 & T1) & 0x8000;
1791
    T0 ^= ~0x8000;
1792
    T1 ^= ~0x8000;
1793
    T0 = (T0 + T1) ^ mask;
1794
}
1795

    
1796
static inline uint8_t do_usad(uint8_t a, uint8_t b)
1797
{
1798
    if (a > b)
1799
        return a - b;
1800
    else
1801
        return b - a;
1802
}
1803

    
1804
/* Unsigned sum of absolute byte differences.  */
1805
void OPPROTO op_usad8_T0_T1(void)
1806
{
1807
    uint32_t sum;
1808
    sum = do_usad(T0, T1);
1809
    sum += do_usad(T0 >> 8, T1 >> 8);
1810
    sum += do_usad(T0 >> 16, T1 >>16);
1811
    sum += do_usad(T0 >> 24, T1 >> 24);
1812
    T0 = sum;
1813
}
1814

    
1815
/* Thumb-2 instructions.  */
1816

    
1817
/* Insert T1 into T0.  Result goes in T1.  */
1818
void OPPROTO op_bfi_T1_T0(void)
1819
{
1820
    int shift = PARAM1;
1821
    uint32_t mask = PARAM2;
1822
    uint32_t bits;
1823

    
1824
    bits = (T1 << shift) & mask;
1825
    T1 = (T0 & ~mask) | bits;
1826
}
1827

    
1828
/* Unsigned bitfield extract.  */
1829
void OPPROTO op_ubfx_T1(void)
1830
{
1831
    uint32_t shift = PARAM1;
1832
    uint32_t mask = PARAM2;
1833

    
1834
    T1 >>= shift;
1835
    T1 &= mask;
1836
}
1837

    
1838
/* Signed bitfield extract.  */
1839
void OPPROTO op_sbfx_T1(void)
1840
{
1841
    uint32_t shift = PARAM1;
1842
    uint32_t width = PARAM2;
1843
    int32_t val;
1844

    
1845
    val = T1 << (32 - (shift + width));
1846
    T1 = val >> (32 - width);
1847
}
1848

    
1849
void OPPROTO op_movtop_T0_im(void)
1850
{
1851
    T0 = (T0 & 0xffff) | PARAM1;
1852
}
1853

    
1854
/* Used by table branch instructions.  */
1855
void OPPROTO op_jmp_T0_im(void)
1856
{
1857
    env->regs[15] = PARAM1 + (T0 << 1);
1858
}
1859

    
1860
void OPPROTO op_set_condexec(void)
1861
{
1862
    env->condexec_bits = PARAM1;
1863
}
1864

    
1865
void OPPROTO op_sdivl_T0_T1(void)
1866
{
1867
  int32_t num;
1868
  int32_t den;
1869
  num = T0;
1870
  den = T1;
1871
  if (den == 0)
1872
    T0 = 0;
1873
  else
1874
    T0 = num / den;
1875
  FORCE_RET();
1876
}
1877

    
1878
void OPPROTO op_udivl_T0_T1(void)
1879
{
1880
  uint32_t num;
1881
  uint32_t den;
1882
  num = T0;
1883
  den = T1;
1884
  if (den == 0)
1885
    T0 = 0;
1886
  else
1887
    T0 = num / den;
1888
  FORCE_RET();
1889
}
1890

    
1891
void OPPROTO op_movl_T1_r13_banked(void)
1892
{
1893
    T1 = helper_get_r13_banked(env, PARAM1);
1894
}
1895

    
1896
void OPPROTO op_movl_r13_T1_banked(void)
1897
{
1898
    helper_set_r13_banked(env, PARAM1, T1);
1899
}
1900

    
1901
void OPPROTO op_v7m_mrs_T0(void)
1902
{
1903
    T0 = helper_v7m_mrs(env, PARAM1);
1904
}
1905

    
1906
void OPPROTO op_v7m_msr_T0(void)
1907
{
1908
    helper_v7m_msr(env, PARAM1, T0);
1909
}
1910

    
1911
void OPPROTO op_movl_T0_sp(void)
1912
{
1913
    if (PARAM1 == env->v7m.current_sp)
1914
        T0 = env->regs[13];
1915
    else
1916
        T0 = env->v7m.other_sp;
1917
    FORCE_RET();
1918
}
1919

    
1920
#include "op_neon.h"
1921

    
1922
/* iwMMXt support */
1923
#include "op_iwmmxt.c"