Revision 4373f3ce

b/target-arm/cpu.h
168 168
        int vec_len;
169 169
        int vec_stride;
170 170

  
171
        /* Temporary variables if we don't have spare fp regs.  */
172
        float32 tmp0s, tmp1s;
173
        float64 tmp0d, tmp1d;
174 171
        /* scratch space when Tn are not sufficient.  */
175 172
        uint32_t scratch[8];
176 173

  
b/target-arm/exec.h
25 25
register uint32_t T1 asm(AREG2);
26 26
register uint32_t T2 asm(AREG3);
27 27

  
28
/* TODO: Put these in FP regs on targets that have such things.  */
29
/* It is ok for FT0s and FT0d to overlap.  Likewise FT1s and FT1d.  */
30
#define FT0s env->vfp.tmp0s
31
#define FT1s env->vfp.tmp1s
32
#define FT0d env->vfp.tmp0d
33
#define FT1d env->vfp.tmp1d
34

  
35 28
#define M0   env->iwmmxt.val
36 29

  
37 30
#include "cpu.h"
......
83 76

  
84 77
void raise_exception(int);
85 78

  
86
void do_vfp_abss(void);
87
void do_vfp_absd(void);
88
void do_vfp_negs(void);
89
void do_vfp_negd(void);
90
void do_vfp_sqrts(void);
91
void do_vfp_sqrtd(void);
92
void do_vfp_cmps(void);
93
void do_vfp_cmpd(void);
94
void do_vfp_cmpes(void);
95
void do_vfp_cmped(void);
96
void do_vfp_set_fpscr(void);
97
void do_vfp_get_fpscr(void);
98
float32 helper_recps_f32(float32, float32);
99
float32 helper_rsqrts_f32(float32, float32);
100
uint32_t helper_recpe_u32(uint32_t);
101
uint32_t helper_rsqrte_u32(uint32_t);
102
float32 helper_recpe_f32(float32);
103
float32 helper_rsqrte_f32(float32);
104 79
void helper_neon_tbl(int rn, int maxindex);
105 80
uint32_t helper_neon_mul_p8(uint32_t op1, uint32_t op2);
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

  
b/target-arm/helpers.h
122 122
DEF_HELPER_1_1(get_user_reg, uint32_t, (uint32_t))
123 123
DEF_HELPER_0_2(set_user_reg, void, (uint32_t, uint32_t))
124 124

  
125
DEF_HELPER_1_1(vfp_get_fpscr, uint32_t, (CPUState *))
126
DEF_HELPER_0_2(vfp_set_fpscr, void, (CPUState *, uint32_t))
127

  
128
DEF_HELPER_1_3(vfp_adds, float32, (float32, float32, CPUState *))
129
DEF_HELPER_1_3(vfp_addd, float64, (float64, float64, CPUState *))
130
DEF_HELPER_1_3(vfp_subs, float32, (float32, float32, CPUState *))
131
DEF_HELPER_1_3(vfp_subd, float64, (float64, float64, CPUState *))
132
DEF_HELPER_1_3(vfp_muls, float32, (float32, float32, CPUState *))
133
DEF_HELPER_1_3(vfp_muld, float64, (float64, float64, CPUState *))
134
DEF_HELPER_1_3(vfp_divs, float32, (float32, float32, CPUState *))
135
DEF_HELPER_1_3(vfp_divd, float64, (float64, float64, CPUState *))
136
DEF_HELPER_1_1(vfp_negs, float32, (float32))
137
DEF_HELPER_1_1(vfp_negd, float64, (float64))
138
DEF_HELPER_1_1(vfp_abss, float32, (float32))
139
DEF_HELPER_1_1(vfp_absd, float64, (float64))
140
DEF_HELPER_1_2(vfp_sqrts, float32, (float32, CPUState *))
141
DEF_HELPER_1_2(vfp_sqrtd, float64, (float64, CPUState *))
142
DEF_HELPER_0_3(vfp_cmps, void, (float32, float32, CPUState *))
143
DEF_HELPER_0_3(vfp_cmpd, void, (float64, float64, CPUState *))
144
DEF_HELPER_0_3(vfp_cmpes, void, (float32, float32, CPUState *))
145
DEF_HELPER_0_3(vfp_cmped, void, (float64, float64, CPUState *))
146

  
147
DEF_HELPER_1_2(vfp_fcvtds, float64, (float32, CPUState *))
148
DEF_HELPER_1_2(vfp_fcvtsd, float32, (float64, CPUState *))
149

  
150
DEF_HELPER_1_2(vfp_uitos, float32, (float32, CPUState *))
151
DEF_HELPER_1_2(vfp_uitod, float64, (float32, CPUState *))
152
DEF_HELPER_1_2(vfp_sitos, float32, (float32, CPUState *))
153
DEF_HELPER_1_2(vfp_sitod, float64, (float32, CPUState *))
154

  
155
DEF_HELPER_1_2(vfp_touis, float32, (float32, CPUState *))
156
DEF_HELPER_1_2(vfp_touid, float32, (float64, CPUState *))
157
DEF_HELPER_1_2(vfp_touizs, float32, (float32, CPUState *))
158
DEF_HELPER_1_2(vfp_touizd, float32, (float64, CPUState *))
159
DEF_HELPER_1_2(vfp_tosis, float32, (float32, CPUState *))
160
DEF_HELPER_1_2(vfp_tosid, float32, (float64, CPUState *))
161
DEF_HELPER_1_2(vfp_tosizs, float32, (float32, CPUState *))
162
DEF_HELPER_1_2(vfp_tosizd, float32, (float64, CPUState *))
163

  
164
DEF_HELPER_1_3(vfp_toshs, float32, (float32, uint32_t, CPUState *))
165
DEF_HELPER_1_3(vfp_tosls, float32, (float32, uint32_t, CPUState *))
166
DEF_HELPER_1_3(vfp_touhs, float32, (float32, uint32_t, CPUState *))
167
DEF_HELPER_1_3(vfp_touls, float32, (float32, uint32_t, CPUState *))
168
DEF_HELPER_1_3(vfp_toshd, float64, (float64, uint32_t, CPUState *))
169
DEF_HELPER_1_3(vfp_tosld, float64, (float64, uint32_t, CPUState *))
170
DEF_HELPER_1_3(vfp_touhd, float64, (float64, uint32_t, CPUState *))
171
DEF_HELPER_1_3(vfp_tould, float64, (float64, uint32_t, CPUState *))
172
DEF_HELPER_1_3(vfp_shtos, float32, (float32, uint32_t, CPUState *))
173
DEF_HELPER_1_3(vfp_sltos, float32, (float32, uint32_t, CPUState *))
174
DEF_HELPER_1_3(vfp_uhtos, float32, (float32, uint32_t, CPUState *))
175
DEF_HELPER_1_3(vfp_ultos, float32, (float32, uint32_t, CPUState *))
176
DEF_HELPER_1_3(vfp_shtod, float64, (float64, uint32_t, CPUState *))
177
DEF_HELPER_1_3(vfp_sltod, float64, (float64, uint32_t, CPUState *))
178
DEF_HELPER_1_3(vfp_uhtod, float64, (float64, uint32_t, CPUState *))
179
DEF_HELPER_1_3(vfp_ultod, float64, (float64, uint32_t, CPUState *))
180

  
181
DEF_HELPER_1_3(recps_f32, float32, (float32, float32, CPUState *))
182
DEF_HELPER_1_3(rsqrts_f32, float32, (float32, float32, CPUState *))
183
DEF_HELPER_1_2(recpe_f32, float32, (float32, CPUState *))
184
DEF_HELPER_1_2(rsqrte_f32, float32, (float32, CPUState *))
185
DEF_HELPER_1_2(recpe_u32, uint32_t, (uint32_t, CPUState *))
186
DEF_HELPER_1_2(rsqrte_u32, uint32_t, (uint32_t, CPUState *))
187

  
125 188
#undef DEF_HELPER
126 189
#undef DEF_HELPER_0_0
127 190
#undef DEF_HELPER_0_1
b/target-arm/op.c
252 252
    FORCE_RET();
253 253
}
254 254

  
255
/* VFP support.  We follow the convention used for VFP instrunctions:
256
   Single precition routines have a "s" suffix, double precision a
257
   "d" suffix.  */
258

  
259
#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void)
260

  
261
#define VFP_BINOP(name) \
262
VFP_OP(name, s)             \
263
{                           \
264
    FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status);    \
265
}                           \
266
VFP_OP(name, d)             \
267
{                           \
268
    FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status);    \
269
}
270
VFP_BINOP(add)
271
VFP_BINOP(sub)
272
VFP_BINOP(mul)
273
VFP_BINOP(div)
274
#undef VFP_BINOP
275

  
276
#define VFP_HELPER(name)  \
277
VFP_OP(name, s)           \
278
{                         \
279
    do_vfp_##name##s();    \
280
}                         \
281
VFP_OP(name, d)           \
282
{                         \
283
    do_vfp_##name##d();    \
284
}
285
VFP_HELPER(abs)
286
VFP_HELPER(sqrt)
287
VFP_HELPER(cmp)
288
VFP_HELPER(cmpe)
289
#undef VFP_HELPER
290

  
291
/* XXX: Will this do the right thing for NANs.  Should invert the signbit
292
   without looking at the rest of the value.  */
293
VFP_OP(neg, s)
294
{
295
    FT0s = float32_chs(FT0s);
296
}
297

  
298
VFP_OP(neg, d)
299
{
300
    FT0d = float64_chs(FT0d);
301
}
302

  
303
VFP_OP(F1_ld0, s)
304
{
305
    union {
306
        uint32_t i;
307
        float32 s;
308
    } v;
309
    v.i = 0;
310
    FT1s = v.s;
311
}
312

  
313
VFP_OP(F1_ld0, d)
314
{
315
    union {
316
        uint64_t i;
317
        float64 d;
318
    } v;
319
    v.i = 0;
320
    FT1d = v.d;
321
}
322

  
323
/* Helper routines to perform bitwise copies between float and int.  */
324
static inline float32 vfp_itos(uint32_t i)
325
{
326
    union {
327
        uint32_t i;
328
        float32 s;
329
    } v;
330

  
331
    v.i = i;
332
    return v.s;
333
}
334

  
335
static inline uint32_t vfp_stoi(float32 s)
336
{
337
    union {
338
        uint32_t i;
339
        float32 s;
340
    } v;
341

  
342
    v.s = s;
343
    return v.i;
344
}
345

  
346
static inline float64 vfp_itod(uint64_t i)
347
{
348
    union {
349
        uint64_t i;
350
        float64 d;
351
    } v;
352

  
353
    v.i = i;
354
    return v.d;
355
}
356

  
357
static inline uint64_t vfp_dtoi(float64 d)
358
{
359
    union {
360
        uint64_t i;
361
        float64 d;
362
    } v;
363

  
364
    v.d = d;
365
    return v.i;
366
}
367

  
368
/* Integer to float conversion.  */
369
VFP_OP(uito, s)
370
{
371
    FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
372
}
373

  
374
VFP_OP(uito, d)
375
{
376
    FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
377
}
378

  
379
VFP_OP(sito, s)
380
{
381
    FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
382
}
383

  
384
VFP_OP(sito, d)
385
{
386
    FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
387
}
388

  
389
/* Float to integer conversion.  */
390
VFP_OP(toui, s)
391
{
392
    FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status));
393
}
394

  
395
VFP_OP(toui, d)
396
{
397
    FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status));
398
}
399

  
400
VFP_OP(tosi, s)
401
{
402
    FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status));
403
}
404

  
405
VFP_OP(tosi, d)
406
{
407
    FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status));
408
}
409

  
410
/* TODO: Set rounding mode properly.  */
411
VFP_OP(touiz, s)
412
{
413
    FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status));
414
}
415

  
416
VFP_OP(touiz, d)
417
{
418
    FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status));
419
}
420

  
421
VFP_OP(tosiz, s)
422
{
423
    FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status));
424
}
425

  
426
VFP_OP(tosiz, d)
427
{
428
    FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status));
429
}
430

  
431
/* floating point conversion */
432
VFP_OP(fcvtd, s)
433
{
434
    FT0d = float32_to_float64(FT0s, &env->vfp.fp_status);
435
}
436

  
437
VFP_OP(fcvts, d)
438
{
439
    FT0s = float64_to_float32(FT0d, &env->vfp.fp_status);
440
}
441

  
442
/* VFP3 fixed point conversion.  */
443
#define VFP_CONV_FIX(name, p, ftype, itype, sign) \
444
VFP_OP(name##to, p) \
445
{ \
446
    ftype tmp; \
447
    tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(FT0##p), \
448
                                  &env->vfp.fp_status); \
449
    FT0##p = ftype##_scalbn(tmp, PARAM1, &env->vfp.fp_status); \
450
} \
451
VFP_OP(to##name, p) \
452
{ \
453
    ftype tmp; \
454
    tmp = ftype##_scalbn(FT0##p, PARAM1, &env->vfp.fp_status); \
455
    FT0##p = vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \
456
            &env->vfp.fp_status)); \
457
}
458

  
459
VFP_CONV_FIX(sh, d, float64, int16, )
460
VFP_CONV_FIX(sl, d, float64, int32, )
461
VFP_CONV_FIX(uh, d, float64, uint16, u)
462
VFP_CONV_FIX(ul, d, float64, uint32, u)
463
VFP_CONV_FIX(sh, s, float32, int16, )
464
VFP_CONV_FIX(sl, s, float32, int32, )
465
VFP_CONV_FIX(uh, s, float32, uint16, u)
466
VFP_CONV_FIX(ul, s, float32, uint32, u)
467

  
468
/* Get and Put values from registers.  */
469
VFP_OP(getreg_F0, d)
470
{
471
  FT0d = *(float64 *)((char *) env + PARAM1);
472
}
473

  
474
VFP_OP(getreg_F0, s)
475
{
476
  FT0s = *(float32 *)((char *) env + PARAM1);
477
}
478

  
479
VFP_OP(getreg_F1, d)
480
{
481
  FT1d = *(float64 *)((char *) env + PARAM1);
482
}
483

  
484
VFP_OP(getreg_F1, s)
485
{
486
  FT1s = *(float32 *)((char *) env + PARAM1);
487
}
488

  
489
VFP_OP(setreg_F0, d)
490
{
491
  *(float64 *)((char *) env + PARAM1) = FT0d;
492
}
493

  
494
VFP_OP(setreg_F0, s)
495
{
496
  *(float32 *)((char *) env + PARAM1) = FT0s;
497
}
498

  
499
void OPPROTO op_vfp_movl_T0_fpscr(void)
500
{
501
    do_vfp_get_fpscr ();
502
}
503

  
504
void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
505
{
506
    T0 = env->vfp.xregs[ARM_VFP_FPSCR] & (0xf << 28);
507
}
508

  
509
void OPPROTO op_vfp_movl_fpscr_T0(void)
510
{
511
    do_vfp_set_fpscr();
512
}
513

  
514
void OPPROTO op_vfp_movl_T0_xreg(void)
515
{
516
    T0 = env->vfp.xregs[PARAM1];
517
}
518

  
519
void OPPROTO op_vfp_movl_xreg_T0(void)
520
{
521
    env->vfp.xregs[PARAM1] = T0;
522
}
523

  
524
/* Move between FT0s to T0  */
525
void OPPROTO op_vfp_mrs(void)
526
{
527
    T0 = vfp_stoi(FT0s);
528
}
529

  
530
void OPPROTO op_vfp_msr(void)
531
{
532
    FT0s = vfp_itos(T0);
533
}
534

  
535
/* Move between FT0d and {T0,T1} */
536
void OPPROTO op_vfp_mrrd(void)
537
{
538
    CPU_DoubleU u;
539

  
540
    u.d = FT0d;
541
    T0 = u.l.lower;
542
    T1 = u.l.upper;
543
}
544

  
545
void OPPROTO op_vfp_mdrr(void)
546
{
547
    CPU_DoubleU u;
548

  
549
    u.l.lower = T0;
550
    u.l.upper = T1;
551
    FT0d = u.d;
552
}
553

  
554
/* Load immediate.  PARAM1 is the 32 most significant bits of the value.  */
555
void OPPROTO op_vfp_fconstd(void)
556
{
557
    CPU_DoubleU u;
558
    u.l.upper = PARAM1;
559
    u.l.lower = 0;
560
    FT0d = u.d;
561
}
562

  
563
void OPPROTO op_vfp_fconsts(void)
564
{
565
    FT0s = vfp_itos(PARAM1);
566
}
567

  
568 255
void OPPROTO op_movl_cp_T0(void)
569 256
{
570 257
    helper_set_cp(env, PARAM1, T0);
b/target-arm/op_helper.c
40 40
    spin_unlock(&global_cpu_lock);
41 41
}
42 42

  
43
/* VFP support.  */
44

  
45
void do_vfp_abss(void)
46
{
47
    FT0s = float32_abs(FT0s);
48
}
49

  
50
void do_vfp_absd(void)
51
{
52
    FT0d = float64_abs(FT0d);
53
}
54

  
55
void do_vfp_sqrts(void)
56
{
57
    FT0s = float32_sqrt(FT0s, &env->vfp.fp_status);
58
}
59

  
60
void do_vfp_sqrtd(void)
61
{
62
    FT0d = float64_sqrt(FT0d, &env->vfp.fp_status);
63
}
64

  
65
/* XXX: check quiet/signaling case */
66
#define DO_VFP_cmp(p, size)               \
67
void do_vfp_cmp##p(void)                  \
68
{                                         \
69
    uint32_t flags;                       \
70
    switch(float ## size ## _compare_quiet(FT0##p, FT1##p, &env->vfp.fp_status)) {\
71
    case 0: flags = 0x6; break;\
72
    case -1: flags = 0x8; break;\
73
    case 1: flags = 0x2; break;\
74
    default: case 2: flags = 0x3; break;\
75
    }\
76
    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\
77
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
78
    FORCE_RET();                          \
79
}\
80
\
81
void do_vfp_cmpe##p(void)                   \
82
{                                           \
83
    uint32_t flags;                       \
84
    switch(float ## size ## _compare(FT0##p, FT1##p, &env->vfp.fp_status)) {\
85
    case 0: flags = 0x6; break;\
86
    case -1: flags = 0x8; break;\
87
    case 1: flags = 0x2; break;\
88
    default: case 2: flags = 0x3; break;\
89
    }\
90
    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\
91
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
92
    FORCE_RET();                          \
93
}
94
DO_VFP_cmp(s, 32)
95
DO_VFP_cmp(d, 64)
96
#undef DO_VFP_cmp
97

  
98
/* Convert host exception flags to vfp form.  */
99
static inline int vfp_exceptbits_from_host(int host_bits)
100
{
101
    int target_bits = 0;
102

  
103
    if (host_bits & float_flag_invalid)
104
        target_bits |= 1;
105
    if (host_bits & float_flag_divbyzero)
106
        target_bits |= 2;
107
    if (host_bits & float_flag_overflow)
108
        target_bits |= 4;
109
    if (host_bits & float_flag_underflow)
110
        target_bits |= 8;
111
    if (host_bits & float_flag_inexact)
112
        target_bits |= 0x10;
113
    return target_bits;
114
}
115

  
116
/* Convert vfp exception flags to target form.  */
117
static inline int vfp_exceptbits_to_host(int target_bits)
118
{
119
    int host_bits = 0;
120

  
121
    if (target_bits & 1)
122
        host_bits |= float_flag_invalid;
123
    if (target_bits & 2)
124
        host_bits |= float_flag_divbyzero;
125
    if (target_bits & 4)
126
        host_bits |= float_flag_overflow;
127
    if (target_bits & 8)
128
        host_bits |= float_flag_underflow;
129
    if (target_bits & 0x10)
130
        host_bits |= float_flag_inexact;
131
    return host_bits;
132
}
133

  
134
void do_vfp_set_fpscr(void)
135
{
136
    int i;
137
    uint32_t changed;
138

  
139
    changed = env->vfp.xregs[ARM_VFP_FPSCR];
140
    env->vfp.xregs[ARM_VFP_FPSCR] = (T0 & 0xffc8ffff);
141
    env->vfp.vec_len = (T0 >> 16) & 7;
142
    env->vfp.vec_stride = (T0 >> 20) & 3;
143

  
144
    changed ^= T0;
145
    if (changed & (3 << 22)) {
146
        i = (T0 >> 22) & 3;
147
        switch (i) {
148
        case 0:
149
            i = float_round_nearest_even;
150
            break;
151
        case 1:
152
            i = float_round_up;
153
            break;
154
        case 2:
155
            i = float_round_down;
156
            break;
157
        case 3:
158
            i = float_round_to_zero;
159
            break;
160
        }
161
        set_float_rounding_mode(i, &env->vfp.fp_status);
162
    }
163

  
164
    i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);
165
    set_float_exception_flags(i, &env->vfp.fp_status);
166
    /* XXX: FZ and DN are not implemented.  */
167
}
168

  
169
void do_vfp_get_fpscr(void)
170
{
171
    int i;
172

  
173
    T0 = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | (env->vfp.vec_len << 16)
174
          | (env->vfp.vec_stride << 20);
175
    i = get_float_exception_flags(&env->vfp.fp_status);
176
    T0 |= vfp_exceptbits_from_host(i);
177
}
178

  
179
float32 helper_recps_f32(float32 a, float32 b)
180
{
181
    float_status *s = &env->vfp.fp_status;
182
    float32 two = int32_to_float32(2, s);
183
    return float32_sub(two, float32_mul(a, b, s), s);
184
}
185

  
186
float32 helper_rsqrts_f32(float32 a, float32 b)
187
{
188
    float_status *s = &env->vfp.fp_status;
189
    float32 three = int32_to_float32(3, s);
190
    return float32_sub(three, float32_mul(a, b, s), s);
191
}
192

  
193
/* TODO: The architecture specifies the value that the estimate functions
194
   should return.  We return the exact reciprocal/root instead.  */
195
float32 helper_recpe_f32(float32 a)
196
{
197
    float_status *s = &env->vfp.fp_status;
198
    float32 one = int32_to_float32(1, s);
199
    return float32_div(one, a, s);
200
}
201

  
202
float32 helper_rsqrte_f32(float32 a)
203
{
204
    float_status *s = &env->vfp.fp_status;
205
    float32 one = int32_to_float32(1, s);
206
    return float32_div(one, float32_sqrt(a, s), s);
207
}
208

  
209
uint32_t helper_recpe_u32(uint32_t a)
210
{
211
    float_status *s = &env->vfp.fp_status;
212
    float32 tmp;
213
    tmp = int32_to_float32(a, s);
214
    tmp = float32_scalbn(tmp, -32, s);
215
    tmp = helper_recpe_f32(tmp);
216
    tmp = float32_scalbn(tmp, 31, s);
217
    return float32_to_int32(tmp, s);
218
}
219

  
220
uint32_t helper_rsqrte_u32(uint32_t a)
221
{
222
    float_status *s = &env->vfp.fp_status;
223
    float32 tmp;
224
    tmp = int32_to_float32(a, s);
225
    tmp = float32_scalbn(tmp, -32, s);
226
    tmp = helper_rsqrte_f32(tmp);
227
    tmp = float32_scalbn(tmp, 31, s);
228
    return float32_to_int32(tmp, s);
229
}
230

  
231 43
void helper_neon_tbl(int rn, int maxindex)
232 44
{
233 45
    uint32_t val;
b/target-arm/op_mem.h
77 77
    FORCE_RET();
78 78
}
79 79

  
80
/* Floating point load/store.  Address is in T1 */
81
#define VFP_MEM_OP(p, w) \
82
void OPPROTO glue(op_vfp_ld##p,MEMSUFFIX)(void) \
83
{ \
84
    FT0##p = glue(ldf##w,MEMSUFFIX)(T1); \
85
    FORCE_RET(); \
86
} \
87
void OPPROTO glue(op_vfp_st##p,MEMSUFFIX)(void) \
88
{ \
89
    glue(stf##w,MEMSUFFIX)(T1, FT0##p); \
90
    FORCE_RET(); \
91
}
92

  
93
VFP_MEM_OP(s,l)
94
VFP_MEM_OP(d,q)
95

  
96
#undef VFP_MEM_OP
97

  
98 80
/* iwMMXt load/store.  Address is in T1 */
99 81
#define MMX_MEM_OP(name, ldname) \
100 82
void OPPROTO glue(op_iwmmxt_ld##name,MEMSUFFIX)(void) \
b/target-arm/op_neon.h
14 14
#define NFS &env->vfp.fp_status
15 15
#define NEON_OP(name) void OPPROTO op_neon_##name (void)
16 16

  
17
/* Helper routines to perform bitwise copies between float and int.  */
18
static inline float32 vfp_itos(uint32_t i)
19
{
20
    union {
21
        uint32_t i;
22
        float32 s;
23
    } v;
24

  
25
    v.i = i;
26
    return v.s;
27
}
28

  
29
static inline uint32_t vfp_stoi(float32 s)
30
{
31
    union {
32
        uint32_t i;
33
        float32 s;
34
    } v;
35

  
36
    v.s = s;
37
    return v.i;
38
}
39

  
17 40
NEON_OP(getreg_T0)
18 41
{
19 42
    T0 = *(uint32_t *)((char *) env + PARAM1);
......
754 777
#undef NEON_FN
755 778
#undef NEON_QDMULH32
756 779

  
757
NEON_OP(recps_f32)
758
{
759
    T0 = vfp_stoi(helper_recps_f32(vfp_itos(T0), vfp_itos(T1)));
760
    FORCE_RET();
761
}
762

  
763
NEON_OP(rsqrts_f32)
764
{
765
    T0 = vfp_stoi(helper_rsqrts_f32(vfp_itos(T0), vfp_itos(T1)));
766
    FORCE_RET();
767
}
768

  
769 780
/* Floating point comparisons produce an integer result.  */
770 781
#define NEON_VOP_FCMP(name, cmp) \
771 782
NEON_OP(name) \
......
1702 1713
    FORCE_RET();
1703 1714
}
1704 1715

  
1705
/* Reciprocal/root estimate.  */
1706
NEON_OP(recpe_u32)
1707
{
1708
    T0 = helper_recpe_u32(T0);
1709
}
1710

  
1711
NEON_OP(rsqrte_u32)
1712
{
1713
    T0 = helper_rsqrte_u32(T0);
1714
}
1715

  
1716
NEON_OP(recpe_f32)
1717
{
1718
    FT0s = helper_recpe_f32(FT0s);
1719
}
1720

  
1721
NEON_OP(rsqrte_f32)
1722
{
1723
    FT0s = helper_rsqrte_f32(FT0s);
1724
}
1725

  
1726 1716
/* Table lookup.  This accessed the register file directly.  */
1727 1717
NEON_OP(tbl)
1728 1718
{
b/target-arm/translate.c
79 79
static TCGv cpu_env;
80 80
/* FIXME:  These should be removed.  */
81 81
static TCGv cpu_T[3];
82
static TCGv cpu_F0s, cpu_F1s, cpu_F0d, cpu_F1d;
82 83

  
83 84
/* initialize TCG globals.  */
84 85
void arm_translate_init(void)
......
959 960
    }
960 961
}
961 962

  
962
#define VFP_OP(name)                      \
963
static inline void gen_vfp_##name(int dp) \
964
{                                         \
965
    if (dp)                               \
966
        gen_op_vfp_##name##d();           \
967
    else                                  \
968
        gen_op_vfp_##name##s();           \
963
#define VFP_OP2(name)                                                 \
964
static inline void gen_vfp_##name(int dp)                             \
965
{                                                                     \
966
    if (dp)                                                           \
967
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
968
    else                                                              \
969
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
969 970
}
970 971

  
971
#define VFP_OP1(name)                               \
972
#define VFP_OP1i(name)                               \
972 973
static inline void gen_vfp_##name(int dp, int arg)  \
973 974
{                                                   \
974 975
    if (dp)                                         \
......
977 978
        gen_op_vfp_##name##s(arg);                  \
978 979
}
979 980

  
980
VFP_OP(add)
981
VFP_OP(sub)
982
VFP_OP(mul)
983
VFP_OP(div)
984
VFP_OP(neg)
985
VFP_OP(abs)
986
VFP_OP(sqrt)
987
VFP_OP(cmp)
988
VFP_OP(cmpe)
989
VFP_OP(F1_ld0)
990
VFP_OP(uito)
991
VFP_OP(sito)
992
VFP_OP(toui)
993
VFP_OP(touiz)
994
VFP_OP(tosi)
995
VFP_OP(tosiz)
996
VFP_OP1(tosh)
997
VFP_OP1(tosl)
998
VFP_OP1(touh)
999
VFP_OP1(toul)
1000
VFP_OP1(shto)
1001
VFP_OP1(slto)
1002
VFP_OP1(uhto)
1003
VFP_OP1(ulto)
1004

  
1005
#undef VFP_OP
1006

  
1007
static inline void gen_vfp_fconst(int dp, uint32_t val)
981
VFP_OP2(add)
982
VFP_OP2(sub)
983
VFP_OP2(mul)
984
VFP_OP2(div)
985

  
986
#undef VFP_OP2
987

  
988
static inline void gen_vfp_abs(int dp)
989
{
990
    if (dp)
991
        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
992
    else
993
        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
994
}
995

  
996
static inline void gen_vfp_neg(int dp)
997
{
998
    if (dp)
999
        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1000
    else
1001
        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1002
}
1003

  
1004
static inline void gen_vfp_sqrt(int dp)
1005
{
1006
    if (dp)
1007
        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1008
    else
1009
        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1010
}
1011

  
1012
static inline void gen_vfp_cmp(int dp)
1013
{
1014
    if (dp)
1015
        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1016
    else
1017
        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1018
}
1019

  
1020
static inline void gen_vfp_cmpe(int dp)
1021
{
1022
    if (dp)
1023
        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1024
    else
1025
        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1026
}
1027

  
1028
static inline void gen_vfp_F1_ld0(int dp)
1029
{
1030
    if (dp)
1031
        tcg_gen_movi_i64(cpu_F0d, 0);
1032
    else
1033
        tcg_gen_movi_i32(cpu_F0s, 0);
1034
}
1035

  
1036
static inline void gen_vfp_uito(int dp)
1037
{
1038
    if (dp)
1039
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1040
    else
1041
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1042
}
1043

  
1044
static inline void gen_vfp_sito(int dp)
1045
{
1046
    if (dp)
1047
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1048
    else
1049
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1050
}
1051

  
1052
static inline void gen_vfp_toui(int dp)
1053
{
1054
    if (dp)
1055
        gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1056
    else
1057
        gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1058
}
1059

  
1060
static inline void gen_vfp_touiz(int dp)
1061
{
1062
    if (dp)
1063
        gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1064
    else
1065
        gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1066
}
1067

  
1068
static inline void gen_vfp_tosi(int dp)
1069
{
1070
    if (dp)
1071
        gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1072
    else
1073
        gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1074
}
1075

  
1076
static inline void gen_vfp_tosiz(int dp)
1008 1077
{
1009 1078
    if (dp)
1010
        gen_op_vfp_fconstd(val);
1079
        gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1011 1080
    else
1012
        gen_op_vfp_fconsts(val);
1081
        gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1082
}
1083

  
1084
#define VFP_GEN_FIX(name) \
1085
static inline void gen_vfp_##name(int dp, int shift) \
1086
{ \
1087
    if (dp) \
1088
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1089
    else \
1090
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1013 1091
}
1092
VFP_GEN_FIX(tosh)
1093
VFP_GEN_FIX(tosl)
1094
VFP_GEN_FIX(touh)
1095
VFP_GEN_FIX(toul)
1096
VFP_GEN_FIX(shto)
1097
VFP_GEN_FIX(slto)
1098
VFP_GEN_FIX(uhto)
1099
VFP_GEN_FIX(ulto)
1100
#undef VFP_GEN_FIX
1014 1101

  
1015 1102
static inline void gen_vfp_ld(DisasContext *s, int dp)
1016 1103
{
1017 1104
    if (dp)
1018
        gen_ldst(vfp_ldd, s);
1105
        tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1019 1106
    else
1020
        gen_ldst(vfp_lds, s);
1107
        tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1021 1108
}
1022 1109

  
1023 1110
static inline void gen_vfp_st(DisasContext *s, int dp)
1024 1111
{
1025 1112
    if (dp)
1026
        gen_ldst(vfp_std, s);
1113
        tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1027 1114
    else
1028
        gen_ldst(vfp_sts, s);
1115
        tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1029 1116
}
1030 1117

  
1031 1118
static inline long
......
1055 1142
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
1056 1143
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
1057 1144

  
1145
#define tcg_gen_ld_f32 tcg_gen_ld_i32
1146
#define tcg_gen_ld_f64 tcg_gen_ld_i64
1147
#define tcg_gen_st_f32 tcg_gen_st_i32
1148
#define tcg_gen_st_f64 tcg_gen_st_i64
1149

  
1058 1150
static inline void gen_mov_F0_vreg(int dp, int reg)
1059 1151
{
1060 1152
    if (dp)
1061
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
1153
        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1062 1154
    else
1063
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
1155
        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1064 1156
}
1065 1157

  
1066 1158
static inline void gen_mov_F1_vreg(int dp, int reg)
1067 1159
{
1068 1160
    if (dp)
1069
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
1161
        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1070 1162
    else
1071
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
1163
        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1072 1164
}
1073 1165

  
1074 1166
static inline void gen_mov_vreg_F0(int dp, int reg)
1075 1167
{
1076 1168
    if (dp)
1077
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
1169
        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1078 1170
    else
1079
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
1171
        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1080 1172
}
1081 1173

  
1082 1174
#define ARM_CP_RW_BIT	(1 << 20)
......
2262 2354
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2263 2355
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2264 2356

  
2357
/* Move between integer and VFP cores.  */
2358
static TCGv gen_vfp_mrs(void)
2359
{
2360
    TCGv tmp = new_tmp();
2361
    tcg_gen_mov_i32(tmp, cpu_F0s);
2362
    return tmp;
2363
}
2364

  
2365
static void gen_vfp_msr(TCGv tmp)
2366
{
2367
    tcg_gen_mov_i32(cpu_F0s, tmp);
2368
    dead_tmp(tmp);
2369
}
2370

  
2265 2371
static inline int
2266 2372
vfp_enabled(CPUState * env)
2267 2373
{
......
2274 2380
{
2275 2381
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2276 2382
    int dp, veclen;
2383
    TCGv tmp;
2277 2384

  
2278 2385
    if (!arm_feature(env, ARM_FEATURE_VFP))
2279 2386
        return 1;
......
2396 2503

  
2397 2504
                        switch (rn) {
2398 2505
                        case ARM_VFP_FPSID:
2399
                            /* VFP2 allows access for FSID from userspace.
2506
                            /* VFP2 allows access to FSID from userspace.
2400 2507
                               VFP3 restricts all id registers to privileged
2401 2508
                               accesses.  */
2402 2509
                            if (IS_USER(s)
2403 2510
                                && arm_feature(env, ARM_FEATURE_VFP3))
2404 2511
                                return 1;
2405
                            gen_op_vfp_movl_T0_xreg(rn);
2512
                            tmp = load_cpu_field(vfp.xregs[rn]);
2406 2513
                            break;
2407 2514
                        case ARM_VFP_FPEXC:
2408 2515
                            if (IS_USER(s))
2409 2516
                                return 1;
2410
                            gen_op_vfp_movl_T0_xreg(rn);
2517
                            tmp = load_cpu_field(vfp.xregs[rn]);
2411 2518
                            break;
2412 2519
                        case ARM_VFP_FPINST:
2413 2520
                        case ARM_VFP_FPINST2:
......
2415 2522
                            if (IS_USER(s)
2416 2523
                                || arm_feature(env, ARM_FEATURE_VFP3))
2417 2524
                                return 1;
2418
                            gen_op_vfp_movl_T0_xreg(rn);
2525
                            tmp = load_cpu_field(vfp.xregs[rn]);
2419 2526
                            break;
2420 2527
                        case ARM_VFP_FPSCR:
2421
			    if (rd == 15)
2422
				gen_op_vfp_movl_T0_fpscr_flags();
2423
			    else
2424
				gen_op_vfp_movl_T0_fpscr();
2528
			    if (rd == 15) {
2529
                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2530
                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2531
                            } else {
2532
                                tmp = new_tmp();
2533
                                gen_helper_vfp_get_fpscr(tmp, cpu_env);
2534
                            }
2425 2535
                            break;
2426 2536
                        case ARM_VFP_MVFR0:
2427 2537
                        case ARM_VFP_MVFR1:
2428 2538
                            if (IS_USER(s)
2429 2539
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2430 2540
                                return 1;
2431
                            gen_op_vfp_movl_T0_xreg(rn);
2541
                            tmp = load_cpu_field(vfp.xregs[rn]);
2432 2542
                            break;
2433 2543
                        default:
2434 2544
                            return 1;
2435 2545
                        }
2436 2546
                    } else {
2437 2547
                        gen_mov_F0_vreg(0, rn);
2438
                        gen_op_vfp_mrs();
2548
                        tmp = gen_vfp_mrs();
2439 2549
                    }
2440 2550
                    if (rd == 15) {
2441 2551
                        /* Set the 4 flag bits in the CPSR.  */
2442
                        gen_set_nzcv(cpu_T[0]);
2443
                    } else
2444
                        gen_movl_reg_T0(s, rd);
2552
                        gen_set_nzcv(tmp);
2553
                        dead_tmp(tmp);
2554
                    } else {
2555
                        store_reg(s, rd, tmp);
2556
                    }
2445 2557
                } else {
2446 2558
                    /* arm->vfp */
2447
                    gen_movl_T0_reg(s, rd);
2559
                    tmp = load_reg(s, rd);
2448 2560
                    if (insn & (1 << 21)) {
2449 2561
                        rn >>= 1;
2450 2562
                        /* system register */
......
2455 2567
                            /* Writes are ignored.  */
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff