py: Add support for 64-bit NaN-boxing object model, on 32-bit machine.
To use, put the following in mpconfigport.h: #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) typedef int64_t mp_int_t; typedef uint64_t mp_uint_t; #define UINT_FMT "%llu" #define INT_FMT "%lld" Currently does not work with native emitter enabled.
This commit is contained in:
parent
999cedb90f
commit
b8cfb0d7b2
@ -2439,7 +2439,12 @@ STATIC void compile_bytes(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||||
|
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||||
|
// nodes are 32-bit pointers, but need to extract 64-bit object
|
||||||
|
EMIT_ARG(load_const_obj, (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
|
||||||
|
#else
|
||||||
EMIT_ARG(load_const_obj, (mp_obj_t)pns->nodes[0]);
|
EMIT_ARG(load_const_obj, (mp_obj_t)pns->nodes[0]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
|
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
|
||||||
|
@ -76,6 +76,19 @@
|
|||||||
|
|
||||||
#define MICROPY_OBJ_REPR_C (2)
|
#define MICROPY_OBJ_REPR_C (2)
|
||||||
|
|
||||||
|
// A MicroPython object is a 64-bit word having the following form (called R):
|
||||||
|
// - seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 64-bit fp, e != 0x7ff
|
||||||
|
// - s1111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000 +/- inf
|
||||||
|
// - 01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 normalised nan
|
||||||
|
// - 01111111 11111101 00000000 00000000 iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int
|
||||||
|
// - 01111111 11111110 00000000 00000000 qqqqqqqq qqqqqqqq qqqqqqqq qqqqqqq1 str
|
||||||
|
// - 01111111 11111100 00000000 00000000 pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment)
|
||||||
|
// Stored as O = R + 0x8004000000000000, retrieved as R = O - 0x8004000000000000.
|
||||||
|
// This makes pointers have all zeros in the top 32 bits.
|
||||||
|
// Small-ints and strs have 1 as LSB to make sure they don't look like pointers
|
||||||
|
// to the garbage collector.
|
||||||
|
#define MICROPY_OBJ_REPR_D (3)
|
||||||
|
|
||||||
#ifndef MICROPY_OBJ_REPR
|
#ifndef MICROPY_OBJ_REPR
|
||||||
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A)
|
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A)
|
||||||
#endif
|
#endif
|
||||||
|
57
py/obj.h
57
py/obj.h
@ -32,10 +32,15 @@
|
|||||||
#include "py/mpprint.h"
|
#include "py/mpprint.h"
|
||||||
|
|
||||||
// All Micro Python objects are at least this type
|
// All Micro Python objects are at least this type
|
||||||
// It must be of pointer size
|
// The bit-size must be at least pointer size
|
||||||
|
|
||||||
|
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||||
|
typedef uint64_t mp_obj_t;
|
||||||
|
typedef uint64_t mp_const_obj_t;
|
||||||
|
#else
|
||||||
typedef machine_ptr_t mp_obj_t;
|
typedef machine_ptr_t mp_obj_t;
|
||||||
typedef machine_const_ptr_t mp_const_obj_t;
|
typedef machine_const_ptr_t mp_const_obj_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Anything that wants to be a Micro Python object must have
|
// Anything that wants to be a Micro Python object must have
|
||||||
// mp_obj_base_t as its first member (except small ints and qstrs)
|
// mp_obj_base_t as its first member (except small ints and qstrs)
|
||||||
@ -158,6 +163,56 @@ static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o)
|
|||||||
static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)
|
static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)
|
||||||
{ return ((((mp_int_t)(o)) & 3) == 0); }
|
{ return ((((mp_int_t)(o)) & 3) == 0); }
|
||||||
|
|
||||||
|
#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||||
|
|
||||||
|
static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o)
|
||||||
|
{ return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0001000000000000); }
|
||||||
|
#define MP_OBJ_SMALL_INT_VALUE(o) (((intptr_t)(o)) >> 1)
|
||||||
|
#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)(((uintptr_t)(small_int)) << 1) | 0x0001000000000001)
|
||||||
|
|
||||||
|
static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o)
|
||||||
|
{ return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0002000000000000); }
|
||||||
|
#define MP_OBJ_QSTR_VALUE(o) ((((mp_uint_t)(o)) >> 1) & 0xffffffff)
|
||||||
|
#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 1) | 0x0002000000000001))
|
||||||
|
|
||||||
|
#if MICROPY_PY_BUILTINS_FLOAT
|
||||||
|
#define mp_const_float_e {((mp_obj_t)((uint64_t)0x4005bf0a8b125769 + 0x8004000000000000))}
|
||||||
|
#define mp_const_float_pi {((mp_obj_t)((uint64_t)0x400921fb54442d18 + 0x8004000000000000))}
|
||||||
|
|
||||||
|
static inline bool mp_obj_is_float(mp_const_obj_t o) {
|
||||||
|
return ((uint64_t)(o) & 0xfffc000000000000) != 0;
|
||||||
|
}
|
||||||
|
static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) {
|
||||||
|
union {
|
||||||
|
mp_float_t f;
|
||||||
|
uint64_t r;
|
||||||
|
} num = {.r = o - 0x8004000000000000};
|
||||||
|
return num.f;
|
||||||
|
}
|
||||||
|
static inline mp_obj_t mp_obj_new_float(mp_float_t f) {
|
||||||
|
union {
|
||||||
|
mp_float_t f;
|
||||||
|
uint64_t r;
|
||||||
|
} num = {.f = f};
|
||||||
|
return num.r + 0x8004000000000000;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)
|
||||||
|
{ return ((((uint64_t)(o)) & 0xffff000000000000) == 0x0000000000000000); }
|
||||||
|
#define MP_OBJ_TO_PTR(o) ((void*)(uintptr_t)(o))
|
||||||
|
#define MP_OBJ_FROM_PTR(p) ((mp_obj_t)((uintptr_t)(p)))
|
||||||
|
|
||||||
|
// rom object storage needs special handling to widen 32-bit pointer to 64-bits
|
||||||
|
typedef union _mp_rom_obj_t { uint64_t u64; struct { const void *lo, *hi; } u32; } mp_rom_obj_t;
|
||||||
|
#define MP_ROM_INT(i) {MP_OBJ_NEW_SMALL_INT(i)}
|
||||||
|
#define MP_ROM_QSTR(q) {MP_OBJ_NEW_QSTR(q)}
|
||||||
|
#if MP_ENDIANNESS_LITTLE
|
||||||
|
#define MP_ROM_PTR(p) {.u32 = {.lo = (p), .hi = NULL}}
|
||||||
|
#else
|
||||||
|
#define MP_ROM_PTR(p) {.u32 = {.lo = NULL, .hi = (p)}}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Macros to convert between mp_obj_t and concrete object types.
|
// Macros to convert between mp_obj_t and concrete object types.
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "py/formatfloat.h"
|
#include "py/formatfloat.h"
|
||||||
|
|
||||||
#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C
|
#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D
|
||||||
|
|
||||||
typedef struct _mp_obj_float_t {
|
typedef struct _mp_obj_float_t {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
@ -125,7 +125,7 @@ const mp_obj_type_t mp_type_float = {
|
|||||||
.binary_op = float_binary_op,
|
.binary_op = float_binary_op,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C
|
#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D
|
||||||
|
|
||||||
mp_obj_t mp_obj_new_float(mp_float_t value) {
|
mp_obj_t mp_obj_new_float(mp_float_t value) {
|
||||||
mp_obj_float_t *o = m_new(mp_obj_float_t, 1);
|
mp_obj_float_t *o = m_new(mp_obj_float_t, 1);
|
||||||
|
11
py/parse.c
11
py/parse.c
@ -283,7 +283,11 @@ void mp_parse_node_print(mp_parse_node_t pn, mp_uint_t indent) {
|
|||||||
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_bytes) {
|
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_bytes) {
|
||||||
printf("literal bytes(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
|
printf("literal bytes(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
|
||||||
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
|
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
|
||||||
|
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||||
|
printf("literal const(%016llx)\n", (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
|
||||||
|
#else
|
||||||
printf("literal const(%p)\n", (mp_obj_t)pns->nodes[0]);
|
printf("literal const(%p)\n", (mp_obj_t)pns->nodes[0]);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
mp_uint_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
mp_uint_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||||
#ifdef USE_RULE_NAME
|
#ifdef USE_RULE_NAME
|
||||||
@ -362,8 +366,15 @@ STATIC mp_parse_node_t make_node_const_object(parser_t *parser, mp_uint_t src_li
|
|||||||
return MP_PARSE_NODE_NULL;
|
return MP_PARSE_NODE_NULL;
|
||||||
}
|
}
|
||||||
pn->source_line = src_line;
|
pn->source_line = src_line;
|
||||||
|
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||||
|
// nodes are 32-bit pointers, but need to store 64-bit object
|
||||||
|
pn->kind_num_nodes = RULE_const_object | (2 << 8);
|
||||||
|
pn->nodes[0] = (uint64_t)obj;
|
||||||
|
pn->nodes[1] = (uint64_t)obj >> 32;
|
||||||
|
#else
|
||||||
pn->kind_num_nodes = RULE_const_object | (1 << 8);
|
pn->kind_num_nodes = RULE_const_object | (1 << 8);
|
||||||
pn->nodes[0] = (mp_uint_t)obj;
|
pn->nodes[0] = (mp_uint_t)obj;
|
||||||
|
#endif
|
||||||
return (mp_parse_node_t)pn;
|
return (mp_parse_node_t)pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,13 @@
|
|||||||
// Mask to truncate mp_int_t to positive value
|
// Mask to truncate mp_int_t to positive value
|
||||||
#define MP_SMALL_INT_POSITIVE_MASK ~(WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1) | (WORD_MSBIT_HIGH >> 2))
|
#define MP_SMALL_INT_POSITIVE_MASK ~(WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1) | (WORD_MSBIT_HIGH >> 2))
|
||||||
|
|
||||||
|
#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||||
|
|
||||||
|
#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)0xffffffff80000000) >> 1))
|
||||||
|
#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & 0xffffffff80000000) == 0)
|
||||||
|
// Mask to truncate mp_int_t to positive value
|
||||||
|
#define MP_SMALL_INT_POSITIVE_MASK ~(0xffffffff80000000 | (0xffffffff80000000 >> 1))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MP_SMALL_INT_MAX ((mp_int_t)(~(MP_SMALL_INT_MIN)))
|
#define MP_SMALL_INT_MAX ((mp_int_t)(~(MP_SMALL_INT_MIN)))
|
||||||
|
Loading…
Reference in New Issue
Block a user