diff --git a/py/builtin.c b/py/builtin.c
index 8b380b231086561c6672347fbc4f533fca11fb92..e45cdc98bc861c827bd3b806d554aa6e7236b01b 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -16,6 +16,35 @@
 #include "objprivate.h"
 #include "builtin.h"
 
+py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
+    // we differ from CPython: we set the new __locals__ object here
+    py_map_t *old_locals = rt_get_map_locals();
+    py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
+    rt_set_map_locals(class_locals);
+
+    // call the class code
+    rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
+
+    // restore old __locals__ object
+    rt_set_map_locals(old_locals);
+
+    // create and return the new class
+    py_obj_base_t *o = m_new(py_obj_base_t, 1);
+    o->kind = O_CLASS;
+    o->u_class.locals = class_locals;
+    return o;
+}
+
+py_obj_t py_builtin___import__(int n, py_obj_t *args) {
+    printf("import:\n");
+    for (int i = 0; i < n; i++) {
+    printf("  ");
+    py_obj_print(args[i]);
+    printf("\n");
+    }
+    return py_const_none;
+}
+
 py_obj_t py_builtin___repl_print__(py_obj_t o) {
     if (o != py_const_none) {
         py_obj_print(o);
@@ -24,21 +53,150 @@ py_obj_t py_builtin___repl_print__(py_obj_t o) {
     return py_const_none;
 }
 
-py_obj_t py_builtin_print(int n_args, const py_obj_t* args) {
-    for (int i = 0; i < n_args; i++) {
-        if (i > 0) {
-            printf(" ");
+py_obj_t py_builtin_abs(py_obj_t o_in) {
+    if (IS_SMALL_INT(o_in)) {
+        py_small_int_t val = FROM_SMALL_INT(o_in);
+        if (val < 0) {
+            val = -val;
         }
-        if (IS_O(args[i], O_STR)) {
-            // special case, print string raw
-            printf("%s", qstr_str(((py_obj_base_t*)args[i])->u_str));
+        return TO_SMALL_INT(val);
+#if MICROPY_ENABLE_FLOAT
+    } else if (IS_O(o_in, O_FLOAT)) {
+        py_obj_base_t *o = o_in;
+        // TODO check for NaN etc
+        if (o->u_float < 0) {
+            return py_obj_new_float(-o->u_float);
         } else {
-            // print the object Python style
-            py_obj_print(args[i]);
+            return o_in;
         }
+    } else if (IS_O(o_in, O_COMPLEX)) {
+        py_obj_base_t *o = o_in;
+        return py_obj_new_float(machine_sqrt(o->u_complex.real*o->u_complex.real + o->u_complex.imag*o->u_complex.imag));
+#endif
+    } else {
+        assert(0);
+        return py_const_none;
+    }
+}
+
+py_obj_t py_builtin_all(py_obj_t o_in) {
+    py_obj_t iterable = rt_getiter(o_in);
+    py_obj_t item;
+    while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+        if (!rt_is_true(item)) {
+            return py_const_false;
+        }
+    }
+    return py_const_true;
+}
+
+py_obj_t py_builtin_any(py_obj_t o_in) {
+    py_obj_t iterable = rt_getiter(o_in);
+    py_obj_t item;
+    while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+        if (rt_is_true(item)) {
+            return py_const_true;
+        }
+    }
+    return py_const_false;
+}
+
+py_obj_t py_builtin_bool(int n_args, const py_obj_t *args) {
+    switch (n_args) {
+        case 0: return py_const_false;
+        case 1: if (rt_is_true(args[0])) { return py_const_true; } else { return py_const_false; }
+        default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args, NULL));
+    }
+}
+
+py_obj_t py_builtin_callable(py_obj_t o_in) {
+    if (py_obj_is_callable(o_in)) {
+        return py_const_true;
+    } else {
+        return py_const_false;
+    }
+}
+
+#if MICROPY_ENABLE_FLOAT
+py_obj_t py_builtin_complex(int n_args, const py_obj_t *args) {
+    switch (n_args) {
+        case 0:
+            return py_obj_new_complex(0, 0);
+
+        case 1:
+            // TODO allow string as first arg
+            if (IS_O(args[0], O_COMPLEX)) {
+                return args[0];
+            } else {
+                return py_obj_new_complex(py_obj_get_float(args[0]), 0);
+            }
+
+        case 2:
+        {
+            py_float_t real, imag;
+            if (IS_O(args[0], O_COMPLEX)) {
+                py_obj_get_complex(args[0], &real, &imag);
+            } else {
+                real = py_obj_get_float(args[0]);
+                imag = 0;
+            }
+            if (IS_O(args[1], O_COMPLEX)) {
+                py_float_t real2, imag2;
+                py_obj_get_complex(args[1], &real2, &imag2);
+                real -= imag2;
+                imag += real2;
+            } else {
+                imag += py_obj_get_float(args[1]);
+            }
+            return py_obj_new_complex(real, imag);
+        }
+
+        default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "comlpex() takes at most 2 arguments (%d given)", (void*)(machine_int_t)n_args, NULL));
+    }
+}
+#endif
+
+py_obj_t py_builtin_chr(py_obj_t o_in) {
+    int ord = py_obj_get_int(o_in);
+    if (0 <= ord && ord <= 0x10ffff) {
+        char *str = m_new(char, 2);
+        str[0] = ord;
+        str[1] = '\0';
+        return py_obj_new_str(qstr_from_str_take(str));
+    } else {
+        nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "chr() arg not in range(0x110000)", NULL, NULL));
     }
-    printf("\n");
-    return py_const_none;
+}
+
+py_obj_t py_builtin_dict(void) {
+    // TODO create from an iterable!
+    return rt_build_map(0);
+}
+
+py_obj_t py_builtin_divmod(py_obj_t o1_in, py_obj_t o2_in) {
+    if (IS_SMALL_INT(o1_in) && IS_SMALL_INT(o2_in)) {
+        py_small_int_t i1 = FROM_SMALL_INT(o1_in);
+        py_small_int_t i2 = FROM_SMALL_INT(o2_in);
+        py_obj_t revs_args[2];
+        revs_args[1] = TO_SMALL_INT(i1 / i2);
+        revs_args[0] = TO_SMALL_INT(i1 % i2);
+        return rt_build_tuple(2, revs_args);
+    } else {
+        nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", py_obj_get_type_str(o1_in), py_obj_get_type_str(o2_in)));
+    }
+}
+
+py_obj_t py_builtin_hash(py_obj_t o_in) {
+    // TODO hash will generally overflow small integer; can we safely truncate it?
+    return py_obj_new_int(py_obj_hash(o_in));
+}
+
+py_obj_t py_builtin_iter(py_obj_t o_in) {
+    return rt_getiter(o_in);
+}
+
+py_obj_t py_builtin_next(py_obj_t o_in) {
+    return rt_gen_instance_next(o_in);
 }
 
 py_obj_t py_builtin_len(py_obj_t o_in) {
@@ -53,57 +211,118 @@ py_obj_t py_builtin_len(py_obj_t o_in) {
         py_obj_base_t *o = o_in;
         len = o->u_map.used;
     } else {
-        assert(0);
+        nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "object of type '%s' has no len()", py_obj_get_type_str(o_in), NULL));
     }
     return TO_SMALL_INT(len);
 }
 
-py_obj_t py_builtin_abs(py_obj_t o_in) {
-    if (IS_SMALL_INT(o_in)) {
-        py_small_int_t val = FROM_SMALL_INT(o_in);
-        if (val < 0) {
-            val = -val;
+py_obj_t py_builtin_list(int n_args, const py_obj_t *args) {
+    switch (n_args) {
+        case 0: return rt_build_list(0, NULL);
+        case 1:
+        {
+            // make list from iterable
+            py_obj_t iterable = rt_getiter(args[0]);
+            py_obj_t list = rt_build_list(0, NULL);
+            py_obj_t item;
+            while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+                rt_list_append(list, item);
+            }
+            return list;
         }
-        return TO_SMALL_INT(val);
-#if MICROPY_ENABLE_FLOAT
-    } else if (IS_O(o_in, O_FLOAT)) {
-        py_obj_base_t *o = o_in;
-        // TODO check for NaN etc
-        if (o->u_float < 0) {
-            return py_obj_new_float(-o->u_float);
-        } else {
-            return o_in;
+        default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args, NULL));
+    }
+}
+
+py_obj_t py_builtin_max(int n_args, const py_obj_t *args) {
+    if (n_args == 1) {
+        // given an iterable
+        py_obj_t iterable = rt_getiter(args[0]);
+        py_obj_t max_obj = NULL;
+        py_obj_t item;
+        while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+            if (max_obj == NULL || py_obj_less(max_obj, item)) {
+                max_obj = item;
+            }
         }
-    } else if (IS_O(o_in, O_COMPLEX)) {
-        py_obj_base_t *o = o_in;
-        return py_obj_new_float(machine_sqrt(o->u_complex.real*o->u_complex.real + o->u_complex.imag*o->u_complex.imag));
-#endif
+        if (max_obj == NULL) {
+            nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "max() arg is an empty sequence", NULL, NULL));
+        }
+        return max_obj;
     } else {
-        assert(0);
-        return py_const_none;
+        // given many args
+        py_obj_t max_obj = args[0];
+        for (int i = 1; i < n_args; i++) {
+            if (py_obj_less(max_obj, args[i])) {
+                max_obj = args[i];
+            }
+        }
+        return max_obj;
     }
 }
 
-py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
-    // we differ from CPython: we set the new __locals__ object here
-    py_map_t *old_locals = rt_get_map_locals();
-    py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
-    rt_set_map_locals(class_locals);
+py_obj_t py_builtin_min(int n_args, const py_obj_t *args) {
+    if (n_args == 1) {
+        // given an iterable
+        py_obj_t iterable = rt_getiter(args[0]);
+        py_obj_t min_obj = NULL;
+        py_obj_t item;
+        while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+            if (min_obj == NULL || py_obj_less(item, min_obj)) {
+                min_obj = item;
+            }
+        }
+        if (min_obj == NULL) {
+            nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "min() arg is an empty sequence", NULL, NULL));
+        }
+        return min_obj;
+    } else {
+        // given many args
+        py_obj_t min_obj = args[0];
+        for (int i = 1; i < n_args; i++) {
+            if (py_obj_less(args[i], min_obj)) {
+                min_obj = args[i];
+            }
+        }
+        return min_obj;
+    }
+}
 
-    // call the class code
-    rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
+py_obj_t py_builtin_ord(py_obj_t o_in) {
+    const char *str = qstr_str(py_obj_get_qstr(o_in));
+    if (strlen(str) == 1) {
+        return py_obj_new_int(str[0]);
+    } else {
+        nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str), NULL));
+    }
+}
 
-    // restore old __locals__ object
-    rt_set_map_locals(old_locals);
+py_obj_t py_builtin_pow(int n_args, const py_obj_t *args) {
+    switch (n_args) {
+        case 2: return rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]);
+        case 3: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise...
+        default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args, NULL));
+    }
+}
 
-    // create and return the new class
-    py_obj_base_t *o = m_new(py_obj_base_t, 1);
-    o->kind = O_CLASS;
-    o->u_class.locals = class_locals;
-    return o;
+py_obj_t py_builtin_print(int n_args, const py_obj_t *args) {
+    for (int i = 0; i < n_args; i++) {
+        if (i > 0) {
+            printf(" ");
+        }
+        if (IS_O(args[i], O_STR)) {
+            // special case, print string raw
+            printf("%s", qstr_str(((py_obj_base_t*)args[i])->u_str));
+        } else {
+            // print the object Python style
+            py_obj_print(args[i]);
+        }
+    }
+    printf("\n");
+    return py_const_none;
 }
 
-py_obj_t py_builtin_range(int n_args, const py_obj_t* args) {
+py_obj_t py_builtin_range(int n_args, const py_obj_t *args) {
     switch (n_args) {
         case 1: return py_obj_new_range(0, py_obj_get_int(args[0]), 1);
         case 2: return py_obj_new_range(py_obj_get_int(args[0]), py_obj_get_int(args[1]), 1);
@@ -111,3 +330,18 @@ py_obj_t py_builtin_range(int n_args, const py_obj_t* args) {
         default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args, NULL));
     }
 }
+
+py_obj_t py_builtin_sum(int n_args, const py_obj_t *args) {
+    py_obj_t value;
+    switch (n_args) {
+        case 1: value = py_obj_new_int(0); break;
+        case 2: value = args[1]; break;
+        default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args, NULL));
+    }
+    py_obj_t iterable = rt_getiter(args[0]);
+    py_obj_t item;
+    while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
+        value = rt_binary_op(RT_BINARY_OP_ADD, value, item);
+    }
+    return value;
+}
diff --git a/py/builtin.h b/py/builtin.h
index 6ca1752bdacfe31b0593dd3f5bac0324097c3ae2..0a0470a842de74ff79aebb3edc161dfd9637d9a2 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -1,6 +1,24 @@
+py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name);
+py_obj_t py_builtin___import__(int n, py_obj_t *args);
 py_obj_t py_builtin___repl_print__(py_obj_t o);
-py_obj_t py_builtin_print(int n_args, const py_obj_t* args);
-py_obj_t py_builtin_len(py_obj_t o_in);
 py_obj_t py_builtin_abs(py_obj_t o_in);
-py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name);
-py_obj_t py_builtin_range(int n_args, const py_obj_t* args);
+py_obj_t py_builtin_all(py_obj_t o_in);
+py_obj_t py_builtin_any(py_obj_t o_in);
+py_obj_t py_builtin_bool(int n_args, const py_obj_t *args);
+py_obj_t py_builtin_callable(py_obj_t o_in);
+py_obj_t py_builtin_complex(int n_args, const py_obj_t *args);
+py_obj_t py_builtin_chr(py_obj_t o_in);
+py_obj_t py_builtin_dict(void);
+py_obj_t py_builtin_divmod(py_obj_t o1_in, py_obj_t o2_in);
+py_obj_t py_builtin_hash(py_obj_t o_in);
+py_obj_t py_builtin_iter(py_obj_t o_in);
+py_obj_t py_builtin_len(py_obj_t o_in);
+py_obj_t py_builtin_list(int n_args, const py_obj_t *args);
+py_obj_t py_builtin_max(int n_args, const py_obj_t *args);
+py_obj_t py_builtin_min(int n_args, const py_obj_t *args);
+py_obj_t py_builtin_next(py_obj_t o_in);
+py_obj_t py_builtin_ord(py_obj_t o_in);
+py_obj_t py_builtin_pow(int n_args, const py_obj_t *args);
+py_obj_t py_builtin_print(int n_args, const py_obj_t *args);
+py_obj_t py_builtin_range(int n_args, const py_obj_t *args);
+py_obj_t py_builtin_sum(int n_args, const py_obj_t *args);
diff --git a/py/obj.c b/py/obj.c
index d678f411464e91afdfccc99b413997970ef8fe11..0699d4cde7cc7935a8f7029f8c5a36ee01c0d89e 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -358,6 +358,17 @@ bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
     }
 }
 
+bool py_obj_less(py_obj_t o1, py_obj_t o2) {
+    if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
+        py_small_int_t i1 = FROM_SMALL_INT(o1);
+        py_small_int_t i2 = FROM_SMALL_INT(o2);
+        return i1 < i2;
+    } else {
+        assert(0);
+        return false;
+    }
+}
+
 machine_int_t py_obj_get_int(py_obj_t arg) {
     if (arg == py_const_false) {
         return 0;
diff --git a/py/obj.h b/py/obj.h
index cbb885503e1007e19248c4de2efe10273c5072ca..746c92bbadc0b0cd1f2f20eb5f238a0cd989e943 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -39,6 +39,7 @@ void py_obj_print(py_obj_t o);
 bool py_obj_is_callable(py_obj_t o_in);
 machine_int_t py_obj_hash(py_obj_t o_in);
 bool py_obj_equal(py_obj_t o1, py_obj_t o2);
+bool py_obj_less(py_obj_t o1, py_obj_t o2);
 
 machine_int_t py_obj_get_int(py_obj_t arg);
 #if MICROPY_ENABLE_FLOAT
diff --git a/py/runtime.c b/py/runtime.c
index f1938d6ec8be874c18c44bad883a2259f6820fe4..35f4f2af29f133fd9774d59ecf71ea0ceb353e6c 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -128,7 +128,7 @@ bad_arg:
     nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "?str.join expecting a list of str's", NULL, NULL));
 }
 
-py_obj_t rt_str_format(int n_args, const py_obj_t* args) {
+py_obj_t rt_str_format(int n_args, const py_obj_t *args) {
     assert(IS_O(args[0], O_STR));
     py_obj_base_t *self = args[0];
 
@@ -302,12 +302,29 @@ void rt_init(void) {
     py_qstr_map_lookup(map_globals, qstr_from_str_static("__name__"), true)->value = py_obj_new_str(qstr_from_str_static("__main__"));
 
     py_map_init(&map_builtins, MAP_QSTR, 3);
+    py_qstr_map_lookup(&map_builtins, rt_q___build_class__, true)->value = rt_make_function_2(py_builtin___build_class__);
     py_qstr_map_lookup(&map_builtins, qstr_from_str_static("__repl_print__"), true)->value = rt_make_function_1(py_builtin___repl_print__);
-    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("print"), true)->value = rt_make_function_var(0, py_builtin_print);
-    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("len"), true)->value = rt_make_function_1(py_builtin_len);
     py_qstr_map_lookup(&map_builtins, qstr_from_str_static("abs"), true)->value = rt_make_function_1(py_builtin_abs);
-    py_qstr_map_lookup(&map_builtins, rt_q___build_class__, true)->value = rt_make_function_2(py_builtin___build_class__);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("all"), true)->value = rt_make_function_1(py_builtin_all);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("any"), true)->value = rt_make_function_1(py_builtin_any);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("bool"), true)->value = rt_make_function_var(0, py_builtin_bool);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("callable"), true)->value = rt_make_function_1(py_builtin_callable);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("complex"), true)->value = rt_make_function_var(0, py_builtin_complex);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("chr"), true)->value = rt_make_function_1(py_builtin_chr);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("dict"), true)->value = rt_make_function_0(py_builtin_dict);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("divmod"), true)->value = rt_make_function_2(py_builtin_divmod);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("hash"), true)->value = rt_make_function_1(py_builtin_hash);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("iter"), true)->value = rt_make_function_1(py_builtin_iter);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("len"), true)->value = rt_make_function_1(py_builtin_len);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("list"), true)->value = rt_make_function_var(0, py_builtin_list);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("max"), true)->value = rt_make_function_var(1, py_builtin_max);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("min"), true)->value = rt_make_function_var(1, py_builtin_min);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("next"), true)->value = rt_make_function_1(py_builtin_next);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("ord"), true)->value = rt_make_function_1(py_builtin_ord);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("pow"), true)->value = rt_make_function_var(2, py_builtin_pow);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("print"), true)->value = rt_make_function_var(0, py_builtin_print);
     py_qstr_map_lookup(&map_builtins, qstr_from_str_static("range"), true)->value = rt_make_function_var(1, py_builtin_range);
+    py_qstr_map_lookup(&map_builtins, qstr_from_str_static("sum"), true)->value = rt_make_function_var(1, py_builtin_sum);
 
     next_unique_code_id = 2; // 1 is reserved for the __main__ module scope
     unique_codes = NULL;
@@ -676,13 +693,27 @@ py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
             case RT_BINARY_OP_TRUE_DIVIDE:
             case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return py_obj_new_float((py_float_t)lhs_val / (py_float_t)rhs_val);
 #endif
+
+            // TODO implement modulo as specified by Python
+            case RT_BINARY_OP_MODULO:
+            case RT_BINARY_OP_INPLACE_MODULO: lhs_val %= rhs_val; break;
+
+            // TODO check for negative power, and overflow
             case RT_BINARY_OP_POWER:
             case RT_BINARY_OP_INPLACE_POWER:
-                // TODO
-                if (rhs_val == 2) {
-                    lhs_val = lhs_val * lhs_val;
-                    break;
+            {
+                int ans = 1;
+                while (rhs_val > 0) {
+                    if (rhs_val & 1) {
+                        ans *= lhs_val;
+                    }
+                    lhs_val *= lhs_val;
+                    rhs_val /= 2;
                 }
+                lhs_val = ans;
+                break;
+            }
+
             default: printf("%d\n", op); assert(0);
         }
         if (fit_small_int(lhs_val)) {
@@ -1456,16 +1487,6 @@ py_obj_t rt_iternext(py_obj_t o_in) {
     }
 }
 
-py_obj_t py_builtin___import__(int n, py_obj_t *args) {
-    printf("import:\n");
-    for (int i = 0; i < n; i++) {
-    printf("  ");
-    py_obj_print(args[i]);
-    printf("\n");
-    }
-    return py_const_none;
-}
-
 py_obj_t rt_import_name(qstr name, py_obj_t fromlist, py_obj_t level) {
     // build args array
     py_obj_t args[5];
diff --git a/py/runtime.h b/py/runtime.h
index c4cd09438933f5dc31ae077fc53790a90727e229..d5d160535f29ca4723c04012bed9324b33c0e096 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -157,3 +157,5 @@ py_obj_t rt_getiter(py_obj_t o);
 py_obj_t rt_iternext(py_obj_t o);
 py_obj_t rt_import_name(qstr name, py_obj_t fromlist, py_obj_t level);
 py_obj_t rt_import_from(py_obj_t module, qstr name);
+
+py_obj_t rt_gen_instance_next(py_obj_t self_in);