From 8fe261d344eb7607ffbe05713bd808cd1d766e46 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 25 Jan 2019 07:06:05 -0800 Subject: itypes: take advantage of double_intptr_t. If double_intptr_t is at least 64 bits wide (which is always going to be true) we can take advantage of it. * itypes.c (c_i64, c_u64): Provide implementations that use the new dbl_intptr_t and dbl_uintptr_t infrastructure. The fallback implementation that uses ash and logior is basically not used now. (num_64, unum_64): New functions for obtaining a Lisp value from a 64 bit number, abstracting whether this is done via the cnum or dbl_cnum route. * itypes.h (u64_t, i64_t): Define in terms of double_uintptr_t and double_intptr_t, if no other 64 bit type is available. (num_64, unum_64): Declared. --- itypes.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- itypes.h | 7 +++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/itypes.c b/itypes.c index 5c1e3e69..d9aa7aaa 100644 --- a/itypes.c +++ b/itypes.c @@ -98,7 +98,8 @@ u32_t c_u32(val n, val self) #endif #if HAVE_I64 -#if CHAR_BIT * SIZEOF_PTR == 64 + +#if CHAR_BIT * SIZEOF_PTR >= 64 i64_t c_i64(val n, val self) { cnum v = c_num(n); @@ -116,6 +117,24 @@ u64_t c_u64(val n, val self) self, n, nao); return v; } +#elif HAVE_DOUBLE_INTPTR_T && CHAR_BIT * SIZEOF_DOUBLE_INTPTR >= 64 +i64_t c_i64(val n, val self) +{ + dbl_cnum v = c_dbl_num(n); + if (v < (- (dbl_cnum) 0x7FFFFFFFFFFFFFFF - 1) || v > (dbl_cnum) 0x7FFFFFFFFFFFFFFF) + uw_throwf(error_s, lit("~a: value ~s is out of signed 64 bit range"), + self, n, nao); + return v; +} + +u64_t c_u64(val n, val self) +{ + dbl_ucnum v = c_dbl_unum(n); + if (v > (dbl_ucnum) 0xFFFFFFFFFFFFFFFF) + uw_throwf(error_s, lit("~a: value ~s is out of unsigned 64 bit range"), + self, n, nao); + return v; +} #else i64_t c_i64(val n, val self) { @@ -131,6 +150,33 @@ u64_t c_u64(val n, val self) return convert(u64_t, c_u32(high32, self)) << 32 | c_u32(low32, self); } #endif + +val num_64(i64_t n) +{ +#if CHAR_BIT * SIZEOF_PTR >= 64 + return num(n); +#elif HAVE_DOUBLE_INTPTR_T && CHAR_BIT * SIZEOF_DOUBLE_INTPTR >= 64 + return normalize(bignum_dbl_ipt(n)); +#else + cnum hi32 = n >> 32; + ucnum lo32 = n & 0xFFFFFFFFU; + return logior(ash(num(hi32), num_fast(32)), unum(lo32)); +#endif +} + +val unum_64(u64_t n) +{ +#if CHAR_BIT * SIZEOF_PTR >= 64 + return unum(n); +#elif HAVE_DOUBLE_INTPTR_T && CHAR_BIT * SIZEOF_DOUBLE_INTPTR >= 64 + return normalize(bignum_dbl_uipt(n)); +#else + ucnum hi32 = n >> 32; + ucnum lo32 = n & 0xFFFFFFFFU; + return logior(ash(unum(hi32), num_fast(32)), unum(lo32)); +#endif +} + #endif char c_char(val n, val self) diff --git a/itypes.h b/itypes.h index 23fd5581..a2e38672 100644 --- a/itypes.h +++ b/itypes.h @@ -75,6 +75,10 @@ typedef long i64_t; #define HAVE_I64 1 typedef ulonglong_t u64_t; typedef longlong_t i64_t; +#elif HAVE_DBL_INTPTR_T && (SIZEOF_DOUBLE_INTPTR * CHAR_BIT) == 64 +#define HAVE_I64 1 +typedef double_uintptr_t u64_t; +typedef double_intptr_t i64_t; #endif #if HAVE_I8 @@ -95,6 +99,9 @@ u32_t c_u32(val, val self); #if HAVE_I64 i64_t c_i64(val, val self); u64_t c_u64(val, val self); + +val num_64(i64_t n); +val unum_64(u64_t n); #endif char c_char(val, val self); -- cgit v1.2.3