Revision 4373f3ce target-arm/helper.c

b/target-arm/helper.c
2167 2167
    return (a & mask) | (b & ~mask);
2168 2168
}
2169 2169

  
2170

  
2171
/* VFP support.  We follow the convention used for VFP instrunctions:
2172
   Single precition routines have a "s" suffix, double precision a
2173
   "d" suffix.  */
2174

  
2175
/* Convert host exception flags to vfp form.  */
2176
static inline int vfp_exceptbits_from_host(int host_bits)
2177
{
2178
    int target_bits = 0;
2179

  
2180
    if (host_bits & float_flag_invalid)
2181
        target_bits |= 1;
2182
    if (host_bits & float_flag_divbyzero)
2183
        target_bits |= 2;
2184
    if (host_bits & float_flag_overflow)
2185
        target_bits |= 4;
2186
    if (host_bits & float_flag_underflow)
2187
        target_bits |= 8;
2188
    if (host_bits & float_flag_inexact)
2189
        target_bits |= 0x10;
2190
    return target_bits;
2191
}
2192

  
2193
uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
2194
{
2195
    int i;
2196
    uint32_t fpscr;
2197

  
2198
    fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff)
2199
            | (env->vfp.vec_len << 16)
2200
            | (env->vfp.vec_stride << 20);
2201
    i = get_float_exception_flags(&env->vfp.fp_status);
2202
    fpscr |= vfp_exceptbits_from_host(i);
2203
    return fpscr;
2204
}
2205

  
2206
/* Convert vfp exception flags to target form.  */
2207
static inline int vfp_exceptbits_to_host(int target_bits)
2208
{
2209
    int host_bits = 0;
2210

  
2211
    if (target_bits & 1)
2212
        host_bits |= float_flag_invalid;
2213
    if (target_bits & 2)
2214
        host_bits |= float_flag_divbyzero;
2215
    if (target_bits & 4)
2216
        host_bits |= float_flag_overflow;
2217
    if (target_bits & 8)
2218
        host_bits |= float_flag_underflow;
2219
    if (target_bits & 0x10)
2220
        host_bits |= float_flag_inexact;
2221
    return host_bits;
2222
}
2223

  
2224
void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
2225
{
2226
    int i;
2227
    uint32_t changed;
2228

  
2229
    changed = env->vfp.xregs[ARM_VFP_FPSCR];
2230
    env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
2231
    env->vfp.vec_len = (val >> 16) & 7;
2232
    env->vfp.vec_stride = (val >> 20) & 3;
2233

  
2234
    changed ^= val;
2235
    if (changed & (3 << 22)) {
2236
        i = (val >> 22) & 3;
2237
        switch (i) {
2238
        case 0:
2239
            i = float_round_nearest_even;
2240
            break;
2241
        case 1:
2242
            i = float_round_up;
2243
            break;
2244
        case 2:
2245
            i = float_round_down;
2246
            break;
2247
        case 3:
2248
            i = float_round_to_zero;
2249
            break;
2250
        }
2251
        set_float_rounding_mode(i, &env->vfp.fp_status);
2252
    }
2253

  
2254
    i = vfp_exceptbits_to_host((val >> 8) & 0x1f);
2255
    set_float_exception_flags(i, &env->vfp.fp_status);
2256
    /* XXX: FZ and DN are not implemented.  */
2257
}
2258

  
2259
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
2260

  
2261
#define VFP_BINOP(name) \
2262
float32 VFP_HELPER(name, s)(float32 a, float32 b, CPUState *env) \
2263
{ \
2264
    return float32_ ## name (a, b, &env->vfp.fp_status); \
2265
} \
2266
float64 VFP_HELPER(name, d)(float64 a, float64 b, CPUState *env) \
2267
{ \
2268
    return float64_ ## name (a, b, &env->vfp.fp_status); \
2269
}
2270
VFP_BINOP(add)
2271
VFP_BINOP(sub)
2272
VFP_BINOP(mul)
2273
VFP_BINOP(div)
2274
#undef VFP_BINOP
2275

  
2276
float32 VFP_HELPER(neg, s)(float32 a)
2277
{
2278
    return float32_chs(a);
2279
}
2280

  
2281
float64 VFP_HELPER(neg, d)(float64 a)
2282
{
2283
    return float32_chs(a);
2284
}
2285

  
2286
float32 VFP_HELPER(abs, s)(float32 a)
2287
{
2288
    return float32_abs(a);
2289
}
2290

  
2291
float64 VFP_HELPER(abs, d)(float64 a)
2292
{
2293
    return float32_abs(a);
2294
}
2295

  
2296
float32 VFP_HELPER(sqrt, s)(float32 a, CPUState *env)
2297
{
2298
    return float32_sqrt(a, &env->vfp.fp_status);
2299
}
2300

  
2301
float64 VFP_HELPER(sqrt, d)(float64 a, CPUState *env)
2302
{
2303
    return float64_sqrt(a, &env->vfp.fp_status);
2304
}
2305

  
2306
/* XXX: check quiet/signaling case */
2307
#define DO_VFP_cmp(p, type) \
2308
void VFP_HELPER(cmp, p)(type a, type b, CPUState *env)  \
2309
{ \
2310
    uint32_t flags; \
2311
    switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \
2312
    case 0: flags = 0x6; break; \
2313
    case -1: flags = 0x8; break; \
2314
    case 1: flags = 0x2; break; \
2315
    default: case 2: flags = 0x3; break; \
2316
    } \
2317
    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
2318
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
2319
} \
2320
void VFP_HELPER(cmpe, p)(type a, type b, CPUState *env) \
2321
{ \
2322
    uint32_t flags; \
2323
    switch(type ## _compare(a, b, &env->vfp.fp_status)) { \
2324
    case 0: flags = 0x6; break; \
2325
    case -1: flags = 0x8; break; \
2326
    case 1: flags = 0x2; break; \
2327
    default: case 2: flags = 0x3; break; \
2328
    } \
2329
    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
2330
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
2331
}
2332
DO_VFP_cmp(s, float32)
2333
DO_VFP_cmp(d, float64)
2334
#undef DO_VFP_cmp
2335

  
2336
/* Helper routines to perform bitwise copies between float and int.  */
2337
static inline float32 vfp_itos(uint32_t i)
2338
{
2339
    union {
2340
        uint32_t i;
2341
        float32 s;
2342
    } v;
2343

  
2344
    v.i = i;
2345
    return v.s;
2346
}
2347

  
2348
static inline uint32_t vfp_stoi(float32 s)
2349
{
2350
    union {
2351
        uint32_t i;
2352
        float32 s;
2353
    } v;
2354

  
2355
    v.s = s;
2356
    return v.i;
2357
}
2358

  
2359
static inline float64 vfp_itod(uint64_t i)
2360
{
2361
    union {
2362
        uint64_t i;
2363
        float64 d;
2364
    } v;
2365

  
2366
    v.i = i;
2367
    return v.d;
2368
}
2369

  
2370
static inline uint64_t vfp_dtoi(float64 d)
2371
{
2372
    union {
2373
        uint64_t i;
2374
        float64 d;
2375
    } v;
2376

  
2377
    v.d = d;
2378
    return v.i;
2379
}
2380

  
2381
/* Integer to float conversion.  */
2382
float32 VFP_HELPER(uito, s)(float32 x, CPUState *env)
2383
{
2384
    return uint32_to_float32(vfp_stoi(x), &env->vfp.fp_status);
2385
}
2386

  
2387
float64 VFP_HELPER(uito, d)(float32 x, CPUState *env)
2388
{
2389
    return uint32_to_float64(vfp_stoi(x), &env->vfp.fp_status);
2390
}
2391

  
2392
float32 VFP_HELPER(sito, s)(float32 x, CPUState *env)
2393
{
2394
    return int32_to_float32(vfp_stoi(x), &env->vfp.fp_status);
2395
}
2396

  
2397
float64 VFP_HELPER(sito, d)(float32 x, CPUState *env)
2398
{
2399
    return int32_to_float64(vfp_stoi(x), &env->vfp.fp_status);
2400
}
2401

  
2402
/* Float to integer conversion.  */
2403
float32 VFP_HELPER(toui, s)(float32 x, CPUState *env)
2404
{
2405
    return vfp_itos(float32_to_uint32(x, &env->vfp.fp_status));
2406
}
2407

  
2408
float32 VFP_HELPER(toui, d)(float64 x, CPUState *env)
2409
{
2410
    return vfp_itos(float64_to_uint32(x, &env->vfp.fp_status));
2411
}
2412

  
2413
float32 VFP_HELPER(tosi, s)(float32 x, CPUState *env)
2414
{
2415
    return vfp_itos(float32_to_int32(x, &env->vfp.fp_status));
2416
}
2417

  
2418
float32 VFP_HELPER(tosi, d)(float64 x, CPUState *env)
2419
{
2420
    return vfp_itos(float64_to_int32(x, &env->vfp.fp_status));
2421
}
2422

  
2423
float32 VFP_HELPER(touiz, s)(float32 x, CPUState *env)
2424
{
2425
    return vfp_itos(float32_to_uint32_round_to_zero(x, &env->vfp.fp_status));
2426
}
2427

  
2428
float32 VFP_HELPER(touiz, d)(float64 x, CPUState *env)
2429
{
2430
    return vfp_itos(float64_to_uint32_round_to_zero(x, &env->vfp.fp_status));
2431
}
2432

  
2433
float32 VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
2434
{
2435
    return vfp_itos(float32_to_int32_round_to_zero(x, &env->vfp.fp_status));
2436
}
2437

  
2438
float32 VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
2439
{
2440
    return vfp_itos(float64_to_int32_round_to_zero(x, &env->vfp.fp_status));
2441
}
2442

  
2443
/* floating point conversion */
2444
float64 VFP_HELPER(fcvtd, s)(float32 x, CPUState *env)
2445
{
2446
    return float32_to_float64(x, &env->vfp.fp_status);
2447
}
2448

  
2449
float32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env)
2450
{
2451
    return float64_to_float32(x, &env->vfp.fp_status);
2452
}
2453

  
2454
/* VFP3 fixed point conversion.  */
2455
#define VFP_CONV_FIX(name, p, ftype, itype, sign) \
2456
ftype VFP_HELPER(name##to, p)(ftype x, uint32_t shift, CPUState *env) \
2457
{ \
2458
    ftype tmp; \
2459
    tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(x), \
2460
                                  &env->vfp.fp_status); \
2461
    return ftype##_scalbn(tmp, shift, &env->vfp.fp_status); \
2462
} \
2463
ftype VFP_HELPER(to##name, p)(ftype x, uint32_t shift, CPUState *env) \
2464
{ \
2465
    ftype tmp; \
2466
    tmp = ftype##_scalbn(x, shift, &env->vfp.fp_status); \
2467
    return vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \
2468
        &env->vfp.fp_status)); \
2469
}
2470

  
2471
VFP_CONV_FIX(sh, d, float64, int16, )
2472
VFP_CONV_FIX(sl, d, float64, int32, )
2473
VFP_CONV_FIX(uh, d, float64, uint16, u)
2474
VFP_CONV_FIX(ul, d, float64, uint32, u)
2475
VFP_CONV_FIX(sh, s, float32, int16, )
2476
VFP_CONV_FIX(sl, s, float32, int32, )
2477
VFP_CONV_FIX(uh, s, float32, uint16, u)
2478
VFP_CONV_FIX(ul, s, float32, uint32, u)
2479
#undef VFP_CONV_FIX
2480

  
2481
float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
2482
{
2483
    float_status *s = &env->vfp.fp_status;
2484
    float32 two = int32_to_float32(2, s);
2485
    return float32_sub(two, float32_mul(a, b, s), s);
2486
}
2487

  
2488
float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
2489
{
2490
    float_status *s = &env->vfp.fp_status;
2491
    float32 three = int32_to_float32(3, s);
2492
    return float32_sub(three, float32_mul(a, b, s), s);
2493
}
2494

  
2495
/* TODO: The architecture specifies the value that the estimate functions
2496
   should return.  We return the exact reciprocal/root instead.  */
2497
float32 HELPER(recpe_f32)(float32 a, CPUState *env)
2498
{
2499
    float_status *s = &env->vfp.fp_status;
2500
    float32 one = int32_to_float32(1, s);
2501
    return float32_div(one, a, s);
2502
}
2503

  
2504
float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
2505
{
2506
    float_status *s = &env->vfp.fp_status;
2507
    float32 one = int32_to_float32(1, s);
2508
    return float32_div(one, float32_sqrt(a, s), s);
2509
}
2510

  
2511
uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
2512
{
2513
    float_status *s = &env->vfp.fp_status;
2514
    float32 tmp;
2515
    tmp = int32_to_float32(a, s);
2516
    tmp = float32_scalbn(tmp, -32, s);
2517
    tmp = helper_recpe_f32(tmp, env);
2518
    tmp = float32_scalbn(tmp, 31, s);
2519
    return float32_to_int32(tmp, s);
2520
}
2521

  
2522
uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
2523
{
2524
    float_status *s = &env->vfp.fp_status;
2525
    float32 tmp;
2526
    tmp = int32_to_float32(a, s);
2527
    tmp = float32_scalbn(tmp, -32, s);
2528
    tmp = helper_rsqrte_f32(tmp, env);
2529
    tmp = float32_scalbn(tmp, 31, s);
2530
    return float32_to_int32(tmp, s);
2531
}
2532

  

Also available in: Unified diff