diff --git a/py/bc.c b/py/bc.c
index 1d6e4322b2b182477a8a2d4e3eb4ea1ec974a1bd..4a29f439e3b94dc56b4f7750caf3299e78b5edb3 100644
--- a/py/bc.c
+++ b/py/bc.c
@@ -321,7 +321,7 @@ STATIC const byte opcode_format_table[64] = {
     OC4(O, O, U, U), // 0x38-0x3b
     OC4(U, O, B, O), // 0x3c-0x3f
     OC4(O, B, B, O), // 0x40-0x43
-    OC4(B, B, O, B), // 0x44-0x47
+    OC4(O, U, O, B), // 0x44-0x47
     OC4(U, U, U, U), // 0x48-0x4b
     OC4(U, U, U, U), // 0x4c-0x4f
     OC4(V, V, U, V), // 0x50-0x53
diff --git a/py/bc0.h b/py/bc0.h
index 70acfb0cac1b0f89757252af5ff29bbe8a0c8482..175ee263a00cb010d46831cf8f2f23d9739d82e0 100644
--- a/py/bc0.h
+++ b/py/bc0.h
@@ -77,8 +77,7 @@
 #define MP_BC_END_FINALLY        (0x41)
 #define MP_BC_GET_ITER           (0x42)
 #define MP_BC_FOR_ITER           (0x43) // rel byte code offset, 16-bit unsigned
-#define MP_BC_POP_BLOCK          (0x44)
-#define MP_BC_POP_EXCEPT         (0x45)
+#define MP_BC_POP_EXCEPT_JUMP    (0x44) // rel byte code offset, 16-bit unsigned
 #define MP_BC_UNWIND_JUMP        (0x46) // rel byte code offset, 16-bit signed, in excess; then a byte
 #define MP_BC_GET_ITER_STACK     (0x47)
 
diff --git a/py/compile.c b/py/compile.c
index ca01d74785b2a86f0453e9f9b45cd56f2475668b..b7f1d7b0c12190dba53c2d4089803466461be307 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -1535,8 +1535,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
     compile_increase_except_level(comp, l1, MP_EMIT_SETUP_BLOCK_EXCEPT);
 
     compile_node(comp, pn_body); // body
-    EMIT(pop_block);
-    EMIT_ARG(jump, success_label); // jump over exception handler
+    EMIT_ARG(pop_except_jump, success_label, false); // jump over exception handler
 
     EMIT_ARG(label_assign, l1); // start of exception handler
     EMIT(start_except_handler);
@@ -1607,8 +1606,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
             compile_decrease_except_level(comp);
         }
 
-        EMIT(pop_except);
-        EMIT_ARG(jump, l2);
+        EMIT_ARG(pop_except_jump, l2, true);
         EMIT_ARG(label_assign, end_finally_label);
         EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance
     }
@@ -1741,8 +1739,7 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns
     compile_load_id(comp, context);
     compile_await_object_method(comp, MP_QSTR___anext__);
     c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
-    EMIT(pop_block);
-    EMIT_ARG(jump, try_else_label);
+    EMIT_ARG(pop_except_jump, try_else_label, false);
 
     EMIT_ARG(label_assign, try_exception_label);
     EMIT(start_except_handler);
@@ -1751,8 +1748,7 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns
     EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
     EMIT_ARG(pop_jump_if, false, try_finally_label);
     EMIT(pop_top); // pop exception instance
-    EMIT(pop_except);
-    EMIT_ARG(jump, while_else_label);
+    EMIT_ARG(pop_except_jump, while_else_label, true);
 
     EMIT_ARG(label_assign, try_finally_label);
     EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack
diff --git a/py/emit.h b/py/emit.h
index 3c42bdf14360e1300fa6c752f1fd46cf648de704..34c6cfd845e349318352d0a1e0999c86b3ba93ea 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -134,8 +134,7 @@ typedef struct _emit_method_table_t {
     void (*get_iter)(emit_t *emit, bool use_stack);
     void (*for_iter)(emit_t *emit, mp_uint_t label);
     void (*for_iter_end)(emit_t *emit);
-    void (*pop_block)(emit_t *emit);
-    void (*pop_except)(emit_t *emit);
+    void (*pop_except_jump)(emit_t *emit, mp_uint_t label, bool within_exc_handler);
     void (*unary_op)(emit_t *emit, mp_unary_op_t op);
     void (*binary_op)(emit_t *emit, mp_binary_op_t op);
     void (*build)(emit_t *emit, mp_uint_t n_args, int kind);
@@ -232,8 +231,7 @@ void mp_emit_bc_end_finally(emit_t *emit);
 void mp_emit_bc_get_iter(emit_t *emit, bool use_stack);
 void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label);
 void mp_emit_bc_for_iter_end(emit_t *emit);
-void mp_emit_bc_pop_block(emit_t *emit);
-void mp_emit_bc_pop_except(emit_t *emit);
+void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler);
 void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op);
 void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op);
 void mp_emit_bc_build(emit_t *emit, mp_uint_t n_args, int kind);
diff --git a/py/emitbc.c b/py/emitbc.c
index 65d6509051092d70a5482bb38d1626fa432b74b3..4142e892d6e1f935781532fe459e9be7e7c6a494 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -764,14 +764,10 @@ void mp_emit_bc_for_iter_end(emit_t *emit) {
     emit_bc_pre(emit, -MP_OBJ_ITER_BUF_NSLOTS);
 }
 
-void mp_emit_bc_pop_block(emit_t *emit) {
+void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) {
+    (void)within_exc_handler;
     emit_bc_pre(emit, 0);
-    emit_write_bytecode_byte(emit, MP_BC_POP_BLOCK);
-}
-
-void mp_emit_bc_pop_except(emit_t *emit) {
-    emit_bc_pre(emit, 0);
-    emit_write_bytecode_byte(emit, MP_BC_POP_EXCEPT);
+    emit_write_bytecode_byte_unsigned_label(emit, MP_BC_POP_EXCEPT_JUMP, label);
 }
 
 void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
@@ -958,8 +954,7 @@ const emit_method_table_t emit_bc_method_table = {
     mp_emit_bc_get_iter,
     mp_emit_bc_for_iter,
     mp_emit_bc_for_iter_end,
-    mp_emit_bc_pop_block,
-    mp_emit_bc_pop_except,
+    mp_emit_bc_pop_except_jump,
     mp_emit_bc_unary_op,
     mp_emit_bc_binary_op,
     mp_emit_bc_build,
diff --git a/py/emitnative.c b/py/emitnative.c
index 8b7ebe5301c0cc2fbbae638c666659ca4f732d6e..c8a1a33d6b4bd4cf2b396aa22adf2bb0e6acff8b 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -1916,7 +1916,7 @@ STATIC void emit_native_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t exc
             prev_finally->unwind_label = UNWIND_LABEL_DO_FINAL_UNWIND;
             ASM_MOV_REG_PCREL(emit->as, REG_RET, label & ~MP_EMIT_BREAK_FROM_FOR);
             ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_RET);
-            // Cancel any active exception (see also emit_native_pop_except)
+            // Cancel any active exception (see also emit_native_pop_except_jump)
             emit_native_mov_reg_const(emit, REG_RET, MP_F_CONST_NONE_OBJ);
             ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_RET);
             // Jump to the innermost active finally
@@ -2111,18 +2111,15 @@ STATIC void emit_native_for_iter_end(emit_t *emit) {
     emit_post(emit);
 }
 
-STATIC void emit_native_pop_block(emit_t *emit) {
-    emit_native_pre(emit);
-    if (!emit->exc_stack[emit->exc_stack_size - 1].is_finally) {
+STATIC void emit_native_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) {
+    if (within_exc_handler) {
+        // Cancel any active exception so subsequent handlers don't see it
+        emit_native_mov_reg_const(emit, REG_TEMP0, MP_F_CONST_NONE_OBJ);
+        ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
+    } else {
         emit_native_leave_exc_stack(emit, false);
     }
-    emit_post(emit);
-}
-
-STATIC void emit_native_pop_except(emit_t *emit) {
-    // Cancel any active exception so subsequent handlers don't see it
-    emit_native_mov_reg_const(emit, REG_TEMP0, MP_F_CONST_NONE_OBJ);
-    ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
+    emit_native_jump(emit, label);
 }
 
 STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
@@ -2726,8 +2723,7 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
     emit_native_get_iter,
     emit_native_for_iter,
     emit_native_for_iter_end,
-    emit_native_pop_block,
-    emit_native_pop_except,
+    emit_native_pop_except_jump,
     emit_native_unary_op,
     emit_native_binary_op,
     emit_native_build,
diff --git a/py/showbc.c b/py/showbc.c
index 3deb18cd31dcf61ac33d186c12e3b5d04592d12e..b9024b716de676cb4fb97f718b2c30583e8289fd 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -401,14 +401,9 @@ const byte *mp_bytecode_print_str(const byte *ip) {
             printf("FOR_ITER " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
-        case MP_BC_POP_BLOCK:
-            // pops block and restores the stack
-            printf("POP_BLOCK");
-            break;
-
-        case MP_BC_POP_EXCEPT:
-            // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
-            printf("POP_EXCEPT");
+        case MP_BC_POP_EXCEPT_JUMP:
+            DECODE_ULABEL; // these labels are always forward
+            printf("POP_EXCEPT_JUMP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_BUILD_TUPLE:
diff --git a/py/vm.c b/py/vm.c
index a53b4a0838e66864002662a411d3834e99a12b83..901a23f225f0515e7deaa1c065816ab2ec74df92 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -759,17 +759,13 @@ unwind_jump:;
                 }
 
                 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
-                ENTRY(MP_BC_POP_BLOCK):
-                    // we are exiting an exception handler, so pop the last one of the exception-stack
+                ENTRY(MP_BC_POP_EXCEPT_JUMP): {
                     assert(exc_sp >= exc_stack);
                     POP_EXC_BLOCK();
-                    DISPATCH();
-
-                // matched against: SETUP_EXCEPT
-                ENTRY(MP_BC_POP_EXCEPT):
-                    assert(exc_sp >= exc_stack);
-                    POP_EXC_BLOCK();
-                    DISPATCH();
+                    DECODE_ULABEL;
+                    ip += ulab;
+                    DISPATCH_WITH_PEND_EXC_CHECK();
+                }
 
                 ENTRY(MP_BC_BUILD_TUPLE): {
                     MARK_EXC_IP_SELECTIVE();
diff --git a/py/vmentrytable.h b/py/vmentrytable.h
index 615f4e2ce439e7ff5915373c3d2361b898ef2f8f..641c8ee422b6317f6e57318ce6fdb37fd2b2ff58 100644
--- a/py/vmentrytable.h
+++ b/py/vmentrytable.h
@@ -76,8 +76,7 @@ static const void *const entry_table[256] = {
     [MP_BC_GET_ITER] = &&entry_MP_BC_GET_ITER,
     [MP_BC_GET_ITER_STACK] = &&entry_MP_BC_GET_ITER_STACK,
     [MP_BC_FOR_ITER] = &&entry_MP_BC_FOR_ITER,
-    [MP_BC_POP_BLOCK] = &&entry_MP_BC_POP_BLOCK,
-    [MP_BC_POP_EXCEPT] = &&entry_MP_BC_POP_EXCEPT,
+    [MP_BC_POP_EXCEPT_JUMP] = &&entry_MP_BC_POP_EXCEPT_JUMP,
     [MP_BC_BUILD_TUPLE] = &&entry_MP_BC_BUILD_TUPLE,
     [MP_BC_BUILD_LIST] = &&entry_MP_BC_BUILD_LIST,
     [MP_BC_BUILD_MAP] = &&entry_MP_BC_BUILD_MAP,
diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp
index d119a6198b47b26385572f58733120d8e3e6eb4f..8d36b89df75d4940249e8bad7cb08c3b9cac8c4f 100644
--- a/tests/cmdline/cmd_showbc.py.exp
+++ b/tests/cmdline/cmd_showbc.py.exp
@@ -257,13 +257,11 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
 \\d\+ JUMP \\d\+
 \\d\+ LOAD_FAST 0
 \\d\+ POP_JUMP_IF_TRUE \\d\+
-\\d\+ POP_BLOCK
-\\d\+ JUMP \\d\+
+\\d\+ POP_EXCEPT_JUMP \\d\+
 \\d\+ POP_TOP
 \\d\+ LOAD_DEREF 14
 \\d\+ POP_TOP
-\\d\+ POP_EXCEPT
-\\d\+ JUMP \\d\+
+\\d\+ POP_EXCEPT_JUMP \\d\+
 \\d\+ END_FINALLY
 \\d\+ LOAD_CONST_NONE
 \\d\+ LOAD_FAST 1
@@ -272,11 +270,9 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
 \\d\+ JUMP \\d\+
 \\d\+ SETUP_EXCEPT \\d\+
 \\d\+ UNWIND_JUMP \\d\+ 1
-\\d\+ POP_BLOCK
-\\d\+ JUMP \\d\+
+\\d\+ POP_EXCEPT_JUMP \\d\+
 \\d\+ POP_TOP
-\\d\+ POP_EXCEPT
-\\d\+ JUMP \\d\+
+\\d\+ POP_EXCEPT_JUMP \\d\+
 \\d\+ END_FINALLY
 \\d\+ LOAD_FAST 0
 \\d\+ POP_JUMP_IF_TRUE \\d\+
diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py
index 6fbb10a39d87267c7537c3dbcc2a4ee99dca474b..62f2ac4815c912f9df9e2ba19e245b9a56c16c34 100755
--- a/tools/mpy-tool.py
+++ b/tools/mpy-tool.py
@@ -105,7 +105,7 @@ def make_opcode_format():
     OC4(O, O, U, U), # 0x38-0x3b
     OC4(U, O, B, O), # 0x3c-0x3f
     OC4(O, B, B, O), # 0x40-0x43
-    OC4(B, B, O, B), # 0x44-0x47
+    OC4(O, U, O, B), # 0x44-0x47
     OC4(U, U, U, U), # 0x48-0x4b
     OC4(U, U, U, U), # 0x4c-0x4f
     OC4(V, V, U, V), # 0x50-0x53