aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--bare-arm/mpconfigport.h4
-rw-r--r--examples/asmled.py34
-rw-r--r--examples/asmsum.py57
-rw-r--r--py/asmthumb.c84
-rw-r--r--py/asmthumb.h93
-rw-r--r--py/builtin.h4
-rw-r--r--py/builtinevex.c7
-rw-r--r--py/builtinimport.c15
-rw-r--r--py/builtintables.c5
-rw-r--r--py/compile.c15
-rw-r--r--py/emitbc.c34
-rw-r--r--py/emitcommon.c4
-rw-r--r--py/emitcpy.c2
-rw-r--r--py/emitglue.c159
-rw-r--r--py/emitglue.h40
-rw-r--r--py/emitinlinethumb.c233
-rw-r--r--py/emitnative.c20
-rw-r--r--py/emitpass1.c2
-rw-r--r--py/makeqstrdata.py32
-rw-r--r--py/modcollections.c4
-rw-r--r--py/modsys.c50
-rw-r--r--py/mpconfig.h9
-rw-r--r--py/obj.c8
-rw-r--r--py/obj.h2
-rw-r--r--py/objdict.c9
-rw-r--r--py/objfun.c56
-rw-r--r--py/objint.c23
-rw-r--r--py/objlist.c56
-rw-r--r--py/objlist.h6
-rw-r--r--py/objset.c2
-rw-r--r--py/objstr.c39
-rw-r--r--py/opmethods.c20
-rw-r--r--py/parsehelper.c22
-rw-r--r--py/parsehelper.h2
-rw-r--r--py/py.mk2
-rw-r--r--py/qstrdefs.h16
-rw-r--r--py/runtime.c13
-rw-r--r--py/runtime.h9
-rw-r--r--py/runtime0.h2
-rw-r--r--py/scope.c6
-rw-r--r--py/scope.h4
-rw-r--r--py/showbc.c13
-rw-r--r--py/vm.c30
-rw-r--r--stm/main.c9
-rw-r--r--stmhal/dac.c6
-rw-r--r--stmhal/i2c.c11
-rw-r--r--stmhal/main.c8
-rw-r--r--stmhal/modpyb.c9
-rw-r--r--tests/basics/list1.py2
-rw-r--r--tests/basics/namedtuple1.py5
-rwxr-xr-xtools/pip-micropython15
-rw-r--r--unix-cpy/mpconfigport.h2
-rw-r--r--unix/file.c9
-rw-r--r--unix/main.c11
-rw-r--r--unix/mpconfigport.h1
-rw-r--r--unix/mpconfigport.mk2
-rw-r--r--unix/qstrdefsport.h4
58 files changed, 869 insertions, 475 deletions
diff --git a/README.md b/README.md
index be062dc2f..925ed342d 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,8 @@ Then to test it:
Debian/Ubuntu/Mint derivative Linux distros will require build-essentials and
libreadline-dev packages installed. To build FFI (Foreign Function Interface)
-module (recommended, enable in unix/mpconfigport.mk), libffi-dev is required.
+module, libffi-dev package is required. If you have problems with some
+dependencies, they can be disabled in unix/mpconfigport.mk .
The STM version
---------------
diff --git a/bare-arm/mpconfigport.h b/bare-arm/mpconfigport.h
index 7f4c37890..dfb6312a8 100644
--- a/bare-arm/mpconfigport.h
+++ b/bare-arm/mpconfigport.h
@@ -11,6 +11,10 @@
#define MICROPY_ENABLE_REPL_HELPERS (0)
#define MICROPY_ENABLE_LEXER_UNIX (0)
#define MICROPY_ENABLE_SOURCE_LINE (0)
+#define MICROPY_ENABLE_MOD_IO (0)
+#define MICROPY_ENABLE_MOD_STRUCT (0)
+#define MICROPY_ENABLE_MOD_SYS (0)
+#define MICROPY_CPYTHON_COMPAT (0)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
#define MICROPY_PATH_MAX (512)
diff --git a/examples/asmled.py b/examples/asmled.py
index e0d6c73ce..917d9ba03 100644
--- a/examples/asmled.py
+++ b/examples/asmled.py
@@ -1,4 +1,5 @@
# flash LED #1 using inline assembler
+# this version is overly verbose and uses word stores
@micropython.asm_thumb
def flash_led(r0):
movw(r1, (stm.GPIOA + stm.GPIO_BSRRL) & 0xffff)
@@ -13,69 +14,72 @@ def flash_led(r0):
label(loop1)
# turn LED on
- str(r2, r1, 0)
+ str(r2, [r1, 0])
# delay for a bit
movw(r4, 5599900 & 0xffff)
movt(r4, (5599900 >> 16) & 0xffff)
label(delay_on)
- subs(r4, r4, 1)
+ sub(r4, r4, 1)
cmp(r4, 0)
bgt(delay_on)
# turn LED off
- str(r3, r1, 0)
+ str(r3, [r1, 0])
# delay for a bit
movw(r4, 5599900 & 0xffff)
movt(r4, (5599900 >> 16) & 0xffff)
label(delay_off)
- subs(r4, r4, 1)
+ sub(r4, r4, 1)
cmp(r4, 0)
bgt(delay_off)
# loop r0 times
- subs(r0, r0, 1)
+ sub(r0, r0, 1)
label(loop_entry)
cmp(r0, 0)
bgt(loop1)
-# flash LED #1 using inline assembler
-# this version uses the convenience assembler operation 'movwt'
+# flash LED #2 using inline assembler
+# this version uses half-word sortes, and the convenience assembler operation 'movwt'
@micropython.asm_thumb
def flash_led_v2(r0):
- movwt(r1, stm.GPIOA + stm.GPIO_BSRRL)
- movwt(r2, 1 << 13)
- movwt(r3, 1 << (16 + 13))
+ # get the GPIOA address in r1
+ movwt(r1, stm.GPIOA)
+
+ # get the bit mask for PA14 (the pin LED #2 is on)
+ movw(r2, 1 << 14)
b(loop_entry)
label(loop1)
# turn LED on
- str(r2, r1, 0)
+ strh(r2, [r1, stm.GPIO_BSRRL])
# delay for a bit
movwt(r4, 5599900)
label(delay_on)
- subs(r4, r4, 1)
+ sub(r4, r4, 1)
cmp(r4, 0)
bgt(delay_on)
# turn LED off
- str(r3, r1, 0)
+ strh(r2, [r1, stm.GPIO_BSRRH])
# delay for a bit
movwt(r4, 5599900)
label(delay_off)
- subs(r4, r4, 1)
+ sub(r4, r4, 1)
cmp(r4, 0)
bgt(delay_off)
# loop r0 times
- subs(r0, r0, 1)
+ sub(r0, r0, 1)
label(loop_entry)
cmp(r0, 0)
bgt(loop1)
+flash_led(5)
flash_led_v2(5)
diff --git a/examples/asmsum.py b/examples/asmsum.py
new file mode 100644
index 000000000..07e71c738
--- /dev/null
+++ b/examples/asmsum.py
@@ -0,0 +1,57 @@
+@micropython.asm_thumb
+def asm_sum_words(r0, r1):
+
+ # r0 = len
+ # r1 = ptr
+ # r2 = sum
+ # r3 = dummy
+ mov(r2, 0)
+
+ b(loop_entry)
+
+ label(loop1)
+ ldr(r3, [r1, 0])
+ add(r2, r2, r3)
+
+ add(r1, r1, 4)
+ sub(r0, r0, 1)
+
+ label(loop_entry)
+ cmp(r0, 0)
+ bgt(loop1)
+
+ mov(r0, r2)
+
+@micropython.asm_thumb
+def asm_sum_bytes(r0, r1):
+
+ # r0 = len
+ # r1 = ptr
+ # r2 = sum
+ # r3 = dummy
+ mov(r2, 0)
+
+ b(loop_entry)
+
+ label(loop1)
+ ldrb(r3, [r1, 0])
+ add(r2, r2, r3)
+
+ add(r1, r1, 1)
+ sub(r0, r0, 1)
+
+ label(loop_entry)
+ cmp(r0, 0)
+ bgt(loop1)
+
+ mov(r0, r2)
+
+import array
+
+b = array.array('l', (100, 200, 300, 400))
+n = asm_sum_words(len(b), b)
+print(b, n)
+
+b = array.array('b', (10, 20, 30, 40, 50, 60, 70, 80))
+n = asm_sum_bytes(len(b), b)
+print(b, n)
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 1cd971c76..6bf6d6658 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -230,33 +230,33 @@ STATIC int get_label_dest(asm_thumb_t *as, uint label) {
return as->label_offsets[label];
}
-#define OP_MOVS_RLO_I8(rlo_dest, i8_src) (0x2000 | ((rlo_dest) << 8) | (i8_src))
+#define OP_FORMAT_2(op, rlo_dest, rlo_src, src_b) ((op) | ((src_b) << 6) | ((rlo_src) << 3) | (rlo_dest))
-// the i8_src value will be zero extended into the r32 register!
-void asm_thumb_movs_rlo_i8(asm_thumb_t *as, uint rlo_dest, int i8_src) {
+void asm_thumb_format_2(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src, int src_b) {
assert(rlo_dest < REG_R8);
- // movs rlo_dest, #i8_src
- asm_thumb_write_op16(as, OP_MOVS_RLO_I8(rlo_dest, i8_src));
+ assert(rlo_src < REG_R8);
+ asm_thumb_write_op16(as, OP_FORMAT_2(op, rlo_dest, rlo_src, src_b));
}
-#define OP_MOVW (0xf240)
-#define OP_MOVT (0xf2c0)
+#define OP_FORMAT_3(op, rlo, i8) ((op) | ((rlo) << 8) | (i8))
-// if loading lo half with movw, the i16 value will be zero extended into the r32 register!
-STATIC void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src) {
- assert(reg_dest < REG_R15);
- // mov[wt] reg_dest, #i16_src
- asm_thumb_write_op32(as, mov_op | ((i16_src >> 1) & 0x0400) | ((i16_src >> 12) & 0xf), ((i16_src << 4) & 0x7000) | (reg_dest << 8) | (i16_src & 0xff));
+void asm_thumb_format_3(asm_thumb_t *as, uint op, uint rlo, int i8) {
+ assert(rlo < REG_R8);
+ asm_thumb_write_op16(as, OP_FORMAT_3(op, rlo, i8));
}
-// the i16_src value will be zero extended into the r32 register!
-void asm_thumb_movw_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) {
- asm_thumb_mov_reg_i16(as, OP_MOVW, reg_dest, i16_src);
+#define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest))
+
+void asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src) {
+ assert(rlo_dest < REG_R8);
+ assert(rlo_src < REG_R8);
+ asm_thumb_write_op16(as, OP_FORMAT_4(op, rlo_dest, rlo_src));
}
-// the i16_src value will be zero extended into the r32 register!
-void asm_thumb_movt_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) {
- asm_thumb_mov_reg_i16(as, OP_MOVT, reg_dest, i16_src);
+#define OP_FORMAT_9_10(op, rlo_dest, rlo_base, offset) ((op) | (((offset) << 6) & 0x07c0) | ((rlo_base) << 3) | (rlo_dest))
+
+void asm_thumb_format_9_10(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_base, uint offset) {
+ asm_thumb_write_op16(as, OP_FORMAT_9_10(op, rlo_dest, rlo_base, offset));
}
void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) {
@@ -275,42 +275,24 @@ void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) {
asm_thumb_write_op16(as, 0x4600 | op_lo);
}
-#define OP_ADD_RLO_RLO_RLO(rlo_dest, rlo_src_a, rlo_src_b) (0x1800 | ((rlo_src_b) << 6) | ((rlo_src_a) << 3) | (rlo_dest))
-
-void asm_thumb_add_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b) {
- asm_thumb_write_op16(as, OP_ADD_RLO_RLO_RLO(rlo_dest, rlo_src_a, rlo_src_b));
-}
-
-#define OP_SUBS_RLO_RLO_I3(rlo_dest, rlo_src, i3_src) (0x1e00 | ((i3_src) << 6) | ((rlo_src) << 3) | (rlo_dest))
-
-void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int i3_src) {
- assert(rlo_dest < REG_R8);
- assert(rlo_src < REG_R8);
- asm_thumb_write_op16(as, OP_SUBS_RLO_RLO_I3(rlo_dest, rlo_src, i3_src));
-}
-
-#define OP_CMP_REG_REG(rlo_a, rlo_b) (0x4280 | ((rlo_b) << 3) | (rlo_a))
-
-void asm_thumb_cmp_reg_reg(asm_thumb_t *as, uint rlo_a, uint rlo_b) {
- asm_thumb_write_op16(as, OP_CMP_REG_REG(rlo_a, rlo_b));
-}
-
-#define OP_CMP_RLO_I8(rlo, i8) (0x2800 | ((rlo) << 8) | (i8))
+#define OP_MOVW (0xf240)
+#define OP_MOVT (0xf2c0)
-void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8) {
- assert(rlo < REG_R8);
- asm_thumb_write_op16(as, OP_CMP_RLO_I8(rlo, i8));
+// if loading lo half with movw, the i16 value will be zero extended into the r32 register!
+STATIC void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src) {
+ assert(reg_dest < REG_R15);
+ // mov[wt] reg_dest, #i16_src
+ asm_thumb_write_op32(as, mov_op | ((i16_src >> 1) & 0x0400) | ((i16_src >> 12) & 0xf), ((i16_src << 4) & 0x7000) | (reg_dest << 8) | (i16_src & 0xff));
}
-#define OP_LDR_RLO_RLO_I5(rlo_dest, rlo_base, word_offset) (0x6800 | (((word_offset) << 6) & 0x07c0) | ((rlo_base) << 3) | (rlo_dest))
-#define OP_STR_RLO_RLO_I5(rlo_dest, rlo_base, word_offset) (0x6000 | (((word_offset) << 6) & 0x07c0) | ((rlo_base) << 3) | (rlo_dest))
-
-void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset) {
- asm_thumb_write_op16(as, OP_LDR_RLO_RLO_I5(rlo_dest, rlo_base, word_offset));
+// the i16_src value will be zero extended into the r32 register!
+void asm_thumb_movw_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) {
+ asm_thumb_mov_reg_i16(as, OP_MOVW, reg_dest, i16_src);
}
-void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset) {
- asm_thumb_write_op16(as, OP_STR_RLO_RLO_I5(rlo_src, rlo_base, word_offset));
+// the i16_src value will be zero extended into the r32 register!
+void asm_thumb_movt_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) {
+ asm_thumb_mov_reg_i16(as, OP_MOVT, reg_dest, i16_src);
}
void asm_thumb_ite_ge(asm_thumb_t *as) {
@@ -353,7 +335,7 @@ void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, machine_uint_t i32) {
void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) {
if (reg_dest < 8 && UNSIGNED_FIT8(i32)) {
- asm_thumb_movs_rlo_i8(as, reg_dest, i32);
+ asm_thumb_mov_rlo_i8(as, reg_dest, i32);
} else if (UNSIGNED_FIT16(i32)) {
asm_thumb_mov_reg_i16(as, OP_MOVW, reg_dest, i32);
} else {
@@ -452,7 +434,7 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp
asm_thumb_mov_reg_i32(as, reg_temp, (machine_uint_t)fun_ptr);
asm_thumb_write_op16(as, OP_BLX(reg_temp));
} else if (1) {
- asm_thumb_write_op16(as, OP_LDR_RLO_RLO_I5(reg_temp, REG_R7, fun_id));
+ asm_thumb_write_op16(as, OP_FORMAT_9_10(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, reg_temp, REG_R7, fun_id));
asm_thumb_write_op16(as, OP_BLX(reg_temp));
} else {
// use SVC
diff --git a/py/asmthumb.h b/py/asmthumb.h
index de376fd2c..6b4f5506b 100644
--- a/py/asmthumb.h
+++ b/py/asmthumb.h
@@ -58,16 +58,93 @@ void asm_thumb_label_assign(asm_thumb_t *as, uint label);
// argument order follows ARM, in general dest is first
// note there is a difference between movw and mov.w, and many others!
-void asm_thumb_movs_rlo_i8(asm_thumb_t *as, uint rlo_dest, int i8_src);
+// FORMAT 2: add/subtract
+
+#define ASM_THUMB_FORMAT_2_ADD (0x1800)
+#define ASM_THUMB_FORMAT_2_SUB (0x1a00)
+#define ASM_THUMB_FORMAT_2_REG_OPERAND (0x0000)
+#define ASM_THUMB_FORMAT_2_IMM_OPERAND (0x0400)
+
+void asm_thumb_format_2(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src, int src_b);
+
+static inline void asm_thumb_add_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b)
+ { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_ADD | ASM_THUMB_FORMAT_2_REG_OPERAND, rlo_dest, rlo_src_a, rlo_src_b); }
+static inline void asm_thumb_add_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, int i3_src)
+ { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_ADD | ASM_THUMB_FORMAT_2_IMM_OPERAND, rlo_dest, rlo_src_a, i3_src); }
+static inline void asm_thumb_sub_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b)
+ { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_SUB | ASM_THUMB_FORMAT_2_REG_OPERAND, rlo_dest, rlo_src_a, rlo_src_b); }
+static inline void asm_thumb_sub_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, int i3_src)
+ { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_SUB | ASM_THUMB_FORMAT_2_IMM_OPERAND, rlo_dest, rlo_src_a, i3_src); }
+
+// FORMAT 3: move/compare/add/subtract immediate
+// These instructions all do zero extension of the i8 value
+
+#define ASM_THUMB_FORMAT_3_MOV (0x2000)
+#define ASM_THUMB_FORMAT_3_CMP (0x2800)
+#define ASM_THUMB_FORMAT_3_ADD (0x3000)
+#define ASM_THUMB_FORMAT_3_SUB (0x3800)
+
+void asm_thumb_format_3(asm_thumb_t *as, uint op, uint rlo, int i8);
+
+static inline void asm_thumb_mov_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_MOV, rlo, i8); }
+static inline void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_CMP, rlo, i8); }
+static inline void asm_thumb_add_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_ADD, rlo, i8); }
+static inline void asm_thumb_sub_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_SUB, rlo, i8); }
+
+// FORMAT 4: ALU operations
+
+#define ASM_THUMB_FORMAT_4_AND (0x4000)
+#define ASM_THUMB_FORMAT_4_EOR (0x4040)
+#define ASM_THUMB_FORMAT_4_LSL (0x4080)
+#define ASM_THUMB_FORMAT_4_LSR (0x40c0)
+#define ASM_THUMB_FORMAT_4_ASR (0x4100)
+#define ASM_THUMB_FORMAT_4_ADC (0x4140)
+#define ASM_THUMB_FORMAT_4_SBC (0x4180)
+#define ASM_THUMB_FORMAT_4_ROR (0x41c0)
+#define ASM_THUMB_FORMAT_4_TST (0x4200)
+#define ASM_THUMB_FORMAT_4_NEG (0x4240)
+#define ASM_THUMB_FORMAT_4_CMP (0x4280)
+#define ASM_THUMB_FORMAT_4_CMN (0x42c0)
+#define ASM_THUMB_FORMAT_4_ORR (0x4300)
+#define ASM_THUMB_FORMAT_4_MUL (0x4340)
+#define ASM_THUMB_FORMAT_4_BIC (0x4380)
+#define ASM_THUMB_FORMAT_4_MVN (0x43c0)
+
+void asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src);
+
+static inline void asm_thumb_cmp_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src) { asm_thumb_format_4(as, ASM_THUMB_FORMAT_4_CMP, rlo_dest, rlo_src); }
+
+// FORMAT 9: load/store with immediate offset
+// For word transfers the offset must be aligned, and >>2
+
+// FORMAT 10: load/store halfword
+// The offset must be aligned, and >>1
+// The load is zero extended into the register
+
+#define ASM_THUMB_FORMAT_9_STR (0x6000)
+#define ASM_THUMB_FORMAT_9_LDR (0x6800)
+#define ASM_THUMB_FORMAT_9_WORD_TRANSFER (0x0000)
+#define ASM_THUMB_FORMAT_9_BYTE_TRANSFER (0x1000)
+
+#define ASM_THUMB_FORMAT_10_STRH (0x8000)
+#define ASM_THUMB_FORMAT_10_LDRH (0x8800)
+
+void asm_thumb_format_9_10(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_base, uint offset);
+
+static inline void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset)
+ { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_src, rlo_base, word_offset); }
+static inline void asm_thumb_strb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint byte_offset)
+ { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER, rlo_src, rlo_base, byte_offset); }
+static inline void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset)
+ { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_dest, rlo_base, word_offset); }
+static inline void asm_thumb_ldrb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint byte_offset)
+ { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER , rlo_dest, rlo_base, byte_offset); }
+
+// TODO convert these to above format style
+
+void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src);
void asm_thumb_movw_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src);
void asm_thumb_movt_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src);
-void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src);
-void asm_thumb_add_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b);
-void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int i3_src);
-void asm_thumb_cmp_reg_reg(asm_thumb_t *as, uint rlo_a, uint rlo_b);
-void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8);
-void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset);
-void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset);
void asm_thumb_ite_ge(asm_thumb_t *as);
void asm_thumb_b_n(asm_thumb_t *as, uint label);
void asm_thumb_bcc_n(asm_thumb_t *as, int cond, uint label);
diff --git a/py/builtin.h b/py/builtin.h
index a29844498..743f748da 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -35,6 +35,9 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_op_contains_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_op_getitem_obj);
+
extern const mp_obj_module_t mp_module___main__;
extern const mp_obj_module_t mp_module_array;
extern const mp_obj_module_t mp_module_collections;
@@ -42,3 +45,4 @@ extern const mp_obj_module_t mp_module_io;
extern const mp_obj_module_t mp_module_math;
extern const mp_obj_module_t mp_module_micropython;
extern const mp_obj_module_t mp_module_struct;
+extern const mp_obj_module_t mp_module_sys;
diff --git a/py/builtinevex.c b/py/builtinevex.c
index fc3a60182..ae8253737 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -25,13 +25,16 @@ STATIC mp_obj_t parse_compile_execute(mp_obj_t o_in, mp_parse_input_kind_t parse
// parse the string
mp_parse_error_kind_t parse_error_kind;
mp_parse_node_t pn = mp_parse(lex, parse_input_kind, &parse_error_kind);
- mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) {
// parse error; raise exception
- nlr_raise(mp_parse_make_exception(parse_error_kind));
+ mp_obj_t exc = mp_parse_make_exception(lex, parse_error_kind);
+ mp_lexer_free(lex);
+ nlr_raise(exc);
}
+ mp_lexer_free(lex);
+
// compile the string
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false);
mp_parse_node_free(pn);
diff --git a/py/builtinimport.c b/py/builtinimport.c
index 697244878..3f63768ad 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -28,8 +28,6 @@
#define PATH_SEP_CHAR '/'
-mp_obj_t mp_sys_path;
-
mp_import_stat_t stat_dir_or_file(vstr_t *path) {
//printf("stat %s\n", vstr_str(path));
mp_import_stat_t stat = mp_import_stat(vstr_str(path));
@@ -48,9 +46,9 @@ mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest) {
// extract the list of paths
uint path_num = 0;
mp_obj_t *path_items;
- if (mp_sys_path != MP_OBJ_NULL) {
- mp_obj_list_get(mp_sys_path, &path_num, &path_items);
- }
+#if MICROPY_ENABLE_MOD_SYS
+ mp_obj_list_get(mp_sys_path, &path_num, &path_items);
+#endif
if (path_num == 0) {
// mp_sys_path is empty, so just use the given file name
@@ -100,15 +98,18 @@ void do_load(mp_obj_t module_obj, vstr_t *file) {
// parse the imported script
mp_parse_error_kind_t parse_error_kind;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind);
- mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) {
// parse error; clean up and raise exception
+ mp_obj_t exc = mp_parse_make_exception(lex, parse_error_kind);
+ mp_lexer_free(lex);
mp_locals_set(old_locals);
mp_globals_set(old_globals);
- nlr_raise(mp_parse_make_exception(parse_error_kind));
+ nlr_raise(exc);
}
+ mp_lexer_free(lex);
+
// compile the imported script
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false);
mp_parse_node_free(pn);
diff --git a/py/builtintables.c b/py/builtintables.c
index e2007f3b4..8edc69987 100644
--- a/py/builtintables.c
+++ b/py/builtintables.c
@@ -126,7 +126,7 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
#if MICROPY_ENABLE_MOD_IO
{ MP_OBJ_NEW_QSTR(MP_QSTR_io), (mp_obj_t)&mp_module_io },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_collections), (mp_obj_t)&mp_module_collections },
+ { MP_OBJ_NEW_QSTR(MP_QSTR__collections), (mp_obj_t)&mp_module_collections },
#if MICROPY_ENABLE_MOD_STRUCT
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_struct },
#endif
@@ -134,6 +134,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
#if MICROPY_ENABLE_FLOAT
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&mp_module_math },
#endif
+#if MICROPY_ENABLE_MOD_SYS
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sys), (mp_obj_t)&mp_module_sys },
+#endif
// extra builtin modules as defined by a port
MICROPY_EXTRA_BUILTIN_MODULES
diff --git a/py/compile.c b/py/compile.c
index f397501f1..7a3d810f9 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -10,11 +10,11 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
-#include "scope.h"
#include "runtime0.h"
-#include "emit.h"
-#include "emitglue.h"
#include "obj.h"
+#include "emitglue.h"
+#include "scope.h"
+#include "emit.h"
#include "compile.h"
#include "runtime.h"
#include "builtin.h"
@@ -283,7 +283,7 @@ STATIC void compile_decrease_except_level(compiler_t *comp) {
}
STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
- scope_t *scope = scope_new(kind, pn, comp->source_file, mp_emit_glue_get_unique_code_id(), emit_options);
+ scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options);
scope->parent = comp->scope_cur;
scope->next = NULL;
if (comp->scope_head == NULL) {
@@ -3454,7 +3454,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is
#endif // !MICROPY_EMIT_CPYTHON
// free the scopes
- uint unique_code_id = module_scope->unique_code_id;
+ mp_raw_code_t *outer_raw_code = module_scope->raw_code;
for (scope_t *s = module_scope; s;) {
scope_t *next = s->next;
scope_free(s);
@@ -3471,12 +3471,11 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is
} else {
#if MICROPY_EMIT_CPYTHON
// can't create code, so just return true
- (void)unique_code_id; // to suppress warning that unique_code_id is unused
+ (void)outer_raw_code; // to suppress warning that outer_raw_code is unused
return mp_const_true;
#else
// return function that executes the outer module
- // we can free the unique_code slot because no-one has reference to this unique_code_id anymore
- return mp_make_function_from_id_and_free(unique_code_id, MP_OBJ_NULL, MP_OBJ_NULL);
+ return mp_make_function_from_raw_code(outer_raw_code, MP_OBJ_NULL, MP_OBJ_NULL);
#endif
}
}
diff --git a/py/emitbc.c b/py/emitbc.c
index d1d59ef4a..2d71d8685 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -9,10 +9,11 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
-#include "emitglue.h"
#include "bc0.h"
struct _emit_t {
@@ -65,6 +66,10 @@ STATIC byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_writ
}
}
+STATIC void emit_align_code_info_to_machine_word(emit_t* emit) {
+ emit->code_info_offset = (emit->code_info_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1));
+}
+
STATIC void emit_write_code_info_qstr(emit_t* emit, qstr qstr) {
byte* c = emit_get_cur_to_write_code_info(emit, 4);
// TODO variable length encoding for qstr
@@ -98,6 +103,10 @@ STATIC byte* emit_get_cur_to_write_byte_code(emit_t* emit, int num_bytes_to_writ
}
}
+STATIC void emit_align_byte_code_to_machine_word(emit_t* emit) {
+ emit->byte_code_offset = (emit->byte_code_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1));
+}
+
STATIC void emit_write_byte_code_byte(emit_t* emit, byte b1) {
byte* c = emit_get_cur_to_write_byte_code(emit, 1);
c[0] = b1;
@@ -158,6 +167,14 @@ STATIC void emit_write_byte_code_byte_uint(emit_t* emit, byte b, uint num) {
emit_write_byte_code_uint(emit, num);
}
+// aligns the pointer so it is friendly to GC
+STATIC void emit_write_byte_code_byte_ptr(emit_t* emit, byte b, void *ptr) {
+ emit_write_byte_code_byte(emit, b);
+ emit_align_byte_code_to_machine_word(emit);
+ machine_uint_t *c = (machine_uint_t*)emit_get_cur_to_write_byte_code(emit, sizeof(machine_uint_t));
+ *c = (machine_uint_t)ptr;
+}
+
/* currently unused
STATIC void emit_write_byte_code_byte_uint_uint(emit_t* emit, byte b, uint num1, uint num2) {
emit_write_byte_code_byte(emit, b);
@@ -178,7 +195,7 @@ STATIC void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, uint
} else {
byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3;
}
- byte* c = emit_get_cur_to_write_byte_code(emit, 3);
+ byte *c = emit_get_cur_to_write_byte_code(emit, 3);
c[0] = b1;
c[1] = byte_code_offset;
c[2] = byte_code_offset >> 8;
@@ -269,19 +286,20 @@ STATIC void emit_bc_end_pass(emit_t *emit) {
}
emit_write_code_info_bytes_lines(emit, 0, 0); // end of line number info
+ emit_align_code_info_to_machine_word(emit); // align so that following byte_code is aligned
if (emit->pass == PASS_2) {
// calculate size of code in bytes
emit->code_info_size = emit->code_info_offset;
emit->byte_code_size = emit->byte_code_offset;
- emit->code_base = m_new(byte, emit->code_info_size + emit->byte_code_size);
+ emit->code_base = m_new0(byte, emit->code_info_size + emit->byte_code_size);
} else if (emit->pass == PASS_3) {
qstr *arg_names = m_new(qstr, emit->scope->num_params);
for (int i = 0; i < emit->scope->num_params; i++) {
arg_names[i] = emit->scope->id_info[i].qstr;
}
- mp_emit_glue_assign_byte_code(emit->scope->unique_code_id, emit->code_base,
+ mp_emit_glue_assign_byte_code(emit->scope->raw_code, emit->code_base,
emit->code_info_size + emit->byte_code_size,
emit->scope->num_params, emit->scope->num_locals,
emit->scope->scope_flags, arg_names);
@@ -733,7 +751,7 @@ STATIC void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
if (n_pos_defaults == 0 && n_kw_defaults == 0) {
emit_bc_pre(emit, 1);
- emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
+ emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_FUNCTION, scope->raw_code);
} else {
if (n_pos_defaults == 0) {
// load dummy entry for non-existent positional default tuple
@@ -744,14 +762,14 @@ STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defau
emit_bc_load_null(emit);
}
emit_bc_pre(emit, -1);
- emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->unique_code_id);
+ emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->raw_code);
}
}
STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
if (n_pos_defaults == 0 && n_kw_defaults == 0) {
emit_bc_pre(emit, 0);
- emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
+ emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE, scope->raw_code);
} else {
if (n_pos_defaults == 0) {
// load dummy entry for non-existent positional default tuple
@@ -763,7 +781,7 @@ STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaul
emit_bc_rot_two(emit);
}
emit_bc_pre(emit, -2);
- emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->unique_code_id);
+ emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code);
}
}
diff --git a/py/emitcommon.c b/py/emitcommon.c
index 044ec3463..62d8bd18a 100644
--- a/py/emitcommon.c
+++ b/py/emitcommon.c
@@ -7,8 +7,10 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
-#include "scope.h"
#include "runtime0.h"
+#include "obj.h"
+#include "emitglue.h"
+#include "scope.h"
#include "emit.h"
#define EMIT(fun, ...) (emit_method_table->fun(emit, __VA_ARGS__))
diff --git a/py/emitcpy.c b/py/emitcpy.c
index 5866d474e..010219d12 100644
--- a/py/emitcpy.c
+++ b/py/emitcpy.c
@@ -9,6 +9,8 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
diff --git a/py/emitglue.c b/py/emitglue.c
index bcc9b2cca..ce296f432 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -23,46 +23,11 @@
#define DEBUG_OP_printf(...) (void)0
#endif
-typedef enum {
- MP_CODE_UNUSED,
- MP_CODE_RESERVED,
- MP_CODE_BYTE,
- MP_CODE_NATIVE,
- MP_CODE_INLINE_ASM,
-} mp_code_kind_t;
-
-typedef struct _mp_code_t {
- mp_code_kind_t kind : 8;
- uint scope_flags : 8;
- uint n_args : 16;
- union {
- struct {
- byte *code;
- uint len;
- } u_byte;
- struct {
- mp_fun_t fun;
- } u_native;
- struct {
- void *fun;
- } u_inline_asm;
- };
- qstr *arg_names;
-} mp_code_t;
-
-STATIC machine_uint_t unique_codes_alloc = 0;
-STATIC machine_uint_t unique_codes_total = 0; // always >= unique_codes_alloc
-STATIC mp_code_t *unique_codes = NULL;
-
#ifdef WRITE_CODE
FILE *fp_write_code = NULL;
#endif
void mp_emit_glue_init(void) {
- unique_codes_alloc = 0;
- unique_codes_total = 0;
- unique_codes = NULL;
-
#ifdef WRITE_CODE
fp_write_code = fopen("out-code", "wb");
#endif
@@ -74,50 +39,24 @@ void mp_emit_glue_deinit(void) {
fclose(fp_write_code);
}
#endif
-
- m_del(mp_code_t, unique_codes, unique_codes_alloc);
-}
-
-uint mp_emit_glue_get_unique_code_id(void) {
- // look for an existing unused slot
- for (uint i = 0; i < unique_codes_alloc; i++) {
- if (unique_codes[i].kind == MP_CODE_UNUSED) {
- unique_codes[i].kind = MP_CODE_RESERVED;
- return i;
- }
- }
- // no existing slot
- // return next available id, memory will be allocated later
- return unique_codes_total++;
}
-STATIC void mp_emit_glue_alloc_unique_codes(void) {
- if (unique_codes_total > unique_codes_alloc) {
- DEBUG_printf("allocate more unique codes: " UINT_FMT " -> %u\n", unique_codes_alloc, unique_codes_total);
- // increase size of unique_codes table (all new entries are already reserved)
- unique_codes = m_renew(mp_code_t, unique_codes, unique_codes_alloc, unique_codes_total);
- for (uint i = unique_codes_alloc; i < unique_codes_total; i++) {
- unique_codes[i].kind = MP_CODE_RESERVED;
- }
- unique_codes_alloc = unique_codes_total;
- }
+mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
+ mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1);
+ rc->kind = MP_CODE_RESERVED;
+ return rc;
}
-void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names) {
- mp_emit_glue_alloc_unique_codes();
-
- assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED);
- unique_codes[unique_code_id].kind = MP_CODE_BYTE;
- unique_codes[unique_code_id].scope_flags = scope_flags;
- unique_codes[unique_code_id].n_args = n_args;
- unique_codes[unique_code_id].u_byte.code = code;
- unique_codes[unique_code_id].u_byte.len = len;
- unique_codes[unique_code_id].arg_names = arg_names;
-
- //printf("byte code: %d bytes\n", len);
+void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names) {
+ rc->kind = MP_CODE_BYTE;
+ rc->scope_flags = scope_flags;
+ rc->n_args = n_args;
+ rc->u_byte.code = code;
+ rc->u_byte.len = len;
+ rc->arg_names = arg_names;
#ifdef DEBUG_PRINT
- DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d n_locals=%d\n", unique_code_id, code, len, n_args, n_locals);
+ DEBUG_printf("assign byte code: code=%p len=%u n_args=%d n_locals=%d\n", code, len, n_args, n_locals);
for (int i = 0; i < 128 && i < len; i++) {
if (i > 0 && i % 16 == 0) {
DEBUG_printf("\n");
@@ -131,19 +70,14 @@ void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, in
#endif
}
-void mp_emit_glue_assign_native_code(uint unique_code_id, void *fun, uint len, int n_args) {
- mp_emit_glue_alloc_unique_codes();
-
- assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED);
- unique_codes[unique_code_id].kind = MP_CODE_NATIVE;
- unique_codes[unique_code_id].scope_flags = 0;
- unique_codes[unique_code_id].n_args = n_args;
- unique_codes[unique_code_id].u_native.fun = fun;
-
- //printf("native code: %d bytes\n", len);
+void mp_emit_glue_assign_native_code(mp_raw_code_t *rc, void *fun, uint len, int n_args) {
+ rc->kind = MP_CODE_NATIVE;
+ rc->scope_flags = 0;
+ rc->n_args = n_args;
+ rc->u_native.fun = fun;
#ifdef DEBUG_PRINT
- DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
+ DEBUG_printf("assign native code: fun=%p len=%u n_args=%d\n", fun, len, n_args);
byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
for (int i = 0; i < 128 && i < len; i++) {
if (i > 0 && i % 16 == 0) {
@@ -162,17 +96,14 @@ void mp_emit_glue_assign_native_code(uint unique_code_id, void *fun, uint len, i
#endif
}
-void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *fun, uint len, int n_args) {
- mp_emit_glue_alloc_unique_codes();
-
- assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED);
- unique_codes[unique_code_id].kind = MP_CODE_INLINE_ASM;
- unique_codes[unique_code_id].scope_flags = 0;
- unique_codes[unique_code_id].n_args = n_args;
- unique_codes[unique_code_id].u_inline_asm.fun = fun;
+void mp_emit_glue_assign_inline_asm_code(mp_raw_code_t *rc, void *fun, uint len, int n_args) {
+ rc->kind = MP_CODE_INLINE_ASM;
+ rc->scope_flags = 0;
+ rc->n_args = n_args;
+ rc->u_inline_asm.fun = fun;
#ifdef DEBUG_PRINT
- DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
+ DEBUG_printf("assign inline asm code: fun=%p len=%u n_args=%d\n", fun, len, n_args);
byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
for (int i = 0; i < 128 && i < len; i++) {
if (i > 0 && i % 16 == 0) {
@@ -191,12 +122,9 @@ void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *fun, uint le
#endif
}
-mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args) {
- DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
- if (unique_code_id >= unique_codes_total) {
- // illegal code id
- return mp_const_none;
- }
+mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) {
+ DEBUG_OP_printf("make_function_from_raw_code %p\n", rc);
+ assert(rc != NULL);
// def_args must be MP_OBJ_NULL or a tuple
assert(def_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_args, &mp_type_tuple));
@@ -204,49 +132,36 @@ mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj
// TODO implement default kw args
assert(def_kw_args == MP_OBJ_NULL);
- // make the function, depending on the code kind
- mp_code_t *c = &unique_codes[unique_code_id];
+ // make the function, depending on the raw code kind
mp_obj_t fun;
- switch (c->kind) {
+ switch (rc->kind) {
case MP_CODE_BYTE:
- fun = mp_obj_new_fun_bc(c->scope_flags, c->arg_names, c->n_args, def_args, c->u_byte.code);
+ fun = mp_obj_new_fun_bc(rc->scope_flags, rc->arg_names, rc->n_args, def_args, rc->u_byte.code);
break;
case MP_CODE_NATIVE:
- fun = mp_make_function_n(c->n_args, c->u_native.fun);
+ fun = mp_make_function_n(rc->n_args, rc->u_native.fun);
break;
case MP_CODE_INLINE_ASM:
- fun = mp_obj_new_fun_asm(c->n_args, c->u_inline_asm.fun);
+ fun = mp_obj_new_fun_asm(rc->n_args, rc->u_inline_asm.fun);
break;
default:
- // code id was never assigned (this should not happen)
+ // raw code was never set (this should not happen)
assert(0);
return mp_const_none;
}
// check for generator functions and if so wrap in generator object
- if ((c->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
+ if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
fun = mp_obj_new_gen_wrap(fun);
}
return fun;
}
-mp_obj_t mp_make_function_from_id_and_free(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args) {
- mp_obj_t f = mp_make_function_from_id(unique_code_id, def_args, def_kw_args);
-
- // in some cases we can free the unique_code slot
- // any dynamically allocated memory is now owned by the fun object
- mp_code_t *c = &unique_codes[unique_code_id];
- memset(c, 0, sizeof *c); // make sure all pointers are zeroed
- c->kind = MP_CODE_UNUSED;
-
- return f;
-}
-
-mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args) {
- DEBUG_OP_printf("make_closure_from_id %d\n", unique_code_id);
+mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args) {
+ DEBUG_OP_printf("make_closure_from_raw_code %p\n", rc);
// make function object
- mp_obj_t ffun = mp_make_function_from_id(unique_code_id, def_args, def_kw_args);
+ mp_obj_t ffun = mp_make_function_from_raw_code(rc, def_args, def_kw_args);
// wrap function in closure object
return mp_obj_new_closure(ffun, closure_tuple);
}
diff --git a/py/emitglue.h b/py/emitglue.h
index 8f69951c2..2f9960bfa 100644
--- a/py/emitglue.h
+++ b/py/emitglue.h
@@ -1,8 +1,40 @@
// These variables and functions glue the code emitters to the runtime.
+typedef enum {
+ MP_CODE_UNUSED,
+ MP_CODE_RESERVED,
+ MP_CODE_BYTE,
+ MP_CODE_NATIVE,
+ MP_CODE_INLINE_ASM,
+} mp_raw_code_kind_t;
+
+typedef struct _mp_code_t {
+ mp_raw_code_kind_t kind : 8;
+ uint scope_flags : 8;
+ uint n_args : 16;
+ union {
+ struct {
+ byte *code;
+ uint len;
+ } u_byte;
+ struct {
+ mp_fun_t fun;
+ } u_native;
+ struct {
+ void *fun;
+ } u_inline_asm;
+ };
+ qstr *arg_names;
+} mp_raw_code_t;
+
void mp_emit_glue_init(void);
void mp_emit_glue_deinit(void);
-uint mp_emit_glue_get_unique_code_id(void);
-void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names);
-void mp_emit_glue_assign_native_code(uint unique_code_id, void *f, uint len, int n_args);
-void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *f, uint len, int n_args);
+
+mp_raw_code_t *mp_emit_glue_new_raw_code(void);
+
+void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names);
+void mp_emit_glue_assign_native_code(mp_raw_code_t *rc, void *f, uint len, int n_args);
+void mp_emit_glue_assign_inline_asm_code(mp_raw_code_t *rc, void *f, uint len, int n_args);
+
+mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args);
+mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args);
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 58aeed1f6..812e702af 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -9,14 +9,23 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
-#include "emitglue.h"
#include "asmthumb.h"
#if MICROPY_EMIT_INLINE_THUMB
+typedef enum {
+ PN_none = 0,
+#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
+#include "grammar.h"
+#undef DEF_RULE
+ PN_maximum_number_of,
+} pn_kind_t;
+
struct _emit_inline_asm_t {
uint16_t pass;
uint16_t success;
@@ -64,7 +73,7 @@ STATIC bool emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
if (emit->pass == PASS_3) {
void *f = asm_thumb_get_code(emit->as);
- mp_emit_glue_assign_inline_asm_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
+ mp_emit_glue_assign_inline_asm_code(emit->scope->raw_code, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
}
return emit->success;
@@ -120,15 +129,15 @@ STATIC const reg_name_t reg_name_table[] = {
{15, "pc\0"},
};
-STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t *pn_args, uint wanted_arg_num, uint max_reg) {
- if (MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
- qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
+STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint max_reg) {
+ if (MP_PARSE_NODE_IS_ID(pn)) {
+ qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn);
const char *reg_str = qstr_str(reg_qstr);
for (uint i = 0; i < sizeof(reg_name_table) / sizeof(reg_name_table[0]); i++) {
const reg_name_t *r = &reg_name_table[i];
if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) {
if (r->reg > max_reg) {
- emit_inline_thumb_error(emit, "'%s' expects at most r%d in position %d\n", op, max_reg, wanted_arg_num);
+ emit_inline_thumb_error(emit, "'%s' expects at most r%d\n", op, max_reg);
return 0;
} else {
return r->reg;
@@ -136,16 +145,16 @@ STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t
}
}
}
- emit_inline_thumb_error(emit, "'%s' expects a register in position %d\n", op, wanted_arg_num);
+ emit_inline_thumb_error(emit, "'%s' expects a register\n", op);
return 0;
}
-STATIC int get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t *pn_args, int wanted_arg_num, int fit_mask) {
- if (!MP_PARSE_NODE_IS_SMALL_INT(pn_args[wanted_arg_num])) {
- emit_inline_thumb_error(emit, "'%s' expects an integer in position %d\n", op, wanted_arg_num);
+STATIC int get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, int fit_mask) {
+ if (!MP_PARSE_NODE_IS_SMALL_INT(pn)) {
+ emit_inline_thumb_error(emit, "'%s' expects an integer\n", op);
return 0;
}
- int i = MP_PARSE_NODE_LEAF_SMALL_INT(pn_args[wanted_arg_num]);
+ int i = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
if ((i & (~fit_mask)) != 0) {
emit_inline_thumb_error(emit, "'%s' integer 0x%x does not fit in mask 0x%x\n", op, i, fit_mask);
return 0;
@@ -153,12 +162,34 @@ STATIC int get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t *p
return i;
}
-STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t *pn_args, int wanted_arg_num) {
- if (!MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
- emit_inline_thumb_error(emit, "'%s' expects a label in position %d\n", op, wanted_arg_num);
+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) {
+ if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_bracket)) {
+ goto bad_arg;
+ }
+ mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
+ if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
+ goto bad_arg;
+ }
+ pns = (mp_parse_node_struct_t*)pns->nodes[0];
+ if (MP_PARSE_NODE_STRUCT_NUM_NODES(pns) != 2) {
+ goto bad_arg;
+ }
+
+ *pn_base = pns->nodes[0];
+ *pn_offset = pns->nodes[1];
+ return true;
+
+bad_arg:
+ emit_inline_thumb_error(emit, "'%s' expects an address of the form [a, b]\n", op);
+ return false;
+}
+
+STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) {
+ if (!MP_PARSE_NODE_IS_ID(pn)) {
+ emit_inline_thumb_error(emit, "'%s' expects a label\n", op);
return 0;
}
- qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
+ qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn);
for (int i = 0; i < emit->max_num_labels; i++) {
if (emit->label_lookup[i] == label_qstr) {
return i;
@@ -212,7 +243,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
} else if (n_args == 1) {
if (strcmp(op_str, "b") == 0) {
- int label_num = get_arg_label(emit, op_str, pn_args, 0);
+ int label_num = get_arg_label(emit, op_str, pn_args[0]);
// TODO check that this succeeded, ie branch was within range
asm_thumb_b_n(emit->as, label_num);
} else if (op_str[0] == 'b' && op_len == 3) {
@@ -225,7 +256,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
if (cc == -1) {
goto unknown_op;
}
- int label_num = get_arg_label(emit, op_str, pn_args, 0);
+ int label_num = get_arg_label(emit, op_str, pn_args[0]);
// TODO check that this succeeded, ie branch was within range
asm_thumb_bcc_n(emit->as, cc, label_num);
} else {
@@ -233,59 +264,131 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
}
} else if (n_args == 2) {
- if (strcmp(op_str, "mov") == 0) {
- uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7);
- uint rlo_src = get_arg_reg(emit, op_str, pn_args, 1, 7);
- asm_thumb_mov_reg_reg(emit->as, rlo_dest, rlo_src);
- } else if (strcmp(op_str, "movs") == 0) {
- uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7);
- int i_src = get_arg_i(emit, op_str, pn_args, 1, 0xff);
- asm_thumb_movs_rlo_i8(emit->as, rlo_dest, i_src);
- } else if (strcmp(op_str, "movw") == 0) {
- uint reg_dest = get_arg_reg(emit, op_str, pn_args, 0, 15);
- int i_src = get_arg_i(emit, op_str, pn_args, 1, 0xffff);
- asm_thumb_movw_reg_i16(emit->as, reg_dest, i_src);
- } else if (strcmp(op_str, "movt") == 0) {
- uint reg_dest = get_arg_reg(emit, op_str, pn_args, 0, 15);
- int i_src = get_arg_i(emit, op_str, pn_args, 1, 0xffff);
- asm_thumb_movt_reg_i16(emit->as, reg_dest, i_src);
- } else if (strcmp(op_str, "movwt") == 0) {
- // this is a convenience instruction
- // we clear the MSB since it might be set from extracting the small int value
- uint reg_dest = get_arg_reg(emit, op_str, pn_args, 0, 15);
- int i_src = get_arg_i(emit, op_str, pn_args, 1, 0xffffffff);
- asm_thumb_movw_reg_i16(emit->as, reg_dest, i_src & 0xffff);
- asm_thumb_movt_reg_i16(emit->as, reg_dest, (i_src >> 16) & 0x7fff);
- } else if (strcmp(op_str, "cmp") == 0) {
- uint rlo = get_arg_reg(emit, op_str, pn_args, 0, 7);
- int i8 = get_arg_i(emit, op_str, pn_args, 1, 0xff);
- asm_thumb_cmp_rlo_i8(emit->as, rlo, i8);
+ if (MP_PARSE_NODE_IS_ID(pn_args[1])) {
+ // second arg is a register (or should be)
+ uint op_code;
+ if (strcmp(op_str, "mov") == 0) {
+ uint reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
+ uint reg_src = get_arg_reg(emit, op_str, pn_args[1], 15);
+ asm_thumb_mov_reg_reg(emit->as, reg_dest, reg_src);
+ } else if (strcmp(op_str, "and") == 0) {
+ op_code = ASM_THUMB_FORMAT_4_AND;
+ uint reg_dest, reg_src;
+ op_format_4:
+ reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
+ reg_src = get_arg_reg(emit, op_str, pn_args[1], 7);
+ asm_thumb_format_4(emit->as, op_code, reg_dest, reg_src);
+ // TODO probably uses less ROM if these ops are in a lookup table
+ } else if (strcmp(op_str, "and") == 0) { op_code = ASM_THUMB_FORMAT_4_AND; goto op_format_4;
+ } else if (strcmp(op_str, "eor") == 0) { op_code = ASM_THUMB_FORMAT_4_EOR; goto op_format_4;
+ } else if (strcmp(op_str, "lsl") == 0) { op_code = ASM_THUMB_FORMAT_4_LSL; goto op_format_4;
+ } else if (strcmp(op_str, "lsr") == 0) { op_code = ASM_THUMB_FORMAT_4_LSR; goto op_format_4;
+ } else if (strcmp(op_str, "asr") == 0) { op_code = ASM_THUMB_FORMAT_4_ASR; goto op_format_4;
+ } else if (strcmp(op_str, "adc") == 0) { op_code = ASM_THUMB_FORMAT_4_ADC; goto op_format_4;
+ } else if (strcmp(op_str, "sbc") == 0) { op_code = ASM_THUMB_FORMAT_4_SBC; goto op_format_4;
+ } else if (strcmp(op_str, "ror") == 0) { op_code = ASM_THUMB_FORMAT_4_ROR; goto op_format_4;
+ } else if (strcmp(op_str, "tst") == 0) { op_code = ASM_THUMB_FORMAT_4_TST; goto op_format_4;
+ } else if (strcmp(op_str, "neg") == 0) { op_code = ASM_THUMB_FORMAT_4_NEG; goto op_format_4;
+ } else if (strcmp(op_str, "cmp") == 0) { op_code = ASM_THUMB_FORMAT_4_CMP; goto op_format_4;
+ } else if (strcmp(op_str, "cmn") == 0) { op_code = ASM_THUMB_FORMAT_4_CMN; goto op_format_4;
+ } else if (strcmp(op_str, "orr") == 0) { op_code = ASM_THUMB_FORMAT_4_ORR; goto op_format_4;
+ } else if (strcmp(op_str, "mul") == 0) { op_code = ASM_THUMB_FORMAT_4_MUL; goto op_format_4;
+ } else if (strcmp(op_str, "bic") == 0) { op_code = ASM_THUMB_FORMAT_4_BIC; goto op_format_4;
+ } else if (strcmp(op_str, "mvn") == 0) { op_code = ASM_THUMB_FORMAT_4_MVN; goto op_format_4;
+ } else {
+ goto unknown_op;
+ }
} else {
- goto unknown_op;
+ // second arg is not a register
+ uint op_code;
+ if (strcmp(op_str, "mov") == 0) {
+ op_code = ASM_THUMB_FORMAT_3_MOV;
+ uint rlo_dest, i8_src;
+ op_format_3:
+ rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
+ i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff);
+ asm_thumb_format_3(emit->as, op_code, rlo_dest, i8_src);
+ } else if (strcmp(op_str, "cmp") == 0) {
+ op_code = ASM_THUMB_FORMAT_3_CMP;
+ goto op_format_3;
+ } else if (strcmp(op_str, "add") == 0) {
+ op_code = ASM_THUMB_FORMAT_3_ADD;
+ goto op_format_3;
+ } else if (strcmp(op_str, "sub") == 0) {
+ op_code = ASM_THUMB_FORMAT_3_SUB;
+ goto op_format_3;
+ } else if (strcmp(op_str, "movw") == 0) {
+ uint reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
+ int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff);
+ asm_thumb_movw_reg_i16(emit->as, reg_dest, i_src);
+ } else if (strcmp(op_str, "movt") == 0) {
+ uint reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
+ int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff);
+ asm_thumb_movt_reg_i16(emit->as, reg_dest, i_src);
+ } else if (strcmp(op_str, "movwt") == 0) {
+ // this is a convenience instruction
+ // we clear the MSB since it might be set from extracting the small int value
+ uint reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15);
+ int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff);
+ asm_thumb_movw_reg_i16(emit->as, reg_dest, i_src & 0xffff);
+ asm_thumb_movt_reg_i16(emit->as, reg_dest, (i_src >> 16) & 0x7fff);
+ } else if (strcmp(op_str, "ldr") == 0) {
+ op_code = ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER;
+ uint rlo_dest, rlo_base, i5;
+ mp_parse_node_t pn_base, pn_offset;
+ op_format_9_10:
+ rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
+ if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) {
+ rlo_base = get_arg_reg(emit, op_str, pn_base, 7);
+ if (op_code & ASM_THUMB_FORMAT_9_BYTE_TRANSFER) {
+ i5 = get_arg_i(emit, op_str, pn_offset, 0x1f);
+ } else if (op_code & ASM_THUMB_FORMAT_10_STRH) { // also catches LDRH
+ i5 = get_arg_i(emit, op_str, pn_offset, 0x3e) >> 1;
+ } else {
+ i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2;
+ }
+ asm_thumb_format_9_10(emit->as, op_code, rlo_dest, rlo_base, i5);
+ }
+ } else if (strcmp(op_str, "ldrb") == 0) {
+ op_code = ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER;
+ goto op_format_9_10;
+ } else if (strcmp(op_str, "ldrh") == 0) {
+ op_code = ASM_THUMB_FORMAT_10_LDRH;
+ goto op_format_9_10;
+ } else if (strcmp(op_str, "str") == 0) {
+ op_code = ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER;
+ goto op_format_9_10;
+ } else if (strcmp(op_str, "strb") == 0) {
+ op_code = ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER;
+ goto op_format_9_10;
+ } else if (strcmp(op_str, "strh") == 0) {
+ op_code = ASM_THUMB_FORMAT_10_STRH;
+ goto op_format_9_10;
+ } else {
+ goto unknown_op;
+ }
}
} else if (n_args == 3) {
+ uint op_code;
if (strcmp(op_str, "add") == 0) {
- uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7);
- uint rlo_src_a = get_arg_reg(emit, op_str, pn_args, 1, 7);
- uint rlo_src_b = get_arg_reg(emit, op_str, pn_args, 2, 7);
- asm_thumb_add_rlo_rlo_rlo(emit->as, rlo_dest, rlo_src_a, rlo_src_b);
- } else if (strcmp(op_str, "subs") == 0) {
- uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7);
- uint rlo_src = get_arg_reg(emit, op_str, pn_args, 1, 7);
- int i3_src = get_arg_i(emit, op_str, pn_args, 2, 0x7);
- asm_thumb_subs_rlo_rlo_i3(emit->as, rlo_dest, rlo_src, i3_src);
- } else if (strcmp(op_str, "ldr") == 0) {
- // TODO maybe use ldr(rd, [rb, 4]) syntax?
- uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7);
- uint rlo_base = get_arg_reg(emit, op_str, pn_args, 1, 7);
- int i5 = get_arg_i(emit, op_str, pn_args, 2, 0x7c);
- asm_thumb_ldr_rlo_rlo_i5(emit->as, rlo_dest, rlo_base, i5 >> 2);
- } else if (strcmp(op_str, "str") == 0) {
- uint rlo_src = get_arg_reg(emit, op_str, pn_args, 0, 7);
- uint rlo_base = get_arg_reg(emit, op_str, pn_args, 1, 7);
- int i5 = get_arg_i(emit, op_str, pn_args, 2, 0x7c);
- asm_thumb_str_rlo_rlo_i5(emit->as, rlo_src, rlo_base, i5 >> 2);
+ op_code = ASM_THUMB_FORMAT_2_ADD;
+ uint rlo_dest, rlo_src;
+ op_format_2:
+ rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7);
+ rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7);
+ int src_b;
+ if (MP_PARSE_NODE_IS_ID(pn_args[2])) {
+ op_code |= ASM_THUMB_FORMAT_2_REG_OPERAND;
+ src_b = get_arg_reg(emit, op_str, pn_args[2], 7);
+ } else {
+ op_code |= ASM_THUMB_FORMAT_2_IMM_OPERAND;
+ src_b = get_arg_i(emit, op_str, pn_args[2], 0x7);
+ }
+ asm_thumb_format_2(emit->as, op_code, rlo_dest, rlo_src, src_b);
+ } else if (strcmp(op_str, "sub") == 0) {
+ op_code = ASM_THUMB_FORMAT_2_SUB;
+ goto op_format_2;
} else {
goto unknown_op;
}
diff --git a/py/emitnative.c b/py/emitnative.c
index 29da5b8c9..3046aef4d 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -27,11 +27,11 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
-#include "emitglue.h"
-#include "obj.h"
#include "runtime.h"
#if 0 // print debugging info
@@ -283,10 +283,10 @@ STATIC void emit_native_end_pass(emit_t *emit) {
if (emit->pass == PASS_3) {
#if N_X64
void *f = asm_x64_get_code(emit->as);
- mp_emit_glue_assign_native_code(emit->scope->unique_code_id, f, asm_x64_get_code_size(emit->as), emit->scope->num_params);
+ mp_emit_glue_assign_native_code(emit->scope->raw_code, f, asm_x64_get_code_size(emit->as), emit->scope->num_params);
#elif N_THUMB
void *f = asm_thumb_get_code(emit->as);
- mp_emit_glue_assign_native_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
+ mp_emit_glue_assign_native_code(emit->scope->raw_code, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
#endif
}
}
@@ -1020,7 +1020,7 @@ STATIC void emit_native_for_iter(emit_t *emit, uint label) {
asm_x64_cmp_r64_with_r64(emit->as, REG_RET, REG_TEMP1);
asm_x64_jcc_label(emit->as, JCC_JE, label);
#elif N_THUMB
- asm_thumb_cmp_reg_reg(emit->as, REG_RET, REG_TEMP1);
+ asm_thumb_cmp_rlo_rlo(emit->as, REG_RET, REG_TEMP1);
asm_thumb_bcc_label(emit->as, THUMB_CC_EQ, label);
#endif
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
@@ -1067,10 +1067,10 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
asm_x64_cmp_r64_with_r64(emit->as, REG_ARG_3, REG_ARG_2);
asm_x64_setcc_r8(emit->as, JCC_JL, REG_RET);
#elif N_THUMB
- asm_thumb_cmp_reg_reg(emit->as, REG_ARG_2, REG_ARG_3);
+ asm_thumb_cmp_rlo_rlo(emit->as, REG_ARG_2, REG_ARG_3);
asm_thumb_ite_ge(emit->as);
- asm_thumb_movs_rlo_i8(emit->as, REG_RET, 0); // if r0 >= r1
- asm_thumb_movs_rlo_i8(emit->as, REG_RET, 1); // if r0 < r1
+ asm_thumb_mov_rlo_i8(emit->as, REG_RET, 0); // if r0 >= r1
+ asm_thumb_mov_rlo_i8(emit->as, REG_RET, 1); // if r0 < r1
#endif
emit_post_push_reg(emit, VTYPE_BOOL, REG_RET);
} else {
@@ -1188,7 +1188,9 @@ STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_d
// call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them
assert(n_pos_defaults == 0 && n_kw_defaults == 0);
emit_native_pre(emit);
- emit_call_with_3_imm_args(emit, MP_F_MAKE_FUNCTION_FROM_ID, mp_make_function_from_id, scope->unique_code_id, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
+ assert(0);
+ // TODO we need to store the raw_code ptr aligned within the code for the GC
+ emit_call_with_3_imm_args(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
diff --git a/py/emitpass1.c b/py/emitpass1.c
index ad86588e2..01156bfbe 100644
--- a/py/emitpass1.c
+++ b/py/emitpass1.c
@@ -7,6 +7,8 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py
index 81b003545..e0917b336 100644
--- a/py/makeqstrdata.py
+++ b/py/makeqstrdata.py
@@ -10,6 +10,7 @@ if platform.python_version_tuple()[0] == '2':
from htmlentitydefs import codepoint2name
elif platform.python_version_tuple()[0] == '3':
from html.entities import codepoint2name
+codepoint2name[ord('-')] = 'hyphen';
# add some custom names to map characters that aren't in HTML
codepoint2name[ord('.')] = 'dot'
@@ -23,10 +24,17 @@ def compute_hash(qstr):
hash = (hash * 33) ^ ord(char)
return hash & 0xffff
+# given a list of (name,regex) pairs, find the first one that matches the given line
+def re_match(regexs, line):
+ for name, regex in regexs:
+ match = re.match(regex, line)
+ if match:
+ return name, match
+ return None, None
+
def do_work(infiles):
# read the qstrs in from the input files
qstrs = {}
- cpp_header_blocks = 3
for infile in infiles:
with open(infile, 'rt') as f:
line_number = 0
@@ -34,23 +42,19 @@ def do_work(infiles):
line_number += 1
line = line.strip()
- # ignore blank lines and comments
- if len(line) == 0 or line.startswith('//'):
+ # ignore blank lines, comments and preprocessor directives
+ if len(line) == 0 or line.startswith('//') or line.startswith('#'):
continue
- # We'll have 3 line-number lines for py/qstrdefs.h - initial, leaving it to
- # go into other headers, and returning to it.
- if line.startswith('# ') and 'py/qstrdefs.h' in line:
- cpp_header_blocks -= 1
- continue
- if cpp_header_blocks != 0:
- continue
-
- # verify line is of the correct form
- match = re.match(r'Q\((.+)\)$', line)
- if not match:
+ # work out what kind of line it is
+ match_kind, match = re_match([('qstr', r'Q\((.+)\)$'), ('cdecl', r'(typedef|extern) [A-Za-z0-9_* ]+;$')], line)
+ if match_kind is None:
+ # unknown line format
print('({}:{}) bad qstr format, got {}'.format(infile, line_number, line), file=sys.stderr)
return False
+ elif match_kind != 'qstr':
+ # not a line with a qstr
+ continue
# get the qstr value
qstr = match.group(1)
diff --git a/py/modcollections.c b/py/modcollections.c
index dbd1896f2..11845a00c 100644
--- a/py/modcollections.c
+++ b/py/modcollections.c
@@ -5,7 +5,7 @@
#include "builtin.h"
STATIC const mp_map_elem_t mp_module_collections_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_collections) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR__collections) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_namedtuple), (mp_obj_t)&mp_namedtuple_obj },
};
@@ -22,6 +22,6 @@ STATIC const mp_obj_dict_t mp_module_collections_globals = {
const mp_obj_module_t mp_module_collections = {
.base = { &mp_type_module },
- .name = MP_QSTR_collections,
+ .name = MP_QSTR__collections,
.globals = (mp_obj_dict_t*)&mp_module_collections_globals,
};
diff --git a/py/modsys.c b/py/modsys.c
new file mode 100644
index 000000000..59539b3b9
--- /dev/null
+++ b/py/modsys.c
@@ -0,0 +1,50 @@
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "builtin.h"
+#include "runtime.h"
+#include "objlist.h"
+
+#if MICROPY_ENABLE_MOD_SYS
+
+// These should be implemented by ports, specific types don't matter,
+// only addresses.
+struct _dummy_t;
+extern struct _dummy_t mp_sys_stdin_obj;
+extern struct _dummy_t mp_sys_stdout_obj;
+extern struct _dummy_t mp_sys_stderr_obj;
+
+mp_obj_list_t mp_sys_path_obj;
+mp_obj_list_t mp_sys_argv_obj;
+
+STATIC const mp_map_elem_t mp_module_sys_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_sys) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_path), (mp_obj_t)&mp_sys_path_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_argv), (mp_obj_t)&mp_sys_argv_obj },
+
+#if MICROPY_MOD_SYS_STDFILES
+ { MP_OBJ_NEW_QSTR(MP_QSTR_stdin), (mp_obj_t)&mp_sys_stdin_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_stdout), (mp_obj_t)&mp_sys_stdout_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_stderr), (mp_obj_t)&mp_sys_stderr_obj },
+#endif
+};
+
+STATIC const mp_obj_dict_t mp_module_sys_globals = {
+ .base = {&mp_type_dict},
+ .map = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = sizeof(mp_module_sys_globals_table) / sizeof(mp_map_elem_t),
+ .alloc = sizeof(mp_module_sys_globals_table) / sizeof(mp_map_elem_t),
+ .table = (mp_map_elem_t*)mp_module_sys_globals_table,
+ },
+};
+
+const mp_obj_module_t mp_module_sys = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_sys,
+ .globals = (mp_obj_dict_t*)&mp_module_sys_globals,
+};
+
+#endif
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 2c118b4bb..cbe18b409 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -120,6 +120,15 @@ typedef double mp_float_t;
#define MICROPY_ENABLE_MOD_STRUCT (1)
#endif
+// Whether to provide "sys" module
+#ifndef MICROPY_ENABLE_MOD_SYS
+#define MICROPY_ENABLE_MOD_SYS (1)
+#endif
+
+#ifndef MICROPY_MOD_SYS_STDFILES
+#define MICROPY_MOD_SYS_STDFILES (0)
+#endif
+
// Whether to support slice object and correspondingly
// slice subscript operators
#ifndef MICROPY_ENABLE_SLICE
diff --git a/py/obj.c b/py/obj.c
index 7666855e5..bdafc7247 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -110,7 +110,7 @@ machine_int_t mp_obj_hash(mp_obj_t o_in) {
return 1; // needs to hash to same as the integer 1, since True==1
} else if (MP_OBJ_IS_SMALL_INT(o_in)) {
return MP_OBJ_SMALL_INT_VALUE(o_in);
- } else if (MP_OBJ_IS_STR(o_in)) {
+ } else if (MP_OBJ_IS_STR(o_in) || MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {
return mp_obj_str_get_hash(o_in);
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_NoneType)) {
return (machine_int_t)o_in;
@@ -333,11 +333,11 @@ mp_obj_t mp_identity(mp_obj_t self) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);
bool mp_get_buffer(mp_obj_t obj, buffer_info_t *bufinfo) {
- mp_obj_base_t *o = (mp_obj_base_t *)obj;
- if (o->type->buffer_p.get_buffer == NULL) {
+ mp_obj_type_t *type = mp_obj_get_type(obj);
+ if (type->buffer_p.get_buffer == NULL) {
return false;
}
- o->type->buffer_p.get_buffer(o, bufinfo, BUFFER_READ);
+ type->buffer_p.get_buffer(obj, bufinfo, BUFFER_READ);
if (bufinfo->buf == NULL) {
return false;
}
diff --git a/py/obj.h b/py/obj.h
index 356e722dc..6e5796668 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -454,6 +454,8 @@ machine_int_t mp_obj_tuple_hash(mp_obj_t self_in);
mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args);
// list
+struct _mp_obj_list_t;
+void mp_obj_list_init(struct _mp_obj_list_t *o, uint n);
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
void mp_obj_list_set_len(mp_obj_t self_in, uint len);
diff --git a/py/objdict.c b/py/objdict.c
index 8bdd0026a..2c56540d1 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -10,6 +10,7 @@
#include "objtuple.h"
#include "runtime0.h"
#include "runtime.h"
+#include "builtin.h"
STATIC mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur);
STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in);
@@ -137,12 +138,6 @@ STATIC bool dict_store_item(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return true;
}
-STATIC mp_obj_t dict_getitem(mp_obj_t lhs_in, mp_obj_t rhs_in) {
- return dict_binary_op(MP_BINARY_OP_SUBSCR, lhs_in, rhs_in);
-}
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(dict_getitem_obj, dict_getitem);
-
/******************************************************************************/
/* dict iterator */
@@ -501,7 +496,7 @@ STATIC const mp_map_elem_t dict_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_setdefault), (mp_obj_t)&dict_setdefault_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&dict_update_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_values), (mp_obj_t)&dict_values_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR___getitem__), (mp_obj_t)&dict_getitem_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___getitem__), (mp_obj_t)&mp_op_getitem_obj },
};
STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table);
diff --git a/py/objfun.c b/py/objfun.c
index dd4b7347c..8fadbc611 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -229,7 +229,8 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o
if (n_args > self->n_args) {
// given more than enough arguments
if (!self->takes_var_args) {
- goto arg_error;
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ "function takes %d positional arguments but %d were given", self->n_args, n_args));
}
// put extra arguments in varargs tuple
*extra_args = mp_obj_new_tuple(n_args - self->n_args, args + self->n_args);
@@ -249,7 +250,9 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o
extra_args -= self->n_args - n_args;
n_extra_args += self->n_args - n_args;
} else {
- goto arg_error;
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ "function takes at least %d positional arguments but %d were given",
+ self->n_args - self->n_def_args, n_args));
}
}
}
@@ -344,9 +347,6 @@ continue2:;
} else { // MP_VM_RETURN_EXCEPTION
nlr_raise(result);
}
-
-arg_error:
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args));
}
const mp_obj_type_t mp_type_fun_bc = {
@@ -422,26 +422,36 @@ STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
// pointer to the string (it's probably constant though!)
uint l;
return (machine_uint_t)mp_obj_str_get_data(obj, &l);
+ } else {
+ mp_obj_type_t *type = mp_obj_get_type(obj);
+ if (0) {
#if MICROPY_ENABLE_FLOAT
- } else if (MP_OBJ_IS_TYPE(obj, &mp_type_float)) {
- // convert float to int (could also pass in float registers)
- return (machine_int_t)mp_obj_float_get(obj);
+ } else if (type == &mp_type_float) {
+ // convert float to int (could also pass in float registers)
+ return (machine_int_t)mp_obj_float_get(obj);
#endif
- } else if (MP_OBJ_IS_TYPE(obj, &mp_type_tuple)) {
- // pointer to start of tuple (could pass length, but then could use len(x) for that)
- uint len;
- mp_obj_t *items;
- mp_obj_tuple_get(obj, &len, &items);
- return (machine_uint_t)items;
- } else if (MP_OBJ_IS_TYPE(obj, &mp_type_list)) {
- // pointer to start of list (could pass length, but then could use len(x) for that)
- uint len;
- mp_obj_t *items;
- mp_obj_list_get(obj, &len, &items);
- return (machine_uint_t)items;
- } else {
- // just pass along a pointer to the object
- return (machine_uint_t)obj;
+ } else if (type == &mp_type_tuple) {
+ // pointer to start of tuple (could pass length, but then could use len(x) for that)
+ uint len;
+ mp_obj_t *items;
+ mp_obj_tuple_get(obj, &len, &items);
+ return (machine_uint_t)items;
+ } else if (type == &mp_type_list) {
+ // pointer to start of list (could pass length, but then could use len(x) for that)
+ uint len;
+ mp_obj_t *items;
+ mp_obj_list_get(obj, &len, &items);
+ return (machine_uint_t)items;
+ } else {
+ buffer_info_t bufinfo;
+ if (mp_get_buffer(obj, &bufinfo)) {
+ // supports the buffer protocol, return a pointer to the data
+ return (machine_uint_t)bufinfo.buf;
+ } else {
+ // just pass along a pointer to the object
+ return (machine_uint_t)obj;
+ }
+ }
}
}
diff --git a/py/objint.c b/py/objint.c
index 69954168d..2eabff8d4 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -265,18 +265,27 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(int op, mp_obj_t lhs_in, mp_obj_t rhs_
return MP_OBJ_NULL;
}
+// this is a classmethod
STATIC mp_obj_t int_from_bytes(uint n_args, const mp_obj_t *args) {
+ // TODO: Support long ints
+ // TODO: Support byteorder param (assumes 'little' at the moment)
+ // TODO: Support signed param (assumes signed=False at the moment)
+
+ // get the buffer info
buffer_info_t bufinfo;
- mp_get_buffer_raise(args[0], &bufinfo);
+ mp_get_buffer_raise(args[1], &bufinfo);
- assert(bufinfo.len >= sizeof(machine_int_t));
- // TODO: Support long ints
- // TODO: Support byteorder param
- // TODO: Support signed param
- return mp_obj_new_int_from_uint(*(machine_uint_t*)bufinfo.buf);
+ // convert the bytes to an integer
+ machine_uint_t value = 0;
+ for (const byte* buf = bufinfo.buf + bufinfo.len - 1; buf >= (byte*)bufinfo.buf; buf--) {
+ value = (value << 8) | *buf;
+ }
+
+ return mp_obj_new_int_from_uint(value);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_obj, 1, 3, int_from_bytes);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 2, 3, int_from_bytes);
+STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, (const mp_obj_t)&int_from_bytes_fun_obj);
STATIC mp_obj_t int_to_bytes(uint n_args, const mp_obj_t *args) {
machine_int_t val = mp_obj_int_get_checked(args[0]);
diff --git a/py/objlist.c b/py/objlist.c
index 531e4b85b..fa7d2bc1c 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -8,13 +8,7 @@
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
-
-typedef struct _mp_obj_list_t {
- mp_obj_base_t base;
- machine_uint_t alloc;
- machine_uint_t len;
- mp_obj_t *items;
-} mp_obj_list_t;
+#include "objlist.h"
STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, int cur);
STATIC mp_obj_list_t *list_new(uint n);
@@ -39,6 +33,15 @@ STATIC void list_print(void (*print)(void *env, const char *fmt, ...), void *env
print(env, "]");
}
+STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {
+ mp_obj_t iter = mp_getiter(iterable);
+ mp_obj_t item;
+ while ((item = mp_iternext(iter)) != MP_OBJ_NULL) {
+ mp_obj_list_append(list, item);
+ }
+ return list;
+}
+
STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// TODO check n_kw == 0
@@ -50,13 +53,9 @@ STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
case 1:
{
// make list from iterable
- mp_obj_t iterable = mp_getiter(args[0]);
+ // TODO: optimize list/tuple
mp_obj_t list = mp_obj_new_list(0, NULL);
- mp_obj_t item;
- while ((item = mp_iternext(iterable)) != MP_OBJ_NULL) {
- mp_obj_list_append(list, item);
- }
- return list;
+ return list_extend_from_iter(list, args[0]);
}
default:
@@ -173,18 +172,21 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
- assert(MP_OBJ_IS_TYPE(arg_in, &mp_type_list));
- mp_obj_list_t *self = self_in;
- mp_obj_list_t *arg = arg_in;
+ if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) {
+ mp_obj_list_t *self = self_in;
+ mp_obj_list_t *arg = arg_in;
+
+ if (self->len + arg->len > self->alloc) {
+ // TODO: use alloc policy for "4"
+ self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4);
+ self->alloc = self->len + arg->len + 4;
+ }
- if (self->len + arg->len > self->alloc) {
- // TODO: use alloc policy for "4"
- self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4);
- self->alloc = self->len + arg->len + 4;
+ memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len);
+ self->len += arg->len;
+ } else {
+ list_extend_from_iter(self_in, arg_in);
}
-
- memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len);
- self->len += arg->len;
return mp_const_none; // return None, as per CPython
}
@@ -363,12 +365,16 @@ const mp_obj_type_t mp_type_list = {
.locals_dict = (mp_obj_t)&list_locals_dict,
};
-STATIC mp_obj_list_t *list_new(uint n) {
- mp_obj_list_t *o = m_new_obj(mp_obj_list_t);
+void mp_obj_list_init(mp_obj_list_t *o, uint n) {
o->base.type = &mp_type_list;
o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n;
o->len = n;
o->items = m_new(mp_obj_t, o->alloc);
+}
+
+STATIC mp_obj_list_t *list_new(uint n) {
+ mp_obj_list_t *o = m_new_obj(mp_obj_list_t);
+ mp_obj_list_init(o, n);
return o;
}
diff --git a/py/objlist.h b/py/objlist.h
new file mode 100644
index 000000000..cc8d7de26
--- /dev/null
+++ b/py/objlist.h
@@ -0,0 +1,6 @@
+typedef struct _mp_obj_list_t {
+ mp_obj_base_t base;
+ machine_uint_t alloc;
+ machine_uint_t len;
+ mp_obj_t *items;
+} mp_obj_list_t;
diff --git a/py/objset.c b/py/objset.c
index 05d064a04..bdc8d7f38 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -9,6 +9,7 @@
#include "obj.h"
#include "runtime.h"
#include "runtime0.h"
+#include "builtin.h"
typedef struct _mp_obj_set_t {
mp_obj_base_t base;
@@ -445,6 +446,7 @@ STATIC const mp_map_elem_t set_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference_update), (mp_obj_t)&set_symmetric_difference_update_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_union), (mp_obj_t)&set_union_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&set_update_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___contains__), (mp_obj_t)&mp_op_contains_obj },
};
STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table);
diff --git a/py/objstr.c b/py/objstr.c
index e55a2edd5..d933fa5e3 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -1298,6 +1298,34 @@ STATIC mp_obj_t str_rpartition(mp_obj_t self_in, mp_obj_t arg) {
return str_partitioner(self_in, arg, -1);
}
+#if MICROPY_CPYTHON_COMPAT
+// These methods are superfluous in the presense of str() and bytes()
+// constructors.
+// TODO: should accept kwargs too
+STATIC mp_obj_t bytes_decode(uint n_args, const mp_obj_t *args) {
+ mp_obj_t new_args[2];
+ if (n_args == 1) {
+ new_args[0] = args[0];
+ new_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8);
+ args = new_args;
+ n_args++;
+ }
+ return str_make_new(NULL, n_args, 0, args);
+}
+
+// TODO: should accept kwargs too
+STATIC mp_obj_t str_encode(uint n_args, const mp_obj_t *args) {
+ mp_obj_t new_args[2];
+ if (n_args == 1) {
+ new_args[0] = args[0];
+ new_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8);
+ args = new_args;
+ n_args++;
+ }
+ return bytes_make_new(NULL, n_args, 0, args);
+}
+#endif
+
STATIC machine_int_t str_get_buffer(mp_obj_t self_in, buffer_info_t *bufinfo, int flags) {
if (flags == BUFFER_READ) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
@@ -1312,6 +1340,10 @@ STATIC machine_int_t str_get_buffer(mp_obj_t self_in, buffer_info_t *bufinfo, in
}
}
+#if MICROPY_CPYTHON_COMPAT
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode);
+#endif
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index);
@@ -1327,6 +1359,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);
STATIC const mp_map_elem_t str_locals_dict_table[] = {
+#if MICROPY_CPYTHON_COMPAT
+ { MP_OBJ_NEW_QSTR(MP_QSTR_decode), (mp_obj_t)&bytes_decode_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_encode), (mp_obj_t)&str_encode_obj },
+#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&str_find_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rfind), (mp_obj_t)&str_rfind_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&str_index_obj },
@@ -1444,7 +1480,8 @@ STATIC void bad_implicit_conversion(mp_obj_t self_in) {
}
uint mp_obj_str_get_hash(mp_obj_t self_in) {
- if (MP_OBJ_IS_STR(self_in)) {
+ // TODO: This has too big overhead for hash accessor
+ if (MP_OBJ_IS_STR(self_in) || MP_OBJ_IS_TYPE(self_in, &mp_type_bytes)) {
GET_STR_HASH(self_in, h);
return h;
} else {
diff --git a/py/opmethods.c b/py/opmethods.c
new file mode 100644
index 000000000..af2524cf2
--- /dev/null
+++ b/py/opmethods.c
@@ -0,0 +1,20 @@
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "runtime0.h"
+#include "builtin.h"
+
+STATIC mp_obj_t op_getitem(mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ mp_obj_type_t *type = mp_obj_get_type(lhs_in);
+ return type->binary_op(MP_BINARY_OP_SUBSCR, lhs_in, rhs_in);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem);
+
+STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ mp_obj_type_t *type = mp_obj_get_type(lhs_in);
+ return type->binary_op(MP_BINARY_OP_IN, lhs_in, rhs_in);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains);
diff --git a/py/parsehelper.c b/py/parsehelper.c
index e069657b1..d467399a1 100644
--- a/py/parsehelper.c
+++ b/py/parsehelper.c
@@ -38,20 +38,30 @@ void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_
}
}
-mp_obj_t mp_parse_make_exception(mp_parse_error_kind_t parse_error_kind) {
- // TODO add source file and line number to exception?
+mp_obj_t mp_parse_make_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind) {
+ // make exception object
+ mp_obj_t exc;
switch (parse_error_kind) {
case MP_PARSE_ERROR_MEMORY:
- return mp_obj_new_exception_msg(&mp_type_MemoryError, STR_MEMORY);
+ exc = mp_obj_new_exception_msg(&mp_type_MemoryError, STR_MEMORY);
+ break;
case MP_PARSE_ERROR_UNEXPECTED_INDENT:
- return mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNEXPECTED_INDENT);
+ exc = mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNEXPECTED_INDENT);
+ break;
case MP_PARSE_ERROR_UNMATCHED_UNINDENT:
- return mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNMATCHED_UNINDENT);
+ exc = mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNMATCHED_UNINDENT);
+ break;
case MP_PARSE_ERROR_INVALID_SYNTAX:
default:
- return mp_obj_new_exception_msg(&mp_type_SyntaxError, STR_INVALID_SYNTAX);
+ exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, STR_INVALID_SYNTAX);
+ break;
}
+
+ // add traceback to give info about file name and location
+ mp_obj_exception_add_traceback(exc, mp_lexer_source_name(lex), mp_lexer_cur(lex)->src_line, mp_lexer_cur(lex)->src_column);
+
+ return exc;
}
diff --git a/py/parsehelper.h b/py/parsehelper.h
index 1de70d19d..b8f8c106d 100644
--- a/py/parsehelper.h
+++ b/py/parsehelper.h
@@ -1,2 +1,2 @@
void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind);
-mp_obj_t mp_parse_make_exception(mp_parse_error_kind_t parse_error_kind);
+mp_obj_t mp_parse_make_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind);
diff --git a/py/py.mk b/py/py.mk
index 23ba9ebe7..741d4438f 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -69,6 +69,7 @@ PY_O_BASENAME = \
objtuple.o \
objtype.o \
objzip.o \
+ opmethods.o \
sequence.o \
stream.o \
binary.o \
@@ -82,6 +83,7 @@ PY_O_BASENAME = \
modmath.o \
modmicropython.o \
modstruct.o \
+ modsys.o \
vm.o \
showbc.o \
repl.o \
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index d52b870e6..b332e22fa 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -17,6 +17,7 @@ Q(__path__)
Q(__repl_print__)
Q(__bool__)
+Q(__contains__)
Q(__enter__)
Q(__exit__)
Q(__len__)
@@ -90,7 +91,7 @@ Q(calcsize)
#endif
Q(chr)
Q(classmethod)
-Q(collections)
+Q(_collections)
Q(complex)
Q(dict)
Q(dir)
@@ -263,3 +264,16 @@ Q(<setcomp>)
Q(<genexpr>)
Q(<string>)
Q(<stdin>)
+
+#if MICROPY_CPYTHON_COMPAT
+Q(encode)
+Q(decode)
+Q(utf-8)
+#endif
+
+#if MICROPY_ENABLE_MOD_SYS
+Q(argv)
+Q(stdin)
+Q(stdout)
+Q(stderr)
+#endif
diff --git a/py/runtime.c b/py/runtime.c
index 053367e3f..a507f97f3 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -53,17 +53,6 @@ void mp_init(void) {
// locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
dict_locals = dict_globals = &dict_main;
-
-#if MICROPY_CPYTHON_COMPAT
- // Precreate sys module, so "import sys" didn't throw exceptions.
- mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys);
- // Avoid warning of unused var
- (void)m_sys;
-#endif
- // init sys.path
- // for efficiency, left to platform-specific startup code
- //mp_sys_path = mp_obj_new_list(0, NULL);
- //mp_store_attr(m_sys, MP_QSTR_path, mp_sys_path);
}
void mp_deinit(void) {
@@ -1143,7 +1132,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_obj_dict_store,
mp_obj_new_set,
mp_obj_set_store,
- mp_make_function_from_id,
+ mp_make_function_from_raw_code,
mp_call_function_n_kw_for_native,
mp_call_method_n_kw,
mp_getiter,
diff --git a/py/runtime.h b/py/runtime.h
index 867d63352..1d60181e7 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -29,12 +29,9 @@ mp_obj_t mp_load_const_dec(qstr qstr);
mp_obj_t mp_load_const_str(qstr qstr);
mp_obj_t mp_load_const_bytes(qstr qstr);
-mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args);
-mp_obj_t mp_make_function_from_id_and_free(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args);
mp_obj_t mp_make_function_n(int n_args, void *fun); // fun must have the correct signature for n_args fixed arguments
mp_obj_t mp_make_function_var(int n_args_min, mp_fun_var_t fun);
mp_obj_t mp_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun); // min and max are inclusive
-mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args);
mp_obj_t mp_call_function_0(mp_obj_t fun);
mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg);
@@ -60,8 +57,12 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
mp_obj_t mp_make_raise_obj(mp_obj_t o);
-extern mp_obj_t mp_sys_path;
mp_map_t *mp_loaded_modules_get(void);
mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level);
mp_obj_t mp_import_from(mp_obj_t module, qstr name);
void mp_import_all(mp_obj_t module);
+
+extern struct _mp_obj_list_t mp_sys_path_obj;
+extern struct _mp_obj_list_t mp_sys_argv_obj;
+#define mp_sys_path ((mp_obj_t)&mp_sys_path_obj)
+#define mp_sys_argv ((mp_obj_t)&mp_sys_argv_obj)
diff --git a/py/runtime0.h b/py/runtime0.h
index 6ee70aa01..eef370679 100644
--- a/py/runtime0.h
+++ b/py/runtime0.h
@@ -86,7 +86,7 @@ typedef enum {
MP_F_STORE_MAP,
MP_F_BUILD_SET,
MP_F_STORE_SET,
- MP_F_MAKE_FUNCTION_FROM_ID,
+ MP_F_MAKE_FUNCTION_FROM_RAW_CODE,
MP_F_CALL_FUNCTION_N_KW_FOR_NATIVE,
MP_F_CALL_METHOD_N_KW,
MP_F_GETITER,
diff --git a/py/scope.c b/py/scope.c
index 51701727e..391ad5da8 100644
--- a/py/scope.c
+++ b/py/scope.c
@@ -6,10 +6,12 @@
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
+#include "obj.h"
#include "parse.h"
+#include "emitglue.h"
#include "scope.h"
-scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint unique_code_id, uint emit_options) {
+scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint emit_options) {
scope_t *scope = m_new0(scope_t, 1);
scope->kind = kind;
scope->pn = pn;
@@ -41,7 +43,7 @@ scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint
default:
assert(0);
}
- scope->unique_code_id = unique_code_id;
+ scope->raw_code = mp_emit_glue_new_raw_code();
scope->emit_options = emit_options;
scope->id_info_alloc = 8;
scope->id_info = m_new(id_info_t, scope->id_info_alloc);
diff --git a/py/scope.h b/py/scope.h
index 07b41fe72..6e0990ea9 100644
--- a/py/scope.h
+++ b/py/scope.h
@@ -29,7 +29,7 @@ typedef struct _scope_t {
mp_parse_node_t pn;
qstr source_file;
qstr simple_name;
- uint unique_code_id;
+ mp_raw_code_t *raw_code;
uint8_t scope_flags; // see runtime0.h
uint8_t emit_options; // see compile.h
uint16_t num_params;
@@ -41,7 +41,7 @@ typedef struct _scope_t {
id_info_t *id_info;
} scope_t;
-scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint unique_code_id, uint emit_options);
+scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint emit_options);
void scope_free(scope_t *scope);
id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added);
id_info_t *scope_find(scope_t *scope, qstr qstr);
diff --git a/py/showbc.c b/py/showbc.c
index 615d1fe0d..25b1b2ffb 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -22,6 +22,11 @@
qstr = (qstr << 7) + (*ip & 0x7f); \
} while ((*ip++ & 0x80) != 0); \
}
+#define DECODE_PTR do { \
+ ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \
+ unum = *(machine_uint_t*)ip; \
+ ip += sizeof(machine_uint_t); \
+} while (0)
void mp_byte_code_print(const byte *ip, int len) {
const byte *ip_start = ip;
@@ -389,22 +394,22 @@ void mp_byte_code_print(const byte *ip, int len) {
break;
case MP_BC_MAKE_FUNCTION:
- DECODE_UINT;
+ DECODE_PTR;
printf("MAKE_FUNCTION " UINT_FMT, unum);
break;
case MP_BC_MAKE_FUNCTION_DEFARGS:
- DECODE_UINT;
+ DECODE_PTR;
printf("MAKE_FUNCTION_DEFARGS " UINT_FMT, unum);
break;
case MP_BC_MAKE_CLOSURE:
- DECODE_UINT;
+ DECODE_PTR;
printf("MAKE_CLOSURE " UINT_FMT, unum);
break;
case MP_BC_MAKE_CLOSURE_DEFARGS:
- DECODE_UINT;
+ DECODE_PTR;
printf("MAKE_CLOSURE_DEFARGS " UINT_FMT, unum);
break;
diff --git a/py/vm.c b/py/vm.c
index f62cb2d7b..be7cf01f0 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -7,6 +7,7 @@
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
+#include "emitglue.h"
#include "runtime.h"
#include "bc0.h"
#include "bc.h"
@@ -29,20 +30,25 @@ typedef enum {
UNWIND_JUMP,
} mp_unwind_reason_t;
-#define DECODE_UINT { \
+#define DECODE_UINT do { \
unum = 0; \
do { \
unum = (unum << 7) + (*ip & 0x7f); \
} while ((*ip++ & 0x80) != 0); \
-}
+} while (0)
#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
-#define DECODE_QSTR { \
+#define DECODE_QSTR do { \
qst = 0; \
do { \
qst = (qst << 7) + (*ip & 0x7f); \
} while ((*ip++ & 0x80) != 0); \
-}
+} while (0)
+#define DECODE_PTR do { \
+ ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \
+ unum = *(machine_uint_t*)ip; \
+ ip += sizeof(machine_uint_t); \
+} while (0)
#define PUSH(val) *++sp = (val)
#define POP() (*sp--)
#define TOP() (*sp)
@@ -704,29 +710,29 @@ unwind_jump:
break;
case MP_BC_MAKE_FUNCTION:
- DECODE_UINT;
- PUSH(mp_make_function_from_id(unum, MP_OBJ_NULL, MP_OBJ_NULL));
+ DECODE_PTR;
+ PUSH(mp_make_function_from_raw_code((mp_raw_code_t*)unum, MP_OBJ_NULL, MP_OBJ_NULL));
break;
case MP_BC_MAKE_FUNCTION_DEFARGS:
- DECODE_UINT;
+ DECODE_PTR;
// Stack layout: def_tuple def_dict <- TOS
obj1 = POP();
- SET_TOP(mp_make_function_from_id(unum, TOP(), obj1));
+ SET_TOP(mp_make_function_from_raw_code((mp_raw_code_t*)unum, TOP(), obj1));
break;
case MP_BC_MAKE_CLOSURE:
- DECODE_UINT;
+ DECODE_PTR;
// Stack layout: closure_tuple <- TOS
- SET_TOP(mp_make_closure_from_id(unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL));
+ SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL));
break;
case MP_BC_MAKE_CLOSURE_DEFARGS:
- DECODE_UINT;
+ DECODE_PTR;
// Stack layout: def_tuple def_dict closure_tuple <- TOS
obj1 = POP();
obj2 = POP();
- SET_TOP(mp_make_closure_from_id(unum, obj1, TOP(), obj2));
+ SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, obj1, TOP(), obj2));
break;
case MP_BC_CALL_FUNCTION:
diff --git a/stm/main.c b/stm/main.c
index 636f90021..d7f2624c3 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -239,11 +239,10 @@ soft_reset:
// Micro Python init
qstr_init();
mp_init();
- mp_obj_t def_path[3];
- def_path[0] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_);
- def_path[1] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_src);
- def_path[2] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib);
- mp_sys_path = mp_obj_new_list(3, def_path);
+ mp_obj_list_init(mp_sys_path, 0);
+ mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_));
+ mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib));
+ mp_obj_list_init(mp_sys_argv, 0);
exti_init();
diff --git a/stmhal/dac.c b/stmhal/dac.c
index 22622d474..5e809412e 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -180,12 +180,8 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// set TIM6 to trigger the DAC at the given frequency
TIM6_Config(mp_obj_get_int(args[2]));
- mp_obj_type_t *type = mp_obj_get_type(args[1]);
- if (type->buffer_p.get_buffer == NULL) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "buffer argument must support buffer protocol"));
- }
buffer_info_t bufinfo;
- type->buffer_p.get_buffer(args[1], &bufinfo, BUFFER_READ);
+ mp_get_buffer_raise(args[1], &bufinfo);
__DMA1_CLK_ENABLE();
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index 9528a3c3c..65bc3600e 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -143,16 +143,13 @@ STATIC mp_obj_t pyb_i2c_mem_write(uint n_args, const mp_obj_t *args) {
machine_uint_t i2c_addr = mp_obj_get_int(args[1]) << 1;
machine_uint_t mem_addr = mp_obj_get_int(args[2]);
HAL_StatusTypeDef status;
- mp_obj_type_t *type = mp_obj_get_type(args[3]);
- if (type->buffer_p.get_buffer != NULL) {
- buffer_info_t bufinfo;
- type->buffer_p.get_buffer(args[3], &bufinfo, BUFFER_READ);
- status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, bufinfo.buf, bufinfo.len, 200);
- } else if (MP_OBJ_IS_INT(args[3])) {
+ if (MP_OBJ_IS_INT(args[3])) {
uint8_t data[1] = {mp_obj_get_int(args[3])};
status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
} else {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "data argument must be an integer or support the buffer protocol"));
+ buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[3], &bufinfo);
+ status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, bufinfo.buf, bufinfo.len, 200);
}
//printf("Write got %d\n", status);
diff --git a/stmhal/main.c b/stmhal/main.c
index 29c704b10..2f40f140a 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -263,10 +263,10 @@ soft_reset:
// Micro Python init
qstr_init();
mp_init();
- mp_obj_t def_path[2];
- def_path[0] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_);
- def_path[1] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib);
- mp_sys_path = mp_obj_new_list(2, def_path);
+ mp_obj_list_init(mp_sys_path, 0);
+ mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_));
+ mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib));
+ mp_obj_list_init(mp_sys_argv, 0);
readline_init();
diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c
index a6cb5adb6..c564a0f19 100644
--- a/stmhal/modpyb.c
+++ b/stmhal/modpyb.c
@@ -32,7 +32,7 @@
#include "ff.h"
// get lots of info about the board
-STATIC mp_obj_t pyb_info(void) {
+STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) {
// get and print unique id; 96 bits
{
byte *id = (byte*)0x1fff7a10;
@@ -89,10 +89,15 @@ STATIC mp_obj_t pyb_info(void) {
printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512));
}
+ if (n_args == 1) {
+ // arg given means dump gc allocation table
+ gc_dump_alloc_table();
+ }
+
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_info_obj, pyb_info);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info);
// sync all file systems
STATIC mp_obj_t pyb_sync(void) {
diff --git a/tests/basics/list1.py b/tests/basics/list1.py
index 122f61d49..a0c8afc4f 100644
--- a/tests/basics/list1.py
+++ b/tests/basics/list1.py
@@ -13,6 +13,8 @@ print(x)
x.extend([100, 200])
print(x)
+x.extend(range(3))
+print(x)
x += [2, 1]
print(x)
diff --git a/tests/basics/namedtuple1.py b/tests/basics/namedtuple1.py
index 1e194472f..98628cc54 100644
--- a/tests/basics/namedtuple1.py
+++ b/tests/basics/namedtuple1.py
@@ -1,4 +1,7 @@
-from collections import namedtuple
+try:
+ from collections import namedtuple
+except ImportError:
+ from _collections import namedtuple
T = namedtuple("Tup", "foo bar")
# CPython prints fully qualified name, what we don't bother to do so far
diff --git a/tools/pip-micropython b/tools/pip-micropython
index fab880983..d5b84b0e2 100755
--- a/tools/pip-micropython
+++ b/tools/pip-micropython
@@ -30,6 +30,21 @@ fi
# installed if it's already installed for main python distribution.
if [ ! -d /tmp/pip-micropy-venv ]; then
virtualenv --no-site-packages /tmp/pip-micropy-venv
+ # distutils, setuptools, pip are buggy and allow target packages affect
+ # their execution environment. For example, if distribution they install
+ # has re.py, they will import that instead of system re. So, we need
+ # to remove current dir from sys.path, but that appear to be quite uneasy
+ # with CPython, so we hook __import__ and exterminate it persistently.
+ # See also https://bitbucket.org/pypa/setuptools/issue/187/
+ cat > $(ls -1d /tmp/pip-micropy-venv/lib/python*/)/sitecustomize.py <<EOF
+import sys
+import __builtin__
+old_imp = __import__
+def new_imp(*a, **kw):
+ if not sys.path[0]: sys.path.pop(0)
+ return old_imp(*a, **kw)
+__builtin__.__import__ = new_imp
+EOF
fi
. /tmp/pip-micropy-venv/bin/activate
diff --git a/unix-cpy/mpconfigport.h b/unix-cpy/mpconfigport.h
index 752df4f49..7d0e3258e 100644
--- a/unix-cpy/mpconfigport.h
+++ b/unix-cpy/mpconfigport.h
@@ -22,5 +22,3 @@ typedef unsigned int machine_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef double machine_float_t;
-
-machine_float_t machine_sqrt(machine_float_t x);
diff --git a/unix/file.c b/unix/file.c
index fa7be791a..a0a865a26 100644
--- a/unix/file.c
+++ b/unix/file.c
@@ -146,9 +146,6 @@ mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open);
-void file_init() {
- mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys);
- mp_store_attr(m_sys, MP_QSTR_stdin, fdfile_new(STDIN_FILENO));
- mp_store_attr(m_sys, MP_QSTR_stdout, fdfile_new(STDOUT_FILENO));
- mp_store_attr(m_sys, MP_QSTR_stderr, fdfile_new(STDERR_FILENO));
-}
+const mp_obj_fdfile_t mp_sys_stdin_obj = { .base = {&rawfile_type}, .fd = STDIN_FILENO };
+const mp_obj_fdfile_t mp_sys_stdout_obj = { .base = {&rawfile_type}, .fd = STDOUT_FILENO };
+const mp_obj_fdfile_t mp_sys_stderr_obj = { .base = {&rawfile_type}, .fd = STDERR_FILENO };
diff --git a/unix/main.c b/unix/main.c
index f18e40a7f..e582244b3 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -42,7 +42,6 @@ long heap_size = 128*1024 * (sizeof(machine_uint_t) / 4);
// Stack top at the start of program
void *stack_top;
-void file_init();
void microsocket_init();
void time_init();
void ffi_init();
@@ -326,7 +325,7 @@ int main(int argc, char **argv) {
p++;
}
}
- mp_sys_path = mp_obj_new_list(path_num, NULL);
+ mp_obj_list_init(mp_sys_path, path_num);
mp_obj_t *path_items;
mp_obj_list_get(mp_sys_path, &path_num, &path_items);
path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_);
@@ -348,10 +347,7 @@ int main(int argc, char **argv) {
p = p1 + 1;
}
- mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys);
- mp_store_attr(m_sys, MP_QSTR_path, mp_sys_path);
- mp_obj_t py_argv = mp_obj_new_list(0, NULL);
- mp_store_attr(m_sys, MP_QSTR_argv, py_argv);
+ mp_obj_list_init(mp_sys_argv, 0);
mp_store_name(qstr_from_str("test"), test_obj_new(42));
mp_store_name(qstr_from_str("mem_info"), mp_make_function_n(0, mem_info));
@@ -360,7 +356,6 @@ int main(int argc, char **argv) {
mp_store_name(qstr_from_str("gc"), (mp_obj_t)&pyb_gc_obj);
#endif
- file_init();
microsocket_init();
#if MICROPY_MOD_TIME
time_init();
@@ -418,7 +413,7 @@ int main(int argc, char **argv) {
free(basedir);
for (int i = a; i < argc; i++) {
- mp_obj_list_append(py_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
+ mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
}
do_file(argv[a]);
executed = true;
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index e2f2a69e1..832bdb05f 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -13,6 +13,7 @@
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_PATH_MAX (PATH_MAX)
+#define MICROPY_MOD_SYS_STDFILES (1)
// type definitions for the specific machine
diff --git a/unix/mpconfigport.mk b/unix/mpconfigport.mk
index d30be8b98..bfb01a71f 100644
--- a/unix/mpconfigport.mk
+++ b/unix/mpconfigport.mk
@@ -7,4 +7,4 @@ MICROPY_USE_READLINE = 1
MICROPY_MOD_TIME = 1
# ffi module requires libffi (libffi-dev Debian package)
-MICROPY_MOD_FFI = 0
+MICROPY_MOD_FFI = 1
diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h
index a4772a2be..42f20d265 100644
--- a/unix/qstrdefsport.h
+++ b/unix/qstrdefsport.h
@@ -2,10 +2,6 @@
Q(Test)
-Q(argv)
-Q(stdin)
-Q(stdout)
-Q(stderr)
Q(rawsocket)
Q(socket)
Q(sockaddr_in)