From 1f7202d122a478b0c8cedcf7cf252849b2d3d881 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 2 Sep 2019 21:35:26 +1000 Subject: [PATCH] py/bc: Replace big opcode format table with simple macro. --- py/bc.c | 106 +++------------------------------------ py/bc.h | 5 -- py/bc0.h | 8 +++ py/persistentcode.c | 8 +-- tools/mpy-tool.py | 118 ++++++-------------------------------------- 5 files changed, 32 insertions(+), 213 deletions(-) diff --git a/py/bc.c b/py/bc.c index 5625da8cf3..6887dc4380 100644 --- a/py/bc.c +++ b/py/bc.c @@ -292,106 +292,17 @@ continue2:; #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE // The following table encodes the number of bytes that a specific opcode -// takes up. There are 4 special opcodes that always have an extra byte: -// MP_BC_UNWIND_JUMP -// MP_BC_MAKE_CLOSURE -// MP_BC_MAKE_CLOSURE_DEFARGS -// MP_BC_RAISE_VARARGS +// takes up. Some opcodes have an extra byte, defined by MP_BC_MASK_EXTRA_BYTE. // There are 4 special opcodes that have an extra byte only when // MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE is enabled (and they take a qstr): // MP_BC_LOAD_NAME // MP_BC_LOAD_GLOBAL // MP_BC_LOAD_ATTR // MP_BC_STORE_ATTR -#define OC4(a, b, c, d) (a | (b << 2) | (c << 4) | (d << 6)) -#define U (0) // undefined opcode -#define B (MP_OPCODE_BYTE) // single byte -#define Q (MP_OPCODE_QSTR) // single byte plus 2-byte qstr -#define V (MP_OPCODE_VAR_UINT) // single byte plus variable encoded unsigned int -#define O (MP_OPCODE_OFFSET) // single byte plus 2-byte bytecode offset -STATIC const byte opcode_format_table[64] = { - OC4(U, U, U, U), // 0x00-0x03 - OC4(U, U, U, U), // 0x04-0x07 - OC4(U, U, U, U), // 0x08-0x0b - OC4(U, U, U, U), // 0x0c-0x0f - OC4(B, B, B, U), // 0x10-0x13 - OC4(V, U, Q, V), // 0x14-0x17 - OC4(B, V, V, Q), // 0x18-0x1b - OC4(Q, Q, Q, Q), // 0x1c-0x1f - OC4(B, B, V, V), // 0x20-0x23 - OC4(Q, Q, Q, B), // 0x24-0x27 - OC4(V, V, Q, Q), // 0x28-0x2b - OC4(U, U, U, U), // 0x2c-0x2f - OC4(B, B, B, B), // 0x30-0x33 - OC4(B, O, O, O), // 0x34-0x37 - OC4(O, O, U, U), // 0x38-0x3b - OC4(U, O, B, O), // 0x3c-0x3f - OC4(O, B, B, O), // 0x40-0x43 - OC4(O, U, O, B), // 0x44-0x47 - OC4(U, U, U, U), // 0x48-0x4b - OC4(U, U, U, U), // 0x4c-0x4f - OC4(V, V, U, V), // 0x50-0x53 - OC4(B, U, V, V), // 0x54-0x57 - OC4(V, V, V, B), // 0x58-0x5b - OC4(B, B, B, U), // 0x5c-0x5f - OC4(V, V, V, V), // 0x60-0x63 - OC4(V, V, V, V), // 0x64-0x67 - OC4(Q, Q, B, U), // 0x68-0x6b - OC4(U, U, U, U), // 0x6c-0x6f - - OC4(B, B, B, B), // 0x70-0x73 - OC4(B, B, B, B), // 0x74-0x77 - OC4(B, B, B, B), // 0x78-0x7b - OC4(B, B, B, B), // 0x7c-0x7f - OC4(B, B, B, B), // 0x80-0x83 - OC4(B, B, B, B), // 0x84-0x87 - OC4(B, B, B, B), // 0x88-0x8b - OC4(B, B, B, B), // 0x8c-0x8f - OC4(B, B, B, B), // 0x90-0x93 - OC4(B, B, B, B), // 0x94-0x97 - OC4(B, B, B, B), // 0x98-0x9b - OC4(B, B, B, B), // 0x9c-0x9f - OC4(B, B, B, B), // 0xa0-0xa3 - OC4(B, B, B, B), // 0xa4-0xa7 - OC4(B, B, B, B), // 0xa8-0xab - OC4(B, B, B, B), // 0xac-0xaf - - OC4(B, B, B, B), // 0xb0-0xb3 - OC4(B, B, B, B), // 0xb4-0xb7 - OC4(B, B, B, B), // 0xb8-0xbb - OC4(B, B, B, B), // 0xbc-0xbf - - OC4(B, B, B, B), // 0xc0-0xc3 - OC4(B, B, B, B), // 0xc4-0xc7 - OC4(B, B, B, B), // 0xc8-0xcb - OC4(B, B, B, B), // 0xcc-0xcf - - OC4(B, B, B, B), // 0xd0-0xd3 - OC4(U, U, U, B), // 0xd4-0xd7 - OC4(B, B, B, B), // 0xd8-0xdb - OC4(B, B, B, B), // 0xdc-0xdf - - OC4(B, B, B, B), // 0xe0-0xe3 - OC4(B, B, B, B), // 0xe4-0xe7 - OC4(B, B, B, B), // 0xe8-0xeb - OC4(B, B, B, B), // 0xec-0xef - - OC4(B, B, B, B), // 0xf0-0xf3 - OC4(B, B, B, B), // 0xf4-0xf7 - OC4(U, U, U, U), // 0xf8-0xfb - OC4(U, U, U, U), // 0xfc-0xff -}; -#undef OC4 -#undef U -#undef B -#undef Q -#undef V -#undef O - uint mp_opcode_format(const byte *ip, size_t *opcode_size, bool count_var_uint) { - uint f = (opcode_format_table[*ip >> 2] >> (2 * (*ip & 3))) & 3; + uint f = MP_BC_FORMAT(*ip); const byte *ip_start = ip; - if (f == MP_OPCODE_QSTR) { + if (f == MP_BC_FORMAT_QSTR) { if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) { if (*ip == MP_BC_LOAD_NAME || *ip == MP_BC_LOAD_GLOBAL @@ -402,19 +313,14 @@ uint mp_opcode_format(const byte *ip, size_t *opcode_size, bool count_var_uint) } ip += 3; } else { - int extra_byte = ( - *ip == MP_BC_UNWIND_JUMP - || *ip == MP_BC_RAISE_VARARGS - || *ip == MP_BC_MAKE_CLOSURE - || *ip == MP_BC_MAKE_CLOSURE_DEFARGS - ); + int extra_byte = (*ip & MP_BC_MASK_EXTRA_BYTE) == 0; ip += 1; - if (f == MP_OPCODE_VAR_UINT) { + if (f == MP_BC_FORMAT_VAR_UINT) { if (count_var_uint) { while ((*ip++ & 0x80) != 0) { } } - } else if (f == MP_OPCODE_OFFSET) { + } else if (f == MP_BC_FORMAT_OFFSET) { ip += 2; } ip += extra_byte; diff --git a/py/bc.h b/py/bc.h index ac9105a553..e1b39c03d8 100644 --- a/py/bc.h +++ b/py/bc.h @@ -128,11 +128,6 @@ const byte *mp_bytecode_print_str(const byte *ip); #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE -#define MP_OPCODE_BYTE (0) -#define MP_OPCODE_QSTR (1) -#define MP_OPCODE_VAR_UINT (2) -#define MP_OPCODE_OFFSET (3) - uint mp_opcode_format(const byte *ip, size_t *opcode_size, bool count_var_uint); #endif diff --git a/py/bc0.h b/py/bc0.h index 857b75db97..96f9f2136b 100644 --- a/py/bc0.h +++ b/py/bc0.h @@ -31,6 +31,14 @@ #define MP_BC_MASK_FORMAT (0xf0) #define MP_BC_MASK_EXTRA_BYTE (0x9e) +#define MP_BC_FORMAT_BYTE (0) +#define MP_BC_FORMAT_QSTR (1) +#define MP_BC_FORMAT_VAR_UINT (2) +#define MP_BC_FORMAT_OFFSET (3) + +// Nibbles in magic number are: BB BB BB BB BB BO VV QU +#define MP_BC_FORMAT(op) ((0x000003a4 >> (2 * ((op) >> 4))) & 3) + // Load, Store, Delete, Import, Make, Build, Unpack, Call, Jump, Exception, For, sTack, Return, Yield, Op #define MP_BC_BASE_RESERVED (0x00) // ---------------- #define MP_BC_BASE_QSTR_O (0x10) // LLLLLLSSSDDII--- diff --git a/py/persistentcode.c b/py/persistentcode.c index 5e970b5531..3b59746ba7 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -32,7 +32,7 @@ #include "py/reader.h" #include "py/emitglue.h" #include "py/persistentcode.h" -#include "py/bc.h" +#include "py/bc0.h" #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE @@ -307,12 +307,12 @@ STATIC void load_bytecode(mp_reader_t *reader, qstr_window_t *qw, byte *ip, byte uint f = mp_opcode_format(ip, &sz, false); ++ip; --sz; - if (f == MP_OPCODE_QSTR) { + if (f == MP_BC_FORMAT_QSTR) { qstr qst = load_qstr(reader, qw); *ip++ = qst; *ip++ = qst >> 8; sz -= 2; - } else if (f == MP_OPCODE_VAR_UINT) { + } else if (f == MP_BC_FORMAT_VAR_UINT) { while ((*ip++ = read_byte(reader)) & 0x80) { } } @@ -600,7 +600,7 @@ STATIC void save_bytecode(mp_print_t *print, qstr_window_t *qw, const byte *ip, while (ip < ip_top) { size_t sz; uint f = mp_opcode_format(ip, &sz, true); - if (f == MP_OPCODE_QSTR) { + if (f == MP_BC_FORMAT_QSTR) { mp_print_bytes(print, ip, 1); qstr qst = ip[1] | (ip[2] << 8); save_qstr(print, qw, qst); diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index d497896209..557ee98ffe 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -103,110 +103,25 @@ MP_NATIVE_ARCH_ARMV7EMSP = 7 MP_NATIVE_ARCH_ARMV7EMDP = 8 MP_NATIVE_ARCH_XTENSA = 9 -MP_OPCODE_BYTE = 0 -MP_OPCODE_QSTR = 1 -MP_OPCODE_VAR_UINT = 2 -MP_OPCODE_OFFSET = 3 +MP_BC_MASK_EXTRA_BYTE = 0x9e + +MP_BC_FORMAT_BYTE = 0 +MP_BC_FORMAT_QSTR = 1 +MP_BC_FORMAT_VAR_UINT = 2 +MP_BC_FORMAT_OFFSET = 3 -# extra bytes: -MP_BC_UNWIND_JUMP = 0x40 -MP_BC_MAKE_CLOSURE = 0x20 -MP_BC_MAKE_CLOSURE_DEFARGS = 0x21 -MP_BC_RAISE_VARARGS = 0x60 # extra byte if caching enabled: MP_BC_LOAD_NAME = 0x11 MP_BC_LOAD_GLOBAL = 0x12 MP_BC_LOAD_ATTR = 0x13 MP_BC_STORE_ATTR = 0x18 -def make_opcode_format(): - def OC4(a, b, c, d): - return a | (b << 2) | (c << 4) | (d << 6) - U = 0 - B = 0 - Q = 1 - V = 2 - O = 3 - return bytes_cons(( - # this table is taken verbatim from py/bc.c - OC4(U, U, U, U), # 0x00-0x03 - OC4(U, U, U, U), # 0x04-0x07 - OC4(U, U, U, U), # 0x08-0x0b - OC4(U, U, U, U), # 0x0c-0x0f - OC4(B, B, B, U), # 0x10-0x13 - OC4(V, U, Q, V), # 0x14-0x17 - OC4(B, V, V, Q), # 0x18-0x1b - OC4(Q, Q, Q, Q), # 0x1c-0x1f - OC4(B, B, V, V), # 0x20-0x23 - OC4(Q, Q, Q, B), # 0x24-0x27 - OC4(V, V, Q, Q), # 0x28-0x2b - OC4(U, U, U, U), # 0x2c-0x2f - OC4(B, B, B, B), # 0x30-0x33 - OC4(B, O, O, O), # 0x34-0x37 - OC4(O, O, U, U), # 0x38-0x3b - OC4(U, O, B, O), # 0x3c-0x3f - OC4(O, B, B, O), # 0x40-0x43 - OC4(O, U, O, B), # 0x44-0x47 - OC4(U, U, U, U), # 0x48-0x4b - OC4(U, U, U, U), # 0x4c-0x4f - OC4(V, V, U, V), # 0x50-0x53 - OC4(B, U, V, V), # 0x54-0x57 - OC4(V, V, V, B), # 0x58-0x5b - OC4(B, B, B, U), # 0x5c-0x5f - OC4(V, V, V, V), # 0x60-0x63 - OC4(V, V, V, V), # 0x64-0x67 - OC4(Q, Q, B, U), # 0x68-0x6b - OC4(U, U, U, U), # 0x6c-0x6f - - OC4(B, B, B, B), # 0x70-0x73 - OC4(B, B, B, B), # 0x74-0x77 - OC4(B, B, B, B), # 0x78-0x7b - OC4(B, B, B, B), # 0x7c-0x7f - OC4(B, B, B, B), # 0x80-0x83 - OC4(B, B, B, B), # 0x84-0x87 - OC4(B, B, B, B), # 0x88-0x8b - OC4(B, B, B, B), # 0x8c-0x8f - OC4(B, B, B, B), # 0x90-0x93 - OC4(B, B, B, B), # 0x94-0x97 - OC4(B, B, B, B), # 0x98-0x9b - OC4(B, B, B, B), # 0x9c-0x9f - OC4(B, B, B, B), # 0xa0-0xa3 - OC4(B, B, B, B), # 0xa4-0xa7 - OC4(B, B, B, B), # 0xa8-0xab - OC4(B, B, B, B), # 0xac-0xaf - - OC4(B, B, B, B), # 0xb0-0xb3 - OC4(B, B, B, B), # 0xb4-0xb7 - OC4(B, B, B, B), # 0xb8-0xbb - OC4(B, B, B, B), # 0xbc-0xbf - - OC4(B, B, B, B), # 0xc0-0xc3 - OC4(B, B, B, B), # 0xc4-0xc7 - OC4(B, B, B, B), # 0xc8-0xcb - OC4(B, B, B, B), # 0xcc-0xcf - - OC4(B, B, B, B), # 0xd0-0xd3 - OC4(U, U, U, B), # 0xd4-0xd7 - OC4(B, B, B, B), # 0xd8-0xdb - OC4(B, B, B, B), # 0xdc-0xdf - - OC4(B, B, B, B), # 0xe0-0xe3 - OC4(B, B, B, B), # 0xe4-0xe7 - OC4(B, B, B, B), # 0xe8-0xeb - OC4(B, B, B, B), # 0xec-0xef - - OC4(B, B, B, B), # 0xf0-0xf3 - OC4(B, B, B, B), # 0xf4-0xf7 - OC4(U, U, U, U), # 0xf8-0xfb - OC4(U, U, U, U), # 0xfc-0xff - )) - # this function mirrors that in py/bc.c -def mp_opcode_format(bytecode, ip, count_var_uint, opcode_format=make_opcode_format()): +def mp_opcode_format(bytecode, ip, count_var_uint): opcode = bytecode[ip] ip_start = ip - f = (opcode_format[opcode >> 2] >> (2 * (opcode & 3))) & 3 - if f == MP_OPCODE_QSTR: + f = ((0x000003a4 >> (2 * ((opcode) >> 4))) & 3) + if f == MP_BC_FORMAT_QSTR: if config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE: if (opcode == MP_BC_LOAD_NAME or opcode == MP_BC_LOAD_GLOBAL @@ -215,19 +130,14 @@ def mp_opcode_format(bytecode, ip, count_var_uint, opcode_format=make_opcode_for ip += 1 ip += 3 else: - extra_byte = ( - opcode == MP_BC_UNWIND_JUMP - or opcode == MP_BC_RAISE_VARARGS - or opcode == MP_BC_MAKE_CLOSURE - or opcode == MP_BC_MAKE_CLOSURE_DEFARGS - ) + extra_byte = (opcode & MP_BC_MASK_EXTRA_BYTE) == 0 ip += 1 - if f == MP_OPCODE_VAR_UINT: + if f == MP_BC_FORMAT_VAR_UINT: if count_var_uint: while bytecode[ip] & 0x80 != 0: ip += 1 ip += 1 - elif f == MP_OPCODE_OFFSET: + elif f == MP_BC_FORMAT_OFFSET: ip += 2 ip += extra_byte return f, ip - ip_start @@ -672,10 +582,10 @@ def read_bytecode(file, bytecode, qstr_win): op = read_byte(file, bytecode) f, sz = mp_opcode_format(bytecode.buf, bytecode.idx - 1, False) sz -= 1 - if f == MP_OPCODE_QSTR: + if f == MP_BC_FORMAT_QSTR: read_qstr_and_pack(file, bytecode, qstr_win) sz -= 2 - elif f == MP_OPCODE_VAR_UINT: + elif f == MP_BC_FORMAT_VAR_UINT: while read_byte(file, bytecode) & 0x80: pass for _ in range(sz):