Port of MicroPython to the mbed platform. See micropython-repl for an interactive program.

Dependents:   micropython-repl

This a port of MicroPython to the mbed Classic platform.

This provides an interpreter running on the board's USB serial connection.

Getting Started

Import the micropython-repl program into your IDE workspace on developer.mbed.org. Compile and download to your board. Connect to the USB serial port in your usual manner. You should get a startup message similar to the following:

  MicroPython v1.7-155-gdddcdd8 on 2016-04-23; K64F with ARM
  Type "help()" for more information.
  >>>

Then you can start using micropython. For example:

  >>> from mbed import DigitalOut
  >>> from pins import LED1
  >>> led = DigitalOut(LED1)
  >>> led.write(1)

Requirements

You need approximately 100K of flash memory, so this will be no good for boards with smaller amounts of storage.

Caveats

This can be considered an alpha release of the port; things may not work; APIs may change in later releases. It is NOT an official part part the micropython project, so if anything doesn't work, blame me. If it does work, most of the credit is due to micropython.

  • Only a few of the mbed classes are available in micropython so far, and not all methods of those that are.
  • Only a few boards have their full range of pin names available; for others, only a few standard ones (USBTX, USBRX, LED1) are implemented.
  • The garbage collector is not yet implemented. The interpreter will gradually consume memory and then fail.
  • Exceptions from the mbed classes are not yet handled.
  • Asynchronous processing (e.g. events on inputs) is not supported.

Credits

  • Damien P. George and other contributors who created micropython.
  • Colin Hogben, author of this port.
Committer:
Colin Hogben
Date:
Wed Apr 27 22:11:29 2016 +0100
Revision:
10:33521d742af1
Parent:
0:5868e8752d44
Update README and version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pythontech 0:5868e8752d44 1 /*
pythontech 0:5868e8752d44 2 * This file is part of the Micro Python project, http://micropython.org/
pythontech 0:5868e8752d44 3 *
pythontech 0:5868e8752d44 4 * The MIT License (MIT)
pythontech 0:5868e8752d44 5 *
pythontech 0:5868e8752d44 6 * Copyright (c) 2013, 2014 Damien P. George
pythontech 0:5868e8752d44 7 *
pythontech 0:5868e8752d44 8 * Permission is hereby granted, free of charge, to any person obtaining a copy
pythontech 0:5868e8752d44 9 * of this software and associated documentation files (the "Software"), to deal
pythontech 0:5868e8752d44 10 * in the Software without restriction, including without limitation the rights
pythontech 0:5868e8752d44 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
pythontech 0:5868e8752d44 12 * copies of the Software, and to permit persons to whom the Software is
pythontech 0:5868e8752d44 13 * furnished to do so, subject to the following conditions:
pythontech 0:5868e8752d44 14 *
pythontech 0:5868e8752d44 15 * The above copyright notice and this permission notice shall be included in
pythontech 0:5868e8752d44 16 * all copies or substantial portions of the Software.
pythontech 0:5868e8752d44 17 *
pythontech 0:5868e8752d44 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
pythontech 0:5868e8752d44 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
pythontech 0:5868e8752d44 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
pythontech 0:5868e8752d44 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
pythontech 0:5868e8752d44 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
pythontech 0:5868e8752d44 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
pythontech 0:5868e8752d44 24 * THE SOFTWARE.
pythontech 0:5868e8752d44 25 */
pythontech 0:5868e8752d44 26
pythontech 0:5868e8752d44 27 #include <stdint.h>
pythontech 0:5868e8752d44 28 #include <stdio.h>
pythontech 0:5868e8752d44 29 #include <string.h>
pythontech 0:5868e8752d44 30 #include <stdarg.h>
pythontech 0:5868e8752d44 31 #include <assert.h>
pythontech 0:5868e8752d44 32
pythontech 0:5868e8752d44 33 #include "py/emit.h"
pythontech 0:5868e8752d44 34 #include "py/asmthumb.h"
pythontech 0:5868e8752d44 35
pythontech 0:5868e8752d44 36 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 37
pythontech 0:5868e8752d44 38 typedef enum {
pythontech 0:5868e8752d44 39 #define DEF_RULE(rule, comp, kind, ...) PN_##rule,
pythontech 0:5868e8752d44 40 #include "py/grammar.h"
pythontech 0:5868e8752d44 41 #undef DEF_RULE
pythontech 0:5868e8752d44 42 PN_maximum_number_of,
pythontech 0:5868e8752d44 43 } pn_kind_t;
pythontech 0:5868e8752d44 44
pythontech 0:5868e8752d44 45 struct _emit_inline_asm_t {
pythontech 0:5868e8752d44 46 uint16_t pass;
pythontech 0:5868e8752d44 47 scope_t *scope;
pythontech 0:5868e8752d44 48 mp_obj_t *error_slot;
pythontech 0:5868e8752d44 49 mp_uint_t max_num_labels;
pythontech 0:5868e8752d44 50 qstr *label_lookup;
pythontech 0:5868e8752d44 51 asm_thumb_t *as;
pythontech 0:5868e8752d44 52 };
pythontech 0:5868e8752d44 53
pythontech 0:5868e8752d44 54 STATIC void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, const char *msg) {
pythontech 0:5868e8752d44 55 *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
pythontech 0:5868e8752d44 56 }
pythontech 0:5868e8752d44 57
pythontech 0:5868e8752d44 58 STATIC void emit_inline_thumb_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) {
pythontech 0:5868e8752d44 59 *emit->error_slot = exc;
pythontech 0:5868e8752d44 60 }
pythontech 0:5868e8752d44 61
pythontech 0:5868e8752d44 62 emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels) {
pythontech 0:5868e8752d44 63 emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);
pythontech 0:5868e8752d44 64 emit->max_num_labels = max_num_labels;
pythontech 0:5868e8752d44 65 emit->label_lookup = m_new(qstr, max_num_labels);
pythontech 0:5868e8752d44 66 emit->as = asm_thumb_new(max_num_labels);
pythontech 0:5868e8752d44 67 return emit;
pythontech 0:5868e8752d44 68 }
pythontech 0:5868e8752d44 69
pythontech 0:5868e8752d44 70 void emit_inline_thumb_free(emit_inline_asm_t *emit) {
pythontech 0:5868e8752d44 71 m_del(qstr, emit->label_lookup, emit->max_num_labels);
pythontech 0:5868e8752d44 72 asm_thumb_free(emit->as, false);
pythontech 0:5868e8752d44 73 m_del_obj(emit_inline_asm_t, emit);
pythontech 0:5868e8752d44 74 }
pythontech 0:5868e8752d44 75
pythontech 0:5868e8752d44 76 STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope, mp_obj_t *error_slot) {
pythontech 0:5868e8752d44 77 emit->pass = pass;
pythontech 0:5868e8752d44 78 emit->scope = scope;
pythontech 0:5868e8752d44 79 emit->error_slot = error_slot;
pythontech 0:5868e8752d44 80 if (emit->pass == MP_PASS_CODE_SIZE) {
pythontech 0:5868e8752d44 81 memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));
pythontech 0:5868e8752d44 82 }
pythontech 0:5868e8752d44 83 asm_thumb_start_pass(emit->as, pass == MP_PASS_EMIT ? ASM_THUMB_PASS_EMIT : ASM_THUMB_PASS_COMPUTE);
pythontech 0:5868e8752d44 84 asm_thumb_entry(emit->as, 0);
pythontech 0:5868e8752d44 85 }
pythontech 0:5868e8752d44 86
pythontech 0:5868e8752d44 87 STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {
pythontech 0:5868e8752d44 88 asm_thumb_exit(emit->as);
pythontech 0:5868e8752d44 89 asm_thumb_end_pass(emit->as);
pythontech 0:5868e8752d44 90
pythontech 0:5868e8752d44 91 if (emit->pass == MP_PASS_EMIT) {
pythontech 0:5868e8752d44 92 void *f = asm_thumb_get_code(emit->as);
pythontech 0:5868e8752d44 93 mp_emit_glue_assign_native(emit->scope->raw_code, MP_CODE_NATIVE_ASM, f,
pythontech 0:5868e8752d44 94 asm_thumb_get_code_size(emit->as), NULL, emit->scope->num_pos_args, 0, type_sig);
pythontech 0:5868e8752d44 95 }
pythontech 0:5868e8752d44 96 }
pythontech 0:5868e8752d44 97
pythontech 0:5868e8752d44 98 STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) {
pythontech 0:5868e8752d44 99 if (n_params > 4) {
pythontech 0:5868e8752d44 100 emit_inline_thumb_error_msg(emit, "can only have up to 4 parameters to Thumb assembly");
pythontech 0:5868e8752d44 101 return 0;
pythontech 0:5868e8752d44 102 }
pythontech 0:5868e8752d44 103 for (mp_uint_t i = 0; i < n_params; i++) {
pythontech 0:5868e8752d44 104 if (!MP_PARSE_NODE_IS_ID(pn_params[i])) {
pythontech 0:5868e8752d44 105 emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3");
pythontech 0:5868e8752d44 106 return 0;
pythontech 0:5868e8752d44 107 }
pythontech 0:5868e8752d44 108 const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i]));
pythontech 0:5868e8752d44 109 if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) {
pythontech 0:5868e8752d44 110 emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3");
pythontech 0:5868e8752d44 111 return 0;
pythontech 0:5868e8752d44 112 }
pythontech 0:5868e8752d44 113 }
pythontech 0:5868e8752d44 114 return n_params;
pythontech 0:5868e8752d44 115 }
pythontech 0:5868e8752d44 116
pythontech 0:5868e8752d44 117 STATIC bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) {
pythontech 0:5868e8752d44 118 assert(label_num < emit->max_num_labels);
pythontech 0:5868e8752d44 119 if (emit->pass == MP_PASS_CODE_SIZE) {
pythontech 0:5868e8752d44 120 // check for duplicate label on first pass
pythontech 0:5868e8752d44 121 for (uint i = 0; i < emit->max_num_labels; i++) {
pythontech 0:5868e8752d44 122 if (emit->label_lookup[i] == label_id) {
pythontech 0:5868e8752d44 123 return false;
pythontech 0:5868e8752d44 124 }
pythontech 0:5868e8752d44 125 }
pythontech 0:5868e8752d44 126 }
pythontech 0:5868e8752d44 127 emit->label_lookup[label_num] = label_id;
pythontech 0:5868e8752d44 128 asm_thumb_label_assign(emit->as, label_num);
pythontech 0:5868e8752d44 129 return true;
pythontech 0:5868e8752d44 130 }
pythontech 0:5868e8752d44 131
pythontech 0:5868e8752d44 132 STATIC void emit_inline_thumb_align(emit_inline_asm_t *emit, mp_uint_t align) {
pythontech 0:5868e8752d44 133 asm_thumb_align(emit->as, align);
pythontech 0:5868e8752d44 134 }
pythontech 0:5868e8752d44 135
pythontech 0:5868e8752d44 136 STATIC void emit_inline_thumb_data(emit_inline_asm_t *emit, mp_uint_t bytesize, mp_uint_t val) {
pythontech 0:5868e8752d44 137 asm_thumb_data(emit->as, bytesize, val);
pythontech 0:5868e8752d44 138 }
pythontech 0:5868e8752d44 139
pythontech 0:5868e8752d44 140 typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t;
pythontech 0:5868e8752d44 141 STATIC const reg_name_t reg_name_table[] = {
pythontech 0:5868e8752d44 142 {0, "r0\0"},
pythontech 0:5868e8752d44 143 {1, "r1\0"},
pythontech 0:5868e8752d44 144 {2, "r2\0"},
pythontech 0:5868e8752d44 145 {3, "r3\0"},
pythontech 0:5868e8752d44 146 {4, "r4\0"},
pythontech 0:5868e8752d44 147 {5, "r5\0"},
pythontech 0:5868e8752d44 148 {6, "r6\0"},
pythontech 0:5868e8752d44 149 {7, "r7\0"},
pythontech 0:5868e8752d44 150 {8, "r8\0"},
pythontech 0:5868e8752d44 151 {9, "r9\0"},
pythontech 0:5868e8752d44 152 {10, "r10"},
pythontech 0:5868e8752d44 153 {11, "r11"},
pythontech 0:5868e8752d44 154 {12, "r12"},
pythontech 0:5868e8752d44 155 {13, "r13"},
pythontech 0:5868e8752d44 156 {14, "r14"},
pythontech 0:5868e8752d44 157 {15, "r15"},
pythontech 0:5868e8752d44 158 {10, "sl\0"},
pythontech 0:5868e8752d44 159 {11, "fp\0"},
pythontech 0:5868e8752d44 160 {13, "sp\0"},
pythontech 0:5868e8752d44 161 {14, "lr\0"},
pythontech 0:5868e8752d44 162 {15, "pc\0"},
pythontech 0:5868e8752d44 163 };
pythontech 0:5868e8752d44 164
pythontech 0:5868e8752d44 165 #define MAX_SPECIAL_REGISTER_NAME_LENGTH 7
pythontech 0:5868e8752d44 166 typedef struct _special_reg_name_t { byte reg; char name[MAX_SPECIAL_REGISTER_NAME_LENGTH + 1]; } special_reg_name_t;
pythontech 0:5868e8752d44 167 STATIC const special_reg_name_t special_reg_name_table[] = {
pythontech 0:5868e8752d44 168 {5, "IPSR"},
pythontech 0:5868e8752d44 169 {17, "BASEPRI"},
pythontech 0:5868e8752d44 170 };
pythontech 0:5868e8752d44 171
pythontech 0:5868e8752d44 172 // return empty string in case of error, so we can attempt to parse the string
pythontech 0:5868e8752d44 173 // without a special check if it was in fact a string
pythontech 0:5868e8752d44 174 STATIC const char *get_arg_str(mp_parse_node_t pn) {
pythontech 0:5868e8752d44 175 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 176 qstr qst = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 177 return qstr_str(qst);
pythontech 0:5868e8752d44 178 } else {
pythontech 0:5868e8752d44 179 return "";
pythontech 0:5868e8752d44 180 }
pythontech 0:5868e8752d44 181 }
pythontech 0:5868e8752d44 182
pythontech 0:5868e8752d44 183 STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_uint_t max_reg) {
pythontech 0:5868e8752d44 184 const char *reg_str = get_arg_str(pn);
pythontech 0:5868e8752d44 185 for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) {
pythontech 0:5868e8752d44 186 const reg_name_t *r = &reg_name_table[i];
pythontech 0:5868e8752d44 187 if (reg_str[0] == r->name[0]
pythontech 0:5868e8752d44 188 && reg_str[1] == r->name[1]
pythontech 0:5868e8752d44 189 && reg_str[2] == r->name[2]
pythontech 0:5868e8752d44 190 && (reg_str[2] == '\0' || reg_str[3] == '\0')) {
pythontech 0:5868e8752d44 191 if (r->reg > max_reg) {
pythontech 0:5868e8752d44 192 emit_inline_thumb_error_exc(emit,
pythontech 0:5868e8752d44 193 mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,
pythontech 0:5868e8752d44 194 "'%s' expects at most r%d", op, max_reg));
pythontech 0:5868e8752d44 195 return 0;
pythontech 0:5868e8752d44 196 } else {
pythontech 0:5868e8752d44 197 return r->reg;
pythontech 0:5868e8752d44 198 }
pythontech 0:5868e8752d44 199 }
pythontech 0:5868e8752d44 200 }
pythontech 0:5868e8752d44 201 emit_inline_thumb_error_exc(emit,
pythontech 0:5868e8752d44 202 mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,
pythontech 0:5868e8752d44 203 "'%s' expects a register", op));
pythontech 0:5868e8752d44 204 return 0;
pythontech 0:5868e8752d44 205 }
pythontech 0:5868e8752d44 206
pythontech 0:5868e8752d44 207 STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 208 const char *reg_str = get_arg_str(pn);
pythontech 0:5868e8752d44 209 for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(special_reg_name_table); i++) {
pythontech 0:5868e8752d44 210 const special_reg_name_t *r = &special_reg_name_table[i];
pythontech 0:5868e8752d44 211 if (strcmp(r->name, reg_str) == 0) {
pythontech 0:5868e8752d44 212 return r->reg;
pythontech 0:5868e8752d44 213 }
pythontech 0:5868e8752d44 214 }
pythontech 0:5868e8752d44 215 emit_inline_thumb_error_exc(emit,
pythontech 0:5868e8752d44 216 mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,
pythontech 0:5868e8752d44 217 "'%s' expects a special register", op));
pythontech 0:5868e8752d44 218 return 0;
pythontech 0:5868e8752d44 219 }
pythontech 0:5868e8752d44 220
pythontech 0:5868e8752d44 221 #if MICROPY_EMIT_INLINE_THUMB_FLOAT
pythontech 0:5868e8752d44 222 STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 223 const char *reg_str = get_arg_str(pn);
pythontech 0:5868e8752d44 224 if (reg_str[0] == 's' && reg_str[1] != '\0') {
pythontech 0:5868e8752d44 225 mp_uint_t regno = 0;
pythontech 0:5868e8752d44 226 for (++reg_str; *reg_str; ++reg_str) {
pythontech 0:5868e8752d44 227 mp_uint_t v = *reg_str;
pythontech 0:5868e8752d44 228 if (!('0' <= v && v <= '9')) {
pythontech 0:5868e8752d44 229 goto malformed;
pythontech 0:5868e8752d44 230 }
pythontech 0:5868e8752d44 231 regno = 10 * regno + v - '0';
pythontech 0:5868e8752d44 232 }
pythontech 0:5868e8752d44 233 if (regno > 31) {
pythontech 0:5868e8752d44 234 emit_inline_thumb_error_exc(emit,
pythontech 0:5868e8752d44 235 mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,
pythontech 0:5868e8752d44 236 "'%s' expects at most r%d", op, 31));
pythontech 0:5868e8752d44 237 return 0;
pythontech 0:5868e8752d44 238 } else {
pythontech 0:5868e8752d44 239 return regno;
pythontech 0:5868e8752d44 240 }
pythontech 0:5868e8752d44 241 }
pythontech 0:5868e8752d44 242 malformed:
pythontech 0:5868e8752d44 243 emit_inline_thumb_error_exc(emit,
pythontech 0:5868e8752d44 244 mp_obj_new_exception_msg_varg(&mp_type_SyntaxError,
pythontech 0:5868e8752d44 245 "'%s' expects an FPU register", op));
pythontech 0:5868e8752d44 246 return 0;
pythontech 0:5868e8752d44 247 }
pythontech 0:5868e8752d44 248 #endif
pythontech 0:5868e8752d44 249
pythontech 0:5868e8752d44 250 STATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 251 // a register list looks like {r0, r1, r2} and is parsed as a Python set
pythontech 0:5868e8752d44 252
pythontech 0:5868e8752d44 253 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_brace)) {
pythontech 0:5868e8752d44 254 goto bad_arg;
pythontech 0:5868e8752d44 255 }
pythontech 0:5868e8752d44 256
pythontech 0:5868e8752d44 257 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 258 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 1); // should always be
pythontech 0:5868e8752d44 259 pn = pns->nodes[0];
pythontech 0:5868e8752d44 260
pythontech 0:5868e8752d44 261 mp_uint_t reglist = 0;
pythontech 0:5868e8752d44 262
pythontech 0:5868e8752d44 263 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 264 // set with one element
pythontech 0:5868e8752d44 265 reglist |= 1 << get_arg_reg(emit, op, pn, 15);
pythontech 0:5868e8752d44 266 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
pythontech 0:5868e8752d44 267 pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 268 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
pythontech 0:5868e8752d44 269 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
pythontech 0:5868e8752d44 270 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 271 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
pythontech 0:5868e8752d44 272 // set with multiple elements
pythontech 0:5868e8752d44 273
pythontech 0:5868e8752d44 274 // get first element of set (we rely on get_arg_reg to catch syntax errors)
pythontech 0:5868e8752d44 275 reglist |= 1 << get_arg_reg(emit, op, pns->nodes[0], 15);
pythontech 0:5868e8752d44 276
pythontech 0:5868e8752d44 277 // get tail elements (2nd, 3rd, ...)
pythontech 0:5868e8752d44 278 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 279 int n = mp_parse_node_extract_list(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
pythontech 0:5868e8752d44 280
pythontech 0:5868e8752d44 281 // process rest of elements
pythontech 0:5868e8752d44 282 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 283 reglist |= 1 << get_arg_reg(emit, op, nodes[i], 15);
pythontech 0:5868e8752d44 284 }
pythontech 0:5868e8752d44 285 } else {
pythontech 0:5868e8752d44 286 goto bad_arg;
pythontech 0:5868e8752d44 287 }
pythontech 0:5868e8752d44 288 } else {
pythontech 0:5868e8752d44 289 goto bad_arg;
pythontech 0:5868e8752d44 290 }
pythontech 0:5868e8752d44 291 } else {
pythontech 0:5868e8752d44 292 goto bad_arg;
pythontech 0:5868e8752d44 293 }
pythontech 0:5868e8752d44 294
pythontech 0:5868e8752d44 295 return reglist;
pythontech 0:5868e8752d44 296
pythontech 0:5868e8752d44 297 bad_arg:
pythontech 0:5868e8752d44 298 emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects {r0, r1, ...}", op));
pythontech 0:5868e8752d44 299 return 0;
pythontech 0:5868e8752d44 300 }
pythontech 0:5868e8752d44 301
pythontech 0:5868e8752d44 302 STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint32_t fit_mask) {
pythontech 0:5868e8752d44 303 mp_obj_t o;
pythontech 0:5868e8752d44 304 if (!mp_parse_node_get_int_maybe(pn, &o)) {
pythontech 0:5868e8752d44 305 emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an integer", op));
pythontech 0:5868e8752d44 306 return 0;
pythontech 0:5868e8752d44 307 }
pythontech 0:5868e8752d44 308 uint32_t i = mp_obj_get_int_truncated(o);
pythontech 0:5868e8752d44 309 if ((i & (~fit_mask)) != 0) {
pythontech 0:5868e8752d44 310 emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' integer 0x%x does not fit in mask 0x%x", op, i, fit_mask));
pythontech 0:5868e8752d44 311 return 0;
pythontech 0:5868e8752d44 312 }
pythontech 0:5868e8752d44 313 return i;
pythontech 0:5868e8752d44 314 }
pythontech 0:5868e8752d44 315
pythontech 0:5868e8752d44 316 STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_parse_node_t *pn_base, mp_parse_node_t *pn_offset) {
pythontech 0:5868e8752d44 317 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_bracket)) {
pythontech 0:5868e8752d44 318 goto bad_arg;
pythontech 0:5868e8752d44 319 }
pythontech 0:5868e8752d44 320 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 321 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
pythontech 0:5868e8752d44 322 goto bad_arg;
pythontech 0:5868e8752d44 323 }
pythontech 0:5868e8752d44 324 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 325 if (MP_PARSE_NODE_STRUCT_NUM_NODES(pns) != 2) {
pythontech 0:5868e8752d44 326 goto bad_arg;
pythontech 0:5868e8752d44 327 }
pythontech 0:5868e8752d44 328
pythontech 0:5868e8752d44 329 *pn_base = pns->nodes[0];
pythontech 0:5868e8752d44 330 *pn_offset = pns->nodes[1];
pythontech 0:5868e8752d44 331 return true;
pythontech 0:5868e8752d44 332
pythontech 0:5868e8752d44 333 bad_arg:
pythontech 0:5868e8752d44 334 emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an address of the form [a, b]", op));
pythontech 0:5868e8752d44 335 return false;
pythontech 0:5868e8752d44 336 }
pythontech 0:5868e8752d44 337
pythontech 0:5868e8752d44 338 STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 339 if (!MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 340 emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a label", op));
pythontech 0:5868e8752d44 341 return 0;
pythontech 0:5868e8752d44 342 }
pythontech 0:5868e8752d44 343 qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 344 for (uint i = 0; i < emit->max_num_labels; i++) {
pythontech 0:5868e8752d44 345 if (emit->label_lookup[i] == label_qstr) {
pythontech 0:5868e8752d44 346 return i;
pythontech 0:5868e8752d44 347 }
pythontech 0:5868e8752d44 348 }
pythontech 0:5868e8752d44 349 // only need to have the labels on the last pass
pythontech 0:5868e8752d44 350 if (emit->pass == MP_PASS_EMIT) {
pythontech 0:5868e8752d44 351 emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "label '%q' not defined", label_qstr));
pythontech 0:5868e8752d44 352 }
pythontech 0:5868e8752d44 353 return 0;
pythontech 0:5868e8752d44 354 }
pythontech 0:5868e8752d44 355
pythontech 0:5868e8752d44 356 typedef struct _cc_name_t { byte cc; byte name[2]; } cc_name_t;
pythontech 0:5868e8752d44 357 STATIC const cc_name_t cc_name_table[] = {
pythontech 0:5868e8752d44 358 { ASM_THUMB_CC_EQ, "eq" },
pythontech 0:5868e8752d44 359 { ASM_THUMB_CC_NE, "ne" },
pythontech 0:5868e8752d44 360 { ASM_THUMB_CC_CS, "cs" },
pythontech 0:5868e8752d44 361 { ASM_THUMB_CC_CC, "cc" },
pythontech 0:5868e8752d44 362 { ASM_THUMB_CC_MI, "mi" },
pythontech 0:5868e8752d44 363 { ASM_THUMB_CC_PL, "pl" },
pythontech 0:5868e8752d44 364 { ASM_THUMB_CC_VS, "vs" },
pythontech 0:5868e8752d44 365 { ASM_THUMB_CC_VC, "vc" },
pythontech 0:5868e8752d44 366 { ASM_THUMB_CC_HI, "hi" },
pythontech 0:5868e8752d44 367 { ASM_THUMB_CC_LS, "ls" },
pythontech 0:5868e8752d44 368 { ASM_THUMB_CC_GE, "ge" },
pythontech 0:5868e8752d44 369 { ASM_THUMB_CC_LT, "lt" },
pythontech 0:5868e8752d44 370 { ASM_THUMB_CC_GT, "gt" },
pythontech 0:5868e8752d44 371 { ASM_THUMB_CC_LE, "le" },
pythontech 0:5868e8752d44 372 };
pythontech 0:5868e8752d44 373
pythontech 0:5868e8752d44 374 typedef struct _format_4_op_t { byte op; char name[3]; } format_4_op_t;
pythontech 0:5868e8752d44 375 #define X(x) (((x) >> 4) & 0xff) // only need 1 byte to distinguish these ops
pythontech 0:5868e8752d44 376 STATIC const format_4_op_t format_4_op_table[] = {
pythontech 0:5868e8752d44 377 { X(ASM_THUMB_FORMAT_4_EOR), "eor" },
pythontech 0:5868e8752d44 378 { X(ASM_THUMB_FORMAT_4_LSL), "lsl" },
pythontech 0:5868e8752d44 379 { X(ASM_THUMB_FORMAT_4_LSR), "lsr" },
pythontech 0:5868e8752d44 380 { X(ASM_THUMB_FORMAT_4_ASR), "asr" },
pythontech 0:5868e8752d44 381 { X(ASM_THUMB_FORMAT_4_ADC), "adc" },
pythontech 0:5868e8752d44 382 { X(ASM_THUMB_FORMAT_4_SBC), "sbc" },
pythontech 0:5868e8752d44 383 { X(ASM_THUMB_FORMAT_4_ROR), "ror" },
pythontech 0:5868e8752d44 384 { X(ASM_THUMB_FORMAT_4_TST), "tst" },
pythontech 0:5868e8752d44 385 { X(ASM_THUMB_FORMAT_4_NEG), "neg" },
pythontech 0:5868e8752d44 386 { X(ASM_THUMB_FORMAT_4_CMP), "cmp" },
pythontech 0:5868e8752d44 387 { X(ASM_THUMB_FORMAT_4_CMN), "cmn" },
pythontech 0:5868e8752d44 388 { X(ASM_THUMB_FORMAT_4_ORR), "orr" },
pythontech 0:5868e8752d44 389 { X(ASM_THUMB_FORMAT_4_MUL), "mul" },
pythontech 0:5868e8752d44 390 { X(ASM_THUMB_FORMAT_4_BIC), "bic" },
pythontech 0:5868e8752d44 391 { X(ASM_THUMB_FORMAT_4_MVN), "mvn" },
pythontech 0:5868e8752d44 392 };
pythontech 0:5868e8752d44 393 #undef X
pythontech 0:5868e8752d44 394
pythontech 0:5868e8752d44 395 // name is actually a qstr, which should fit in 16 bits
pythontech 0:5868e8752d44 396 typedef struct _format_9_10_op_t { uint16_t op; uint16_t name; } format_9_10_op_t;
pythontech 0:5868e8752d44 397 #define X(x) (x)
pythontech 0:5868e8752d44 398 STATIC const format_9_10_op_t format_9_10_op_table[] = {
pythontech 0:5868e8752d44 399 { X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_ldr },
pythontech 0:5868e8752d44 400 { X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_ldrb },
pythontech 0:5868e8752d44 401 { X(ASM_THUMB_FORMAT_10_LDRH), MP_QSTR_ldrh },
pythontech 0:5868e8752d44 402 { X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_str },
pythontech 0:5868e8752d44 403 { X(ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_strb },
pythontech 0:5868e8752d44 404 { X(ASM_THUMB_FORMAT_10_STRH), MP_QSTR_strh },
pythontech 0:5868e8752d44 405 };
pythontech 0:5868e8752d44 406 #undef X
pythontech 0:5868e8752d44 407
pythontech 0:5868e8752d44 408 #if MICROPY_EMIT_INLINE_THUMB_FLOAT
pythontech 0:5868e8752d44 409 // actual opcodes are: 0xee00 | op.hi_nibble, 0x0a00 | op.lo_nibble
pythontech 0:5868e8752d44 410 typedef struct _format_vfp_op_t { byte op; char name[3]; } format_vfp_op_t;
pythontech 0:5868e8752d44 411 STATIC const format_vfp_op_t format_vfp_op_table[] = {
pythontech 0:5868e8752d44 412 { 0x30, "add" },
pythontech 0:5868e8752d44 413 { 0x34, "sub" },
pythontech 0:5868e8752d44 414 { 0x20, "mul" },
pythontech 0:5868e8752d44 415 { 0x80, "div" },
pythontech 0:5868e8752d44 416 };
pythontech 0:5868e8752d44 417 #endif
pythontech 0:5868e8752d44 418
pythontech 0:5868e8752d44 419 // shorthand alias for whether we allow ARMv7-M instructions
pythontech 0:5868e8752d44 420 #define ARMV7M MICROPY_EMIT_INLINE_THUMB_ARMV7M
pythontech 0:5868e8752d44 421
pythontech 0:5868e8752d44 422 STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) {
pythontech 0:5868e8752d44 423 // TODO perhaps make two tables:
pythontech 0:5868e8752d44 424 // one_args =
pythontech 0:5868e8752d44 425 // "b", LAB, asm_thumb_b_n,
pythontech 0:5868e8752d44 426 // "bgt", LAB, asm_thumb_bgt_n,
pythontech 0:5868e8752d44 427 // two_args =
pythontech 0:5868e8752d44 428 // "movs", RLO, I8, asm_thumb_movs_reg_i8
pythontech 0:5868e8752d44 429 // "movw", REG, REG, asm_thumb_movw_reg_i16
pythontech 0:5868e8752d44 430 // three_args =
pythontech 0:5868e8752d44 431 // "subs", RLO, RLO, I3, asm_thumb_subs_reg_reg_i3
pythontech 0:5868e8752d44 432
pythontech 0:5868e8752d44 433 size_t op_len;
pythontech 0:5868e8752d44 434 const char *op_str = (const char*)qstr_data(op, &op_len);
pythontech 0:5868e8752d44 435
pythontech 0:5868e8752d44 436 #if MICROPY_EMIT_INLINE_THUMB_FLOAT
pythontech 0:5868e8752d44 437 if (op_str[0] == 'v') {
pythontech 0:5868e8752d44 438 // floating point operations
pythontech 0:5868e8752d44 439 if (n_args == 2) {
pythontech 0:5868e8752d44 440 mp_uint_t op_code = 0x0ac0, op_code_hi;
pythontech 0:5868e8752d44 441 if (op == MP_QSTR_vcmp) {
pythontech 0:5868e8752d44 442 op_code_hi = 0xeeb4;
pythontech 0:5868e8752d44 443 op_vfp_twoargs:;
pythontech 0:5868e8752d44 444 mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
pythontech 0:5868e8752d44 445 mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[1]);
pythontech 0:5868e8752d44 446 asm_thumb_op32(emit->as,
pythontech 0:5868e8752d44 447 op_code_hi | ((vd & 1) << 6),
pythontech 0:5868e8752d44 448 op_code | ((vd & 0x1e) << 11) | ((vm & 1) << 5) | (vm & 0x1e) >> 1);
pythontech 0:5868e8752d44 449 } else if (op == MP_QSTR_vsqrt) {
pythontech 0:5868e8752d44 450 op_code_hi = 0xeeb1;
pythontech 0:5868e8752d44 451 goto op_vfp_twoargs;
pythontech 0:5868e8752d44 452 } else if (op == MP_QSTR_vneg) {
pythontech 0:5868e8752d44 453 op_code_hi = 0xeeb1;
pythontech 0:5868e8752d44 454 op_code = 0x0a40;
pythontech 0:5868e8752d44 455 goto op_vfp_twoargs;
pythontech 0:5868e8752d44 456 } else if (op == MP_QSTR_vcvt_f32_s32) {
pythontech 0:5868e8752d44 457 op_code_hi = 0xeeb8; // int to float
pythontech 0:5868e8752d44 458 goto op_vfp_twoargs;
pythontech 0:5868e8752d44 459 } else if (op == MP_QSTR_vcvt_s32_f32) {
pythontech 0:5868e8752d44 460 op_code_hi = 0xeebd; // float to int
pythontech 0:5868e8752d44 461 goto op_vfp_twoargs;
pythontech 0:5868e8752d44 462 } else if (op == MP_QSTR_vmrs) {
pythontech 0:5868e8752d44 463 mp_uint_t reg_dest;
pythontech 0:5868e8752d44 464 const char *reg_str0 = get_arg_str(pn_args[0]);
pythontech 0:5868e8752d44 465 if (strcmp(reg_str0, "APSR_nzcv") == 0) {
pythontech 0:5868e8752d44 466 reg_dest = 15;
pythontech 0:5868e8752d44 467 } else {
pythontech 0:5868e8752d44 468 reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 469 }
pythontech 0:5868e8752d44 470 const char *reg_str1 = get_arg_str(pn_args[1]);
pythontech 0:5868e8752d44 471 if (strcmp(reg_str1, "FPSCR") == 0) {
pythontech 0:5868e8752d44 472 // FP status to ARM reg
pythontech 0:5868e8752d44 473 asm_thumb_op32(emit->as, 0xeef1, 0x0a10 | (reg_dest << 12));
pythontech 0:5868e8752d44 474 } else {
pythontech 0:5868e8752d44 475 goto unknown_op;
pythontech 0:5868e8752d44 476 }
pythontech 0:5868e8752d44 477 } else if (op == MP_QSTR_vmov) {
pythontech 0:5868e8752d44 478 op_code_hi = 0xee00;
pythontech 0:5868e8752d44 479 mp_uint_t r_arm, vm;
pythontech 0:5868e8752d44 480 const char *reg_str = get_arg_str(pn_args[0]);
pythontech 0:5868e8752d44 481 if (reg_str[0] == 'r') {
pythontech 0:5868e8752d44 482 r_arm = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 483 vm = get_arg_vfpreg(emit, op_str, pn_args[1]);
pythontech 0:5868e8752d44 484 op_code_hi |= 0x10;
pythontech 0:5868e8752d44 485 } else {
pythontech 0:5868e8752d44 486 vm = get_arg_vfpreg(emit, op_str, pn_args[0]);
pythontech 0:5868e8752d44 487 r_arm = get_arg_reg(emit, op_str, pn_args[1], 15);
pythontech 0:5868e8752d44 488 }
pythontech 0:5868e8752d44 489 asm_thumb_op32(emit->as,
pythontech 0:5868e8752d44 490 op_code_hi | ((vm & 0x1e) >> 1),
pythontech 0:5868e8752d44 491 0x0a10 | (r_arm << 12) | ((vm & 1) << 7));
pythontech 0:5868e8752d44 492 } else if (op == MP_QSTR_vldr) {
pythontech 0:5868e8752d44 493 op_code_hi = 0xed90;
pythontech 0:5868e8752d44 494 op_vldr_vstr:;
pythontech 0:5868e8752d44 495 mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
pythontech 0:5868e8752d44 496 mp_parse_node_t pn_base, pn_offset;
pythontech 0:5868e8752d44 497 if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
pythontech 0:5868e8752d44 498 mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
pythontech 0:5868e8752d44 499 mp_uint_t i8;
pythontech 0:5868e8752d44 500 i8 = get_arg_i(emit, op_str, pn_offset, 0x3fc) >> 2;
pythontech 0:5868e8752d44 501 asm_thumb_op32(emit->as,
pythontech 0:5868e8752d44 502 op_code_hi | rlo_base | ((vd & 1) << 6),
pythontech 0:5868e8752d44 503 0x0a00 | ((vd & 0x1e) << 11) | i8);
pythontech 0:5868e8752d44 504 }
pythontech 0:5868e8752d44 505 } else if (op == MP_QSTR_vstr) {
pythontech 0:5868e8752d44 506 op_code_hi = 0xed80;
pythontech 0:5868e8752d44 507 goto op_vldr_vstr;
pythontech 0:5868e8752d44 508 } else {
pythontech 0:5868e8752d44 509 goto unknown_op;
pythontech 0:5868e8752d44 510 }
pythontech 0:5868e8752d44 511 } else if (n_args == 3) {
pythontech 0:5868e8752d44 512 // search table for arith ops
pythontech 0:5868e8752d44 513 for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_vfp_op_table); i++) {
pythontech 0:5868e8752d44 514 if (strncmp(op_str + 1, format_vfp_op_table[i].name, 3) == 0 && op_str[4] == '\0') {
pythontech 0:5868e8752d44 515 mp_uint_t op_code_hi = 0xee00 | (format_vfp_op_table[i].op & 0xf0);
pythontech 0:5868e8752d44 516 mp_uint_t op_code = 0x0a00 | ((format_vfp_op_table[i].op & 0x0f) << 4);
pythontech 0:5868e8752d44 517 mp_uint_t vd = get_arg_vfpreg(emit, op_str, pn_args[0]);
pythontech 0:5868e8752d44 518 mp_uint_t vn = get_arg_vfpreg(emit, op_str, pn_args[1]);
pythontech 0:5868e8752d44 519 mp_uint_t vm = get_arg_vfpreg(emit, op_str, pn_args[2]);
pythontech 0:5868e8752d44 520 asm_thumb_op32(emit->as,
pythontech 0:5868e8752d44 521 op_code_hi | ((vd & 1) << 6) | (vn >> 1),
pythontech 0:5868e8752d44 522 op_code | (vm >> 1) | ((vm & 1) << 5) | ((vd & 0x1e) << 11) | ((vn & 1) << 7));
pythontech 0:5868e8752d44 523 return;
pythontech 0:5868e8752d44 524 }
pythontech 0:5868e8752d44 525 }
pythontech 0:5868e8752d44 526 goto unknown_op;
pythontech 0:5868e8752d44 527 } else {
pythontech 0:5868e8752d44 528 goto unknown_op;
pythontech 0:5868e8752d44 529 }
pythontech 0:5868e8752d44 530 } else
pythontech 0:5868e8752d44 531 #endif
pythontech 0:5868e8752d44 532 if (n_args == 0) {
pythontech 0:5868e8752d44 533 if (op == MP_QSTR_nop) {
pythontech 0:5868e8752d44 534 asm_thumb_op16(emit->as, ASM_THUMB_OP_NOP);
pythontech 0:5868e8752d44 535 } else if (op == MP_QSTR_wfi) {
pythontech 0:5868e8752d44 536 asm_thumb_op16(emit->as, ASM_THUMB_OP_WFI);
pythontech 0:5868e8752d44 537 } else {
pythontech 0:5868e8752d44 538 goto unknown_op;
pythontech 0:5868e8752d44 539 }
pythontech 0:5868e8752d44 540
pythontech 0:5868e8752d44 541 } else if (n_args == 1) {
pythontech 0:5868e8752d44 542 if (op == MP_QSTR_b) {
pythontech 0:5868e8752d44 543 int label_num = get_arg_label(emit, op_str, pn_args[0]);
pythontech 0:5868e8752d44 544 if (!asm_thumb_b_n_label(emit->as, label_num)) {
pythontech 0:5868e8752d44 545 goto branch_not_in_range;
pythontech 0:5868e8752d44 546 }
pythontech 0:5868e8752d44 547 } else if (op == MP_QSTR_bl) {
pythontech 0:5868e8752d44 548 int label_num = get_arg_label(emit, op_str, pn_args[0]);
pythontech 0:5868e8752d44 549 if (!asm_thumb_bl_label(emit->as, label_num)) {
pythontech 0:5868e8752d44 550 goto branch_not_in_range;
pythontech 0:5868e8752d44 551 }
pythontech 0:5868e8752d44 552 } else if (op == MP_QSTR_bx) {
pythontech 0:5868e8752d44 553 mp_uint_t r = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 554 asm_thumb_op16(emit->as, 0x4700 | (r << 3));
pythontech 0:5868e8752d44 555 } else if (op_str[0] == 'b' && (op_len == 3
pythontech 0:5868e8752d44 556 || (op_len == 5 && op_str[3] == '_'
pythontech 0:5868e8752d44 557 && (op_str[4] == 'n' || (ARMV7M && op_str[4] == 'w'))))) {
pythontech 0:5868e8752d44 558 mp_uint_t cc = -1;
pythontech 0:5868e8752d44 559 for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {
pythontech 0:5868e8752d44 560 if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) {
pythontech 0:5868e8752d44 561 cc = cc_name_table[i].cc;
pythontech 0:5868e8752d44 562 }
pythontech 0:5868e8752d44 563 }
pythontech 0:5868e8752d44 564 if (cc == (mp_uint_t)-1) {
pythontech 0:5868e8752d44 565 goto unknown_op;
pythontech 0:5868e8752d44 566 }
pythontech 0:5868e8752d44 567 int label_num = get_arg_label(emit, op_str, pn_args[0]);
pythontech 0:5868e8752d44 568 if (!asm_thumb_bcc_nw_label(emit->as, cc, label_num, op_len == 5 && op_str[4] == 'w')) {
pythontech 0:5868e8752d44 569 goto branch_not_in_range;
pythontech 0:5868e8752d44 570 }
pythontech 0:5868e8752d44 571 } else if (ARMV7M && op_str[0] == 'i' && op_str[1] == 't') {
pythontech 0:5868e8752d44 572 const char *arg_str = get_arg_str(pn_args[0]);
pythontech 0:5868e8752d44 573 mp_uint_t cc = -1;
pythontech 0:5868e8752d44 574 for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {
pythontech 0:5868e8752d44 575 if (arg_str[0] == cc_name_table[i].name[0]
pythontech 0:5868e8752d44 576 && arg_str[1] == cc_name_table[i].name[1]
pythontech 0:5868e8752d44 577 && arg_str[2] == '\0') {
pythontech 0:5868e8752d44 578 cc = cc_name_table[i].cc;
pythontech 0:5868e8752d44 579 break;
pythontech 0:5868e8752d44 580 }
pythontech 0:5868e8752d44 581 }
pythontech 0:5868e8752d44 582 if (cc == (mp_uint_t)-1) {
pythontech 0:5868e8752d44 583 goto unknown_op;
pythontech 0:5868e8752d44 584 }
pythontech 0:5868e8752d44 585 const char *os = op_str + 2;
pythontech 0:5868e8752d44 586 while (*os != '\0') {
pythontech 0:5868e8752d44 587 os++;
pythontech 0:5868e8752d44 588 }
pythontech 0:5868e8752d44 589 if (os > op_str + 5) {
pythontech 0:5868e8752d44 590 goto unknown_op;
pythontech 0:5868e8752d44 591 }
pythontech 0:5868e8752d44 592 mp_uint_t it_mask = 8;
pythontech 0:5868e8752d44 593 while (--os >= op_str + 2) {
pythontech 0:5868e8752d44 594 it_mask >>= 1;
pythontech 0:5868e8752d44 595 if (*os == 't') {
pythontech 0:5868e8752d44 596 it_mask |= (cc & 1) << 3;
pythontech 0:5868e8752d44 597 } else if (*os == 'e') {
pythontech 0:5868e8752d44 598 it_mask |= ((~cc) & 1) << 3;
pythontech 0:5868e8752d44 599 } else {
pythontech 0:5868e8752d44 600 goto unknown_op;
pythontech 0:5868e8752d44 601 }
pythontech 0:5868e8752d44 602 }
pythontech 0:5868e8752d44 603 asm_thumb_it_cc(emit->as, cc, it_mask);
pythontech 0:5868e8752d44 604 } else if (op == MP_QSTR_cpsid) {
pythontech 0:5868e8752d44 605 // TODO check pn_args[0] == i
pythontech 0:5868e8752d44 606 asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSID_I);
pythontech 0:5868e8752d44 607 } else if (op == MP_QSTR_cpsie) {
pythontech 0:5868e8752d44 608 // TODO check pn_args[0] == i
pythontech 0:5868e8752d44 609 asm_thumb_op16(emit->as, ASM_THUMB_OP_CPSIE_I);
pythontech 0:5868e8752d44 610 } else if (op == MP_QSTR_push) {
pythontech 0:5868e8752d44 611 mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
pythontech 0:5868e8752d44 612 if ((reglist & 0xff00) == 0) {
pythontech 0:5868e8752d44 613 asm_thumb_op16(emit->as, 0xb400 | reglist);
pythontech 0:5868e8752d44 614 } else {
pythontech 0:5868e8752d44 615 if (!ARMV7M) {
pythontech 0:5868e8752d44 616 goto unknown_op;
pythontech 0:5868e8752d44 617 }
pythontech 0:5868e8752d44 618 asm_thumb_op32(emit->as, 0xe92d, reglist);
pythontech 0:5868e8752d44 619 }
pythontech 0:5868e8752d44 620 } else if (op == MP_QSTR_pop) {
pythontech 0:5868e8752d44 621 mp_uint_t reglist = get_arg_reglist(emit, op_str, pn_args[0]);
pythontech 0:5868e8752d44 622 if ((reglist & 0xff00) == 0) {
pythontech 0:5868e8752d44 623 asm_thumb_op16(emit->as, 0xbc00 | reglist);
pythontech 0:5868e8752d44 624 } else {
pythontech 0:5868e8752d44 625 if (!ARMV7M) {
pythontech 0:5868e8752d44 626 goto unknown_op;
pythontech 0:5868e8752d44 627 }
pythontech 0:5868e8752d44 628 asm_thumb_op32(emit->as, 0xe8bd, reglist);
pythontech 0:5868e8752d44 629 }
pythontech 0:5868e8752d44 630 } else {
pythontech 0:5868e8752d44 631 goto unknown_op;
pythontech 0:5868e8752d44 632 }
pythontech 0:5868e8752d44 633
pythontech 0:5868e8752d44 634 } else if (n_args == 2) {
pythontech 0:5868e8752d44 635 if (MP_PARSE_NODE_IS_ID(pn_args[1])) {
pythontech 0:5868e8752d44 636 // second arg is a register (or should be)
pythontech 0:5868e8752d44 637 mp_uint_t op_code, op_code_hi;
pythontech 0:5868e8752d44 638 if (op == MP_QSTR_mov) {
pythontech 0:5868e8752d44 639 mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 640 mp_uint_t reg_src = get_arg_reg(emit, op_str, pn_args[1], 15);
pythontech 0:5868e8752d44 641 asm_thumb_mov_reg_reg(emit->as, reg_dest, reg_src);
pythontech 0:5868e8752d44 642 } else if (ARMV7M && op == MP_QSTR_clz) {
pythontech 0:5868e8752d44 643 op_code_hi = 0xfab0;
pythontech 0:5868e8752d44 644 op_code = 0xf080;
pythontech 0:5868e8752d44 645 mp_uint_t rd, rm;
pythontech 0:5868e8752d44 646 op_clz_rbit:
pythontech 0:5868e8752d44 647 rd = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 648 rm = get_arg_reg(emit, op_str, pn_args[1], 15);
pythontech 0:5868e8752d44 649 asm_thumb_op32(emit->as, op_code_hi | rm, op_code | (rd << 8) | rm);
pythontech 0:5868e8752d44 650 } else if (ARMV7M && op == MP_QSTR_rbit) {
pythontech 0:5868e8752d44 651 op_code_hi = 0xfa90;
pythontech 0:5868e8752d44 652 op_code = 0xf0a0;
pythontech 0:5868e8752d44 653 goto op_clz_rbit;
pythontech 0:5868e8752d44 654 } else if (ARMV7M && op == MP_QSTR_mrs){
pythontech 0:5868e8752d44 655 mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 12);
pythontech 0:5868e8752d44 656 mp_uint_t reg_src = get_arg_special_reg(emit, op_str, pn_args[1]);
pythontech 0:5868e8752d44 657 asm_thumb_op32(emit->as, 0xf3ef, 0x8000 | (reg_dest << 8) | reg_src);
pythontech 0:5868e8752d44 658 } else {
pythontech 0:5868e8752d44 659 if (op == MP_QSTR_and_) {
pythontech 0:5868e8752d44 660 op_code = ASM_THUMB_FORMAT_4_AND;
pythontech 0:5868e8752d44 661 mp_uint_t reg_dest, reg_src;
pythontech 0:5868e8752d44 662 op_format_4:
pythontech 0:5868e8752d44 663 reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
pythontech 0:5868e8752d44 664 reg_src = get_arg_reg(emit, op_str, pn_args[1], 7);
pythontech 0:5868e8752d44 665 asm_thumb_format_4(emit->as, op_code, reg_dest, reg_src);
pythontech 0:5868e8752d44 666 return;
pythontech 0:5868e8752d44 667 }
pythontech 0:5868e8752d44 668 // search table for ALU ops
pythontech 0:5868e8752d44 669 for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_4_op_table); i++) {
pythontech 0:5868e8752d44 670 if (strncmp(op_str, format_4_op_table[i].name, 3) == 0 && op_str[3] == '\0') {
pythontech 0:5868e8752d44 671 op_code = 0x4000 | (format_4_op_table[i].op << 4);
pythontech 0:5868e8752d44 672 goto op_format_4;
pythontech 0:5868e8752d44 673 }
pythontech 0:5868e8752d44 674 }
pythontech 0:5868e8752d44 675 goto unknown_op;
pythontech 0:5868e8752d44 676 }
pythontech 0:5868e8752d44 677 } else {
pythontech 0:5868e8752d44 678 // second arg is not a register
pythontech 0:5868e8752d44 679 mp_uint_t op_code;
pythontech 0:5868e8752d44 680 if (op == MP_QSTR_mov) {
pythontech 0:5868e8752d44 681 op_code = ASM_THUMB_FORMAT_3_MOV;
pythontech 0:5868e8752d44 682 mp_uint_t rlo_dest, i8_src;
pythontech 0:5868e8752d44 683 op_format_3:
pythontech 0:5868e8752d44 684 rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
pythontech 0:5868e8752d44 685 i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff);
pythontech 0:5868e8752d44 686 asm_thumb_format_3(emit->as, op_code, rlo_dest, i8_src);
pythontech 0:5868e8752d44 687 } else if (op == MP_QSTR_cmp) {
pythontech 0:5868e8752d44 688 op_code = ASM_THUMB_FORMAT_3_CMP;
pythontech 0:5868e8752d44 689 goto op_format_3;
pythontech 0:5868e8752d44 690 } else if (op == MP_QSTR_add) {
pythontech 0:5868e8752d44 691 op_code = ASM_THUMB_FORMAT_3_ADD;
pythontech 0:5868e8752d44 692 goto op_format_3;
pythontech 0:5868e8752d44 693 } else if (op == MP_QSTR_sub) {
pythontech 0:5868e8752d44 694 op_code = ASM_THUMB_FORMAT_3_SUB;
pythontech 0:5868e8752d44 695 goto op_format_3;
pythontech 0:5868e8752d44 696 } else if (ARMV7M && op == MP_QSTR_movw) {
pythontech 0:5868e8752d44 697 op_code = ASM_THUMB_OP_MOVW;
pythontech 0:5868e8752d44 698 mp_uint_t reg_dest;
pythontech 0:5868e8752d44 699 op_movw_movt:
pythontech 0:5868e8752d44 700 reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 701 int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff);
pythontech 0:5868e8752d44 702 asm_thumb_mov_reg_i16(emit->as, op_code, reg_dest, i_src);
pythontech 0:5868e8752d44 703 } else if (ARMV7M && op == MP_QSTR_movt) {
pythontech 0:5868e8752d44 704 op_code = ASM_THUMB_OP_MOVT;
pythontech 0:5868e8752d44 705 goto op_movw_movt;
pythontech 0:5868e8752d44 706 } else if (ARMV7M && op == MP_QSTR_movwt) {
pythontech 0:5868e8752d44 707 // this is a convenience instruction
pythontech 0:5868e8752d44 708 mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 709 uint32_t i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff);
pythontech 0:5868e8752d44 710 asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVW, reg_dest, i_src & 0xffff);
pythontech 0:5868e8752d44 711 asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff);
pythontech 0:5868e8752d44 712 } else if (ARMV7M && op == MP_QSTR_ldrex) {
pythontech 0:5868e8752d44 713 mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 714 mp_parse_node_t pn_base, pn_offset;
pythontech 0:5868e8752d44 715 if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
pythontech 0:5868e8752d44 716 mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
pythontech 0:5868e8752d44 717 mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
pythontech 0:5868e8752d44 718 asm_thumb_op32(emit->as, 0xe850 | r_base, 0x0f00 | (r_dest << 12) | i8);
pythontech 0:5868e8752d44 719 }
pythontech 0:5868e8752d44 720 } else {
pythontech 0:5868e8752d44 721 // search table for ldr/str instructions
pythontech 0:5868e8752d44 722 for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(format_9_10_op_table); i++) {
pythontech 0:5868e8752d44 723 if (op == format_9_10_op_table[i].name) {
pythontech 0:5868e8752d44 724 op_code = format_9_10_op_table[i].op;
pythontech 0:5868e8752d44 725 mp_parse_node_t pn_base, pn_offset;
pythontech 0:5868e8752d44 726 mp_uint_t rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
pythontech 0:5868e8752d44 727 if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
pythontech 0:5868e8752d44 728 mp_uint_t rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
pythontech 0:5868e8752d44 729 mp_uint_t i5;
pythontech 0:5868e8752d44 730 if (op_code & ASM_THUMB_FORMAT_9_BYTE_TRANSFER) {
pythontech 0:5868e8752d44 731 i5 = get_arg_i(emit, op_str, pn_offset, 0x1f);
pythontech 0:5868e8752d44 732 } else if (op_code & ASM_THUMB_FORMAT_10_STRH) { // also catches LDRH
pythontech 0:5868e8752d44 733 i5 = get_arg_i(emit, op_str, pn_offset, 0x3e) >> 1;
pythontech 0:5868e8752d44 734 } else {
pythontech 0:5868e8752d44 735 i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2;
pythontech 0:5868e8752d44 736 }
pythontech 0:5868e8752d44 737 asm_thumb_format_9_10(emit->as, op_code, rlo_dest, rlo_base, i5);
pythontech 0:5868e8752d44 738 return;
pythontech 0:5868e8752d44 739 }
pythontech 0:5868e8752d44 740 break;
pythontech 0:5868e8752d44 741 }
pythontech 0:5868e8752d44 742 }
pythontech 0:5868e8752d44 743 goto unknown_op;
pythontech 0:5868e8752d44 744 }
pythontech 0:5868e8752d44 745 }
pythontech 0:5868e8752d44 746
pythontech 0:5868e8752d44 747 } else if (n_args == 3) {
pythontech 0:5868e8752d44 748 mp_uint_t op_code;
pythontech 0:5868e8752d44 749 if (op == MP_QSTR_lsl) {
pythontech 0:5868e8752d44 750 op_code = ASM_THUMB_FORMAT_1_LSL;
pythontech 0:5868e8752d44 751 mp_uint_t rlo_dest, rlo_src, i5;
pythontech 0:5868e8752d44 752 op_format_1:
pythontech 0:5868e8752d44 753 rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
pythontech 0:5868e8752d44 754 rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
pythontech 0:5868e8752d44 755 i5 = get_arg_i(emit, op_str, pn_args[2], 0x1f);
pythontech 0:5868e8752d44 756 asm_thumb_format_1(emit->as, op_code, rlo_dest, rlo_src, i5);
pythontech 0:5868e8752d44 757 } else if (op == MP_QSTR_lsr) {
pythontech 0:5868e8752d44 758 op_code = ASM_THUMB_FORMAT_1_LSR;
pythontech 0:5868e8752d44 759 goto op_format_1;
pythontech 0:5868e8752d44 760 } else if (op == MP_QSTR_asr) {
pythontech 0:5868e8752d44 761 op_code = ASM_THUMB_FORMAT_1_ASR;
pythontech 0:5868e8752d44 762 goto op_format_1;
pythontech 0:5868e8752d44 763 } else if (op == MP_QSTR_add) {
pythontech 0:5868e8752d44 764 op_code = ASM_THUMB_FORMAT_2_ADD;
pythontech 0:5868e8752d44 765 mp_uint_t rlo_dest, rlo_src;
pythontech 0:5868e8752d44 766 op_format_2:
pythontech 0:5868e8752d44 767 rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
pythontech 0:5868e8752d44 768 rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
pythontech 0:5868e8752d44 769 int src_b;
pythontech 0:5868e8752d44 770 if (MP_PARSE_NODE_IS_ID(pn_args[2])) {
pythontech 0:5868e8752d44 771 op_code |= ASM_THUMB_FORMAT_2_REG_OPERAND;
pythontech 0:5868e8752d44 772 src_b = get_arg_reg(emit, op_str, pn_args[2], 7);
pythontech 0:5868e8752d44 773 } else {
pythontech 0:5868e8752d44 774 op_code |= ASM_THUMB_FORMAT_2_IMM_OPERAND;
pythontech 0:5868e8752d44 775 src_b = get_arg_i(emit, op_str, pn_args[2], 0x7);
pythontech 0:5868e8752d44 776 }
pythontech 0:5868e8752d44 777 asm_thumb_format_2(emit->as, op_code, rlo_dest, rlo_src, src_b);
pythontech 0:5868e8752d44 778 } else if (ARMV7M && op == MP_QSTR_sdiv) {
pythontech 0:5868e8752d44 779 op_code = 0xfb90; // sdiv high part
pythontech 0:5868e8752d44 780 mp_uint_t rd, rn, rm;
pythontech 0:5868e8752d44 781 op_sdiv_udiv:
pythontech 0:5868e8752d44 782 rd = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 783 rn = get_arg_reg(emit, op_str, pn_args[1], 15);
pythontech 0:5868e8752d44 784 rm = get_arg_reg(emit, op_str, pn_args[2], 15);
pythontech 0:5868e8752d44 785 asm_thumb_op32(emit->as, op_code | rn, 0xf0f0 | (rd << 8) | rm);
pythontech 0:5868e8752d44 786 } else if (ARMV7M && op == MP_QSTR_udiv) {
pythontech 0:5868e8752d44 787 op_code = 0xfbb0; // udiv high part
pythontech 0:5868e8752d44 788 goto op_sdiv_udiv;
pythontech 0:5868e8752d44 789 } else if (op == MP_QSTR_sub) {
pythontech 0:5868e8752d44 790 op_code = ASM_THUMB_FORMAT_2_SUB;
pythontech 0:5868e8752d44 791 goto op_format_2;
pythontech 0:5868e8752d44 792 } else if (ARMV7M && op == MP_QSTR_strex) {
pythontech 0:5868e8752d44 793 mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
pythontech 0:5868e8752d44 794 mp_uint_t r_src = get_arg_reg(emit, op_str, pn_args[1], 15);
pythontech 0:5868e8752d44 795 mp_parse_node_t pn_base, pn_offset;
pythontech 0:5868e8752d44 796 if (get_arg_addr(emit, op_str, pn_args[2], &pn_base, &pn_offset)) {
pythontech 0:5868e8752d44 797 mp_uint_t r_base = get_arg_reg(emit, op_str, pn_base, 15);
pythontech 0:5868e8752d44 798 mp_uint_t i8 = get_arg_i(emit, op_str, pn_offset, 0xff) >> 2;
pythontech 0:5868e8752d44 799 asm_thumb_op32(emit->as, 0xe840 | r_base, (r_src << 12) | (r_dest << 8) | i8);
pythontech 0:5868e8752d44 800 }
pythontech 0:5868e8752d44 801 } else {
pythontech 0:5868e8752d44 802 goto unknown_op;
pythontech 0:5868e8752d44 803 }
pythontech 0:5868e8752d44 804
pythontech 0:5868e8752d44 805 } else {
pythontech 0:5868e8752d44 806 goto unknown_op;
pythontech 0:5868e8752d44 807 }
pythontech 0:5868e8752d44 808
pythontech 0:5868e8752d44 809 return;
pythontech 0:5868e8752d44 810
pythontech 0:5868e8752d44 811 unknown_op:
pythontech 0:5868e8752d44 812 emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "unsupported Thumb instruction '%s' with %d arguments", op_str, n_args));
pythontech 0:5868e8752d44 813 return;
pythontech 0:5868e8752d44 814
pythontech 0:5868e8752d44 815 branch_not_in_range:
pythontech 0:5868e8752d44 816 emit_inline_thumb_error_msg(emit, "branch not in range");
pythontech 0:5868e8752d44 817 return;
pythontech 0:5868e8752d44 818 }
pythontech 0:5868e8752d44 819
pythontech 0:5868e8752d44 820 const emit_inline_asm_method_table_t emit_inline_thumb_method_table = {
pythontech 0:5868e8752d44 821 emit_inline_thumb_start_pass,
pythontech 0:5868e8752d44 822 emit_inline_thumb_end_pass,
pythontech 0:5868e8752d44 823 emit_inline_thumb_count_params,
pythontech 0:5868e8752d44 824 emit_inline_thumb_label,
pythontech 0:5868e8752d44 825 emit_inline_thumb_align,
pythontech 0:5868e8752d44 826 emit_inline_thumb_data,
pythontech 0:5868e8752d44 827 emit_inline_thumb_op,
pythontech 0:5868e8752d44 828 };
pythontech 0:5868e8752d44 829
pythontech 0:5868e8752d44 830 #endif // MICROPY_EMIT_INLINE_THUMB