Revision 6ddbc6e4 target-arm/op.c
b/target-arm/op.c | ||
---|---|---|
805 | 805 |
FORCE_RET(); |
806 | 806 |
} |
807 | 807 |
|
808 |
/* ARMv6 Media instructions. */ |
|
809 |
|
|
810 |
/* Note that signed overflow is undefined in C. The following routines are |
|
811 |
careful to use unsigned types where modulo arithmetic is required. |
|
812 |
Failure to do so _will_ break on newer gcc. */ |
|
813 |
|
|
814 |
/* Signed saturating arithmetic. */ |
|
815 |
|
|
816 |
/* Perform 16-bit signed satruating addition. */ |
|
817 |
static inline uint16_t add16_sat(uint16_t a, uint16_t b) |
|
818 |
{ |
|
819 |
uint16_t res; |
|
820 |
|
|
821 |
res = a + b; |
|
822 |
if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) { |
|
823 |
if (a & 0x8000) |
|
824 |
res = 0x8000; |
|
825 |
else |
|
826 |
res = 0x7fff; |
|
827 |
} |
|
828 |
return res; |
|
829 |
} |
|
830 |
|
|
831 |
/* Perform 8-bit signed satruating addition. */ |
|
832 |
static inline uint8_t add8_sat(uint8_t a, uint8_t b) |
|
833 |
{ |
|
834 |
uint8_t res; |
|
835 |
|
|
836 |
res = a + b; |
|
837 |
if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) { |
|
838 |
if (a & 0x80) |
|
839 |
res = 0x80; |
|
840 |
else |
|
841 |
res = 0x7f; |
|
842 |
} |
|
843 |
return res; |
|
844 |
} |
|
845 |
|
|
846 |
/* Perform 16-bit signed satruating subtraction. */ |
|
847 |
static inline uint16_t sub16_sat(uint16_t a, uint16_t b) |
|
848 |
{ |
|
849 |
uint16_t res; |
|
850 |
|
|
851 |
res = a - b; |
|
852 |
if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) { |
|
853 |
if (a & 0x8000) |
|
854 |
res = 0x8000; |
|
855 |
else |
|
856 |
res = 0x7fff; |
|
857 |
} |
|
858 |
return res; |
|
859 |
} |
|
860 |
|
|
861 |
/* Perform 8-bit signed satruating subtraction. */ |
|
862 |
static inline uint8_t sub8_sat(uint8_t a, uint8_t b) |
|
863 |
{ |
|
864 |
uint8_t res; |
|
865 |
|
|
866 |
res = a - b; |
|
867 |
if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) { |
|
868 |
if (a & 0x80) |
|
869 |
res = 0x80; |
|
870 |
else |
|
871 |
res = 0x7f; |
|
872 |
} |
|
873 |
return res; |
|
874 |
} |
|
875 |
|
|
876 |
#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16); |
|
877 |
#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16); |
|
878 |
#define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8); |
|
879 |
#define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8); |
|
880 |
#define PFX q |
|
881 |
|
|
882 |
#include "op_addsub.h" |
|
883 |
|
|
884 |
/* Unsigned saturating arithmetic. */ |
|
885 |
static inline uint16_t add16_usat(uint16_t a, uint8_t b) |
|
886 |
{ |
|
887 |
uint16_t res; |
|
888 |
res = a + b; |
|
889 |
if (res < a) |
|
890 |
res = 0xffff; |
|
891 |
return res; |
|
892 |
} |
|
893 |
|
|
894 |
static inline uint16_t sub16_usat(uint16_t a, uint8_t b) |
|
895 |
{ |
|
896 |
if (a < b) |
|
897 |
return a - b; |
|
898 |
else |
|
899 |
return 0; |
|
900 |
} |
|
901 |
|
|
902 |
static inline uint8_t add8_usat(uint8_t a, uint8_t b) |
|
903 |
{ |
|
904 |
uint8_t res; |
|
905 |
res = a + b; |
|
906 |
if (res < a) |
|
907 |
res = 0xff; |
|
908 |
return res; |
|
909 |
} |
|
910 |
|
|
911 |
static inline uint8_t sub8_usat(uint8_t a, uint8_t b) |
|
912 |
{ |
|
913 |
if (a < b) |
|
914 |
return a - b; |
|
915 |
else |
|
916 |
return 0; |
|
917 |
} |
|
918 |
|
|
919 |
#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16); |
|
920 |
#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16); |
|
921 |
#define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8); |
|
922 |
#define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8); |
|
923 |
#define PFX uq |
|
924 |
|
|
925 |
#include "op_addsub.h" |
|
926 |
|
|
927 |
/* Signed modulo arithmetic. */ |
|
928 |
#define SARITH16(a, b, n, op) do { \ |
|
929 |
int32_t sum; \ |
|
930 |
sum = (int16_t)((uint16_t)(a) op (uint16_t)(b)); \ |
|
931 |
RESULT(sum, n, 16); \ |
|
932 |
if (sum >= 0) \ |
|
933 |
ge |= 3 << (n * 2); \ |
|
934 |
} while(0) |
|
935 |
|
|
936 |
#define SARITH8(a, b, n, op) do { \ |
|
937 |
int32_t sum; \ |
|
938 |
sum = (int8_t)((uint8_t)(a) op (uint8_t)(b)); \ |
|
939 |
RESULT(sum, n, 8); \ |
|
940 |
if (sum >= 0) \ |
|
941 |
ge |= 1 << n; \ |
|
942 |
} while(0) |
|
943 |
|
|
944 |
|
|
945 |
#define ADD16(a, b, n) SARITH16(a, b, n, +) |
|
946 |
#define SUB16(a, b, n) SARITH16(a, b, n, -) |
|
947 |
#define ADD8(a, b, n) SARITH8(a, b, n, +) |
|
948 |
#define SUB8(a, b, n) SARITH8(a, b, n, -) |
|
949 |
#define PFX s |
|
950 |
#define ARITH_GE |
|
951 |
|
|
952 |
#include "op_addsub.h" |
|
953 |
|
|
954 |
/* Unsigned modulo arithmetic. */ |
|
955 |
#define ADD16(a, b, n) do { \ |
|
956 |
uint32_t sum; \ |
|
957 |
sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \ |
|
958 |
RESULT(sum, n, 16); \ |
|
959 |
if ((sum >> 16) == 0) \ |
|
960 |
ge |= 3 << (n * 2); \ |
|
961 |
} while(0) |
|
962 |
|
|
963 |
#define ADD8(a, b, n) do { \ |
|
964 |
uint32_t sum; \ |
|
965 |
sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \ |
|
966 |
RESULT(sum, n, 8); \ |
|
967 |
if ((sum >> 8) == 0) \ |
|
968 |
ge |= 3 << (n * 2); \ |
|
969 |
} while(0) |
|
970 |
|
|
971 |
#define SUB16(a, b, n) do { \ |
|
972 |
uint32_t sum; \ |
|
973 |
sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \ |
|
974 |
RESULT(sum, n, 16); \ |
|
975 |
if ((sum >> 16) == 0) \ |
|
976 |
ge |= 3 << (n * 2); \ |
|
977 |
} while(0) |
|
978 |
|
|
979 |
#define SUB8(a, b, n) do { \ |
|
980 |
uint32_t sum; \ |
|
981 |
sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \ |
|
982 |
RESULT(sum, n, 8); \ |
|
983 |
if ((sum >> 8) == 0) \ |
|
984 |
ge |= 3 << (n * 2); \ |
|
985 |
} while(0) |
|
986 |
|
|
987 |
#define PFX u |
|
988 |
#define ARITH_GE |
|
989 |
|
|
990 |
#include "op_addsub.h" |
|
991 |
|
|
992 |
/* Halved signed arithmetic. */ |
|
993 |
#define ADD16(a, b, n) \ |
|
994 |
RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16) |
|
995 |
#define SUB16(a, b, n) \ |
|
996 |
RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16) |
|
997 |
#define ADD8(a, b, n) \ |
|
998 |
RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8) |
|
999 |
#define SUB8(a, b, n) \ |
|
1000 |
RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8) |
|
1001 |
#define PFX sh |
|
1002 |
|
|
1003 |
#include "op_addsub.h" |
|
1004 |
|
|
1005 |
/* Halved unsigned arithmetic. */ |
|
1006 |
#define ADD16(a, b, n) \ |
|
1007 |
RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16) |
|
1008 |
#define SUB16(a, b, n) \ |
|
1009 |
RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16) |
|
1010 |
#define ADD8(a, b, n) \ |
|
1011 |
RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8) |
|
1012 |
#define SUB8(a, b, n) \ |
|
1013 |
RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8) |
|
1014 |
#define PFX uh |
|
1015 |
|
|
1016 |
#include "op_addsub.h" |
|
1017 |
|
|
1018 |
void OPPROTO op_sel_T0_T1(void) |
|
1019 |
{ |
|
1020 |
uint32_t mask; |
|
1021 |
uint32_t flags; |
|
1022 |
|
|
1023 |
flags = env->GE; |
|
1024 |
mask = 0; |
|
1025 |
if (flags & 1) |
|
1026 |
mask |= 0xff; |
|
1027 |
if (flags & 2) |
|
1028 |
mask |= 0xff00; |
|
1029 |
if (flags & 4) |
|
1030 |
mask |= 0xff0000; |
|
1031 |
if (flags & 8) |
|
1032 |
mask |= 0xff000000; |
|
1033 |
T0 = (T0 & mask) | (T1 & ~mask); |
|
1034 |
FORCE_RET(); |
|
1035 |
} |
|
1036 |
|
|
1037 |
/* Signed saturation. */ |
|
1038 |
static inline uint32_t do_ssat(int32_t val, int shift) |
|
1039 |
{ |
|
1040 |
int32_t top; |
|
1041 |
uint32_t mask; |
|
1042 |
|
|
1043 |
shift = PARAM1; |
|
1044 |
top = val >> shift; |
|
1045 |
mask = (1u << shift) - 1; |
|
1046 |
if (top > 0) { |
|
1047 |
env->QF = 1; |
|
1048 |
return mask; |
|
1049 |
} else if (top < -1) { |
|
1050 |
env->QF = 1; |
|
1051 |
return ~mask; |
|
1052 |
} |
|
1053 |
return val; |
|
1054 |
} |
|
1055 |
|
|
1056 |
/* Unsigned saturation. */ |
|
1057 |
static inline uint32_t do_usat(int32_t val, int shift) |
|
1058 |
{ |
|
1059 |
uint32_t max; |
|
1060 |
|
|
1061 |
shift = PARAM1; |
|
1062 |
max = (1u << shift) - 1; |
|
1063 |
if (val < 0) { |
|
1064 |
env->QF = 1; |
|
1065 |
return 0; |
|
1066 |
} else if (val > max) { |
|
1067 |
env->QF = 1; |
|
1068 |
return max; |
|
1069 |
} |
|
1070 |
return val; |
|
1071 |
} |
|
1072 |
|
|
1073 |
/* Signed saturate. */ |
|
1074 |
void OPPROTO op_ssat_T1(void) |
|
1075 |
{ |
|
1076 |
T0 = do_ssat(T0, PARAM1); |
|
1077 |
FORCE_RET(); |
|
1078 |
} |
|
1079 |
|
|
1080 |
/* Dual halfword signed saturate. */ |
|
1081 |
void OPPROTO op_ssat16_T1(void) |
|
1082 |
{ |
|
1083 |
uint32_t res; |
|
1084 |
|
|
1085 |
res = (uint16_t)do_ssat((int16_t)T0, PARAM1); |
|
1086 |
res |= do_ssat(((int32_t)T0) >> 16, PARAM1) << 16; |
|
1087 |
T0 = res; |
|
1088 |
FORCE_RET(); |
|
1089 |
} |
|
1090 |
|
|
1091 |
/* Unsigned saturate. */ |
|
1092 |
void OPPROTO op_usat_T1(void) |
|
1093 |
{ |
|
1094 |
T0 = do_usat(T0, PARAM1); |
|
1095 |
FORCE_RET(); |
|
1096 |
} |
|
1097 |
|
|
1098 |
/* Dual halfword unsigned saturate. */ |
|
1099 |
void OPPROTO op_usat16_T1(void) |
|
1100 |
{ |
|
1101 |
uint32_t res; |
|
1102 |
|
|
1103 |
res = (uint16_t)do_usat((int16_t)T0, PARAM1); |
|
1104 |
res |= do_usat(((int32_t)T0) >> 16, PARAM1) << 16; |
|
1105 |
T0 = res; |
|
1106 |
FORCE_RET(); |
|
1107 |
} |
|
1108 |
|
|
1109 |
/* Dual 16-bit add. */ |
|
1110 |
static inline uint8_t do_usad(uint8_t a, uint8_t b) |
|
1111 |
{ |
|
1112 |
if (a > b) |
|
1113 |
return a - b; |
|
1114 |
else |
|
1115 |
return b - a; |
|
1116 |
} |
|
1117 |
|
|
1118 |
/* Unsigned sum of absolute byte differences. */ |
|
1119 |
void OPPROTO op_usad8_T0_T1(void) |
|
1120 |
{ |
|
1121 |
uint32_t sum; |
|
1122 |
sum = do_usad(T0, T1); |
|
1123 |
sum += do_usad(T0 >> 8, T1 >> 8); |
|
1124 |
sum += do_usad(T0 >> 16, T1 >>16); |
|
1125 |
sum += do_usad(T0 >> 24, T1 >> 24); |
|
1126 |
T0 = sum; |
|
1127 |
} |
|
1128 |
|
|
1129 | 808 |
void OPPROTO op_movl_T1_r13_banked(void) |
1130 | 809 |
{ |
1131 | 810 |
T1 = helper_get_r13_banked(env, PARAM1); |
Also available in: Unified diff