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