summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffi.c419
1 files changed, 187 insertions, 232 deletions
diff --git a/ffi.c b/ffi.c
index b100d30f..f115b3b5 100644
--- a/ffi.c
+++ b/ffi.c
@@ -924,322 +924,241 @@ static val ffi_val_get(struct txr_ffi_type *tft, mem_t *src, val self)
align_sw_end;
}
-static void ffi_be_i16_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
+static u16_t ffi_swap_u16(u16_t n)
{
- cnum v = c_num(n, self);
-
- (void) tft;
-
- if (v < -32768 || v > 32767)
- uw_throwf(error_s, lit("~a: value ~s is out of signed 16 bit range"),
- self, n, nao);
-
- dst[0] = (v >> 8) & 0xff;
- dst[1] = v & 0xff;
+ return (n << 8 | n >> 8);
}
-static val ffi_be_i16_get(struct txr_ffi_type *tft, mem_t *src, val self)
+static u32_t ffi_swap_u32(u32_t n)
{
- cnum n = (src[0] << 8) | src[1];
- (void) tft;
- (void) self;
- if ((n & 0x8000) != 0)
- n = -((n ^ 0xFFFF) + 1);
- return num(n);
+ n = (n & 0xFF00FF00U) >> 8 | (n & 0x00FF00FF) << 8;
+ return n << 16 | n >> 16;
}
-static void ffi_be_u16_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
+static u64_t ffi_swap_u64(u64_t n)
{
- cnum v = c_num(n, self);
-
- (void) tft;
-
- if (v < -32768 || v > 32767)
- uw_throwf(error_s, lit("~a: value ~s is out of signed 16 bit range"),
- self, n, nao);
+ n = (n & 0xFF00FF00FF00FF00U) >> 8 | (n & 0x00FF00FF00FF00FF) << 8;
+ n = (n & 0xFFFF0000FFFF0000U) >> 16 | (n & 0x0000FFFF0000FFFF) << 16;
+ return n << 32 | n >> 32;
+}
- dst[0] = (v >> 8) & 0xff;
- dst[1] = v & 0xff;
+#if HAVE_I16
+static i16_t ffi_swap_i16(i16_t n)
+{
+ return convert(i16_t, ffi_swap_u16(convert(u16_t, n)));
}
+#endif
-static val ffi_be_u16_get(struct txr_ffi_type *tft, mem_t *src, val self)
+#if HAVE_I32
+static i32_t ffi_swap_i32(i32_t n)
{
- cnum n = (src[0] << 8) | src[1];
- (void) tft;
- (void) self;
- return num(n);
+ return convert(i32_t, ffi_swap_u32(convert(u32_t, n)));
}
+#endif
-static void ffi_le_i16_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
+#if HAVE_I64
+static i64_t ffi_swap_i64(i64_t n)
{
- cnum v = c_num(n, self);
+ return convert(i64_t, ffi_swap_u64(convert(u64_t, n)));
+}
+#endif
+#if HAVE_I16
+static void ffi_swap_i16_put(struct txr_ffi_type *tft, val n,
+ mem_t *dst, val self)
+{
+ i16_t v = ffi_swap_i16(c_i16(n, self));
(void) tft;
-
- if (v < -32768 || v > 32767)
- uw_throwf(error_s, lit("~a: value ~s is out of signed 16 bit range"),
- self, n, nao);
-
- dst[1] = (v >> 8) & 0xff;
- dst[0] = v & 0xff;
+ align_sw_put(i16_t, dst, *coerce(i16_t *, dst) = v);
}
-static val ffi_le_i16_get(struct txr_ffi_type *tft, mem_t *src, val self)
+
+static val ffi_swap_i16_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- cnum n = (src[1] << 8) | src[0];
+ align_sw_get(i16_t, src);
+ i16_t n = ffi_swap_i16(*coerce(i16_t *, src));
(void) tft;
(void) self;
- if ((n & 0x8000) != 0)
- n = -((n ^ 0xFFFF) + 1);
- return num(n);
+ return num_fast(n);
+ align_sw_end;
}
-static void ffi_le_u16_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
+static void ffi_swap_u16_put(struct txr_ffi_type *tft, val n,
+ mem_t *dst, val self)
{
- cnum v = c_num(n, self);
-
+ u16_t v = ffi_swap_u16(c_u16(n, self));
(void) tft;
-
- if (v < 0|| v > 65535)
- uw_throwf(error_s, lit("~a: value ~s is out of unsigned 16 bit range"),
- self, n, nao);
-
- dst[1] = (v >> 8) & 0xff;
- dst[0] = v & 0xff;
+ align_sw_put(u16_t, dst, *coerce(u16_t *, dst) = v);
}
-static val ffi_le_u16_get(struct txr_ffi_type *tft, mem_t *src, val self)
+static val ffi_swap_u16_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- cnum n = (src[1] << 8) | src[0];
+ align_sw_get(u16_t, src);
+ u16_t n = ffi_swap_u16(*coerce(u16_t *, src));
(void) tft;
(void) self;
- return num(n);
+ return num_fast(n);
+ align_sw_end;
}
+#endif
-static void ffi_be_i32_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
+#if HAVE_I32
+static void ffi_swap_i32_put(struct txr_ffi_type *tft, val n,
+ mem_t *dst, val self)
{
- cnum v = c_num(n, self);
-
+ i32_t v = ffi_swap_i32(c_i32(n, self));
(void) tft;
-
- if (v < -convert(cnum, 0x7FFFFFFF) - 1 || v > 0x7FFFFFFF)
- uw_throwf(error_s, lit("~a: value ~s is out of signed 32 bit range"),
- self, n, nao);
-
- dst[0] = (v >> 24) & 0xff;
- dst[1] = (v >> 16) & 0xff;
- dst[2] = (v >> 8) & 0xff;
- dst[3] = v & 0xff;
+ align_sw_put(i32_t, dst, *coerce(i32_t *, dst) = v);
}
-static val ffi_be_i32_get(struct txr_ffi_type *tft, mem_t *src, val self)
+static val ffi_swap_i32_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- cnum n = (convert(cnum, src[0]) << 24 | convert(cnum, src[1]) << 16 |
- convert(cnum, src[2]) << 8 | src[3]);
+ align_sw_get(i32_t, src);
+ i32_t n = ffi_swap_i32(*coerce(i32_t *, src));
(void) tft;
(void) self;
- if ((n & 0x80000000) != 0)
- n = -((n ^ 0xFFFFFFFF) + 1);
return num(n);
+ align_sw_end;
}
-static void ffi_be_u32_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
+static void ffi_swap_u32_put(struct txr_ffi_type *tft, val n,
+ mem_t *dst, val self)
{
- ucnum v = c_unum(n, self);
-
+ u32_t v = ffi_swap_u32(c_u32(n, self));
(void) tft;
-
- if (v > 0xFFFFFFFF)
- uw_throwf(error_s, lit("~a: value ~s is out of unsigned 32 bit range"),
- self, n, nao);
-
- dst[0] = (v >> 24) & 0xff;
- dst[1] = (v >> 16) & 0xff;
- dst[2] = (v >> 8) & 0xff;
- dst[3] = v & 0xff;
+ align_sw_put(u32_t, dst, *coerce(u32_t *, dst) = v);
}
-static val ffi_be_u32_get(struct txr_ffi_type *tft, mem_t *src, val self)
+static val ffi_swap_u32_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- ucnum n = (convert(ucnum, src[0]) << 24 | convert(ucnum, src[1]) << 16 |
- convert(ucnum, src[2]) << 8 | src[3]);
+ align_sw_get(u32_t, src);
+ u32_t n = ffi_swap_u32(*coerce(u32_t *, src));
(void) tft;
(void) self;
return unum(n);
+ align_sw_end;
}
+#endif
-static void ffi_le_i32_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
-{
- cnum v = c_num(n, self);
-
- (void) tft;
-
- if (v < - convert(cnum, 0x7fffffff) - 1 || v > 0x7FFFFFFF)
- uw_throwf(error_s, lit("~a: value ~s is out of signed 32 bit range"),
- self, n, nao);
-
- dst[3] = (v >> 24) & 0xff;
- dst[2] = (v >> 16) & 0xff;
- dst[1] = (v >> 8) & 0xff;
- dst[0] = v & 0xff;
-}
-
-static val ffi_le_i32_get(struct txr_ffi_type *tft, mem_t *src, val self)
+#if HAVE_I64
+static void ffi_swap_i64_put(struct txr_ffi_type *tft, val n,
+ mem_t *dst, val self)
{
- cnum n = (convert(cnum, src[3]) << 24 | convert(cnum, src[2]) << 16 |
- convert(cnum, src[1]) << 8 | src[0]);
+ i64_t v = ffi_swap_i64(c_i64(n, self));
(void) tft;
- (void) self;
- if ((n & 0x80000000) != 0)
- n = -((n ^ 0xFFFFFFFF) + 1);
- return num(n);
+ align_sw_put(i64_t, dst, *coerce(i64_t *, dst) = v);
}
-static void ffi_le_u32_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
+static val ffi_swap_i64_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- ucnum v = c_unum(n, self);
+ align_sw_get(i64_t, src);
+ i64_t n = ffi_swap_i64(*coerce(i64_t *, src));
(void) tft;
+ (void) self;
- if (v > 0xFFFFFFFF)
- uw_throwf(error_s, lit("~a: value ~s is out of unsigned 32 bit range"),
- self, n, nao);
-
- dst[3] = (v >> 24) & 0xff;
- dst[2] = (v >> 16) & 0xff;
- dst[1] = (v >> 8) & 0xff;
- dst[0] = v & 0xff;
+ if (sizeof (i64_t) <= sizeof (cnum)) {
+ return num(n);
+ } else {
+ val high = num(n >> 32);
+ val low = unum(n & 0xFFFFFFFF);
+ return logior(ash(high, num_fast(32)), low);
+ }
+ align_sw_end;
}
-static val ffi_le_u32_get(struct txr_ffi_type *tft, mem_t *src, val self)
+static void ffi_swap_u64_put(struct txr_ffi_type *tft, val n,
+ mem_t *dst, val self)
{
- ucnum n = (convert(ucnum, src[3]) << 24 | convert(ucnum, src[2]) << 16 |
- convert(ucnum, src[1]) << 8 | src[0]);
+ u64_t v = ffi_swap_u64(c_u64(n, self));
(void) tft;
- (void) self;
- return unum(n);
+ align_sw_put(u64_t, dst, *coerce(u64_t *, dst) = v);
}
-static void ffi_be_i64_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
+static val ffi_swap_u64_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
- i64_t v = c_i64(n, self);
+ align_sw_get(u64_t, src);
+ u64_t n = ffi_swap_u64(*coerce(u64_t *, src));
(void) tft;
+ (void) self;
- dst[0] = (v >> 56) & 0xff;
- dst[1] = (v >> 48) & 0xff;
- dst[2] = (v >> 40) & 0xff;
- dst[3] = (v >> 32) & 0xff;
- dst[4] = (v >> 24) & 0xff;
- dst[5] = (v >> 16) & 0xff;
- dst[6] = (v >> 8) & 0xff;
- dst[7] = v & 0xff;
+ if (sizeof (u64_t) <= sizeof (uint_ptr_t)) {
+ return unum(n);
+ } else {
+ val high = unum(n >> 32);
+ val low = unum(n & 0xFFFFFFFF);
+ return logior(ash(high, num_fast(32)), low);
+ }
+ align_sw_end;
}
+#endif
-static val ffi_be_i64_get(struct txr_ffi_type *tft, mem_t *src, val self)
-{
- i64_t n = (convert(i64_t, src[0]) << 56 | convert(i64_t, src[1]) << 48 |
- convert(i64_t, src[2]) << 40 | convert(i64_t, src[3]) << 32 |
- convert(i64_t, src[4]) << 24 | convert(i64_t, src[5]) << 16 |
- convert(i64_t, src[6]) << 8 | src[7]);
- (void) tft;
- (void) self;
- return num_64(n);
-}
+#if HAVE_LITTLE_ENDIAN
-static void ffi_be_u64_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
-{
- u64_t v = c_u64(n, self);
+#define ffi_be_i16_put ffi_swap_i16_put
+#define ffi_be_i16_get ffi_swap_i16_get
+#define ffi_be_u16_put ffi_swap_u16_put
+#define ffi_be_u16_get ffi_swap_u16_get
- (void) tft;
+#define ffi_be_i32_put ffi_swap_i32_put
+#define ffi_be_i32_get ffi_swap_i32_get
+#define ffi_be_u32_put ffi_swap_u32_put
+#define ffi_be_u32_get ffi_swap_u32_get
- dst[0] = (v >> 56) & 0xff;
- dst[1] = (v >> 48) & 0xff;
- dst[2] = (v >> 40) & 0xff;
- dst[3] = (v >> 32) & 0xff;
- dst[4] = (v >> 24) & 0xff;
- dst[5] = (v >> 16) & 0xff;
- dst[6] = (v >> 8) & 0xff;
- dst[7] = v & 0xff;
- return;
-}
+#define ffi_be_i64_put ffi_swap_i64_put
+#define ffi_be_i64_get ffi_swap_i64_get
+#define ffi_be_u64_put ffi_swap_u64_put
+#define ffi_be_u64_get ffi_swap_u64_get
-static val ffi_be_u64_get(struct txr_ffi_type *tft, mem_t *src, val self)
-{
- u64_t n = (convert(u64_t, src[0]) << 56 | convert(u64_t, src[1]) << 48 |
- convert(u64_t, src[2]) << 40 | convert(u64_t, src[3]) << 32 |
- convert(u64_t, src[4]) << 24 | convert(u64_t, src[5]) << 16 |
- convert(u64_t, src[6]) << 8 | src[7]);
- (void) tft;
- (void) self;
- return unum_64(n);
-}
+#define ffi_le_i16_put ffi_i16_put
+#define ffi_le_i16_get ffi_i16_get
+#define ffi_le_u16_put ffi_u16_put
+#define ffi_le_u16_get ffi_u16_get
-static void ffi_le_i64_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
-{
- i64_t v = c_i64(n, self);
+#define ffi_le_i32_put ffi_i32_put
+#define ffi_le_i32_get ffi_i32_get
+#define ffi_le_u32_put ffi_u32_put
+#define ffi_le_u32_get ffi_u32_get
- (void) tft;
+#define ffi_le_i64_put ffi_i64_put
+#define ffi_le_i64_get ffi_i64_get
+#define ffi_le_u64_put ffi_u64_put
+#define ffi_le_u64_get ffi_u64_get
- dst[7] = (v >> 56) & 0xff;
- dst[6] = (v >> 48) & 0xff;
- dst[5] = (v >> 40) & 0xff;
- dst[4] = (v >> 32) & 0xff;
- dst[3] = (v >> 24) & 0xff;
- dst[2] = (v >> 16) & 0xff;
- dst[1] = (v >> 8) & 0xff;
- dst[0] = v & 0xff;
-}
+#else
-static val ffi_le_i64_get(struct txr_ffi_type *tft, mem_t *src, val self)
-{
- u64_t n = (convert(u64_t, src[7]) << 56 | convert(u64_t, src[6]) << 48 |
- convert(u64_t, src[5]) << 40 | convert(u64_t, src[4]) << 32 |
- convert(u64_t, src[3]) << 24 | convert(u64_t, src[2]) << 16 |
- convert(u64_t, src[1]) << 8 | src[0]);
- (void) tft;
- (void) self;
- return num_64(n);
-}
+#define ffi_be_i16_put ffi_i16_put
+#define ffi_be_i16_get ffi_i16_get
+#define ffi_be_u16_put ffi_u16_put
+#define ffi_be_u16_get ffi_u16_get
-static void ffi_le_u64_put(struct txr_ffi_type *tft, val n,
- mem_t *dst, val self)
-{
- u64_t v = c_u64(n, self);
+#define ffi_be_i32_put ffi_i32_put
+#define ffi_be_i32_get ffi_i32_get
+#define ffi_be_u32_put ffi_u32_put
+#define ffi_be_u32_get ffi_u32_get
- (void) tft;
+#define ffi_be_i64_put ffi_i64_put
+#define ffi_be_i64_get ffi_i64_get
+#define ffi_be_u64_put ffi_u64_put
+#define ffi_be_u64_get ffi_u64_get
- dst[7] = (v >> 56) & 0xff;
- dst[6] = (v >> 48) & 0xff;
- dst[5] = (v >> 40) & 0xff;
- dst[4] = (v >> 32) & 0xff;
- dst[3] = (v >> 24) & 0xff;
- dst[2] = (v >> 16) & 0xff;
- dst[1] = (v >> 8) & 0xff;
- dst[0] = v & 0xff;
-}
+#define ffi_le_i16_put ffi_swap_i16_put
+#define ffi_le_i16_get ffi_swap_i16_get
+#define ffi_le_u16_put ffi_swap_u16_put
+#define ffi_le_u16_get ffi_swap_u16_get
-static val ffi_le_u64_get(struct txr_ffi_type *tft, mem_t *src, val self)
-{
- u64_t n = (convert(u64_t, src[7]) << 56 | convert(u64_t, src[6]) << 48 |
- convert(u64_t, src[5]) << 40 | convert(u64_t, src[4]) << 32 |
- convert(u64_t, src[3]) << 24 | convert(u64_t, src[2]) << 16 |
- convert(u64_t, src[1]) << 8 | src[0]);
- (void) tft;
- (void) self;
- return unum_64(n);
-}
+#define ffi_le_i32_put ffi_swap_i32_put
+#define ffi_le_i32_get ffi_swap_i32_get
+#define ffi_le_u32_put ffi_swap_u32_put
+#define ffi_le_u32_get ffi_swap_u32_get
+
+#define ffi_le_i64_put ffi_swap_i64_put
+#define ffi_le_i64_get ffi_swap_i64_get
+#define ffi_le_u64_put ffi_swap_u64_put
+#define ffi_le_u64_get ffi_swap_u64_get
+
+#endif
static void ffi_be_float_put(struct txr_ffi_type *tft, val n,
mem_t *dst, val self)
@@ -1807,6 +1726,8 @@ static val ffi_wchar_rget(struct txr_ffi_type *tft, mem_t *src, val self)
return chr(c);
}
+#if HAVE_I16
+
static void ffi_be_i16_rput(struct txr_ffi_type *tft, val n, mem_t *dst,
val self)
{
@@ -1831,6 +1752,10 @@ static val ffi_be_u16_rget(struct txr_ffi_type *tft, mem_t *src, val self)
return ffi_be_u16_get(tft, src + 6, self);
}
+#endif
+
+#if HAVE_I32
+
static void ffi_be_i32_rput(struct txr_ffi_type *tft, val n, mem_t *dst,
val self)
{
@@ -1855,6 +1780,10 @@ static val ffi_be_u32_rget(struct txr_ffi_type *tft, mem_t *src, val self)
return ffi_be_u32_get(tft, src + 4, self);
}
+#endif
+
+#if HAVE_I16
+
static void ffi_le_i16_rput(struct txr_ffi_type *tft, val n, mem_t *dst,
val self)
{
@@ -1879,6 +1808,10 @@ static val ffi_le_u16_rget(struct txr_ffi_type *tft, mem_t *src, val self)
return ffi_le_u16_get(tft, src + 6, self);
}
+#endif
+
+#if HAVE_I32
+
static void ffi_le_i32_rput(struct txr_ffi_type *tft, val n, mem_t *dst,
val self)
{
@@ -1903,6 +1836,8 @@ static val ffi_le_u32_rget(struct txr_ffi_type *tft, mem_t *src, val self)
return ffi_le_u32_get(tft, src + 4, self);
}
+#endif
+
static void ffi_bool_rput(struct txr_ffi_type *tft, val truth,
mem_t *dst, val self)
{
@@ -4390,6 +4325,8 @@ static void ffi_init_types(void)
&ffi_type_pointer,
ffi_val_put, ffi_val_get,
0, 0));
+
+#if HAVE_I16
ffi_typedef(be_uint16_s, make_ffi_type_builtin(be_uint16_s, integer_s,
FFI_KIND_NUM,
sizeof (u16_t),
@@ -4408,6 +4345,9 @@ static void ffi_init_types(void)
ffi_be_i16_get,
ifbe(ffi_be_i16_rput),
ifbe(ffi_be_i16_rget)));
+#endif
+
+#if HAVE_I32
ffi_typedef(be_uint32_s, make_ffi_type_builtin(be_uint32_s, integer_s,
FFI_KIND_NUM,
sizeof (u32_t),
@@ -4426,6 +4366,9 @@ static void ffi_init_types(void)
ffi_be_i32_get,
ifbe(ffi_be_i32_rput),
ifbe(ffi_be_i32_rget)));
+#endif
+
+#if HAVE_I64
ffi_typedef(be_uint64_s, make_ffi_type_builtin(be_uint64_s, integer_s,
FFI_KIND_NUM,
sizeof (u64_t),
@@ -4440,6 +4383,8 @@ static void ffi_init_types(void)
&ffi_type_sint64,
ffi_be_i64_put,
ffi_be_i64_get, 0, 0));
+#endif
+
ffi_typedef(be_float_s, make_ffi_type_builtin(be_float_s, integer_s,
FFI_KIND_NUM,
sizeof (float),
@@ -4454,6 +4399,8 @@ static void ffi_init_types(void)
&ffi_type_double,
ffi_be_double_put,
ffi_be_double_get, 0, 0));
+
+#if HAVE_I16
ffi_typedef(le_uint16_s, make_ffi_type_builtin(le_uint16_s, integer_s,
FFI_KIND_NUM,
sizeof (u16_t),
@@ -4472,6 +4419,9 @@ static void ffi_init_types(void)
ffi_le_i16_get,
ifbe(ffi_le_i16_rput),
ifbe(ffi_le_i16_rget)));
+#endif
+
+#if HAVE_I32
ffi_typedef(le_uint32_s, make_ffi_type_builtin(le_uint32_s, integer_s,
FFI_KIND_NUM,
sizeof (u32_t),
@@ -4490,6 +4440,9 @@ static void ffi_init_types(void)
ffi_le_i32_get,
ifbe(ffi_le_i32_rput),
ifbe(ffi_le_i32_rget)));
+#endif
+
+#if HAVE_I64
ffi_typedef(le_uint64_s, make_ffi_type_builtin(le_uint64_s, integer_s,
FFI_KIND_NUM,
sizeof (u64_t),
@@ -4504,6 +4457,8 @@ static void ffi_init_types(void)
&ffi_type_sint64,
ffi_le_i64_put,
ffi_le_i64_get, 0, 0));
+#endif
+
ffi_typedef(le_float_s, make_ffi_type_builtin(le_float_s, integer_s,
FFI_KIND_NUM,
sizeof (float),