| 1 |
691 |
jeremybenn |
/* { dg-do run { target { fixed_point } } } */
|
| 2 |
|
|
/* { dg-options "-std=gnu99" } */
|
| 3 |
|
|
|
| 4 |
|
|
/* Check basic arithmetic ops for ARM fixed-point/saturating operation support.
|
| 5 |
|
|
Not target-independent since we make various assumptions about precision and
|
| 6 |
|
|
magnitudes of various types. */
|
| 7 |
|
|
|
| 8 |
|
|
#include <stdlib.h>
|
| 9 |
|
|
#include <stdio.h>
|
| 10 |
|
|
#include <math.h>
|
| 11 |
|
|
#include <stdfix.h>
|
| 12 |
|
|
|
| 13 |
|
|
#define TEST(TYPE, OP, NAME, SUFFIX) \
|
| 14 |
|
|
TYPE NAME##SUFFIX (TYPE A, TYPE B) \
|
| 15 |
|
|
{ \
|
| 16 |
|
|
return A OP B; \
|
| 17 |
|
|
}
|
| 18 |
|
|
|
| 19 |
|
|
#define VARIANTS(TYPE, OP, NAME) \
|
| 20 |
|
|
TEST (short TYPE, OP, NAME, _short); \
|
| 21 |
|
|
TEST (TYPE, OP, NAME, _regular); \
|
| 22 |
|
|
TEST (long TYPE, OP, NAME, _long); \
|
| 23 |
|
|
TEST (_Sat short TYPE, OP, NAME, _sat_short); \
|
| 24 |
|
|
TEST (_Sat TYPE, OP, NAME, _sat_regular); \
|
| 25 |
|
|
TEST (_Sat long TYPE, OP, NAME, _sat_long); \
|
| 26 |
|
|
TEST (unsigned short TYPE, OP, NAME, _uns_short); \
|
| 27 |
|
|
TEST (unsigned TYPE, OP, NAME, _uns_regular); \
|
| 28 |
|
|
TEST (unsigned long TYPE, OP, NAME, _uns_long); \
|
| 29 |
|
|
TEST (unsigned _Sat short TYPE, OP, NAME, _uns_sat_short); \
|
| 30 |
|
|
TEST (unsigned _Sat TYPE, OP, NAME, _uns_sat_regular); \
|
| 31 |
|
|
TEST (unsigned _Sat long TYPE, OP, NAME, _uns_sat_long)
|
| 32 |
|
|
|
| 33 |
|
|
VARIANTS (_Fract, +, plus_fract);
|
| 34 |
|
|
VARIANTS (_Accum, +, plus_accum);
|
| 35 |
|
|
VARIANTS (_Fract, -, minus_fract);
|
| 36 |
|
|
VARIANTS (_Accum, -, minus_accum);
|
| 37 |
|
|
VARIANTS (_Fract, *, mult_fract);
|
| 38 |
|
|
VARIANTS (_Accum, *, mult_accum);
|
| 39 |
|
|
VARIANTS (_Accum, /, div_accum);
|
| 40 |
|
|
|
| 41 |
|
|
/* Inputs for signed add, multiply fractional tests. */
|
| 42 |
|
|
short _Fract sf_a = 0.9hr;
|
| 43 |
|
|
short _Fract sf_b = -0.8hr;
|
| 44 |
|
|
_Fract f_a = 0.9r;
|
| 45 |
|
|
_Fract f_b = -0.8r;
|
| 46 |
|
|
long _Fract lf_a = 0.9lr;
|
| 47 |
|
|
long _Fract lf_b = -0.8lr;
|
| 48 |
|
|
|
| 49 |
|
|
/* Inputs for signed subtract fractional tests. */
|
| 50 |
|
|
short _Fract sf_c = 0.7hr;
|
| 51 |
|
|
short _Fract sf_d = 0.9hr;
|
| 52 |
|
|
_Fract f_c = 0.7r;
|
| 53 |
|
|
_Fract f_d = 0.9r;
|
| 54 |
|
|
long _Fract lf_c = 0.7lr;
|
| 55 |
|
|
long _Fract lf_d = 0.9lr;
|
| 56 |
|
|
|
| 57 |
|
|
/* Inputs for unsigned add, subtract, multiply fractional tests. */
|
| 58 |
|
|
unsigned short _Fract usf_a = 0.4uhr;
|
| 59 |
|
|
unsigned short _Fract usf_b = 0.3uhr;
|
| 60 |
|
|
unsigned _Fract uf_a = 0.4ur;
|
| 61 |
|
|
unsigned _Fract uf_b = 0.3ur;
|
| 62 |
|
|
unsigned long _Fract ulf_a = 0.4ulr;
|
| 63 |
|
|
unsigned long _Fract ulf_b = 0.3ulr;
|
| 64 |
|
|
|
| 65 |
|
|
/* Inputs for saturating signed add tests. */
|
| 66 |
|
|
short _Sat _Fract sf_e = 0.8hr;
|
| 67 |
|
|
short _Sat _Fract sf_f = 0.8hr;
|
| 68 |
|
|
_Sat _Fract f_e = 0.8r;
|
| 69 |
|
|
_Sat _Fract f_f = 0.8r;
|
| 70 |
|
|
long _Sat _Fract lf_e = 0.8r;
|
| 71 |
|
|
long _Sat _Fract lf_f = 0.8r;
|
| 72 |
|
|
|
| 73 |
|
|
short _Sat _Fract sf_g = -0.8hr;
|
| 74 |
|
|
short _Sat _Fract sf_h = -0.8hr;
|
| 75 |
|
|
_Sat _Fract f_g = -0.8r;
|
| 76 |
|
|
_Sat _Fract f_h = -0.8r;
|
| 77 |
|
|
long _Sat _Fract lf_g = -0.8r;
|
| 78 |
|
|
long _Sat _Fract lf_h = -0.8r;
|
| 79 |
|
|
|
| 80 |
|
|
/* Inputs for saturating unsigned subtract tests. */
|
| 81 |
|
|
unsigned short _Sat _Fract usf_c = 0.3uhr;
|
| 82 |
|
|
unsigned short _Sat _Fract usf_d = 0.4uhr;
|
| 83 |
|
|
unsigned _Sat _Fract uf_c = 0.3ur;
|
| 84 |
|
|
unsigned _Sat _Fract uf_d = 0.4ur;
|
| 85 |
|
|
unsigned long _Sat _Fract ulf_c = 0.3ulr;
|
| 86 |
|
|
unsigned long _Sat _Fract ulf_d = 0.4ulr;
|
| 87 |
|
|
|
| 88 |
|
|
/* Inputs for signed accumulator tests. */
|
| 89 |
|
|
|
| 90 |
|
|
short _Accum sa_a = 1.25hk;
|
| 91 |
|
|
short _Accum sa_b = -1.5hk;
|
| 92 |
|
|
_Accum a_a = 100.25k;
|
| 93 |
|
|
_Accum a_b = -100.5k;
|
| 94 |
|
|
long _Accum la_a = 1000.25lk;
|
| 95 |
|
|
long _Accum la_b = -1000.5lk;
|
| 96 |
|
|
|
| 97 |
|
|
/* Inputs for unsigned accumulator tests. */
|
| 98 |
|
|
|
| 99 |
|
|
unsigned short _Accum usa_a = 2.5uhk;
|
| 100 |
|
|
unsigned short _Accum usa_b = 1.75uhk;
|
| 101 |
|
|
unsigned _Accum ua_a = 255.5uk;
|
| 102 |
|
|
unsigned _Accum ua_b = 170.25uk;
|
| 103 |
|
|
unsigned long _Accum ula_a = 1550.5ulk;
|
| 104 |
|
|
unsigned long _Accum ula_b = 999.5ulk;
|
| 105 |
|
|
|
| 106 |
|
|
/* Inputs for signed saturating accumulator tests. */
|
| 107 |
|
|
|
| 108 |
|
|
short _Sat _Accum sa_c = 240.0hk;
|
| 109 |
|
|
short _Sat _Accum sa_d = 250.0hk;
|
| 110 |
|
|
short _Sat _Accum sa_e = -240.0hk;
|
| 111 |
|
|
short _Sat _Accum sa_f = -250.0hk;
|
| 112 |
|
|
short _Sat _Accum sa_g = 0.5hk;
|
| 113 |
|
|
|
| 114 |
|
|
_Sat _Accum a_c = 65000.0k;
|
| 115 |
|
|
_Sat _Accum a_d = 20000.0k;
|
| 116 |
|
|
_Sat _Accum a_e = -65000.0k;
|
| 117 |
|
|
_Sat _Accum a_f = -20000.0k;
|
| 118 |
|
|
_Sat _Accum a_g = 0.5k;
|
| 119 |
|
|
|
| 120 |
|
|
long _Sat _Accum la_c = 3472883712.0lk;
|
| 121 |
|
|
long _Sat _Accum la_d = 3456106496.0lk;
|
| 122 |
|
|
long _Sat _Accum la_e = -3472883712.0lk;
|
| 123 |
|
|
long _Sat _Accum la_f = -3456106496.0lk;
|
| 124 |
|
|
long _Sat _Accum la_g = 0.5lk;
|
| 125 |
|
|
|
| 126 |
|
|
/* Inputs for unsigned saturating accumulator tests. */
|
| 127 |
|
|
|
| 128 |
|
|
unsigned short _Sat _Accum usa_c = 250.0uhk;
|
| 129 |
|
|
unsigned short _Sat _Accum usa_d = 240.0uhk;
|
| 130 |
|
|
unsigned short _Sat _Accum usa_e = 0.5uhk;
|
| 131 |
|
|
|
| 132 |
|
|
unsigned _Sat _Accum ua_c = 65000.0uk;
|
| 133 |
|
|
unsigned _Sat _Accum ua_d = 20000.0uk;
|
| 134 |
|
|
unsigned _Sat _Accum ua_e = 0.5uk;
|
| 135 |
|
|
|
| 136 |
|
|
unsigned long _Sat _Accum ula_c = 3472883712.0ulk;
|
| 137 |
|
|
unsigned long _Sat _Accum ula_d = 3456106496.0ulk;
|
| 138 |
|
|
unsigned long _Sat _Accum ula_e = 0.5ulk;
|
| 139 |
|
|
|
| 140 |
|
|
#define CHECK(FN, EXP) do { \
|
| 141 |
|
|
if (fabs ((float) (FN) - (EXP)) > 0.05) \
|
| 142 |
|
|
{ \
|
| 143 |
|
|
fprintf (stderr, "result for " #FN " (as float): %f\n", (double) (FN));\
|
| 144 |
|
|
abort (); \
|
| 145 |
|
|
} \
|
| 146 |
|
|
} while (0)
|
| 147 |
|
|
|
| 148 |
|
|
#define CHECK_EXACT(FN, EXP) do { \
|
| 149 |
|
|
if ((FN) != (EXP)) \
|
| 150 |
|
|
{ \
|
| 151 |
|
|
fprintf (stderr, "result for " #FN " (as float): %f, should be %f\n", \
|
| 152 |
|
|
(double) (FN), (double) (EXP)); \
|
| 153 |
|
|
abort (); \
|
| 154 |
|
|
} \
|
| 155 |
|
|
} while (0)
|
| 156 |
|
|
|
| 157 |
|
|
int
|
| 158 |
|
|
main (int argc, char *argv[])
|
| 159 |
|
|
{
|
| 160 |
|
|
/* Fract/fract operations, non-saturating. */
|
| 161 |
|
|
|
| 162 |
|
|
CHECK (plus_fract_short (sf_a, sf_b), 0.1);
|
| 163 |
|
|
CHECK (plus_fract_regular (f_a, f_b), 0.1);
|
| 164 |
|
|
CHECK (plus_fract_long (lf_a, lf_b), 0.1);
|
| 165 |
|
|
|
| 166 |
|
|
CHECK (plus_fract_uns_short (usf_a, usf_b), 0.7);
|
| 167 |
|
|
CHECK (plus_fract_uns_regular (uf_a, uf_b), 0.7);
|
| 168 |
|
|
CHECK (plus_fract_uns_long (ulf_a, ulf_b), 0.7);
|
| 169 |
|
|
|
| 170 |
|
|
CHECK (minus_fract_short (sf_c, sf_d), -0.2);
|
| 171 |
|
|
CHECK (minus_fract_regular (f_c, f_d), -0.2);
|
| 172 |
|
|
CHECK (minus_fract_long (lf_c, lf_d), -0.2);
|
| 173 |
|
|
|
| 174 |
|
|
CHECK (minus_fract_uns_short (usf_a, usf_b), 0.1);
|
| 175 |
|
|
CHECK (minus_fract_uns_regular (uf_a, uf_b), 0.1);
|
| 176 |
|
|
CHECK (minus_fract_uns_long (ulf_a, ulf_b), 0.1);
|
| 177 |
|
|
|
| 178 |
|
|
CHECK (mult_fract_short (sf_a, sf_b), -0.72);
|
| 179 |
|
|
CHECK (mult_fract_regular (f_a, f_b), -0.72);
|
| 180 |
|
|
CHECK (mult_fract_long (lf_a, lf_b), -0.72);
|
| 181 |
|
|
|
| 182 |
|
|
CHECK (mult_fract_uns_short (usf_a, usf_b), 0.12);
|
| 183 |
|
|
CHECK (mult_fract_uns_regular (uf_a, uf_b), 0.12);
|
| 184 |
|
|
CHECK (mult_fract_uns_long (ulf_a, ulf_b), 0.12);
|
| 185 |
|
|
|
| 186 |
|
|
/* Fract/fract operations, saturating. */
|
| 187 |
|
|
|
| 188 |
|
|
CHECK (plus_fract_sat_short (sf_e, sf_f), 1.0);
|
| 189 |
|
|
CHECK (plus_fract_sat_regular (f_e, f_f), 1.0);
|
| 190 |
|
|
CHECK (plus_fract_sat_long (lf_e, lf_f), 1.0);
|
| 191 |
|
|
|
| 192 |
|
|
CHECK (plus_fract_sat_short (sf_g, sf_h), -1.0);
|
| 193 |
|
|
CHECK (plus_fract_sat_regular (f_g, f_h), -1.0);
|
| 194 |
|
|
CHECK (plus_fract_sat_long (lf_g, lf_h), -1.0);
|
| 195 |
|
|
|
| 196 |
|
|
CHECK (plus_fract_uns_sat_short (sf_e, sf_f), 1.0);
|
| 197 |
|
|
CHECK (plus_fract_uns_sat_regular (f_e, f_f), 1.0);
|
| 198 |
|
|
CHECK (plus_fract_uns_sat_long (lf_e, lf_f), 1.0);
|
| 199 |
|
|
|
| 200 |
|
|
CHECK (plus_fract_sat_short (sf_a, sf_b), 0.1);
|
| 201 |
|
|
CHECK (plus_fract_sat_regular (f_a, f_b), 0.1);
|
| 202 |
|
|
CHECK (plus_fract_sat_long (lf_a, lf_b), 0.1);
|
| 203 |
|
|
|
| 204 |
|
|
CHECK (plus_fract_uns_sat_short (usf_a, usf_b), 0.7);
|
| 205 |
|
|
CHECK (plus_fract_uns_sat_regular (uf_a, uf_b), 0.7);
|
| 206 |
|
|
CHECK (plus_fract_uns_sat_long (ulf_a, ulf_b), 0.7);
|
| 207 |
|
|
|
| 208 |
|
|
CHECK (minus_fract_uns_sat_short (usf_c, usf_d), 0.0);
|
| 209 |
|
|
CHECK (minus_fract_uns_sat_regular (uf_c, uf_d), 0.0);
|
| 210 |
|
|
CHECK (minus_fract_uns_sat_short (ulf_c, ulf_d), 0.0);
|
| 211 |
|
|
|
| 212 |
|
|
CHECK (minus_fract_sat_short (sf_c, sf_d), -0.2);
|
| 213 |
|
|
CHECK (minus_fract_sat_regular (f_c, f_d), -0.2);
|
| 214 |
|
|
CHECK (minus_fract_sat_long (lf_c, lf_d), -0.2);
|
| 215 |
|
|
|
| 216 |
|
|
/* Accum/accum operations, non-saturating. */
|
| 217 |
|
|
|
| 218 |
|
|
CHECK (plus_accum_short (sa_a, sa_b), -0.25);
|
| 219 |
|
|
CHECK (plus_accum_regular (a_a, a_b), -0.25);
|
| 220 |
|
|
CHECK (plus_accum_long (la_a, la_b), -0.25);
|
| 221 |
|
|
|
| 222 |
|
|
CHECK (minus_accum_short (sa_a, sa_b), 2.75);
|
| 223 |
|
|
CHECK (minus_accum_regular (a_a, a_b), 200.75);
|
| 224 |
|
|
CHECK (minus_accum_long (la_a, la_b), 2000.75);
|
| 225 |
|
|
|
| 226 |
|
|
CHECK (mult_accum_short (sa_a, sa_b), -1.875);
|
| 227 |
|
|
CHECK (mult_accum_regular (a_a, a_b), -10075.125);
|
| 228 |
|
|
CHECK (mult_accum_long (la_a, la_b), -1000750.125);
|
| 229 |
|
|
|
| 230 |
|
|
CHECK (div_accum_short (sa_a, sa_b), -1.25/1.5);
|
| 231 |
|
|
CHECK (div_accum_regular (a_a, a_b), -100.25/100.5);
|
| 232 |
|
|
CHECK (div_accum_long (la_a, la_b), -1000.25/1000.5);
|
| 233 |
|
|
|
| 234 |
|
|
/* Unsigned accum/accum operations, non-saturating. */
|
| 235 |
|
|
|
| 236 |
|
|
CHECK (plus_accum_uns_short (usa_a, usa_b), 4.25);
|
| 237 |
|
|
CHECK (plus_accum_uns_regular (ua_a, ua_b), 425.75);
|
| 238 |
|
|
CHECK (plus_accum_uns_long (ula_a, ula_b), 2550.0);
|
| 239 |
|
|
|
| 240 |
|
|
CHECK (minus_accum_uns_short (usa_a, usa_b), 0.75);
|
| 241 |
|
|
CHECK (minus_accum_uns_regular (ua_a, ua_b), 85.25);
|
| 242 |
|
|
CHECK (minus_accum_uns_long (ula_a, ula_b), 551.0);
|
| 243 |
|
|
|
| 244 |
|
|
CHECK (mult_accum_uns_short (usa_a, usa_b), 4.375);
|
| 245 |
|
|
CHECK (mult_accum_uns_regular (ua_a, ua_b), 43498.875);
|
| 246 |
|
|
CHECK (mult_accum_uns_long (ula_a, ula_b), 1549724.75);
|
| 247 |
|
|
|
| 248 |
|
|
CHECK (div_accum_uns_short (usa_a, usa_b), 2.5/1.75);
|
| 249 |
|
|
CHECK (div_accum_uns_regular (ua_a, ua_b), 255.5/170.25);
|
| 250 |
|
|
CHECK (div_accum_uns_long (ula_a, ula_b), 1550.5/999.5);
|
| 251 |
|
|
|
| 252 |
|
|
/* Signed accum/accum operations, saturating. */
|
| 253 |
|
|
|
| 254 |
|
|
CHECK_EXACT (plus_accum_sat_short (sa_c, sa_d), SACCUM_MAX);
|
| 255 |
|
|
CHECK_EXACT (plus_accum_sat_short (sa_e, sa_f), SACCUM_MIN);
|
| 256 |
|
|
CHECK_EXACT (plus_accum_sat_regular (a_c, a_d), ACCUM_MAX);
|
| 257 |
|
|
CHECK_EXACT (plus_accum_sat_regular (a_e, a_f), ACCUM_MIN);
|
| 258 |
|
|
CHECK_EXACT (plus_accum_sat_long (la_c, la_d), LACCUM_MAX);
|
| 259 |
|
|
CHECK_EXACT (plus_accum_sat_long (la_e, la_f), LACCUM_MIN);
|
| 260 |
|
|
|
| 261 |
|
|
CHECK_EXACT (minus_accum_sat_short (sa_e, sa_d), SACCUM_MIN);
|
| 262 |
|
|
CHECK_EXACT (minus_accum_sat_short (sa_c, sa_f), SACCUM_MAX);
|
| 263 |
|
|
CHECK_EXACT (minus_accum_sat_regular (a_e, a_d), ACCUM_MIN);
|
| 264 |
|
|
CHECK_EXACT (minus_accum_sat_regular (a_c, a_f), ACCUM_MAX);
|
| 265 |
|
|
CHECK_EXACT (minus_accum_sat_long (la_e, la_d), LACCUM_MIN);
|
| 266 |
|
|
CHECK_EXACT (minus_accum_sat_long (la_c, la_f), LACCUM_MAX);
|
| 267 |
|
|
|
| 268 |
|
|
CHECK_EXACT (mult_accum_sat_short (sa_c, sa_d), SACCUM_MAX);
|
| 269 |
|
|
CHECK_EXACT (mult_accum_sat_short (sa_c, sa_e), SACCUM_MIN);
|
| 270 |
|
|
CHECK_EXACT (mult_accum_sat_regular (a_c, a_d), ACCUM_MAX);
|
| 271 |
|
|
CHECK_EXACT (mult_accum_sat_regular (a_c, a_e), ACCUM_MIN);
|
| 272 |
|
|
CHECK_EXACT (mult_accum_sat_long (la_c, la_d), LACCUM_MAX);
|
| 273 |
|
|
CHECK_EXACT (mult_accum_sat_long (la_c, la_e), LACCUM_MIN);
|
| 274 |
|
|
|
| 275 |
|
|
CHECK_EXACT (div_accum_sat_short (sa_d, sa_g), SACCUM_MAX);
|
| 276 |
|
|
CHECK_EXACT (div_accum_sat_short (sa_e, sa_g), SACCUM_MIN);
|
| 277 |
|
|
CHECK_EXACT (div_accum_sat_regular (a_c, a_g), ACCUM_MAX);
|
| 278 |
|
|
CHECK_EXACT (div_accum_sat_regular (a_e, a_g), ACCUM_MIN);
|
| 279 |
|
|
CHECK_EXACT (div_accum_sat_long (la_d, la_g), LACCUM_MAX);
|
| 280 |
|
|
CHECK_EXACT (div_accum_sat_long (la_e, la_g), LACCUM_MIN);
|
| 281 |
|
|
|
| 282 |
|
|
/* Unsigned accum/accum operations, saturating. */
|
| 283 |
|
|
|
| 284 |
|
|
CHECK_EXACT (plus_accum_uns_sat_short (usa_c, usa_d), USACCUM_MAX);
|
| 285 |
|
|
CHECK_EXACT (plus_accum_uns_sat_regular (ua_c, ua_d), UACCUM_MAX);
|
| 286 |
|
|
CHECK_EXACT (plus_accum_uns_sat_long (ula_c, ula_d), ULACCUM_MAX);
|
| 287 |
|
|
|
| 288 |
|
|
CHECK_EXACT (minus_accum_uns_sat_short (usa_d, usa_c), 0uhk);
|
| 289 |
|
|
CHECK_EXACT (minus_accum_uns_sat_regular (ua_d, ua_c), 0uk);
|
| 290 |
|
|
CHECK_EXACT (minus_accum_uns_sat_long (ula_d, ula_c), 0ulk);
|
| 291 |
|
|
|
| 292 |
|
|
CHECK_EXACT (mult_accum_uns_sat_short (usa_c, usa_d), USACCUM_MAX);
|
| 293 |
|
|
CHECK_EXACT (mult_accum_uns_sat_regular (ua_c, ua_d), UACCUM_MAX);
|
| 294 |
|
|
CHECK_EXACT (mult_accum_uns_sat_long (ula_c, ula_d), ULACCUM_MAX);
|
| 295 |
|
|
|
| 296 |
|
|
CHECK_EXACT (div_accum_uns_sat_short (usa_c, usa_e), USACCUM_MAX);
|
| 297 |
|
|
CHECK_EXACT (div_accum_uns_sat_regular (ua_c, ua_e), UACCUM_MAX);
|
| 298 |
|
|
CHECK_EXACT (div_accum_uns_sat_long (ula_c, ula_e), ULACCUM_MAX);
|
| 299 |
|
|
|
| 300 |
|
|
return 0;
|
| 301 |
|
|
}
|