From 183edefddd8c08dd989fa7bec2d33d8b4130e1dc Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 17 Oct 2015 23:20:57 +0100 Subject: [PATCH] py: Add object repr "C", where 30-bit floats are stuffed in obj word. This new object representation puts floats into the object word instead of on the heap, at the expense of reducing their precision to 30 bits. It only makes sense when the word size is 32-bits. --- py/mpconfig.h | 10 ++++++++++ py/obj.h | 35 +++++++++++++++++++++++++++++++++++ py/objfloat.c | 8 ++++++++ py/smallint.h | 2 +- 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/py/mpconfig.h b/py/mpconfig.h index 7ab179304c..98e9406c6b 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -63,6 +63,16 @@ // - xxxx...xxx0 : a pointer to an mp_obj_base_t (unless a fake object) #define MICROPY_OBJ_REPR_B (1) +// A MicroPython object is a machine word having the following form: +// - iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int with 31-bit signed value +// - x1111111 1qqqqqqq qqqqqqqq qqqqq110 str with 20-bit qstr value +// - s1111111 10000000 00000000 00000010 +/- inf +// - s1111111 1xxxxxxx xxxxxxxx xxxxx010 nan, x != 0 +// - seeeeeee efffffff ffffffff ffffff10 30-bit fp, e != 0xff +// - pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment) +// This scheme only works with 32-bit word size and float enabled. +#define MICROPY_OBJ_REPR_C (2) + #ifndef MICROPY_OBJ_REPR #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) #endif diff --git a/py/obj.h b/py/obj.h index faf7e096af..af5652c4ec 100644 --- a/py/obj.h +++ b/py/obj.h @@ -123,6 +123,41 @@ mp_obj_t mp_obj_new_float(mp_float_t value); static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 1) == 0); } +#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C + +static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o) + { return ((((mp_int_t)(o)) & 1) != 0); } +#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1) +#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_int_t)(small_int)) << 1) | 1)) + +#define mp_const_float_e ((mp_obj_t)((0x402df854 & ~3) | 2)) +#define mp_const_float_pi ((mp_obj_t)((0x40490fdb & ~3) | 2)) + +static inline bool mp_obj_is_float(mp_const_obj_t o) + { return (((mp_uint_t)(o)) & 3) == 2 && (((mp_uint_t)(o)) & 0x7f800004) != 0x7f800004; } +static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { + union { + mp_float_t f; + mp_uint_t u; + } num = {.u = (mp_uint_t)o & ~3}; + return num.f; +} +static inline mp_obj_t mp_obj_new_float(mp_float_t f) { + union { + mp_float_t f; + mp_uint_t u; + } num = {.f = f}; + return (mp_obj_t)((num.u & ~0x3) | 2); +} + +static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o) + { return (((mp_uint_t)(o)) & 0x7f800007) == 0x7f800006; } +#define MP_OBJ_QSTR_VALUE(o) ((((mp_uint_t)(o)) >> 3) & 0xfffff) +#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 3) | 0x7f800006)) + +static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o) + { return ((((mp_int_t)(o)) & 3) == 0); } + #endif // Macros to convert between mp_obj_t and concrete object types. diff --git a/py/objfloat.c b/py/objfloat.c index 7c58f320db..81eac99bd1 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -39,6 +39,8 @@ #include #include "py/formatfloat.h" +#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C + typedef struct _mp_obj_float_t { mp_obj_base_t base; mp_float_t value; @@ -47,6 +49,8 @@ typedef struct _mp_obj_float_t { const mp_obj_float_t mp_const_float_e_obj = {{&mp_type_float}, M_E}; const mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, M_PI}; +#endif + STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_float_t o_val = mp_obj_float_get(o_in); @@ -121,6 +125,8 @@ const mp_obj_type_t mp_type_float = { .binary_op = float_binary_op, }; +#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C + mp_obj_t mp_obj_new_float(mp_float_t value) { mp_obj_float_t *o = m_new(mp_obj_float_t, 1); o->base.type = &mp_type_float; @@ -134,6 +140,8 @@ mp_float_t mp_obj_float_get(mp_obj_t self_in) { return self->value; } +#endif + STATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) { // logic here follows that of CPython // https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations diff --git a/py/smallint.h b/py/smallint.h index 19b5209ec7..d9e53ee361 100644 --- a/py/smallint.h +++ b/py/smallint.h @@ -32,7 +32,7 @@ // Functions for small integer arithmetic // In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range -#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A +#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C #define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)WORD_MSBIT_HIGH) >> 1)) #define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0)