Revision 9ee6e8bb target-arm/op.c

b/target-arm/op.c
2 2
 *  ARM micro operations
3 3
 *
4 4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005 CodeSourcery, LLC
5
 *  Copyright (c) 2005-2007 CodeSourcery, LLC
6 6
 *
7 7
 * This library is free software; you can redistribute it and/or
8 8
 * modify it under the terms of the GNU Lesser General Public
......
101 101
    T0 = PARAM1;
102 102
}
103 103

  
104
void OPPROTO op_movl_T0_T1(void)
105
{
106
    T0 = T1;
107
}
108

  
109 104
void OPPROTO op_movl_T1_im(void)
110 105
{
111 106
    T1 = PARAM1;
......
236 231
    T0 &= ~T1;
237 232
}
238 233

  
234
void OPPROTO op_notl_T0(void)
235
{
236
    T0 = ~T0;
237
}
238

  
239 239
void OPPROTO op_notl_T1(void)
240 240
{
241 241
    T1 = ~T1;
......
351 351
    FORCE_RET();
352 352
}
353 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

  
354 367
void OPPROTO op_goto_tb0(void)
355 368
{
356 369
    GOTO_TB(op_goto_tb0, PARAM1, 0);
......
368 381

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

  
......
438 452
    T0 = res;
439 453
}
440 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

  
441 477
void OPPROTO op_logicq_cc(void)
442 478
{
443 479
    env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
......
455 491
#include "op_mem.h"
456 492
#endif
457 493

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

  
458 501
/* shifts */
459 502

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

  
460 509
/* T1 based */
461 510

  
462 511
void OPPROTO op_shll_T1_im(void)
......
813 862
  FORCE_RET();
814 863
}
815 864

  
816
/* thumb shift by immediate */
817
void OPPROTO op_shll_T0_im_thumb(void)
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)
818 898
{
819 899
    int shift;
820 900
    shift = PARAM1;
......
826 906
    FORCE_RET();
827 907
}
828 908

  
829
void OPPROTO op_shrl_T0_im_thumb(void)
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)
830 916
{
831 917
    int shift;
832 918

  
......
842 928
    FORCE_RET();
843 929
}
844 930

  
845
void OPPROTO op_sarl_T0_im_thumb(void)
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)
846 945
{
847 946
    int shift;
848 947

  
......
858 957
    FORCE_RET();
859 958
}
860 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

  
861 973
/* exceptions */
862 974

  
863 975
void OPPROTO op_swi(void)
......
891 1003
    cpu_loop_exit();
892 1004
}
893 1005

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

  
894 1012
/* VFP support.  We follow the convention used for VFP instrunctions:
895 1013
   Single precition routines have a "s" suffix, double precision a
896 1014
   "d" suffix.  */
......
982 1100
    return v.i;
983 1101
}
984 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

  
985 1125
/* Integer to float conversion.  */
986 1126
VFP_OP(uito, s)
987 1127
{
......
1056 1196
    FT0s = float64_to_float32(FT0d, &env->vfp.fp_status);
1057 1197
}
1058 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

  
1059 1225
/* Get and Put values from registers.  */
1060 1226
VFP_OP(getreg_F0, d)
1061 1227
{
......
1142 1308
    FT0d = u.d;
1143 1309
}
1144 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

  
1145 1325
/* Copy the most significant bit of T0 to all bits of T1.  */
1146 1326
void OPPROTO op_signbit_T1_T0(void)
1147 1327
{
......
1204 1384
    FORCE_RET();
1205 1385
}
1206 1386

  
1207
void OPPROTO op_movl_T2_T0(void)
1387
void OPPROTO op_movl_T0_T1(void)
1208 1388
{
1209
    T2 = T0;
1389
    T0 = T1;
1210 1390
}
1211 1391

  
1212 1392
void OPPROTO op_movl_T0_T2(void)
......
1214 1394
    T0 = T2;
1215 1395
}
1216 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

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

Also available in: Unified diff