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:
pythontech
Date:
Sat Apr 16 17:11:56 2016 +0000
Revision:
0:5868e8752d44
Split off library from repl

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 <stdio.h>
pythontech 0:5868e8752d44 28 #include <assert.h>
pythontech 0:5868e8752d44 29 #include <string.h>
pythontech 0:5868e8752d44 30
pythontech 0:5868e8752d44 31 #include "py/mpconfig.h"
pythontech 0:5868e8752d44 32
pythontech 0:5868e8752d44 33 // wrapper around everything in this file
pythontech 0:5868e8752d44 34 #if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 35
pythontech 0:5868e8752d44 36 #include "py/asmthumb.h"
pythontech 0:5868e8752d44 37
pythontech 0:5868e8752d44 38 #define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0)
pythontech 0:5868e8752d44 39 #define UNSIGNED_FIT16(x) (((x) & 0xffff0000) == 0)
pythontech 0:5868e8752d44 40 #define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
pythontech 0:5868e8752d44 41 #define SIGNED_FIT9(x) (((x) & 0xffffff00) == 0) || (((x) & 0xffffff00) == 0xffffff00)
pythontech 0:5868e8752d44 42 #define SIGNED_FIT12(x) (((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)
pythontech 0:5868e8752d44 43 #define SIGNED_FIT23(x) (((x) & 0xffc00000) == 0) || (((x) & 0xffc00000) == 0xffc00000)
pythontech 0:5868e8752d44 44
pythontech 0:5868e8752d44 45 struct _asm_thumb_t {
pythontech 0:5868e8752d44 46 mp_uint_t pass;
pythontech 0:5868e8752d44 47 mp_uint_t code_offset;
pythontech 0:5868e8752d44 48 mp_uint_t code_size;
pythontech 0:5868e8752d44 49 byte *code_base;
pythontech 0:5868e8752d44 50 byte dummy_data[4];
pythontech 0:5868e8752d44 51
pythontech 0:5868e8752d44 52 mp_uint_t max_num_labels;
pythontech 0:5868e8752d44 53 mp_uint_t *label_offsets;
pythontech 0:5868e8752d44 54 mp_uint_t push_reglist;
pythontech 0:5868e8752d44 55 mp_uint_t stack_adjust;
pythontech 0:5868e8752d44 56 };
pythontech 0:5868e8752d44 57
pythontech 0:5868e8752d44 58 asm_thumb_t *asm_thumb_new(uint max_num_labels) {
pythontech 0:5868e8752d44 59 asm_thumb_t *as;
pythontech 0:5868e8752d44 60
pythontech 0:5868e8752d44 61 as = m_new0(asm_thumb_t, 1);
pythontech 0:5868e8752d44 62 as->max_num_labels = max_num_labels;
pythontech 0:5868e8752d44 63 as->label_offsets = m_new(mp_uint_t, max_num_labels);
pythontech 0:5868e8752d44 64
pythontech 0:5868e8752d44 65 return as;
pythontech 0:5868e8752d44 66 }
pythontech 0:5868e8752d44 67
pythontech 0:5868e8752d44 68 void asm_thumb_free(asm_thumb_t *as, bool free_code) {
pythontech 0:5868e8752d44 69 if (free_code) {
pythontech 0:5868e8752d44 70 MP_PLAT_FREE_EXEC(as->code_base, as->code_size);
pythontech 0:5868e8752d44 71 }
pythontech 0:5868e8752d44 72 m_del(mp_uint_t, as->label_offsets, as->max_num_labels);
pythontech 0:5868e8752d44 73 m_del_obj(asm_thumb_t, as);
pythontech 0:5868e8752d44 74 }
pythontech 0:5868e8752d44 75
pythontech 0:5868e8752d44 76 void asm_thumb_start_pass(asm_thumb_t *as, uint pass) {
pythontech 0:5868e8752d44 77 if (pass == ASM_THUMB_PASS_COMPUTE) {
pythontech 0:5868e8752d44 78 memset(as->label_offsets, -1, as->max_num_labels * sizeof(mp_uint_t));
pythontech 0:5868e8752d44 79 } else if (pass == ASM_THUMB_PASS_EMIT) {
pythontech 0:5868e8752d44 80 MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size);
pythontech 0:5868e8752d44 81 if (as->code_base == NULL) {
pythontech 0:5868e8752d44 82 assert(0);
pythontech 0:5868e8752d44 83 }
pythontech 0:5868e8752d44 84 //printf("code_size: %u\n", as->code_size);
pythontech 0:5868e8752d44 85 }
pythontech 0:5868e8752d44 86 as->pass = pass;
pythontech 0:5868e8752d44 87 as->code_offset = 0;
pythontech 0:5868e8752d44 88 }
pythontech 0:5868e8752d44 89
pythontech 0:5868e8752d44 90 void asm_thumb_end_pass(asm_thumb_t *as) {
pythontech 0:5868e8752d44 91 (void)as;
pythontech 0:5868e8752d44 92 // could check labels are resolved...
pythontech 0:5868e8752d44 93 }
pythontech 0:5868e8752d44 94
pythontech 0:5868e8752d44 95 // all functions must go through this one to emit bytes
pythontech 0:5868e8752d44 96 // if as->pass < ASM_THUMB_PASS_EMIT, then this function only returns a buffer of 4 bytes length
pythontech 0:5868e8752d44 97 STATIC byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int num_bytes_to_write) {
pythontech 0:5868e8752d44 98 //printf("emit %d\n", num_bytes_to_write);
pythontech 0:5868e8752d44 99 if (as->pass < ASM_THUMB_PASS_EMIT) {
pythontech 0:5868e8752d44 100 as->code_offset += num_bytes_to_write;
pythontech 0:5868e8752d44 101 return as->dummy_data;
pythontech 0:5868e8752d44 102 } else {
pythontech 0:5868e8752d44 103 assert(as->code_offset + num_bytes_to_write <= as->code_size);
pythontech 0:5868e8752d44 104 byte *c = as->code_base + as->code_offset;
pythontech 0:5868e8752d44 105 as->code_offset += num_bytes_to_write;
pythontech 0:5868e8752d44 106 return c;
pythontech 0:5868e8752d44 107 }
pythontech 0:5868e8752d44 108 }
pythontech 0:5868e8752d44 109
pythontech 0:5868e8752d44 110 uint asm_thumb_get_code_pos(asm_thumb_t *as) {
pythontech 0:5868e8752d44 111 return as->code_offset;
pythontech 0:5868e8752d44 112 }
pythontech 0:5868e8752d44 113
pythontech 0:5868e8752d44 114 uint asm_thumb_get_code_size(asm_thumb_t *as) {
pythontech 0:5868e8752d44 115 return as->code_size;
pythontech 0:5868e8752d44 116 }
pythontech 0:5868e8752d44 117
pythontech 0:5868e8752d44 118 void *asm_thumb_get_code(asm_thumb_t *as) {
pythontech 0:5868e8752d44 119 return as->code_base;
pythontech 0:5868e8752d44 120 }
pythontech 0:5868e8752d44 121
pythontech 0:5868e8752d44 122 /*
pythontech 0:5868e8752d44 123 STATIC void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) {
pythontech 0:5868e8752d44 124 byte *c = asm_thumb_get_cur_to_write_bytes(as, 1);
pythontech 0:5868e8752d44 125 c[0] = b1;
pythontech 0:5868e8752d44 126 }
pythontech 0:5868e8752d44 127 */
pythontech 0:5868e8752d44 128
pythontech 0:5868e8752d44 129 /*
pythontech 0:5868e8752d44 130 #define IMM32_L0(x) ((x) & 0xff)
pythontech 0:5868e8752d44 131 #define IMM32_L1(x) (((x) >> 8) & 0xff)
pythontech 0:5868e8752d44 132 #define IMM32_L2(x) (((x) >> 16) & 0xff)
pythontech 0:5868e8752d44 133 #define IMM32_L3(x) (((x) >> 24) & 0xff)
pythontech 0:5868e8752d44 134
pythontech 0:5868e8752d44 135 STATIC void asm_thumb_write_word32(asm_thumb_t *as, int w32) {
pythontech 0:5868e8752d44 136 byte *c = asm_thumb_get_cur_to_write_bytes(as, 4);
pythontech 0:5868e8752d44 137 c[0] = IMM32_L0(w32);
pythontech 0:5868e8752d44 138 c[1] = IMM32_L1(w32);
pythontech 0:5868e8752d44 139 c[2] = IMM32_L2(w32);
pythontech 0:5868e8752d44 140 c[3] = IMM32_L3(w32);
pythontech 0:5868e8752d44 141 }
pythontech 0:5868e8752d44 142 */
pythontech 0:5868e8752d44 143
pythontech 0:5868e8752d44 144 // rlolist is a bit map indicating desired lo-registers
pythontech 0:5868e8752d44 145 #define OP_PUSH_RLIST(rlolist) (0xb400 | (rlolist))
pythontech 0:5868e8752d44 146 #define OP_PUSH_RLIST_LR(rlolist) (0xb400 | 0x0100 | (rlolist))
pythontech 0:5868e8752d44 147 #define OP_POP_RLIST(rlolist) (0xbc00 | (rlolist))
pythontech 0:5868e8752d44 148 #define OP_POP_RLIST_PC(rlolist) (0xbc00 | 0x0100 | (rlolist))
pythontech 0:5868e8752d44 149
pythontech 0:5868e8752d44 150 #define OP_ADD_SP(num_words) (0xb000 | (num_words))
pythontech 0:5868e8752d44 151 #define OP_SUB_SP(num_words) (0xb080 | (num_words))
pythontech 0:5868e8752d44 152
pythontech 0:5868e8752d44 153 // locals:
pythontech 0:5868e8752d44 154 // - stored on the stack in ascending order
pythontech 0:5868e8752d44 155 // - numbered 0 through num_locals-1
pythontech 0:5868e8752d44 156 // - SP points to first local
pythontech 0:5868e8752d44 157 //
pythontech 0:5868e8752d44 158 // | SP
pythontech 0:5868e8752d44 159 // v
pythontech 0:5868e8752d44 160 // l0 l1 l2 ... l(n-1)
pythontech 0:5868e8752d44 161 // ^ ^
pythontech 0:5868e8752d44 162 // | low address | high address in RAM
pythontech 0:5868e8752d44 163
pythontech 0:5868e8752d44 164 void asm_thumb_entry(asm_thumb_t *as, int num_locals) {
pythontech 0:5868e8752d44 165 // work out what to push and how many extra spaces to reserve on stack
pythontech 0:5868e8752d44 166 // so that we have enough for all locals and it's aligned an 8-byte boundary
pythontech 0:5868e8752d44 167 // we push extra regs (r1, r2, r3) to help do the stack adjustment
pythontech 0:5868e8752d44 168 // we probably should just always subtract from sp, since this would be more efficient
pythontech 0:5868e8752d44 169 // for push rlist, lowest numbered register at the lowest address
pythontech 0:5868e8752d44 170 uint reglist;
pythontech 0:5868e8752d44 171 uint stack_adjust;
pythontech 0:5868e8752d44 172 if (num_locals < 0) {
pythontech 0:5868e8752d44 173 num_locals = 0;
pythontech 0:5868e8752d44 174 }
pythontech 0:5868e8752d44 175 // don't pop r0 because it's used for return value
pythontech 0:5868e8752d44 176 switch (num_locals) {
pythontech 0:5868e8752d44 177 case 0:
pythontech 0:5868e8752d44 178 reglist = 0xf2;
pythontech 0:5868e8752d44 179 stack_adjust = 0;
pythontech 0:5868e8752d44 180 break;
pythontech 0:5868e8752d44 181
pythontech 0:5868e8752d44 182 case 1:
pythontech 0:5868e8752d44 183 reglist = 0xf2;
pythontech 0:5868e8752d44 184 stack_adjust = 0;
pythontech 0:5868e8752d44 185 break;
pythontech 0:5868e8752d44 186
pythontech 0:5868e8752d44 187 case 2:
pythontech 0:5868e8752d44 188 reglist = 0xfe;
pythontech 0:5868e8752d44 189 stack_adjust = 0;
pythontech 0:5868e8752d44 190 break;
pythontech 0:5868e8752d44 191
pythontech 0:5868e8752d44 192 case 3:
pythontech 0:5868e8752d44 193 reglist = 0xfe;
pythontech 0:5868e8752d44 194 stack_adjust = 0;
pythontech 0:5868e8752d44 195 break;
pythontech 0:5868e8752d44 196
pythontech 0:5868e8752d44 197 default:
pythontech 0:5868e8752d44 198 reglist = 0xfe;
pythontech 0:5868e8752d44 199 stack_adjust = ((num_locals - 3) + 1) & (~1);
pythontech 0:5868e8752d44 200 break;
pythontech 0:5868e8752d44 201 }
pythontech 0:5868e8752d44 202 asm_thumb_op16(as, OP_PUSH_RLIST_LR(reglist));
pythontech 0:5868e8752d44 203 if (stack_adjust > 0) {
pythontech 0:5868e8752d44 204 asm_thumb_op16(as, OP_SUB_SP(stack_adjust));
pythontech 0:5868e8752d44 205 }
pythontech 0:5868e8752d44 206 as->push_reglist = reglist;
pythontech 0:5868e8752d44 207 as->stack_adjust = stack_adjust;
pythontech 0:5868e8752d44 208 }
pythontech 0:5868e8752d44 209
pythontech 0:5868e8752d44 210 void asm_thumb_exit(asm_thumb_t *as) {
pythontech 0:5868e8752d44 211 if (as->stack_adjust > 0) {
pythontech 0:5868e8752d44 212 asm_thumb_op16(as, OP_ADD_SP(as->stack_adjust));
pythontech 0:5868e8752d44 213 }
pythontech 0:5868e8752d44 214 asm_thumb_op16(as, OP_POP_RLIST_PC(as->push_reglist));
pythontech 0:5868e8752d44 215 }
pythontech 0:5868e8752d44 216
pythontech 0:5868e8752d44 217 void asm_thumb_label_assign(asm_thumb_t *as, uint label) {
pythontech 0:5868e8752d44 218 assert(label < as->max_num_labels);
pythontech 0:5868e8752d44 219 if (as->pass < ASM_THUMB_PASS_EMIT) {
pythontech 0:5868e8752d44 220 // assign label offset
pythontech 0:5868e8752d44 221 assert(as->label_offsets[label] == -1);
pythontech 0:5868e8752d44 222 as->label_offsets[label] = as->code_offset;
pythontech 0:5868e8752d44 223 } else {
pythontech 0:5868e8752d44 224 // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
pythontech 0:5868e8752d44 225 //printf("l%d: (at %d=%ld)\n", label, as->label_offsets[label], as->code_offset);
pythontech 0:5868e8752d44 226 assert(as->label_offsets[label] == as->code_offset);
pythontech 0:5868e8752d44 227 }
pythontech 0:5868e8752d44 228 }
pythontech 0:5868e8752d44 229
pythontech 0:5868e8752d44 230 void asm_thumb_align(asm_thumb_t* as, uint align) {
pythontech 0:5868e8752d44 231 // TODO fill unused data with NOPs?
pythontech 0:5868e8752d44 232 as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
pythontech 0:5868e8752d44 233 }
pythontech 0:5868e8752d44 234
pythontech 0:5868e8752d44 235 void asm_thumb_data(asm_thumb_t* as, uint bytesize, uint val) {
pythontech 0:5868e8752d44 236 byte *c = asm_thumb_get_cur_to_write_bytes(as, bytesize);
pythontech 0:5868e8752d44 237 // only write to the buffer in the emit pass (otherwise we overflow dummy_data)
pythontech 0:5868e8752d44 238 if (as->pass == ASM_THUMB_PASS_EMIT) {
pythontech 0:5868e8752d44 239 // little endian
pythontech 0:5868e8752d44 240 for (uint i = 0; i < bytesize; i++) {
pythontech 0:5868e8752d44 241 *c++ = val;
pythontech 0:5868e8752d44 242 val >>= 8;
pythontech 0:5868e8752d44 243 }
pythontech 0:5868e8752d44 244 }
pythontech 0:5868e8752d44 245 }
pythontech 0:5868e8752d44 246
pythontech 0:5868e8752d44 247 STATIC mp_uint_t get_label_dest(asm_thumb_t *as, uint label) {
pythontech 0:5868e8752d44 248 assert(label < as->max_num_labels);
pythontech 0:5868e8752d44 249 return as->label_offsets[label];
pythontech 0:5868e8752d44 250 }
pythontech 0:5868e8752d44 251
pythontech 0:5868e8752d44 252 void asm_thumb_op16(asm_thumb_t *as, uint op) {
pythontech 0:5868e8752d44 253 byte *c = asm_thumb_get_cur_to_write_bytes(as, 2);
pythontech 0:5868e8752d44 254 // little endian
pythontech 0:5868e8752d44 255 c[0] = op;
pythontech 0:5868e8752d44 256 c[1] = op >> 8;
pythontech 0:5868e8752d44 257 }
pythontech 0:5868e8752d44 258
pythontech 0:5868e8752d44 259 void asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2) {
pythontech 0:5868e8752d44 260 byte *c = asm_thumb_get_cur_to_write_bytes(as, 4);
pythontech 0:5868e8752d44 261 // little endian, op1 then op2
pythontech 0:5868e8752d44 262 c[0] = op1;
pythontech 0:5868e8752d44 263 c[1] = op1 >> 8;
pythontech 0:5868e8752d44 264 c[2] = op2;
pythontech 0:5868e8752d44 265 c[3] = op2 >> 8;
pythontech 0:5868e8752d44 266 }
pythontech 0:5868e8752d44 267
pythontech 0:5868e8752d44 268 #define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest))
pythontech 0:5868e8752d44 269
pythontech 0:5868e8752d44 270 void asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src) {
pythontech 0:5868e8752d44 271 assert(rlo_dest < ASM_THUMB_REG_R8);
pythontech 0:5868e8752d44 272 assert(rlo_src < ASM_THUMB_REG_R8);
pythontech 0:5868e8752d44 273 asm_thumb_op16(as, OP_FORMAT_4(op, rlo_dest, rlo_src));
pythontech 0:5868e8752d44 274 }
pythontech 0:5868e8752d44 275
pythontech 0:5868e8752d44 276 void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) {
pythontech 0:5868e8752d44 277 uint op_lo;
pythontech 0:5868e8752d44 278 if (reg_src < 8) {
pythontech 0:5868e8752d44 279 op_lo = reg_src << 3;
pythontech 0:5868e8752d44 280 } else {
pythontech 0:5868e8752d44 281 op_lo = 0x40 | ((reg_src - 8) << 3);
pythontech 0:5868e8752d44 282 }
pythontech 0:5868e8752d44 283 if (reg_dest < 8) {
pythontech 0:5868e8752d44 284 op_lo |= reg_dest;
pythontech 0:5868e8752d44 285 } else {
pythontech 0:5868e8752d44 286 op_lo |= 0x80 | (reg_dest - 8);
pythontech 0:5868e8752d44 287 }
pythontech 0:5868e8752d44 288 // mov reg_dest, reg_src
pythontech 0:5868e8752d44 289 asm_thumb_op16(as, 0x4600 | op_lo);
pythontech 0:5868e8752d44 290 }
pythontech 0:5868e8752d44 291
pythontech 0:5868e8752d44 292 // if loading lo half with movw, the i16 value will be zero extended into the r32 register!
pythontech 0:5868e8752d44 293 void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src) {
pythontech 0:5868e8752d44 294 assert(reg_dest < ASM_THUMB_REG_R15);
pythontech 0:5868e8752d44 295 // mov[wt] reg_dest, #i16_src
pythontech 0:5868e8752d44 296 asm_thumb_op32(as, mov_op | ((i16_src >> 1) & 0x0400) | ((i16_src >> 12) & 0xf), ((i16_src << 4) & 0x7000) | (reg_dest << 8) | (i16_src & 0xff));
pythontech 0:5868e8752d44 297 }
pythontech 0:5868e8752d44 298
pythontech 0:5868e8752d44 299 #define OP_B_N(byte_offset) (0xe000 | (((byte_offset) >> 1) & 0x07ff))
pythontech 0:5868e8752d44 300
pythontech 0:5868e8752d44 301 bool asm_thumb_b_n_label(asm_thumb_t *as, uint label) {
pythontech 0:5868e8752d44 302 mp_uint_t dest = get_label_dest(as, label);
pythontech 0:5868e8752d44 303 mp_int_t rel = dest - as->code_offset;
pythontech 0:5868e8752d44 304 rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
pythontech 0:5868e8752d44 305 asm_thumb_op16(as, OP_B_N(rel));
pythontech 0:5868e8752d44 306 return as->pass != ASM_THUMB_PASS_EMIT || SIGNED_FIT12(rel);
pythontech 0:5868e8752d44 307 }
pythontech 0:5868e8752d44 308
pythontech 0:5868e8752d44 309 #define OP_BCC_N(cond, byte_offset) (0xd000 | ((cond) << 8) | (((byte_offset) >> 1) & 0x00ff))
pythontech 0:5868e8752d44 310
pythontech 0:5868e8752d44 311 // all these bit arithmetics need coverage testing!
pythontech 0:5868e8752d44 312 #define OP_BCC_W_HI(cond, byte_offset) (0xf000 | ((cond) << 6) | (((byte_offset) >> 10) & 0x0400) | (((byte_offset) >> 14) & 0x003f))
pythontech 0:5868e8752d44 313 #define OP_BCC_W_LO(byte_offset) (0x8000 | ((byte_offset) & 0x2000) | (((byte_offset) >> 1) & 0x0fff))
pythontech 0:5868e8752d44 314
pythontech 0:5868e8752d44 315 bool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide) {
pythontech 0:5868e8752d44 316 mp_uint_t dest = get_label_dest(as, label);
pythontech 0:5868e8752d44 317 mp_int_t rel = dest - as->code_offset;
pythontech 0:5868e8752d44 318 rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
pythontech 0:5868e8752d44 319 if (!wide) {
pythontech 0:5868e8752d44 320 asm_thumb_op16(as, OP_BCC_N(cond, rel));
pythontech 0:5868e8752d44 321 return as->pass != ASM_THUMB_PASS_EMIT || SIGNED_FIT9(rel);
pythontech 0:5868e8752d44 322 } else {
pythontech 0:5868e8752d44 323 asm_thumb_op32(as, OP_BCC_W_HI(cond, rel), OP_BCC_W_LO(rel));
pythontech 0:5868e8752d44 324 return true;
pythontech 0:5868e8752d44 325 }
pythontech 0:5868e8752d44 326 }
pythontech 0:5868e8752d44 327
pythontech 0:5868e8752d44 328 #define OP_BL_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))
pythontech 0:5868e8752d44 329 #define OP_BL_LO(byte_offset) (0xf800 | (((byte_offset) >> 1) & 0x07ff))
pythontech 0:5868e8752d44 330
pythontech 0:5868e8752d44 331 bool asm_thumb_bl_label(asm_thumb_t *as, uint label) {
pythontech 0:5868e8752d44 332 mp_uint_t dest = get_label_dest(as, label);
pythontech 0:5868e8752d44 333 mp_int_t rel = dest - as->code_offset;
pythontech 0:5868e8752d44 334 rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
pythontech 0:5868e8752d44 335 asm_thumb_op32(as, OP_BL_HI(rel), OP_BL_LO(rel));
pythontech 0:5868e8752d44 336 return as->pass != ASM_THUMB_PASS_EMIT || SIGNED_FIT23(rel);
pythontech 0:5868e8752d44 337 }
pythontech 0:5868e8752d44 338
pythontech 0:5868e8752d44 339 void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32) {
pythontech 0:5868e8752d44 340 // movw, movt does it in 8 bytes
pythontech 0:5868e8752d44 341 // ldr [pc, #], dw does it in 6 bytes, but we might not reach to end of code for dw
pythontech 0:5868e8752d44 342
pythontech 0:5868e8752d44 343 asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, reg_dest, i32);
pythontech 0:5868e8752d44 344 asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVT, reg_dest, i32 >> 16);
pythontech 0:5868e8752d44 345 }
pythontech 0:5868e8752d44 346
pythontech 0:5868e8752d44 347 void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) {
pythontech 0:5868e8752d44 348 if (reg_dest < 8 && UNSIGNED_FIT8(i32)) {
pythontech 0:5868e8752d44 349 asm_thumb_mov_rlo_i8(as, reg_dest, i32);
pythontech 0:5868e8752d44 350 } else if (UNSIGNED_FIT16(i32)) {
pythontech 0:5868e8752d44 351 asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, reg_dest, i32);
pythontech 0:5868e8752d44 352 } else {
pythontech 0:5868e8752d44 353 asm_thumb_mov_reg_i32(as, reg_dest, i32);
pythontech 0:5868e8752d44 354 }
pythontech 0:5868e8752d44 355 }
pythontech 0:5868e8752d44 356
pythontech 0:5868e8752d44 357 // i32 is stored as a full word in the code, and aligned to machine-word boundary
pythontech 0:5868e8752d44 358 // TODO this is very inefficient, improve it!
pythontech 0:5868e8752d44 359 void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) {
pythontech 0:5868e8752d44 360 // align on machine-word + 2
pythontech 0:5868e8752d44 361 if ((as->code_offset & 3) == 0) {
pythontech 0:5868e8752d44 362 asm_thumb_op16(as, ASM_THUMB_OP_NOP);
pythontech 0:5868e8752d44 363 }
pythontech 0:5868e8752d44 364 // jump over the i32 value (instruction prefetch adds 2 to PC)
pythontech 0:5868e8752d44 365 asm_thumb_op16(as, OP_B_N(2));
pythontech 0:5868e8752d44 366 // store i32 on machine-word aligned boundary
pythontech 0:5868e8752d44 367 asm_thumb_data(as, 4, i32);
pythontech 0:5868e8752d44 368 // do the actual load of the i32 value
pythontech 0:5868e8752d44 369 asm_thumb_mov_reg_i32_optimised(as, reg_dest, i32);
pythontech 0:5868e8752d44 370 }
pythontech 0:5868e8752d44 371
pythontech 0:5868e8752d44 372 #define OP_STR_TO_SP_OFFSET(rlo_dest, word_offset) (0x9000 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
pythontech 0:5868e8752d44 373 #define OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset) (0x9800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
pythontech 0:5868e8752d44 374
pythontech 0:5868e8752d44 375 void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num, uint rlo_src) {
pythontech 0:5868e8752d44 376 assert(rlo_src < ASM_THUMB_REG_R8);
pythontech 0:5868e8752d44 377 int word_offset = local_num;
pythontech 0:5868e8752d44 378 assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
pythontech 0:5868e8752d44 379 asm_thumb_op16(as, OP_STR_TO_SP_OFFSET(rlo_src, word_offset));
pythontech 0:5868e8752d44 380 }
pythontech 0:5868e8752d44 381
pythontech 0:5868e8752d44 382 void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {
pythontech 0:5868e8752d44 383 assert(rlo_dest < ASM_THUMB_REG_R8);
pythontech 0:5868e8752d44 384 int word_offset = local_num;
pythontech 0:5868e8752d44 385 assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
pythontech 0:5868e8752d44 386 asm_thumb_op16(as, OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset));
pythontech 0:5868e8752d44 387 }
pythontech 0:5868e8752d44 388
pythontech 0:5868e8752d44 389 #define OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset) (0xa800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
pythontech 0:5868e8752d44 390
pythontech 0:5868e8752d44 391 void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num) {
pythontech 0:5868e8752d44 392 assert(rlo_dest < ASM_THUMB_REG_R8);
pythontech 0:5868e8752d44 393 int word_offset = local_num;
pythontech 0:5868e8752d44 394 assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
pythontech 0:5868e8752d44 395 asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset));
pythontech 0:5868e8752d44 396 }
pythontech 0:5868e8752d44 397
pythontech 0:5868e8752d44 398 // this could be wrong, because it should have a range of +/- 16MiB...
pythontech 0:5868e8752d44 399 #define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))
pythontech 0:5868e8752d44 400 #define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))
pythontech 0:5868e8752d44 401
pythontech 0:5868e8752d44 402 void asm_thumb_b_label(asm_thumb_t *as, uint label) {
pythontech 0:5868e8752d44 403 mp_uint_t dest = get_label_dest(as, label);
pythontech 0:5868e8752d44 404 mp_int_t rel = dest - as->code_offset;
pythontech 0:5868e8752d44 405 rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
pythontech 0:5868e8752d44 406 if (dest != (mp_uint_t)-1 && rel <= -4) {
pythontech 0:5868e8752d44 407 // is a backwards jump, so we know the size of the jump on the first pass
pythontech 0:5868e8752d44 408 // calculate rel assuming 12 bit relative jump
pythontech 0:5868e8752d44 409 if (SIGNED_FIT12(rel)) {
pythontech 0:5868e8752d44 410 asm_thumb_op16(as, OP_B_N(rel));
pythontech 0:5868e8752d44 411 } else {
pythontech 0:5868e8752d44 412 goto large_jump;
pythontech 0:5868e8752d44 413 }
pythontech 0:5868e8752d44 414 } else {
pythontech 0:5868e8752d44 415 // is a forwards jump, so need to assume it's large
pythontech 0:5868e8752d44 416 large_jump:
pythontech 0:5868e8752d44 417 asm_thumb_op32(as, OP_BW_HI(rel), OP_BW_LO(rel));
pythontech 0:5868e8752d44 418 }
pythontech 0:5868e8752d44 419 }
pythontech 0:5868e8752d44 420
pythontech 0:5868e8752d44 421 void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) {
pythontech 0:5868e8752d44 422 mp_uint_t dest = get_label_dest(as, label);
pythontech 0:5868e8752d44 423 mp_int_t rel = dest - as->code_offset;
pythontech 0:5868e8752d44 424 rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
pythontech 0:5868e8752d44 425 if (dest != (mp_uint_t)-1 && rel <= -4) {
pythontech 0:5868e8752d44 426 // is a backwards jump, so we know the size of the jump on the first pass
pythontech 0:5868e8752d44 427 // calculate rel assuming 9 bit relative jump
pythontech 0:5868e8752d44 428 if (SIGNED_FIT9(rel)) {
pythontech 0:5868e8752d44 429 asm_thumb_op16(as, OP_BCC_N(cond, rel));
pythontech 0:5868e8752d44 430 } else {
pythontech 0:5868e8752d44 431 goto large_jump;
pythontech 0:5868e8752d44 432 }
pythontech 0:5868e8752d44 433 } else {
pythontech 0:5868e8752d44 434 // is a forwards jump, so need to assume it's large
pythontech 0:5868e8752d44 435 large_jump:
pythontech 0:5868e8752d44 436 asm_thumb_op32(as, OP_BCC_W_HI(cond, rel), OP_BCC_W_LO(rel));
pythontech 0:5868e8752d44 437 }
pythontech 0:5868e8752d44 438 }
pythontech 0:5868e8752d44 439
pythontech 0:5868e8752d44 440 #define OP_BLX(reg) (0x4780 | ((reg) << 3))
pythontech 0:5868e8752d44 441 #define OP_SVC(arg) (0xdf00 | (arg))
pythontech 0:5868e8752d44 442
pythontech 0:5868e8752d44 443 void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp) {
pythontech 0:5868e8752d44 444 /* TODO make this use less bytes
pythontech 0:5868e8752d44 445 uint rlo_base = ASM_THUMB_REG_R3;
pythontech 0:5868e8752d44 446 uint rlo_dest = ASM_THUMB_REG_R7;
pythontech 0:5868e8752d44 447 uint word_offset = 4;
pythontech 0:5868e8752d44 448 asm_thumb_op16(as, 0x0000);
pythontech 0:5868e8752d44 449 asm_thumb_op16(as, 0x6800 | (word_offset << 6) | (rlo_base << 3) | rlo_dest); // ldr rlo_dest, [rlo_base, #offset]
pythontech 0:5868e8752d44 450 asm_thumb_op16(as, 0x4780 | (ASM_THUMB_REG_R9 << 3)); // blx reg
pythontech 0:5868e8752d44 451 */
pythontech 0:5868e8752d44 452
pythontech 0:5868e8752d44 453 if (fun_id < 32) {
pythontech 0:5868e8752d44 454 // load ptr to function from table, indexed by fun_id (must be in range 0-31); 4 bytes
pythontech 0:5868e8752d44 455 asm_thumb_op16(as, ASM_THUMB_FORMAT_9_10_ENCODE(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, reg_temp, ASM_THUMB_REG_R7, fun_id));
pythontech 0:5868e8752d44 456 asm_thumb_op16(as, OP_BLX(reg_temp));
pythontech 0:5868e8752d44 457 } else {
pythontech 0:5868e8752d44 458 // load ptr to function into register using immediate; 6 bytes
pythontech 0:5868e8752d44 459 asm_thumb_mov_reg_i32(as, reg_temp, (mp_uint_t)fun_ptr);
pythontech 0:5868e8752d44 460 asm_thumb_op16(as, OP_BLX(reg_temp));
pythontech 0:5868e8752d44 461 }
pythontech 0:5868e8752d44 462 }
pythontech 0:5868e8752d44 463
pythontech 0:5868e8752d44 464 #endif // MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB