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