qemu/target/m68k/fpu_helper.c
<<
>>
Prefs
   1/*
   2 *  m68k FPU helpers
   3 *
   4 *  Copyright (c) 2006-2007 CodeSourcery
   5 *  Written by Paul Brook
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2 of the License, or (at your option) any later version.
  11 *
  12 * This library is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public
  18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "cpu.h"
  23#include "exec/helper-proto.h"
  24#include "exec/exec-all.h"
  25#include "exec/cpu_ldst.h"
  26#include "softfloat.h"
  27
  28/* Undefined offsets may be different on various FPU.
  29 * On 68040 they return 0.0 (floatx80_zero)
  30 */
  31
  32static const floatx80 fpu_rom[128] = {
  33    [0x00] = make_floatx80_init(0x4000, 0xc90fdaa22168c235ULL),  /* Pi       */
  34    [0x0b] = make_floatx80_init(0x3ffd, 0x9a209a84fbcff798ULL),  /* Log10(2) */
  35    [0x0c] = make_floatx80_init(0x4000, 0xadf85458a2bb4a9aULL),  /* e        */
  36    [0x0d] = make_floatx80_init(0x3fff, 0xb8aa3b295c17f0bcULL),  /* Log2(e)  */
  37    [0x0e] = make_floatx80_init(0x3ffd, 0xde5bd8a937287195ULL),  /* Log10(e) */
  38    [0x0f] = make_floatx80_init(0x0000, 0x0000000000000000ULL),  /* Zero     */
  39    [0x30] = make_floatx80_init(0x3ffe, 0xb17217f7d1cf79acULL),  /* ln(2)    */
  40    [0x31] = make_floatx80_init(0x4000, 0x935d8dddaaa8ac17ULL),  /* ln(10)   */
  41    [0x32] = make_floatx80_init(0x3fff, 0x8000000000000000ULL),  /* 10^0     */
  42    [0x33] = make_floatx80_init(0x4002, 0xa000000000000000ULL),  /* 10^1     */
  43    [0x34] = make_floatx80_init(0x4005, 0xc800000000000000ULL),  /* 10^2     */
  44    [0x35] = make_floatx80_init(0x400c, 0x9c40000000000000ULL),  /* 10^4     */
  45    [0x36] = make_floatx80_init(0x4019, 0xbebc200000000000ULL),  /* 10^8     */
  46    [0x37] = make_floatx80_init(0x4034, 0x8e1bc9bf04000000ULL),  /* 10^16    */
  47    [0x38] = make_floatx80_init(0x4069, 0x9dc5ada82b70b59eULL),  /* 10^32    */
  48    [0x39] = make_floatx80_init(0x40d3, 0xc2781f49ffcfa6d5ULL),  /* 10^64    */
  49    [0x3a] = make_floatx80_init(0x41a8, 0x93ba47c980e98ce0ULL),  /* 10^128   */
  50    [0x3b] = make_floatx80_init(0x4351, 0xaa7eebfb9df9de8eULL),  /* 10^256   */
  51    [0x3c] = make_floatx80_init(0x46a3, 0xe319a0aea60e91c7ULL),  /* 10^512   */
  52    [0x3d] = make_floatx80_init(0x4d48, 0xc976758681750c17ULL),  /* 10^1024  */
  53    [0x3e] = make_floatx80_init(0x5a92, 0x9e8b3b5dc53d5de5ULL),  /* 10^2048  */
  54    [0x3f] = make_floatx80_init(0x7525, 0xc46052028a20979bULL),  /* 10^4096  */
  55};
  56
  57int32_t HELPER(reds32)(CPUM68KState *env, FPReg *val)
  58{
  59    return floatx80_to_int32(val->d, &env->fp_status);
  60}
  61
  62float32 HELPER(redf32)(CPUM68KState *env, FPReg *val)
  63{
  64    return floatx80_to_float32(val->d, &env->fp_status);
  65}
  66
  67void HELPER(exts32)(CPUM68KState *env, FPReg *res, int32_t val)
  68{
  69    res->d = int32_to_floatx80(val, &env->fp_status);
  70}
  71
  72void HELPER(extf32)(CPUM68KState *env, FPReg *res, float32 val)
  73{
  74    res->d = float32_to_floatx80(val, &env->fp_status);
  75}
  76
  77void HELPER(extf64)(CPUM68KState *env, FPReg *res, float64 val)
  78{
  79    res->d = float64_to_floatx80(val, &env->fp_status);
  80}
  81
  82float64 HELPER(redf64)(CPUM68KState *env, FPReg *val)
  83{
  84    return floatx80_to_float64(val->d, &env->fp_status);
  85}
  86
  87void HELPER(firound)(CPUM68KState *env, FPReg *res, FPReg *val)
  88{
  89    res->d = floatx80_round_to_int(val->d, &env->fp_status);
  90}
  91
  92static void m68k_restore_precision_mode(CPUM68KState *env)
  93{
  94    switch (env->fpcr & FPCR_PREC_MASK) {
  95    case FPCR_PREC_X: /* extended */
  96        set_floatx80_rounding_precision(80, &env->fp_status);
  97        break;
  98    case FPCR_PREC_S: /* single */
  99        set_floatx80_rounding_precision(32, &env->fp_status);
 100        break;
 101    case FPCR_PREC_D: /* double */
 102        set_floatx80_rounding_precision(64, &env->fp_status);
 103        break;
 104    case FPCR_PREC_U: /* undefined */
 105    default:
 106        break;
 107    }
 108}
 109
 110static void cf_restore_precision_mode(CPUM68KState *env)
 111{
 112    if (env->fpcr & FPCR_PREC_S) { /* single */
 113        set_floatx80_rounding_precision(32, &env->fp_status);
 114    } else { /* double */
 115        set_floatx80_rounding_precision(64, &env->fp_status);
 116    }
 117}
 118
 119static void restore_rounding_mode(CPUM68KState *env)
 120{
 121    switch (env->fpcr & FPCR_RND_MASK) {
 122    case FPCR_RND_N: /* round to nearest */
 123        set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
 124        break;
 125    case FPCR_RND_Z: /* round to zero */
 126        set_float_rounding_mode(float_round_to_zero, &env->fp_status);
 127        break;
 128    case FPCR_RND_M: /* round toward minus infinity */
 129        set_float_rounding_mode(float_round_down, &env->fp_status);
 130        break;
 131    case FPCR_RND_P: /* round toward positive infinity */
 132        set_float_rounding_mode(float_round_up, &env->fp_status);
 133        break;
 134    }
 135}
 136
 137void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val)
 138{
 139    env->fpcr = val & 0xffff;
 140
 141    if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
 142        cf_restore_precision_mode(env);
 143    } else {
 144        m68k_restore_precision_mode(env);
 145    }
 146    restore_rounding_mode(env);
 147}
 148
 149void HELPER(fitrunc)(CPUM68KState *env, FPReg *res, FPReg *val)
 150{
 151    int rounding_mode = get_float_rounding_mode(&env->fp_status);
 152    set_float_rounding_mode(float_round_to_zero, &env->fp_status);
 153    res->d = floatx80_round_to_int(val->d, &env->fp_status);
 154    set_float_rounding_mode(rounding_mode, &env->fp_status);
 155}
 156
 157void HELPER(set_fpcr)(CPUM68KState *env, uint32_t val)
 158{
 159    cpu_m68k_set_fpcr(env, val);
 160}
 161
 162#define PREC_BEGIN(prec)                                        \
 163    do {                                                        \
 164        int old;                                                \
 165        old = get_floatx80_rounding_precision(&env->fp_status); \
 166        set_floatx80_rounding_precision(prec, &env->fp_status)  \
 167
 168#define PREC_END()                                              \
 169        set_floatx80_rounding_precision(old, &env->fp_status);  \
 170    } while (0)
 171
 172void HELPER(fsround)(CPUM68KState *env, FPReg *res, FPReg *val)
 173{
 174    PREC_BEGIN(32);
 175    res->d = floatx80_round(val->d, &env->fp_status);
 176    PREC_END();
 177}
 178
 179void HELPER(fdround)(CPUM68KState *env, FPReg *res, FPReg *val)
 180{
 181    PREC_BEGIN(64);
 182    res->d = floatx80_round(val->d, &env->fp_status);
 183    PREC_END();
 184}
 185
 186void HELPER(fsqrt)(CPUM68KState *env, FPReg *res, FPReg *val)
 187{
 188    res->d = floatx80_sqrt(val->d, &env->fp_status);
 189}
 190
 191void HELPER(fssqrt)(CPUM68KState *env, FPReg *res, FPReg *val)
 192{
 193    PREC_BEGIN(32);
 194    res->d = floatx80_sqrt(val->d, &env->fp_status);
 195    PREC_END();
 196}
 197
 198void HELPER(fdsqrt)(CPUM68KState *env, FPReg *res, FPReg *val)
 199{
 200    PREC_BEGIN(64);
 201    res->d = floatx80_sqrt(val->d, &env->fp_status);
 202    PREC_END();
 203}
 204
 205void HELPER(fabs)(CPUM68KState *env, FPReg *res, FPReg *val)
 206{
 207    res->d = floatx80_round(floatx80_abs(val->d), &env->fp_status);
 208}
 209
 210void HELPER(fsabs)(CPUM68KState *env, FPReg *res, FPReg *val)
 211{
 212    PREC_BEGIN(32);
 213    res->d = floatx80_round(floatx80_abs(val->d), &env->fp_status);
 214    PREC_END();
 215}
 216
 217void HELPER(fdabs)(CPUM68KState *env, FPReg *res, FPReg *val)
 218{
 219    PREC_BEGIN(64);
 220    res->d = floatx80_round(floatx80_abs(val->d), &env->fp_status);
 221    PREC_END();
 222}
 223
 224void HELPER(fneg)(CPUM68KState *env, FPReg *res, FPReg *val)
 225{
 226    res->d = floatx80_round(floatx80_chs(val->d), &env->fp_status);
 227}
 228
 229void HELPER(fsneg)(CPUM68KState *env, FPReg *res, FPReg *val)
 230{
 231    PREC_BEGIN(32);
 232    res->d = floatx80_round(floatx80_chs(val->d), &env->fp_status);
 233    PREC_END();
 234}
 235
 236void HELPER(fdneg)(CPUM68KState *env, FPReg *res, FPReg *val)
 237{
 238    PREC_BEGIN(64);
 239    res->d = floatx80_round(floatx80_chs(val->d), &env->fp_status);
 240    PREC_END();
 241}
 242
 243void HELPER(fadd)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 244{
 245    res->d = floatx80_add(val0->d, val1->d, &env->fp_status);
 246}
 247
 248void HELPER(fsadd)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 249{
 250    PREC_BEGIN(32);
 251    res->d = floatx80_add(val0->d, val1->d, &env->fp_status);
 252    PREC_END();
 253}
 254
 255void HELPER(fdadd)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 256{
 257    PREC_BEGIN(64);
 258    res->d = floatx80_add(val0->d, val1->d, &env->fp_status);
 259    PREC_END();
 260}
 261
 262void HELPER(fsub)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 263{
 264    res->d = floatx80_sub(val1->d, val0->d, &env->fp_status);
 265}
 266
 267void HELPER(fssub)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 268{
 269    PREC_BEGIN(32);
 270    res->d = floatx80_sub(val1->d, val0->d, &env->fp_status);
 271    PREC_END();
 272}
 273
 274void HELPER(fdsub)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 275{
 276    PREC_BEGIN(64);
 277    res->d = floatx80_sub(val1->d, val0->d, &env->fp_status);
 278    PREC_END();
 279}
 280
 281void HELPER(fmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 282{
 283    res->d = floatx80_mul(val0->d, val1->d, &env->fp_status);
 284}
 285
 286void HELPER(fsmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 287{
 288    PREC_BEGIN(32);
 289    res->d = floatx80_mul(val0->d, val1->d, &env->fp_status);
 290    PREC_END();
 291}
 292
 293void HELPER(fdmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 294{
 295    PREC_BEGIN(64);
 296    res->d = floatx80_mul(val0->d, val1->d, &env->fp_status);
 297    PREC_END();
 298}
 299
 300void HELPER(fsglmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 301{
 302    int rounding_mode = get_float_rounding_mode(&env->fp_status);
 303    floatx80 a, b;
 304
 305    PREC_BEGIN(32);
 306    set_float_rounding_mode(float_round_to_zero, &env->fp_status);
 307    a = floatx80_round(val0->d, &env->fp_status);
 308    b = floatx80_round(val1->d, &env->fp_status);
 309    set_float_rounding_mode(rounding_mode, &env->fp_status);
 310    res->d = floatx80_mul(a, b, &env->fp_status);
 311    PREC_END();
 312}
 313
 314void HELPER(fdiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 315{
 316    res->d = floatx80_div(val1->d, val0->d, &env->fp_status);
 317}
 318
 319void HELPER(fsdiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 320{
 321    PREC_BEGIN(32);
 322    res->d = floatx80_div(val1->d, val0->d, &env->fp_status);
 323    PREC_END();
 324}
 325
 326void HELPER(fddiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 327{
 328    PREC_BEGIN(64);
 329    res->d = floatx80_div(val1->d, val0->d, &env->fp_status);
 330    PREC_END();
 331}
 332
 333void HELPER(fsgldiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 334{
 335    int rounding_mode = get_float_rounding_mode(&env->fp_status);
 336    floatx80 a, b;
 337
 338    PREC_BEGIN(32);
 339    set_float_rounding_mode(float_round_to_zero, &env->fp_status);
 340    a = floatx80_round(val1->d, &env->fp_status);
 341    b = floatx80_round(val0->d, &env->fp_status);
 342    set_float_rounding_mode(rounding_mode, &env->fp_status);
 343    res->d = floatx80_div(a, b, &env->fp_status);
 344    PREC_END();
 345}
 346
 347static int float_comp_to_cc(int float_compare)
 348{
 349    switch (float_compare) {
 350    case float_relation_equal:
 351        return FPSR_CC_Z;
 352    case float_relation_less:
 353        return FPSR_CC_N;
 354    case float_relation_unordered:
 355        return FPSR_CC_A;
 356    case float_relation_greater:
 357        return 0;
 358    default:
 359        g_assert_not_reached();
 360    }
 361}
 362
 363void HELPER(fcmp)(CPUM68KState *env, FPReg *val0, FPReg *val1)
 364{
 365    int float_compare;
 366
 367    float_compare = floatx80_compare(val1->d, val0->d, &env->fp_status);
 368    env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | float_comp_to_cc(float_compare);
 369}
 370
 371void HELPER(ftst)(CPUM68KState *env, FPReg *val)
 372{
 373    uint32_t cc = 0;
 374
 375    if (floatx80_is_neg(val->d)) {
 376        cc |= FPSR_CC_N;
 377    }
 378
 379    if (floatx80_is_any_nan(val->d)) {
 380        cc |= FPSR_CC_A;
 381    } else if (floatx80_is_infinity(val->d)) {
 382        cc |= FPSR_CC_I;
 383    } else if (floatx80_is_zero(val->d)) {
 384        cc |= FPSR_CC_Z;
 385    }
 386    env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | cc;
 387}
 388
 389void HELPER(fconst)(CPUM68KState *env, FPReg *val, uint32_t offset)
 390{
 391    val->d = fpu_rom[offset];
 392}
 393
 394typedef int (*float_access)(CPUM68KState *env, uint32_t addr, FPReg *fp,
 395                            uintptr_t ra);
 396
 397static uint32_t fmovem_predec(CPUM68KState *env, uint32_t addr, uint32_t mask,
 398                               float_access access)
 399{
 400    uintptr_t ra = GETPC();
 401    int i, size;
 402
 403    for (i = 7; i >= 0; i--, mask <<= 1) {
 404        if (mask & 0x80) {
 405            size = access(env, addr, &env->fregs[i], ra);
 406            if ((mask & 0xff) != 0x80) {
 407                addr -= size;
 408            }
 409        }
 410    }
 411
 412    return addr;
 413}
 414
 415static uint32_t fmovem_postinc(CPUM68KState *env, uint32_t addr, uint32_t mask,
 416                               float_access access)
 417{
 418    uintptr_t ra = GETPC();
 419    int i, size;
 420
 421    for (i = 0; i < 8; i++, mask <<= 1) {
 422        if (mask & 0x80) {
 423            size = access(env, addr, &env->fregs[i], ra);
 424            addr += size;
 425        }
 426    }
 427
 428    return addr;
 429}
 430
 431static int cpu_ld_floatx80_ra(CPUM68KState *env, uint32_t addr, FPReg *fp,
 432                              uintptr_t ra)
 433{
 434    uint32_t high;
 435    uint64_t low;
 436
 437    high = cpu_ldl_data_ra(env, addr, ra);
 438    low = cpu_ldq_data_ra(env, addr + 4, ra);
 439
 440    fp->l.upper = high >> 16;
 441    fp->l.lower = low;
 442
 443    return 12;
 444}
 445
 446static int cpu_st_floatx80_ra(CPUM68KState *env, uint32_t addr, FPReg *fp,
 447                               uintptr_t ra)
 448{
 449    cpu_stl_data_ra(env, addr, fp->l.upper << 16, ra);
 450    cpu_stq_data_ra(env, addr + 4, fp->l.lower, ra);
 451
 452    return 12;
 453}
 454
 455static int cpu_ld_float64_ra(CPUM68KState *env, uint32_t addr, FPReg *fp,
 456                             uintptr_t ra)
 457{
 458    uint64_t val;
 459
 460    val = cpu_ldq_data_ra(env, addr, ra);
 461    fp->d = float64_to_floatx80(*(float64 *)&val, &env->fp_status);
 462
 463    return 8;
 464}
 465
 466static int cpu_st_float64_ra(CPUM68KState *env, uint32_t addr, FPReg *fp,
 467                             uintptr_t ra)
 468{
 469    float64 val;
 470
 471    val = floatx80_to_float64(fp->d, &env->fp_status);
 472    cpu_stq_data_ra(env, addr, *(uint64_t *)&val, ra);
 473
 474    return 8;
 475}
 476
 477uint32_t HELPER(fmovemx_st_predec)(CPUM68KState *env, uint32_t addr,
 478                                   uint32_t mask)
 479{
 480    return fmovem_predec(env, addr, mask, cpu_st_floatx80_ra);
 481}
 482
 483uint32_t HELPER(fmovemx_st_postinc)(CPUM68KState *env, uint32_t addr,
 484                                    uint32_t mask)
 485{
 486    return fmovem_postinc(env, addr, mask, cpu_st_floatx80_ra);
 487}
 488
 489uint32_t HELPER(fmovemx_ld_postinc)(CPUM68KState *env, uint32_t addr,
 490                                    uint32_t mask)
 491{
 492    return fmovem_postinc(env, addr, mask, cpu_ld_floatx80_ra);
 493}
 494
 495uint32_t HELPER(fmovemd_st_predec)(CPUM68KState *env, uint32_t addr,
 496                                   uint32_t mask)
 497{
 498    return fmovem_predec(env, addr, mask, cpu_st_float64_ra);
 499}
 500
 501uint32_t HELPER(fmovemd_st_postinc)(CPUM68KState *env, uint32_t addr,
 502                                    uint32_t mask)
 503{
 504    return fmovem_postinc(env, addr, mask, cpu_st_float64_ra);
 505}
 506
 507uint32_t HELPER(fmovemd_ld_postinc)(CPUM68KState *env, uint32_t addr,
 508                                    uint32_t mask)
 509{
 510    return fmovem_postinc(env, addr, mask, cpu_ld_float64_ra);
 511}
 512
 513static void make_quotient(CPUM68KState *env, floatx80 val)
 514{
 515    int32_t quotient;
 516    int sign;
 517
 518    if (floatx80_is_any_nan(val)) {
 519        return;
 520    }
 521
 522    quotient = floatx80_to_int32(val, &env->fp_status);
 523    sign = quotient < 0;
 524    if (sign) {
 525        quotient = -quotient;
 526    }
 527
 528    quotient = (sign << 7) | (quotient & 0x7f);
 529    env->fpsr = (env->fpsr & ~FPSR_QT_MASK) | (quotient << FPSR_QT_SHIFT);
 530}
 531
 532void HELPER(fmod)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 533{
 534    res->d = floatx80_mod(val1->d, val0->d, &env->fp_status);
 535
 536    make_quotient(env, res->d);
 537}
 538
 539void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 540{
 541    res->d = floatx80_rem(val1->d, val0->d, &env->fp_status);
 542
 543    make_quotient(env, res->d);
 544}
 545
 546void HELPER(fgetexp)(CPUM68KState *env, FPReg *res, FPReg *val)
 547{
 548    res->d = floatx80_getexp(val->d, &env->fp_status);
 549}
 550
 551void HELPER(fgetman)(CPUM68KState *env, FPReg *res, FPReg *val)
 552{
 553    res->d = floatx80_getman(val->d, &env->fp_status);
 554}
 555
 556void HELPER(fscale)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 557{
 558    res->d = floatx80_scale(val1->d, val0->d, &env->fp_status);
 559}
 560
 561void HELPER(flognp1)(CPUM68KState *env, FPReg *res, FPReg *val)
 562{
 563    res->d = floatx80_lognp1(val->d, &env->fp_status);
 564}
 565
 566void HELPER(flogn)(CPUM68KState *env, FPReg *res, FPReg *val)
 567{
 568    res->d = floatx80_logn(val->d, &env->fp_status);
 569}
 570
 571void HELPER(flog10)(CPUM68KState *env, FPReg *res, FPReg *val)
 572{
 573    res->d = floatx80_log10(val->d, &env->fp_status);
 574}
 575
 576void HELPER(flog2)(CPUM68KState *env, FPReg *res, FPReg *val)
 577{
 578    res->d = floatx80_log2(val->d, &env->fp_status);
 579}
 580
 581void HELPER(fetox)(CPUM68KState *env, FPReg *res, FPReg *val)
 582{
 583    res->d = floatx80_etox(val->d, &env->fp_status);
 584}
 585
 586void HELPER(ftwotox)(CPUM68KState *env, FPReg *res, FPReg *val)
 587{
 588    res->d = floatx80_twotox(val->d, &env->fp_status);
 589}
 590
 591void HELPER(ftentox)(CPUM68KState *env, FPReg *res, FPReg *val)
 592{
 593    res->d = floatx80_tentox(val->d, &env->fp_status);
 594}
 595
 596void HELPER(ftan)(CPUM68KState *env, FPReg *res, FPReg *val)
 597{
 598    res->d = floatx80_tan(val->d, &env->fp_status);
 599}
 600
 601void HELPER(fsin)(CPUM68KState *env, FPReg *res, FPReg *val)
 602{
 603    res->d = floatx80_sin(val->d, &env->fp_status);
 604}
 605
 606void HELPER(fcos)(CPUM68KState *env, FPReg *res, FPReg *val)
 607{
 608    res->d = floatx80_cos(val->d, &env->fp_status);
 609}
 610
 611void HELPER(fsincos)(CPUM68KState *env, FPReg *res0, FPReg *res1, FPReg *val)
 612{
 613    floatx80 a = val->d;
 614    /* If res0 and res1 specify the same floating-point data register,
 615     * the sine result is stored in the register, and the cosine
 616     * result is discarded.
 617     */
 618    res1->d = floatx80_cos(a, &env->fp_status);
 619    res0->d = floatx80_sin(a, &env->fp_status);
 620}
 621
 622void HELPER(fatan)(CPUM68KState *env, FPReg *res, FPReg *val)
 623{
 624    res->d = floatx80_atan(val->d, &env->fp_status);
 625}
 626
 627void HELPER(fasin)(CPUM68KState *env, FPReg *res, FPReg *val)
 628{
 629    res->d = floatx80_asin(val->d, &env->fp_status);
 630}
 631
 632void HELPER(facos)(CPUM68KState *env, FPReg *res, FPReg *val)
 633{
 634    res->d = floatx80_acos(val->d, &env->fp_status);
 635}
 636
 637void HELPER(fatanh)(CPUM68KState *env, FPReg *res, FPReg *val)
 638{
 639    res->d = floatx80_atanh(val->d, &env->fp_status);
 640}
 641
 642void HELPER(ftanh)(CPUM68KState *env, FPReg *res, FPReg *val)
 643{
 644    res->d = floatx80_tanh(val->d, &env->fp_status);
 645}
 646
 647void HELPER(fsinh)(CPUM68KState *env, FPReg *res, FPReg *val)
 648{
 649    res->d = floatx80_sinh(val->d, &env->fp_status);
 650}
 651
 652void HELPER(fcosh)(CPUM68KState *env, FPReg *res, FPReg *val)
 653{
 654    res->d = floatx80_cosh(val->d, &env->fp_status);
 655}
 656