Revision 4373f3ce target-arm/op.c

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);

Also available in: Unified diff