162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/arch/arm/vfp/vfp.h 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2004 ARM Limited. 662306a36Sopenharmony_ci * Written by Deep Blue Solutions Limited. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_cistatic inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) 1062306a36Sopenharmony_ci{ 1162306a36Sopenharmony_ci if (shift) { 1262306a36Sopenharmony_ci if (shift < 32) 1362306a36Sopenharmony_ci val = val >> shift | ((val << (32 - shift)) != 0); 1462306a36Sopenharmony_ci else 1562306a36Sopenharmony_ci val = val != 0; 1662306a36Sopenharmony_ci } 1762306a36Sopenharmony_ci return val; 1862306a36Sopenharmony_ci} 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci if (shift) { 2362306a36Sopenharmony_ci if (shift < 64) 2462306a36Sopenharmony_ci val = val >> shift | ((val << (64 - shift)) != 0); 2562306a36Sopenharmony_ci else 2662306a36Sopenharmony_ci val = val != 0; 2762306a36Sopenharmony_ci } 2862306a36Sopenharmony_ci return val; 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic inline u32 vfp_hi64to32jamming(u64 val) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci u32 v; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci asm( 3662306a36Sopenharmony_ci "cmp %Q1, #1 @ vfp_hi64to32jamming\n\t" 3762306a36Sopenharmony_ci "movcc %0, %R1\n\t" 3862306a36Sopenharmony_ci "orrcs %0, %R1, #1" 3962306a36Sopenharmony_ci : "=r" (v) : "r" (val) : "cc"); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci return v; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic inline void add128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci asm( "adds %Q0, %Q2, %Q4\n\t" 4762306a36Sopenharmony_ci "adcs %R0, %R2, %R4\n\t" 4862306a36Sopenharmony_ci "adcs %Q1, %Q3, %Q5\n\t" 4962306a36Sopenharmony_ci "adc %R1, %R3, %R5" 5062306a36Sopenharmony_ci : "=r" (nl), "=r" (nh) 5162306a36Sopenharmony_ci : "0" (nl), "1" (nh), "r" (ml), "r" (mh) 5262306a36Sopenharmony_ci : "cc"); 5362306a36Sopenharmony_ci *resh = nh; 5462306a36Sopenharmony_ci *resl = nl; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic inline void sub128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci asm( "subs %Q0, %Q2, %Q4\n\t" 6062306a36Sopenharmony_ci "sbcs %R0, %R2, %R4\n\t" 6162306a36Sopenharmony_ci "sbcs %Q1, %Q3, %Q5\n\t" 6262306a36Sopenharmony_ci "sbc %R1, %R3, %R5\n\t" 6362306a36Sopenharmony_ci : "=r" (nl), "=r" (nh) 6462306a36Sopenharmony_ci : "0" (nl), "1" (nh), "r" (ml), "r" (mh) 6562306a36Sopenharmony_ci : "cc"); 6662306a36Sopenharmony_ci *resh = nh; 6762306a36Sopenharmony_ci *resl = nl; 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic inline void mul64to128(u64 *resh, u64 *resl, u64 n, u64 m) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci u32 nh, nl, mh, ml; 7362306a36Sopenharmony_ci u64 rh, rma, rmb, rl; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci nl = n; 7662306a36Sopenharmony_ci ml = m; 7762306a36Sopenharmony_ci rl = (u64)nl * ml; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci nh = n >> 32; 8062306a36Sopenharmony_ci rma = (u64)nh * ml; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci mh = m >> 32; 8362306a36Sopenharmony_ci rmb = (u64)nl * mh; 8462306a36Sopenharmony_ci rma += rmb; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci rh = (u64)nh * mh; 8762306a36Sopenharmony_ci rh += ((u64)(rma < rmb) << 32) + (rma >> 32); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci rma <<= 32; 9062306a36Sopenharmony_ci rl += rma; 9162306a36Sopenharmony_ci rh += (rl < rma); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci *resl = rl; 9462306a36Sopenharmony_ci *resh = rh; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic inline void shift64left(u64 *resh, u64 *resl, u64 n) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci *resh = n >> 63; 10062306a36Sopenharmony_ci *resl = n << 1; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic inline u64 vfp_hi64multiply64(u64 n, u64 m) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci u64 rh, rl; 10662306a36Sopenharmony_ci mul64to128(&rh, &rl, n, m); 10762306a36Sopenharmony_ci return rh | (rl != 0); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci u64 mh, ml, remh, reml, termh, terml, z; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci if (nh >= m) 11562306a36Sopenharmony_ci return ~0ULL; 11662306a36Sopenharmony_ci mh = m >> 32; 11762306a36Sopenharmony_ci if (mh << 32 <= nh) { 11862306a36Sopenharmony_ci z = 0xffffffff00000000ULL; 11962306a36Sopenharmony_ci } else { 12062306a36Sopenharmony_ci z = nh; 12162306a36Sopenharmony_ci do_div(z, mh); 12262306a36Sopenharmony_ci z <<= 32; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci mul64to128(&termh, &terml, m, z); 12562306a36Sopenharmony_ci sub128(&remh, &reml, nh, nl, termh, terml); 12662306a36Sopenharmony_ci ml = m << 32; 12762306a36Sopenharmony_ci while ((s64)remh < 0) { 12862306a36Sopenharmony_ci z -= 0x100000000ULL; 12962306a36Sopenharmony_ci add128(&remh, &reml, remh, reml, mh, ml); 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci remh = (remh << 32) | (reml >> 32); 13262306a36Sopenharmony_ci if (mh << 32 <= remh) { 13362306a36Sopenharmony_ci z |= 0xffffffff; 13462306a36Sopenharmony_ci } else { 13562306a36Sopenharmony_ci do_div(remh, mh); 13662306a36Sopenharmony_ci z |= remh; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci return z; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* 14262306a36Sopenharmony_ci * Operations on unpacked elements 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ci#define vfp_sign_negate(sign) (sign ^ 0x8000) 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/* 14762306a36Sopenharmony_ci * Single-precision 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_cistruct vfp_single { 15062306a36Sopenharmony_ci s16 exponent; 15162306a36Sopenharmony_ci u16 sign; 15262306a36Sopenharmony_ci u32 significand; 15362306a36Sopenharmony_ci}; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ciasmlinkage s32 vfp_get_float(unsigned int reg); 15662306a36Sopenharmony_ciasmlinkage void vfp_put_float(s32 val, unsigned int reg); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* 15962306a36Sopenharmony_ci * VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa 16062306a36Sopenharmony_ci * VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent 16162306a36Sopenharmony_ci * VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand 16262306a36Sopenharmony_ci * which are not propagated to the float upon packing. 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_ci#define VFP_SINGLE_MANTISSA_BITS (23) 16562306a36Sopenharmony_ci#define VFP_SINGLE_EXPONENT_BITS (8) 16662306a36Sopenharmony_ci#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2) 16762306a36Sopenharmony_ci#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1) 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci/* 17062306a36Sopenharmony_ci * The bit in an unpacked float which indicates that it is a quiet NaN 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_ci#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS)) 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/* 17562306a36Sopenharmony_ci * Operations on packed single-precision numbers 17662306a36Sopenharmony_ci */ 17762306a36Sopenharmony_ci#define vfp_single_packed_sign(v) ((v) & 0x80000000) 17862306a36Sopenharmony_ci#define vfp_single_packed_negate(v) ((v) ^ 0x80000000) 17962306a36Sopenharmony_ci#define vfp_single_packed_abs(v) ((v) & ~0x80000000) 18062306a36Sopenharmony_ci#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1)) 18162306a36Sopenharmony_ci#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1)) 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci/* 18462306a36Sopenharmony_ci * Unpack a single-precision float. Note that this returns the magnitude 18562306a36Sopenharmony_ci * of the single-precision float mantissa with the 1. if necessary, 18662306a36Sopenharmony_ci * aligned to bit 30. 18762306a36Sopenharmony_ci */ 18862306a36Sopenharmony_cistatic inline void vfp_single_unpack(struct vfp_single *s, s32 val) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci u32 significand; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci s->sign = vfp_single_packed_sign(val) >> 16, 19362306a36Sopenharmony_ci s->exponent = vfp_single_packed_exponent(val); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci significand = (u32) val; 19662306a36Sopenharmony_ci significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2; 19762306a36Sopenharmony_ci if (s->exponent && s->exponent != 255) 19862306a36Sopenharmony_ci significand |= 0x40000000; 19962306a36Sopenharmony_ci s->significand = significand; 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/* 20362306a36Sopenharmony_ci * Re-pack a single-precision float. This assumes that the float is 20462306a36Sopenharmony_ci * already normalised such that the MSB is bit 30, _not_ bit 31. 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_cistatic inline s32 vfp_single_pack(struct vfp_single *s) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci u32 val; 20962306a36Sopenharmony_ci val = (s->sign << 16) + 21062306a36Sopenharmony_ci (s->exponent << VFP_SINGLE_MANTISSA_BITS) + 21162306a36Sopenharmony_ci (s->significand >> VFP_SINGLE_LOW_BITS); 21262306a36Sopenharmony_ci return (s32)val; 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci#define VFP_NUMBER (1<<0) 21662306a36Sopenharmony_ci#define VFP_ZERO (1<<1) 21762306a36Sopenharmony_ci#define VFP_DENORMAL (1<<2) 21862306a36Sopenharmony_ci#define VFP_INFINITY (1<<3) 21962306a36Sopenharmony_ci#define VFP_NAN (1<<4) 22062306a36Sopenharmony_ci#define VFP_NAN_SIGNAL (1<<5) 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci#define VFP_QNAN (VFP_NAN) 22362306a36Sopenharmony_ci#define VFP_SNAN (VFP_NAN|VFP_NAN_SIGNAL) 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic inline int vfp_single_type(struct vfp_single *s) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci int type = VFP_NUMBER; 22862306a36Sopenharmony_ci if (s->exponent == 255) { 22962306a36Sopenharmony_ci if (s->significand == 0) 23062306a36Sopenharmony_ci type = VFP_INFINITY; 23162306a36Sopenharmony_ci else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN) 23262306a36Sopenharmony_ci type = VFP_QNAN; 23362306a36Sopenharmony_ci else 23462306a36Sopenharmony_ci type = VFP_SNAN; 23562306a36Sopenharmony_ci } else if (s->exponent == 0) { 23662306a36Sopenharmony_ci if (s->significand == 0) 23762306a36Sopenharmony_ci type |= VFP_ZERO; 23862306a36Sopenharmony_ci else 23962306a36Sopenharmony_ci type |= VFP_DENORMAL; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci return type; 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci#ifndef DEBUG 24562306a36Sopenharmony_ci#define vfp_single_normaliseround(sd,vsd,fpscr,except,func) __vfp_single_normaliseround(sd,vsd,fpscr,except) 24662306a36Sopenharmony_ciu32 __vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions); 24762306a36Sopenharmony_ci#else 24862306a36Sopenharmony_ciu32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func); 24962306a36Sopenharmony_ci#endif 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci/* 25262306a36Sopenharmony_ci * Double-precision 25362306a36Sopenharmony_ci */ 25462306a36Sopenharmony_cistruct vfp_double { 25562306a36Sopenharmony_ci s16 exponent; 25662306a36Sopenharmony_ci u16 sign; 25762306a36Sopenharmony_ci u64 significand; 25862306a36Sopenharmony_ci}; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci/* 26162306a36Sopenharmony_ci * VFP_REG_ZERO is a special register number for vfp_get_double 26262306a36Sopenharmony_ci * which returns (double)0.0. This is useful for the compare with 26362306a36Sopenharmony_ci * zero instructions. 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_ci#ifdef CONFIG_VFPv3 26662306a36Sopenharmony_ci#define VFP_REG_ZERO 32 26762306a36Sopenharmony_ci#else 26862306a36Sopenharmony_ci#define VFP_REG_ZERO 16 26962306a36Sopenharmony_ci#endif 27062306a36Sopenharmony_ciasmlinkage u64 vfp_get_double(unsigned int reg); 27162306a36Sopenharmony_ciasmlinkage void vfp_put_double(u64 val, unsigned int reg); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci#define VFP_DOUBLE_MANTISSA_BITS (52) 27462306a36Sopenharmony_ci#define VFP_DOUBLE_EXPONENT_BITS (11) 27562306a36Sopenharmony_ci#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2) 27662306a36Sopenharmony_ci#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1) 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci/* 27962306a36Sopenharmony_ci * The bit in an unpacked double which indicates that it is a quiet NaN 28062306a36Sopenharmony_ci */ 28162306a36Sopenharmony_ci#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS)) 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci/* 28462306a36Sopenharmony_ci * Operations on packed single-precision numbers 28562306a36Sopenharmony_ci */ 28662306a36Sopenharmony_ci#define vfp_double_packed_sign(v) ((v) & (1ULL << 63)) 28762306a36Sopenharmony_ci#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63)) 28862306a36Sopenharmony_ci#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63)) 28962306a36Sopenharmony_ci#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1)) 29062306a36Sopenharmony_ci#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1)) 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci/* 29362306a36Sopenharmony_ci * Unpack a double-precision float. Note that this returns the magnitude 29462306a36Sopenharmony_ci * of the double-precision float mantissa with the 1. if necessary, 29562306a36Sopenharmony_ci * aligned to bit 62. 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_cistatic inline void vfp_double_unpack(struct vfp_double *s, s64 val) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci u64 significand; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci s->sign = vfp_double_packed_sign(val) >> 48; 30262306a36Sopenharmony_ci s->exponent = vfp_double_packed_exponent(val); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci significand = (u64) val; 30562306a36Sopenharmony_ci significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2; 30662306a36Sopenharmony_ci if (s->exponent && s->exponent != 2047) 30762306a36Sopenharmony_ci significand |= (1ULL << 62); 30862306a36Sopenharmony_ci s->significand = significand; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/* 31262306a36Sopenharmony_ci * Re-pack a double-precision float. This assumes that the float is 31362306a36Sopenharmony_ci * already normalised such that the MSB is bit 30, _not_ bit 31. 31462306a36Sopenharmony_ci */ 31562306a36Sopenharmony_cistatic inline s64 vfp_double_pack(struct vfp_double *s) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci u64 val; 31862306a36Sopenharmony_ci val = ((u64)s->sign << 48) + 31962306a36Sopenharmony_ci ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) + 32062306a36Sopenharmony_ci (s->significand >> VFP_DOUBLE_LOW_BITS); 32162306a36Sopenharmony_ci return (s64)val; 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic inline int vfp_double_type(struct vfp_double *s) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci int type = VFP_NUMBER; 32762306a36Sopenharmony_ci if (s->exponent == 2047) { 32862306a36Sopenharmony_ci if (s->significand == 0) 32962306a36Sopenharmony_ci type = VFP_INFINITY; 33062306a36Sopenharmony_ci else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN) 33162306a36Sopenharmony_ci type = VFP_QNAN; 33262306a36Sopenharmony_ci else 33362306a36Sopenharmony_ci type = VFP_SNAN; 33462306a36Sopenharmony_ci } else if (s->exponent == 0) { 33562306a36Sopenharmony_ci if (s->significand == 0) 33662306a36Sopenharmony_ci type |= VFP_ZERO; 33762306a36Sopenharmony_ci else 33862306a36Sopenharmony_ci type |= VFP_DENORMAL; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci return type; 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ciu32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ciu32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci/* 34862306a36Sopenharmony_ci * A special flag to tell the normalisation code not to normalise. 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_ci#define VFP_NAN_FLAG 0x100 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci/* 35362306a36Sopenharmony_ci * A bit pattern used to indicate the initial (unset) value of the 35462306a36Sopenharmony_ci * exception mask, in case nothing handles an instruction. This 35562306a36Sopenharmony_ci * doesn't include the NAN flag, which get masked out before 35662306a36Sopenharmony_ci * we check for an error. 35762306a36Sopenharmony_ci */ 35862306a36Sopenharmony_ci#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG) 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci/* 36162306a36Sopenharmony_ci * A flag to tell vfp instruction type. 36262306a36Sopenharmony_ci * OP_SCALAR - this operation always operates in scalar mode 36362306a36Sopenharmony_ci * OP_SD - the instruction exceptionally writes to a single precision result. 36462306a36Sopenharmony_ci * OP_DD - the instruction exceptionally writes to a double precision result. 36562306a36Sopenharmony_ci * OP_SM - the instruction exceptionally reads from a single precision operand. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_ci#define OP_SCALAR (1 << 0) 36862306a36Sopenharmony_ci#define OP_SD (1 << 1) 36962306a36Sopenharmony_ci#define OP_DD (1 << 1) 37062306a36Sopenharmony_ci#define OP_SM (1 << 2) 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistruct op { 37362306a36Sopenharmony_ci u32 (* const fn)(int dd, int dn, int dm, u32 fpscr); 37462306a36Sopenharmony_ci u32 flags; 37562306a36Sopenharmony_ci}; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ciasmlinkage void vfp_save_state(void *location, u32 fpexc); 37862306a36Sopenharmony_ciasmlinkage u32 vfp_load_state(const void *location); 379