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) 2014 Fabian Vogt
pythontech 0:5868e8752d44 7 * Copyright (c) 2013, 2014 Damien P. George
pythontech 0:5868e8752d44 8 *
pythontech 0:5868e8752d44 9 * Permission is hereby granted, free of charge, to any person obtaining a copy
pythontech 0:5868e8752d44 10 * of this software and associated documentation files (the "Software"), to deal
pythontech 0:5868e8752d44 11 * in the Software without restriction, including without limitation the rights
pythontech 0:5868e8752d44 12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
pythontech 0:5868e8752d44 13 * copies of the Software, and to permit persons to whom the Software is
pythontech 0:5868e8752d44 14 * furnished to do so, subject to the following conditions:
pythontech 0:5868e8752d44 15 *
pythontech 0:5868e8752d44 16 * The above copyright notice and this permission notice shall be included in
pythontech 0:5868e8752d44 17 * all copies or substantial portions of the Software.
pythontech 0:5868e8752d44 18 *
pythontech 0:5868e8752d44 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
pythontech 0:5868e8752d44 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
pythontech 0:5868e8752d44 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
pythontech 0:5868e8752d44 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
pythontech 0:5868e8752d44 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
pythontech 0:5868e8752d44 24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
pythontech 0:5868e8752d44 25 * THE SOFTWARE.
pythontech 0:5868e8752d44 26 */
pythontech 0:5868e8752d44 27
pythontech 0:5868e8752d44 28 #include <stdio.h>
pythontech 0:5868e8752d44 29 #include <assert.h>
pythontech 0:5868e8752d44 30 #include <string.h>
pythontech 0:5868e8752d44 31
pythontech 0:5868e8752d44 32 #include "py/mpconfig.h"
pythontech 0:5868e8752d44 33
pythontech 0:5868e8752d44 34 // wrapper around everything in this file
pythontech 0:5868e8752d44 35 #if MICROPY_EMIT_ARM
pythontech 0:5868e8752d44 36
pythontech 0:5868e8752d44 37 #include "py/asmarm.h"
pythontech 0:5868e8752d44 38
pythontech 0:5868e8752d44 39 #define SIGNED_FIT24(x) (((x) & 0xff800000) == 0) || (((x) & 0xff000000) == 0xff000000)
pythontech 0:5868e8752d44 40
pythontech 0:5868e8752d44 41 struct _asm_arm_t {
pythontech 0:5868e8752d44 42 uint pass;
pythontech 0:5868e8752d44 43 mp_uint_t code_offset;
pythontech 0:5868e8752d44 44 mp_uint_t code_size;
pythontech 0:5868e8752d44 45 byte *code_base;
pythontech 0:5868e8752d44 46 byte dummy_data[4];
pythontech 0:5868e8752d44 47
pythontech 0:5868e8752d44 48 mp_uint_t max_num_labels;
pythontech 0:5868e8752d44 49 mp_uint_t *label_offsets;
pythontech 0:5868e8752d44 50 uint push_reglist;
pythontech 0:5868e8752d44 51 uint stack_adjust;
pythontech 0:5868e8752d44 52 };
pythontech 0:5868e8752d44 53
pythontech 0:5868e8752d44 54 asm_arm_t *asm_arm_new(uint max_num_labels) {
pythontech 0:5868e8752d44 55 asm_arm_t *as;
pythontech 0:5868e8752d44 56
pythontech 0:5868e8752d44 57 as = m_new0(asm_arm_t, 1);
pythontech 0:5868e8752d44 58 as->max_num_labels = max_num_labels;
pythontech 0:5868e8752d44 59 as->label_offsets = m_new(mp_uint_t, max_num_labels);
pythontech 0:5868e8752d44 60
pythontech 0:5868e8752d44 61 return as;
pythontech 0:5868e8752d44 62 }
pythontech 0:5868e8752d44 63
pythontech 0:5868e8752d44 64 void asm_arm_free(asm_arm_t *as, bool free_code) {
pythontech 0:5868e8752d44 65 if (free_code) {
pythontech 0:5868e8752d44 66 MP_PLAT_FREE_EXEC(as->code_base, as->code_size);
pythontech 0:5868e8752d44 67 }
pythontech 0:5868e8752d44 68 m_del(mp_uint_t, as->label_offsets, as->max_num_labels);
pythontech 0:5868e8752d44 69 m_del_obj(asm_arm_t, as);
pythontech 0:5868e8752d44 70 }
pythontech 0:5868e8752d44 71
pythontech 0:5868e8752d44 72 void asm_arm_start_pass(asm_arm_t *as, uint pass) {
pythontech 0:5868e8752d44 73 if (pass == ASM_ARM_PASS_COMPUTE) {
pythontech 0:5868e8752d44 74 memset(as->label_offsets, -1, as->max_num_labels * sizeof(mp_uint_t));
pythontech 0:5868e8752d44 75 } else if (pass == ASM_ARM_PASS_EMIT) {
pythontech 0:5868e8752d44 76 MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size);
pythontech 0:5868e8752d44 77 if (as->code_base == NULL) {
pythontech 0:5868e8752d44 78 assert(0);
pythontech 0:5868e8752d44 79 }
pythontech 0:5868e8752d44 80 }
pythontech 0:5868e8752d44 81 as->pass = pass;
pythontech 0:5868e8752d44 82 as->code_offset = 0;
pythontech 0:5868e8752d44 83 }
pythontech 0:5868e8752d44 84
pythontech 0:5868e8752d44 85 void asm_arm_end_pass(asm_arm_t *as) {
pythontech 0:5868e8752d44 86 if (as->pass == ASM_ARM_PASS_EMIT) {
pythontech 0:5868e8752d44 87 #ifdef __arm__
pythontech 0:5868e8752d44 88 // flush I- and D-cache
pythontech 0:5868e8752d44 89 asm volatile(
pythontech 0:5868e8752d44 90 "0:"
pythontech 0:5868e8752d44 91 "mrc p15, 0, r15, c7, c10, 3\n"
pythontech 0:5868e8752d44 92 "bne 0b\n"
pythontech 0:5868e8752d44 93 "mov r0, #0\n"
pythontech 0:5868e8752d44 94 "mcr p15, 0, r0, c7, c7, 0\n"
pythontech 0:5868e8752d44 95 : : : "r0", "cc");
pythontech 0:5868e8752d44 96 #endif
pythontech 0:5868e8752d44 97 }
pythontech 0:5868e8752d44 98 }
pythontech 0:5868e8752d44 99
pythontech 0:5868e8752d44 100 // all functions must go through this one to emit bytes
pythontech 0:5868e8752d44 101 // if as->pass < ASM_ARM_PASS_EMIT, then this function only returns a buffer of 4 bytes length
pythontech 0:5868e8752d44 102 STATIC byte *asm_arm_get_cur_to_write_bytes(asm_arm_t *as, int num_bytes_to_write) {
pythontech 0:5868e8752d44 103 if (as->pass < ASM_ARM_PASS_EMIT) {
pythontech 0:5868e8752d44 104 as->code_offset += num_bytes_to_write;
pythontech 0:5868e8752d44 105 return as->dummy_data;
pythontech 0:5868e8752d44 106 } else {
pythontech 0:5868e8752d44 107 assert(as->code_offset + num_bytes_to_write <= as->code_size);
pythontech 0:5868e8752d44 108 byte *c = as->code_base + as->code_offset;
pythontech 0:5868e8752d44 109 as->code_offset += num_bytes_to_write;
pythontech 0:5868e8752d44 110 return c;
pythontech 0:5868e8752d44 111 }
pythontech 0:5868e8752d44 112 }
pythontech 0:5868e8752d44 113
pythontech 0:5868e8752d44 114 uint asm_arm_get_code_pos(asm_arm_t *as) {
pythontech 0:5868e8752d44 115 return as->code_offset;
pythontech 0:5868e8752d44 116 }
pythontech 0:5868e8752d44 117
pythontech 0:5868e8752d44 118 uint asm_arm_get_code_size(asm_arm_t *as) {
pythontech 0:5868e8752d44 119 return as->code_size;
pythontech 0:5868e8752d44 120 }
pythontech 0:5868e8752d44 121
pythontech 0:5868e8752d44 122 void *asm_arm_get_code(asm_arm_t *as) {
pythontech 0:5868e8752d44 123 return as->code_base;
pythontech 0:5868e8752d44 124 }
pythontech 0:5868e8752d44 125
pythontech 0:5868e8752d44 126 // Insert word into instruction flow
pythontech 0:5868e8752d44 127 STATIC void emit(asm_arm_t *as, uint op) {
pythontech 0:5868e8752d44 128 *(uint*)asm_arm_get_cur_to_write_bytes(as, 4) = op;
pythontech 0:5868e8752d44 129 }
pythontech 0:5868e8752d44 130
pythontech 0:5868e8752d44 131 // Insert word into instruction flow, add "ALWAYS" condition code
pythontech 0:5868e8752d44 132 STATIC void emit_al(asm_arm_t *as, uint op) {
pythontech 0:5868e8752d44 133 emit(as, op | ASM_ARM_CC_AL);
pythontech 0:5868e8752d44 134 }
pythontech 0:5868e8752d44 135
pythontech 0:5868e8752d44 136 // Basic instructions without condition code
pythontech 0:5868e8752d44 137 STATIC uint asm_arm_op_push(uint reglist) {
pythontech 0:5868e8752d44 138 // stmfd sp!, {reglist}
pythontech 0:5868e8752d44 139 return 0x92d0000 | (reglist & 0xFFFF);
pythontech 0:5868e8752d44 140 }
pythontech 0:5868e8752d44 141
pythontech 0:5868e8752d44 142 STATIC uint asm_arm_op_pop(uint reglist) {
pythontech 0:5868e8752d44 143 // ldmfd sp!, {reglist}
pythontech 0:5868e8752d44 144 return 0x8bd0000 | (reglist & 0xFFFF);
pythontech 0:5868e8752d44 145 }
pythontech 0:5868e8752d44 146
pythontech 0:5868e8752d44 147 STATIC uint asm_arm_op_mov_reg(uint rd, uint rn) {
pythontech 0:5868e8752d44 148 // mov rd, rn
pythontech 0:5868e8752d44 149 return 0x1a00000 | (rd << 12) | rn;
pythontech 0:5868e8752d44 150 }
pythontech 0:5868e8752d44 151
pythontech 0:5868e8752d44 152 STATIC uint asm_arm_op_mov_imm(uint rd, uint imm) {
pythontech 0:5868e8752d44 153 // mov rd, #imm
pythontech 0:5868e8752d44 154 return 0x3a00000 | (rd << 12) | imm;
pythontech 0:5868e8752d44 155 }
pythontech 0:5868e8752d44 156
pythontech 0:5868e8752d44 157 STATIC uint asm_arm_op_mvn_imm(uint rd, uint imm) {
pythontech 0:5868e8752d44 158 // mvn rd, #imm
pythontech 0:5868e8752d44 159 return 0x3e00000 | (rd << 12) | imm;
pythontech 0:5868e8752d44 160 }
pythontech 0:5868e8752d44 161
pythontech 0:5868e8752d44 162 STATIC uint asm_arm_op_add_imm(uint rd, uint rn, uint imm) {
pythontech 0:5868e8752d44 163 // add rd, rn, #imm
pythontech 0:5868e8752d44 164 return 0x2800000 | (rn << 16) | (rd << 12) | (imm & 0xFF);
pythontech 0:5868e8752d44 165 }
pythontech 0:5868e8752d44 166
pythontech 0:5868e8752d44 167 STATIC uint asm_arm_op_add_reg(uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 168 // add rd, rn, rm
pythontech 0:5868e8752d44 169 return 0x0800000 | (rn << 16) | (rd << 12) | rm;
pythontech 0:5868e8752d44 170 }
pythontech 0:5868e8752d44 171
pythontech 0:5868e8752d44 172 STATIC uint asm_arm_op_sub_imm(uint rd, uint rn, uint imm) {
pythontech 0:5868e8752d44 173 // sub rd, rn, #imm
pythontech 0:5868e8752d44 174 return 0x2400000 | (rn << 16) | (rd << 12) | (imm & 0xFF);
pythontech 0:5868e8752d44 175 }
pythontech 0:5868e8752d44 176
pythontech 0:5868e8752d44 177 STATIC uint asm_arm_op_sub_reg(uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 178 // sub rd, rn, rm
pythontech 0:5868e8752d44 179 return 0x0400000 | (rn << 16) | (rd << 12) | rm;
pythontech 0:5868e8752d44 180 }
pythontech 0:5868e8752d44 181
pythontech 0:5868e8752d44 182 STATIC uint asm_arm_op_mul_reg(uint rd, uint rm, uint rs) {
pythontech 0:5868e8752d44 183 // mul rd, rm, rs
pythontech 0:5868e8752d44 184 assert(rd != rm);
pythontech 0:5868e8752d44 185 return 0x0000090 | (rd << 16) | (rs << 8) | rm;
pythontech 0:5868e8752d44 186 }
pythontech 0:5868e8752d44 187
pythontech 0:5868e8752d44 188 STATIC uint asm_arm_op_and_reg(uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 189 // and rd, rn, rm
pythontech 0:5868e8752d44 190 return 0x0000000 | (rn << 16) | (rd << 12) | rm;
pythontech 0:5868e8752d44 191 }
pythontech 0:5868e8752d44 192
pythontech 0:5868e8752d44 193 STATIC uint asm_arm_op_eor_reg(uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 194 // eor rd, rn, rm
pythontech 0:5868e8752d44 195 return 0x0200000 | (rn << 16) | (rd << 12) | rm;
pythontech 0:5868e8752d44 196 }
pythontech 0:5868e8752d44 197
pythontech 0:5868e8752d44 198 STATIC uint asm_arm_op_orr_reg(uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 199 // orr rd, rn, rm
pythontech 0:5868e8752d44 200 return 0x1800000 | (rn << 16) | (rd << 12) | rm;
pythontech 0:5868e8752d44 201 }
pythontech 0:5868e8752d44 202
pythontech 0:5868e8752d44 203 void asm_arm_bkpt(asm_arm_t *as) {
pythontech 0:5868e8752d44 204 // bkpt #0
pythontech 0:5868e8752d44 205 emit_al(as, 0x1200070);
pythontech 0:5868e8752d44 206 }
pythontech 0:5868e8752d44 207
pythontech 0:5868e8752d44 208 // locals:
pythontech 0:5868e8752d44 209 // - stored on the stack in ascending order
pythontech 0:5868e8752d44 210 // - numbered 0 through num_locals-1
pythontech 0:5868e8752d44 211 // - SP points to first local
pythontech 0:5868e8752d44 212 //
pythontech 0:5868e8752d44 213 // | SP
pythontech 0:5868e8752d44 214 // v
pythontech 0:5868e8752d44 215 // l0 l1 l2 ... l(n-1)
pythontech 0:5868e8752d44 216 // ^ ^
pythontech 0:5868e8752d44 217 // | low address | high address in RAM
pythontech 0:5868e8752d44 218
pythontech 0:5868e8752d44 219 void asm_arm_entry(asm_arm_t *as, int num_locals) {
pythontech 0:5868e8752d44 220
pythontech 0:5868e8752d44 221 if (num_locals < 0) {
pythontech 0:5868e8752d44 222 num_locals = 0;
pythontech 0:5868e8752d44 223 }
pythontech 0:5868e8752d44 224
pythontech 0:5868e8752d44 225 as->stack_adjust = 0;
pythontech 0:5868e8752d44 226 as->push_reglist = 1 << ASM_ARM_REG_R1
pythontech 0:5868e8752d44 227 | 1 << ASM_ARM_REG_R2
pythontech 0:5868e8752d44 228 | 1 << ASM_ARM_REG_R3
pythontech 0:5868e8752d44 229 | 1 << ASM_ARM_REG_R4
pythontech 0:5868e8752d44 230 | 1 << ASM_ARM_REG_R5
pythontech 0:5868e8752d44 231 | 1 << ASM_ARM_REG_R6
pythontech 0:5868e8752d44 232 | 1 << ASM_ARM_REG_R7
pythontech 0:5868e8752d44 233 | 1 << ASM_ARM_REG_R8;
pythontech 0:5868e8752d44 234
pythontech 0:5868e8752d44 235 // Only adjust the stack if there are more locals than usable registers
pythontech 0:5868e8752d44 236 if (num_locals > 3) {
pythontech 0:5868e8752d44 237 as->stack_adjust = num_locals * 4;
pythontech 0:5868e8752d44 238 // Align stack to 8 bytes
pythontech 0:5868e8752d44 239 if (num_locals & 1) {
pythontech 0:5868e8752d44 240 as->stack_adjust += 4;
pythontech 0:5868e8752d44 241 }
pythontech 0:5868e8752d44 242 }
pythontech 0:5868e8752d44 243
pythontech 0:5868e8752d44 244 emit_al(as, asm_arm_op_push(as->push_reglist | 1 << ASM_ARM_REG_LR));
pythontech 0:5868e8752d44 245 if (as->stack_adjust > 0) {
pythontech 0:5868e8752d44 246 emit_al(as, asm_arm_op_sub_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust));
pythontech 0:5868e8752d44 247 }
pythontech 0:5868e8752d44 248 }
pythontech 0:5868e8752d44 249
pythontech 0:5868e8752d44 250 void asm_arm_exit(asm_arm_t *as) {
pythontech 0:5868e8752d44 251 if (as->stack_adjust > 0) {
pythontech 0:5868e8752d44 252 emit_al(as, asm_arm_op_add_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust));
pythontech 0:5868e8752d44 253 }
pythontech 0:5868e8752d44 254
pythontech 0:5868e8752d44 255 emit_al(as, asm_arm_op_pop(as->push_reglist | (1 << ASM_ARM_REG_PC)));
pythontech 0:5868e8752d44 256 }
pythontech 0:5868e8752d44 257
pythontech 0:5868e8752d44 258 void asm_arm_push(asm_arm_t *as, uint reglist) {
pythontech 0:5868e8752d44 259 emit_al(as, asm_arm_op_push(reglist));
pythontech 0:5868e8752d44 260 }
pythontech 0:5868e8752d44 261
pythontech 0:5868e8752d44 262 void asm_arm_pop(asm_arm_t *as, uint reglist) {
pythontech 0:5868e8752d44 263 emit_al(as, asm_arm_op_pop(reglist));
pythontech 0:5868e8752d44 264 }
pythontech 0:5868e8752d44 265
pythontech 0:5868e8752d44 266 void asm_arm_label_assign(asm_arm_t *as, uint label) {
pythontech 0:5868e8752d44 267 assert(label < as->max_num_labels);
pythontech 0:5868e8752d44 268 if (as->pass < ASM_ARM_PASS_EMIT) {
pythontech 0:5868e8752d44 269 // assign label offset
pythontech 0:5868e8752d44 270 assert(as->label_offsets[label] == -1);
pythontech 0:5868e8752d44 271 as->label_offsets[label] = as->code_offset;
pythontech 0:5868e8752d44 272 } else {
pythontech 0:5868e8752d44 273 // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
pythontech 0:5868e8752d44 274 assert(as->label_offsets[label] == as->code_offset);
pythontech 0:5868e8752d44 275 }
pythontech 0:5868e8752d44 276 }
pythontech 0:5868e8752d44 277
pythontech 0:5868e8752d44 278 void asm_arm_align(asm_arm_t* as, uint align) {
pythontech 0:5868e8752d44 279 // TODO fill unused data with NOPs?
pythontech 0:5868e8752d44 280 as->code_offset = (as->code_offset + align - 1) & (~(align - 1));
pythontech 0:5868e8752d44 281 }
pythontech 0:5868e8752d44 282
pythontech 0:5868e8752d44 283 void asm_arm_data(asm_arm_t* as, uint bytesize, uint val) {
pythontech 0:5868e8752d44 284 byte *c = asm_arm_get_cur_to_write_bytes(as, bytesize);
pythontech 0:5868e8752d44 285 // only write to the buffer in the emit pass (otherwise we overflow dummy_data)
pythontech 0:5868e8752d44 286 if (as->pass == ASM_ARM_PASS_EMIT) {
pythontech 0:5868e8752d44 287 // little endian
pythontech 0:5868e8752d44 288 for (uint i = 0; i < bytesize; i++) {
pythontech 0:5868e8752d44 289 *c++ = val;
pythontech 0:5868e8752d44 290 val >>= 8;
pythontech 0:5868e8752d44 291 }
pythontech 0:5868e8752d44 292 }
pythontech 0:5868e8752d44 293 }
pythontech 0:5868e8752d44 294
pythontech 0:5868e8752d44 295 void asm_arm_mov_reg_reg(asm_arm_t *as, uint reg_dest, uint reg_src) {
pythontech 0:5868e8752d44 296 emit_al(as, asm_arm_op_mov_reg(reg_dest, reg_src));
pythontech 0:5868e8752d44 297 }
pythontech 0:5868e8752d44 298
pythontech 0:5868e8752d44 299 void asm_arm_mov_reg_i32(asm_arm_t *as, uint rd, int imm) {
pythontech 0:5868e8752d44 300 // TODO: There are more variants of immediate values
pythontech 0:5868e8752d44 301 if ((imm & 0xFF) == imm) {
pythontech 0:5868e8752d44 302 emit_al(as, asm_arm_op_mov_imm(rd, imm));
pythontech 0:5868e8752d44 303 } else if (imm < 0 && imm >= -256) {
pythontech 0:5868e8752d44 304 // mvn is "move not", not "move negative"
pythontech 0:5868e8752d44 305 emit_al(as, asm_arm_op_mvn_imm(rd, ~imm));
pythontech 0:5868e8752d44 306 } else {
pythontech 0:5868e8752d44 307 //Insert immediate into code and jump over it
pythontech 0:5868e8752d44 308 emit_al(as, 0x59f0000 | (rd << 12)); // ldr rd, [pc]
pythontech 0:5868e8752d44 309 emit_al(as, 0xa000000); // b pc
pythontech 0:5868e8752d44 310 emit(as, imm);
pythontech 0:5868e8752d44 311 }
pythontech 0:5868e8752d44 312 }
pythontech 0:5868e8752d44 313
pythontech 0:5868e8752d44 314 void asm_arm_mov_local_reg(asm_arm_t *as, int local_num, uint rd) {
pythontech 0:5868e8752d44 315 // str rd, [sp, #local_num*4]
pythontech 0:5868e8752d44 316 emit_al(as, 0x58d0000 | (rd << 12) | (local_num << 2));
pythontech 0:5868e8752d44 317 }
pythontech 0:5868e8752d44 318
pythontech 0:5868e8752d44 319 void asm_arm_mov_reg_local(asm_arm_t *as, uint rd, int local_num) {
pythontech 0:5868e8752d44 320 // ldr rd, [sp, #local_num*4]
pythontech 0:5868e8752d44 321 emit_al(as, 0x59d0000 | (rd << 12) | (local_num << 2));
pythontech 0:5868e8752d44 322 }
pythontech 0:5868e8752d44 323
pythontech 0:5868e8752d44 324 void asm_arm_cmp_reg_i8(asm_arm_t *as, uint rd, int imm) {
pythontech 0:5868e8752d44 325 // cmp rd, #imm
pythontech 0:5868e8752d44 326 emit_al(as, 0x3500000 | (rd << 16) | (imm & 0xFF));
pythontech 0:5868e8752d44 327 }
pythontech 0:5868e8752d44 328
pythontech 0:5868e8752d44 329 void asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn) {
pythontech 0:5868e8752d44 330 // cmp rd, rn
pythontech 0:5868e8752d44 331 emit_al(as, 0x1500000 | (rd << 16) | rn);
pythontech 0:5868e8752d44 332 }
pythontech 0:5868e8752d44 333
pythontech 0:5868e8752d44 334 void asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond) {
pythontech 0:5868e8752d44 335 emit(as, asm_arm_op_mov_imm(rd, 1) | cond); // movCOND rd, #1
pythontech 0:5868e8752d44 336 emit(as, asm_arm_op_mov_imm(rd, 0) | (cond ^ (1 << 28))); // mov!COND rd, #0
pythontech 0:5868e8752d44 337 }
pythontech 0:5868e8752d44 338
pythontech 0:5868e8752d44 339 void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 340 // add rd, rn, rm
pythontech 0:5868e8752d44 341 emit_al(as, asm_arm_op_add_reg(rd, rn, rm));
pythontech 0:5868e8752d44 342 }
pythontech 0:5868e8752d44 343
pythontech 0:5868e8752d44 344 void asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 345 // sub rd, rn, rm
pythontech 0:5868e8752d44 346 emit_al(as, asm_arm_op_sub_reg(rd, rn, rm));
pythontech 0:5868e8752d44 347 }
pythontech 0:5868e8752d44 348
pythontech 0:5868e8752d44 349 void asm_arm_mul_reg_reg_reg(asm_arm_t *as, uint rd, uint rs, uint rm) {
pythontech 0:5868e8752d44 350 // rs and rm are swapped because of restriction rd!=rm
pythontech 0:5868e8752d44 351 // mul rd, rm, rs
pythontech 0:5868e8752d44 352 emit_al(as, asm_arm_op_mul_reg(rd, rm, rs));
pythontech 0:5868e8752d44 353 }
pythontech 0:5868e8752d44 354
pythontech 0:5868e8752d44 355 void asm_arm_and_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 356 // and rd, rn, rm
pythontech 0:5868e8752d44 357 emit_al(as, asm_arm_op_and_reg(rd, rn, rm));
pythontech 0:5868e8752d44 358 }
pythontech 0:5868e8752d44 359
pythontech 0:5868e8752d44 360 void asm_arm_eor_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 361 // eor rd, rn, rm
pythontech 0:5868e8752d44 362 emit_al(as, asm_arm_op_eor_reg(rd, rn, rm));
pythontech 0:5868e8752d44 363 }
pythontech 0:5868e8752d44 364
pythontech 0:5868e8752d44 365 void asm_arm_orr_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
pythontech 0:5868e8752d44 366 // orr rd, rn, rm
pythontech 0:5868e8752d44 367 emit_al(as, asm_arm_op_orr_reg(rd, rn, rm));
pythontech 0:5868e8752d44 368 }
pythontech 0:5868e8752d44 369
pythontech 0:5868e8752d44 370 void asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num) {
pythontech 0:5868e8752d44 371 // add rd, sp, #local_num*4
pythontech 0:5868e8752d44 372 emit_al(as, asm_arm_op_add_imm(rd, ASM_ARM_REG_SP, local_num << 2));
pythontech 0:5868e8752d44 373 }
pythontech 0:5868e8752d44 374
pythontech 0:5868e8752d44 375 void asm_arm_lsl_reg_reg(asm_arm_t *as, uint rd, uint rs) {
pythontech 0:5868e8752d44 376 // mov rd, rd, lsl rs
pythontech 0:5868e8752d44 377 emit_al(as, 0x1a00010 | (rd << 12) | (rs << 8) | rd);
pythontech 0:5868e8752d44 378 }
pythontech 0:5868e8752d44 379
pythontech 0:5868e8752d44 380 void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs) {
pythontech 0:5868e8752d44 381 // mov rd, rd, asr rs
pythontech 0:5868e8752d44 382 emit_al(as, 0x1a00050 | (rd << 12) | (rs << 8) | rd);
pythontech 0:5868e8752d44 383 }
pythontech 0:5868e8752d44 384
pythontech 0:5868e8752d44 385 void asm_arm_ldr_reg_reg(asm_arm_t *as, uint rd, uint rn, uint byte_offset) {
pythontech 0:5868e8752d44 386 // ldr rd, [rn, #off]
pythontech 0:5868e8752d44 387 emit_al(as, 0x5900000 | (rn << 16) | (rd << 12) | byte_offset);
pythontech 0:5868e8752d44 388 }
pythontech 0:5868e8752d44 389
pythontech 0:5868e8752d44 390 void asm_arm_ldrh_reg_reg(asm_arm_t *as, uint rd, uint rn) {
pythontech 0:5868e8752d44 391 // ldrh rd, [rn]
pythontech 0:5868e8752d44 392 emit_al(as, 0x1d000b0 | (rn << 16) | (rd << 12));
pythontech 0:5868e8752d44 393 }
pythontech 0:5868e8752d44 394
pythontech 0:5868e8752d44 395 void asm_arm_ldrb_reg_reg(asm_arm_t *as, uint rd, uint rn) {
pythontech 0:5868e8752d44 396 // ldrb rd, [rn]
pythontech 0:5868e8752d44 397 emit_al(as, 0x5d00000 | (rn << 16) | (rd << 12));
pythontech 0:5868e8752d44 398 }
pythontech 0:5868e8752d44 399
pythontech 0:5868e8752d44 400 void asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm, uint byte_offset) {
pythontech 0:5868e8752d44 401 // str rd, [rm, #off]
pythontech 0:5868e8752d44 402 emit_al(as, 0x5800000 | (rm << 16) | (rd << 12) | byte_offset);
pythontech 0:5868e8752d44 403 }
pythontech 0:5868e8752d44 404
pythontech 0:5868e8752d44 405 void asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm) {
pythontech 0:5868e8752d44 406 // strh rd, [rm]
pythontech 0:5868e8752d44 407 emit_al(as, 0x1c000b0 | (rm << 16) | (rd << 12));
pythontech 0:5868e8752d44 408 }
pythontech 0:5868e8752d44 409
pythontech 0:5868e8752d44 410 void asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm) {
pythontech 0:5868e8752d44 411 // strb rd, [rm]
pythontech 0:5868e8752d44 412 emit_al(as, 0x5c00000 | (rm << 16) | (rd << 12));
pythontech 0:5868e8752d44 413 }
pythontech 0:5868e8752d44 414
pythontech 0:5868e8752d44 415 void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) {
pythontech 0:5868e8752d44 416 // str rd, [rm, rn, lsl #2]
pythontech 0:5868e8752d44 417 emit_al(as, 0x7800100 | (rm << 16) | (rd << 12) | rn);
pythontech 0:5868e8752d44 418 }
pythontech 0:5868e8752d44 419
pythontech 0:5868e8752d44 420 void asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) {
pythontech 0:5868e8752d44 421 // strh doesn't support scaled register index
pythontech 0:5868e8752d44 422 emit_al(as, 0x1a00080 | (ASM_ARM_REG_R8 << 12) | rn); // mov r8, rn, lsl #1
pythontech 0:5868e8752d44 423 emit_al(as, 0x18000b0 | (rm << 16) | (rd << 12) | ASM_ARM_REG_R8); // strh rd, [rm, r8]
pythontech 0:5868e8752d44 424 }
pythontech 0:5868e8752d44 425
pythontech 0:5868e8752d44 426 void asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) {
pythontech 0:5868e8752d44 427 // strb rd, [rm, rn]
pythontech 0:5868e8752d44 428 emit_al(as, 0x7c00000 | (rm << 16) | (rd << 12) | rn);
pythontech 0:5868e8752d44 429 }
pythontech 0:5868e8752d44 430
pythontech 0:5868e8752d44 431 void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label) {
pythontech 0:5868e8752d44 432 assert(label < as->max_num_labels);
pythontech 0:5868e8752d44 433 mp_uint_t dest = as->label_offsets[label];
pythontech 0:5868e8752d44 434 mp_int_t rel = dest - as->code_offset;
pythontech 0:5868e8752d44 435 rel -= 8; // account for instruction prefetch, PC is 8 bytes ahead of this instruction
pythontech 0:5868e8752d44 436 rel >>= 2; // in ARM mode the branch target is 32-bit aligned, so the 2 LSB are omitted
pythontech 0:5868e8752d44 437
pythontech 0:5868e8752d44 438 if (SIGNED_FIT24(rel)) {
pythontech 0:5868e8752d44 439 emit(as, cond | 0xa000000 | (rel & 0xffffff));
pythontech 0:5868e8752d44 440 } else {
pythontech 0:5868e8752d44 441 printf("asm_arm_bcc: branch does not fit in 24 bits\n");
pythontech 0:5868e8752d44 442 }
pythontech 0:5868e8752d44 443 }
pythontech 0:5868e8752d44 444
pythontech 0:5868e8752d44 445 void asm_arm_b_label(asm_arm_t *as, uint label) {
pythontech 0:5868e8752d44 446 asm_arm_bcc_label(as, ASM_ARM_CC_AL, label);
pythontech 0:5868e8752d44 447 }
pythontech 0:5868e8752d44 448
pythontech 0:5868e8752d44 449 void asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp) {
pythontech 0:5868e8752d44 450 // If the table offset fits into the ldr instruction
pythontech 0:5868e8752d44 451 if (fun_id < (0x1000 / 4)) {
pythontech 0:5868e8752d44 452 emit_al(as, asm_arm_op_mov_reg(ASM_ARM_REG_LR, ASM_ARM_REG_PC)); // mov lr, pc
pythontech 0:5868e8752d44 453 emit_al(as, 0x597f000 | (fun_id << 2)); // ldr pc, [r7, #fun_id*4]
pythontech 0:5868e8752d44 454 return;
pythontech 0:5868e8752d44 455 }
pythontech 0:5868e8752d44 456
pythontech 0:5868e8752d44 457 emit_al(as, 0x59f0004 | (reg_temp << 12)); // ldr rd, [pc, #4]
pythontech 0:5868e8752d44 458 // Set lr after fun_ptr
pythontech 0:5868e8752d44 459 emit_al(as, asm_arm_op_add_imm(ASM_ARM_REG_LR, ASM_ARM_REG_PC, 4)); // add lr, pc, #4
pythontech 0:5868e8752d44 460 emit_al(as, asm_arm_op_mov_reg(ASM_ARM_REG_PC, reg_temp)); // mov pc, reg_temp
pythontech 0:5868e8752d44 461 emit(as, (uint) fun_ptr);
pythontech 0:5868e8752d44 462 }
pythontech 0:5868e8752d44 463
pythontech 0:5868e8752d44 464 #endif // MICROPY_EMIT_ARM