unsigned integer of 32-bit widtth support for per
diff --git a/libasn1compiler/asn1c_constraint.c b/libasn1compiler/asn1c_constraint.c
index ea9df80..2b1420e 100644
--- a/libasn1compiler/asn1c_constraint.c
+++ b/libasn1compiler/asn1c_constraint.c
@@ -12,6 +12,7 @@
 static int emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype);
 static asn1p_expr_type_e _find_terminal_type(arg_t *arg);
 static int emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1c_integer_t natural_start, asn1c_integer_t natural_stop);
+static int native_long_sign(asn1cnst_range_t *r);	/* -1, 0, 1 */
 
 int
 asn1c_emit_constraint_checking_code(arg_t *arg) {
@@ -91,7 +92,11 @@
 			switch(etype) {
 			case ASN_BASIC_INTEGER:
 			case ASN_BASIC_ENUMERATED:
-				OUT("long value;\n");
+				if(native_long_sign(r_value) >= 0) {
+					OUT("unsigned long value;\n");
+				} else {
+					OUT("long value;\n");
+				}
 				break;
 			case ASN_BASIC_REAL:
 				OUT("double value;\n");
@@ -133,6 +138,19 @@
 	INDENT(+1);
 
 	/*
+	 * Optimization for unsigned longs.
+	 */
+	if(!r_size && r_value
+		&& (etype == ASN_BASIC_INTEGER
+		|| etype == ASN_BASIC_ENUMERATED)
+	&& native_long_sign(r_value) == 0) {
+		OUT("\n");
+		OUT("/* Constraint check succeeded */\n");
+		OUT("return 0;\n");
+		return 0;
+	}
+
+	/*
 	 * Here is an if() {} else {} consrtaint checking code.
 	 */
 	OUT("\n");
@@ -578,9 +596,15 @@
 	switch(etype) {
 	case ASN_BASIC_INTEGER:
 	case ASN_BASIC_ENUMERATED:
-		if(asn1c_type_fits_long(arg, arg->expr) != FL_NOTFIT) {
+		if(asn1c_type_fits_long(arg, arg->expr) == FL_FITS_UNSIGN) {
+			OUT("value = *(const unsigned long *)sptr;\n");
+		} else if(asn1c_type_fits_long(arg, arg->expr) != FL_NOTFIT) {
 			OUT("value = *(const long *)sptr;\n");
 		} else {
+			/*
+			 * In some cases we can explore our knowledge of
+			 * underlying INTEGER_t->buf format.
+			 */
 			if(r_value->el_count == 0
 			&& (
 				/* Speed-up common case: (0..MAX) */
@@ -598,14 +622,26 @@
 				break;
 			}
 
-			OUT("if(asn_INTEGER2long(st, &value)) {\n");
+			if(native_long_sign(r_value) >= 0) {
+				/* Special case for treating unsigned longs */
+				OUT("if(asn_INTEGER2ulong(st, &value)) {\n");
 				INDENT(+1);
 				OUT("_ASN_CTFAIL(app_key, td, sptr,\n");
 				OUT("\t\"%%s: value too large (%%s:%%d)\",\n");
 				OUT("\ttd->name, __FILE__, __LINE__);\n");
 				OUT("return -1;\n");
 				INDENT(-1);
-			OUT("}\n");
+				OUT("}\n");
+			} else {
+				OUT("if(asn_INTEGER2long(st, &value)) {\n");
+				INDENT(+1);
+				OUT("_ASN_CTFAIL(app_key, td, sptr,\n");
+				OUT("\t\"%%s: value too large (%%s:%%d)\",\n");
+				OUT("\ttd->name, __FILE__, __LINE__);\n");
+				OUT("return -1;\n");
+				INDENT(-1);
+				OUT("}\n");
+			}
 		}
 		break;
 	case ASN_BASIC_REAL:
@@ -652,3 +688,20 @@
 	return A1TC_INVALID;
 }
 
+static int
+native_long_sign(asn1cnst_range_t *r) {
+	if(r->left.type == ARE_VALUE
+	&& r->left.value >= 0
+	&& r->right.type == ARE_VALUE
+	&& r->right.value > 2147483647UL
+	&& r->right.value <= 4294967295UL) {
+		if(r->el_count == 0
+		&& r->left.value == 0
+		&& r->right.value == 4294967295UL)
+			return 0;
+		else
+			return 1;
+	} else {
+		return -1;
+	}
+}