diff --git a/py/compile.c b/py/compile.c
index e00af60ad65c588b2a2fc3bab0dd37835f0bf64a..797d7a95e107ab3548ef96e79bc8497e414b9f2b 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -293,7 +293,9 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
                         // pass
                     } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
                         // int%int
-                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_modulo(arg0, arg1));
+                        if (arg1 != 0) {
+                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_modulo(arg0, arg1));
+                        }
                     } else {
                         assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)); // should be
                         if (arg1 != 0) {
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 69a81d2c399e411cd3db490ca4c9321c6c487a84..73469f30d31bec03985a7498451b9933c21e96d5 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -193,6 +193,9 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
     if (0) {
 #if MICROPY_PY_BUILTINS_FLOAT
     } else if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) {
+        if (mpz_is_zero(zrhs)) {
+            goto zero_division_error;
+        }
         mp_float_t flhs = mpz_as_float(zlhs);
         mp_float_t frhs = mpz_as_float(zrhs);
         return mp_obj_new_float(flhs / frhs);
@@ -216,6 +219,11 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
                 break;
             case MP_BINARY_OP_FLOOR_DIVIDE:
             case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: {
+                if (mpz_is_zero(zrhs)) {
+                    zero_division_error:
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError,
+                        "division by zero"));
+                }
                 mpz_t rem; mpz_init_zero(&rem);
                 mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs);
                 if (zlhs->neg != zrhs->neg) {
@@ -229,6 +237,9 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
             }
             case MP_BINARY_OP_MODULO:
             case MP_BINARY_OP_INPLACE_MODULO: {
+                if (mpz_is_zero(zrhs)) {
+                    goto zero_division_error;
+                }
                 mpz_t quo; mpz_init_zero(&quo);
                 mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs);
                 mpz_deinit(&quo);
@@ -274,6 +285,9 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
                 break;
 
             case MP_BINARY_OP_DIVMOD: {
+                if (mpz_is_zero(zrhs)) {
+                    goto zero_division_error;
+                }
                 mp_obj_int_t *quo = mp_obj_int_new_mpz();
                 mpz_divmod_inpl(&quo->mpz, &res->mpz, zlhs, zrhs);
                 // Check signs and do Python style modulo
diff --git a/py/runtime.c b/py/runtime.c
index 69ac7549b293881a495d05315cbe00483066b9ea..98cde83e53b04f1226316b045d296a71e81dec76 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -389,6 +389,9 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
 
                 case MP_BINARY_OP_MODULO:
                 case MP_BINARY_OP_INPLACE_MODULO: {
+                    if (rhs_val == 0) {
+                        goto zero_division;
+                    }
                     lhs_val = mp_small_int_modulo(lhs_val, rhs_val);
                     break;
                 }
diff --git a/tests/basics/builtin_divmod.py b/tests/basics/builtin_divmod.py
index e3eff306be087703b8d52fd893a350f6e4aa024e..c3b86581976270ea371e35adebec9b1a331fd109 100644
--- a/tests/basics/builtin_divmod.py
+++ b/tests/basics/builtin_divmod.py
@@ -9,6 +9,11 @@ try:
 except ZeroDivisionError:
     print("ZeroDivisionError")
 
+try:
+    divmod(1 << 65, 0)
+except ZeroDivisionError:
+    print("ZeroDivisionError")
+
 try:
     divmod('a', 'b')
 except TypeError:
diff --git a/tests/basics/int_big_error.py b/tests/basics/int_big_error.py
index b7875ee87b8f6c60c0571d7a8559fe69a0a07e72..e036525d1b2ec87dd2f30858ec58207445667f14 100644
--- a/tests/basics/int_big_error.py
+++ b/tests/basics/int_big_error.py
@@ -29,3 +29,13 @@ try:
     i << (-(i >> 40))
 except ValueError:
     print('ValueError')
+
+try:
+    i // 0
+except ZeroDivisionError:
+    print('ZeroDivisionError')
+
+try:
+    i % 0
+except ZeroDivisionError:
+    print('ZeroDivisionError')
diff --git a/tests/basics/int_divzero.py b/tests/basics/int_divzero.py
index 28ec2a6995b1de8a0e99261bcd0a8aeb36271629..aa38eee1d74b74a40d9bbb669bda282dffcf63be 100644
--- a/tests/basics/int_divzero.py
+++ b/tests/basics/int_divzero.py
@@ -2,3 +2,8 @@ try:
     1 // 0
 except ZeroDivisionError:
     print("ZeroDivisionError")
+
+try:
+    1 % 0
+except ZeroDivisionError:
+    print("ZeroDivisionError")
diff --git a/tests/float/int_big_float.py b/tests/float/int_big_float.py
index 2c404189cbbccad328a1ecf2f69b812d0ddd4706..b1a26ca73d51a2890185641832b647c723094049 100644
--- a/tests/float/int_big_float.py
+++ b/tests/float/int_big_float.py
@@ -17,3 +17,8 @@ print("%.5g" % (i / 1.2))
 
 # this should delegate to complex
 print("%.5g" % (i * 1.2j).imag)
+
+try:
+    i / 0
+except ZeroDivisionError:
+    print("ZeroDivisionError")