Revision 6ddbc6e4 targetarm/op.c
b/targetarm/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 16bit 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 8bit 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 16bit 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 8bit 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 16bit 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