-/* The "twos-complement" c4x format is officially defined as
-
- x = s(~s).f * 2**e
-
- This is rather misleading. One must remember that F is signed.
- A better description would be
-
- x = -1**s * ((s + 1 + .f) * 2**e
-
- So if we have a (4 bit) fraction of .1000 with a sign bit of 1,
- that's -1 * (1+1+(-.5)) == -1.5. I think.
-
- The constructions here are taken from Tables 5-1 and 5-2 of the
- TMS320C4x User's Guide wherein step-by-step instructions for
- conversion from IEEE are presented. That's close enough to our
- internal representation so as to make things easy.
-
- See http://www-s.ti.com/sc/psheets/spru063c/spru063c.pdf */
-
-static void encode_c4x_single (const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *);
-static void decode_c4x_single (const struct real_format *,
- REAL_VALUE_TYPE *, const long *);
-static void encode_c4x_extended (const struct real_format *fmt,
- long *, const REAL_VALUE_TYPE *);
-static void decode_c4x_extended (const struct real_format *,
- REAL_VALUE_TYPE *, const long *);
-
-static void
-encode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
- long *buf, const REAL_VALUE_TYPE *r)
-{
- unsigned long image, exp, sig;
-
- switch (r->cl)
- {
- case rvc_zero:
- exp = -128;
- sig = 0;
- break;
-
- case rvc_inf:
- case rvc_nan:
- exp = 127;
- sig = 0x800000 - r->sign;
- break;
-
- case rvc_normal:
- exp = REAL_EXP (r) - 1;
- sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
- if (r->sign)
- {
- if (sig)
- sig = -sig;
- else
- exp--;
- sig |= 0x800000;
- }
- break;
-
- default:
- gcc_unreachable ();
- }
-
- image = ((exp & 0xff) << 24) | (sig & 0xffffff);
- buf[0] = image;
-}
-
-static void
-decode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
- REAL_VALUE_TYPE *r, const long *buf)
-{
- unsigned long image = buf[0];
- unsigned long sig;
- int exp, sf;
-
- exp = (((image >> 24) & 0xff) ^ 0x80) - 0x80;
- sf = ((image & 0xffffff) ^ 0x800000) - 0x800000;
-
- memset (r, 0, sizeof (*r));
-
- if (exp != -128)
- {
- r->cl = rvc_normal;
-
- sig = sf & 0x7fffff;
- if (sf < 0)
- {
- r->sign = 1;
- if (sig)
- sig = -sig;
- else
- exp++;
- }
- sig = (sig << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
-
- SET_REAL_EXP (r, exp + 1);
- r->sig[SIGSZ-1] = sig;
- }
-}
-
-static void
-encode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED,
- long *buf, const REAL_VALUE_TYPE *r)
-{
- unsigned long exp, sig;
-
- switch (r->cl)
- {
- case rvc_zero:
- exp = -128;
- sig = 0;
- break;
-
- case rvc_inf:
- case rvc_nan:
- exp = 127;
- sig = 0x80000000 - r->sign;
- break;
-
- case rvc_normal:
- exp = REAL_EXP (r) - 1;
-
- sig = r->sig[SIGSZ-1];
- if (HOST_BITS_PER_LONG == 64)
- sig = sig >> 1 >> 31;
- sig &= 0x7fffffff;
-
- if (r->sign)
- {
- if (sig)
- sig = -sig;
- else
- exp--;
- sig |= 0x80000000;
- }
- break;
-
- default:
- gcc_unreachable ();
- }
-
- exp = (exp & 0xff) << 24;
- sig &= 0xffffffff;
-
- if (FLOAT_WORDS_BIG_ENDIAN)
- buf[0] = exp, buf[1] = sig;
- else
- buf[0] = sig, buf[0] = exp;
-}
-
-static void
-decode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED,
- REAL_VALUE_TYPE *r, const long *buf)
-{
- unsigned long sig;
- int exp, sf;
-
- if (FLOAT_WORDS_BIG_ENDIAN)
- exp = buf[0], sf = buf[1];
- else
- sf = buf[0], exp = buf[1];
-
- exp = (((exp >> 24) & 0xff) & 0x80) - 0x80;
- sf = ((sf & 0xffffffff) ^ 0x80000000) - 0x80000000;
-
- memset (r, 0, sizeof (*r));
-
- if (exp != -128)
- {
- r->cl = rvc_normal;
-
- sig = sf & 0x7fffffff;
- if (sf < 0)
- {
- r->sign = 1;
- if (sig)
- sig = -sig;
- else
- exp++;
- }
- if (HOST_BITS_PER_LONG == 64)
- sig = sig << 1 << 31;
- sig |= SIG_MSB;
-
- SET_REAL_EXP (r, exp + 1);
- r->sig[SIGSZ-1] = sig;
- }
-}
-
-const struct real_format c4x_single_format =
- {
- encode_c4x_single,
- decode_c4x_single,
- 2,
- 24,
- 24,
- -126,
- 128,
- 23,
- -1,
- false,
- false,
- false,
- false,
- false,
- false
- };
-
-const struct real_format c4x_extended_format =
- {
- encode_c4x_extended,
- decode_c4x_extended,
- 2,
- 32,
- 32,
- -126,
- 128,
- 31,
- -1,
- false,
- false,
- false,
- false,
- false,
- false
- };
-
-\f