diff --git a/mpy-cross/main.c b/mpy-cross/main.c index 246390383a..38190671c6 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -34,6 +34,7 @@ #include "py/persistentcode.h" #include "py/runtime.h" #include "py/gc.h" +#include "py/parsenum.h" #include "genhdr/mpversion.h" #ifdef _WIN32 #include "ports/windows/fmode.h" @@ -144,7 +145,7 @@ static int usage(char **argv) { "-march= : set architecture for native emitter;\n" " x86, x64, armv6, armv6m, armv7m, armv7em, armv7emsp,\n" " armv7emdp, xtensa, xtensawin, rv32imc, rv64imc, host, debug\n" - "-march-flags= : set architecture-specific flags\n" + "-march-flags= : set architecture-specific flags (can be either a dec/hex/bin value or a string)\n" " supported flags for rv32imc: zba\n" "\n" "Implementation specific options:\n", argv[0] @@ -226,6 +227,38 @@ static char *backslash_to_forwardslash(char *path) { return path; } +// This will need to be reworked in case mpy-cross needs to set more bits than +// what its small int representation allows to fit in there. +static bool parse_integer(const char *value, mp_uint_t *integer) { + assert(value && "Attempting to parse a NULL string"); + assert(integer && "Attempting to store into a NULL integer buffer"); + + size_t value_length = strlen(value); + int base = 10; + if (value_length > 2 && value[0] == '0') { + if ((value[1] | 0x20) == 'b') { + base = 2; + } else if ((value[1] | 0x20) == 'x') { + base = 16; + } else { + return false; + } + } + + bool valid = false; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t parsed = mp_parse_num_integer(value, value_length, base, NULL); + if (mp_obj_is_small_int(parsed)) { + *integer = MP_OBJ_SMALL_INT_VALUE(parsed); + valid = true; + } + nlr_pop(); + } + + return valid; +} + MP_NOINLINE int main_(int argc, char **argv) { pre_process_options(argc, argv); @@ -378,7 +411,13 @@ MP_NOINLINE int main_(int argc, char **argv) { #if MICROPY_EMIT_NATIVE && MICROPY_EMIT_RV32 if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_RV32IMC) { mp_dynamic_compiler.backend_options = (void *)&rv32_options; - if (strncmp(arch_flags, "zba", sizeof("zba") - 1) == 0) { + mp_uint_t raw_flags = 0; + if (parse_integer(arch_flags, &raw_flags)) { + if ((raw_flags & ~((mp_uint_t)RV32_EXT_ALL)) == 0) { + rv32_options.allowed_extensions = raw_flags; + processed = true; + } + } else if (strncmp(arch_flags, "zba", sizeof("zba") - 1) == 0) { rv32_options.allowed_extensions |= RV32_EXT_ZBA; processed = true; }