unsigned integer of 32-bit widtth support for per
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index e2b4401..be7f059 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -222,9 +222,28 @@
 			OUT("0,\t/* Enumeration is not extensible */\n");
 		}
 		if(expr->expr_type == ASN_BASIC_ENUMERATED)
-			OUT("1\t/* Strict enumeration */\n");
+			OUT("1,\t/* Strict enumeration */\n");
 		else
-			OUT("0\n");
+			OUT("0,\n");
+		OUT("0,\t/* Native long size */\n");
+		OUT("0\n");
+		INDENT(-1);
+		OUT("};\n");
+	}
+
+	if(expr->expr_type == ASN_BASIC_INTEGER
+	&& asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
+		REDIR(OT_STAT_DEFS);
+		OUT("static asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
+			MKID(expr), expr->_type_unique_index);
+		INDENT(+1);
+		OUT("0,\t");
+		OUT("0,\t");
+		OUT("0,\t");
+		OUT("0,\t");
+		OUT("0,\n");
+		OUT("0,\t/* Native long size */\n");
+		OUT("1\t/* Unsigned representation */\n");
 		INDENT(-1);
 		OUT("};\n");
 	}
@@ -1112,7 +1131,10 @@
 	if((expr->expr_type == ASN_BASIC_ENUMERATED)
 	|| (0 /* -- prohibited by X.693:8.3.4 */
 		&& expr->expr_type == ASN_BASIC_INTEGER
-		&& expr_elements_count(arg, expr)))
+		&& expr_elements_count(arg, expr))
+	|| (expr->expr_type == ASN_BASIC_INTEGER
+		&& asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN)
+	)
 		etd_spec = ETD_HAS_SPECIFICS;
 	else
 		etd_spec = ETD_NO_SPECIFICS;
@@ -2289,7 +2311,9 @@
 		|| expr->expr_type == ASN_BASIC_ENUMERATED
 		|| (0 /* -- prohibited by X.693:8.3.4 */
 			&& expr->expr_type == ASN_BASIC_INTEGER
-			&& expr_elements_count(arg, expr));
+			&& expr_elements_count(arg, expr))
+		|| (expr->expr_type == ASN_BASIC_INTEGER
+			&& asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN);
 	if(C99_MODE) OUT(".type = ");
 	OUT("&asn_DEF_");
 	if(complex_contents) {
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;
+	}
+}
diff --git a/libasn1compiler/asn1c_misc.c b/libasn1compiler/asn1c_misc.c
index 543a165..f48ab08 100644
--- a/libasn1compiler/asn1c_misc.c
+++ b/libasn1compiler/asn1c_misc.c
@@ -215,6 +215,8 @@
 			case TNF_RSAFE:
 				if(expr->expr_type == ASN_BASIC_REAL)
 					return "double";
+				else if(asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN)
+					return "unsigned long";
 				else
 					return "long";
 			default:
@@ -278,7 +280,7 @@
 
 /*
  * Check whether the specified INTEGER or ENUMERATED type can be represented
- * using the generic 'long' type.
+ * using the generic 'long' or 'unsigned long' type.
  */
 enum asn1c_fitslong_e
 asn1c_type_fits_long(arg_t *arg, asn1p_expr_t *expr) {
@@ -339,7 +341,7 @@
 			right = range->right;
 			/* Use 4 instead of sizeof(long) is justified! */
 			if(right.type == ARE_VALUE && right.value <= 4)
-				return FL_FITSOK;
+				return FL_FITS_SIGNED;
 		}
 		asn1constraint_range_free(range);
 	}
@@ -364,6 +366,15 @@
 	right = range->right;
 	asn1constraint_range_free(range);
 
+	/* Special case for unsigned */
+	if(left.type == ARE_VALUE
+		&& left.value >= 0
+	&& right.type == ARE_VALUE
+		&& right.value > 2147483647
+		&& right.value <= 4294967295UL)
+		return FL_FITS_UNSIGN;
+		
+
 	/* If some fixed value is outside of target range, not fit */
 	if(left.type == ARE_VALUE
 			&& (left.value < LEFTMIN || left.value > RIGHTMAX))
@@ -378,6 +389,6 @@
 			? FL_FORCED : FL_NOTFIT;
 	}
 
-	return FL_FITSOK;
+	return FL_FITS_SIGNED;
 }
 
diff --git a/libasn1compiler/asn1c_misc.h b/libasn1compiler/asn1c_misc.h
index b14a155..6e2acb5 100644
--- a/libasn1compiler/asn1c_misc.h
+++ b/libasn1compiler/asn1c_misc.h
@@ -30,12 +30,14 @@
  * using the generic 'long' type.
  * Return values:
  * 	FL_NOTFIT:	No, it cannot be represented using long.
- * 	FL_FITSOK:	It can be represented using long.
+ * 	FL_FITS_SIGNED:	It can be represented using signed long.
+ * 	FL_FITS_UNSIGN:	It can be represented using unsigned long.
  * 	FL_FORCED:	Probably can't, but -fnative-types is in force.
  */
 enum asn1c_fitslong_e {
 	FL_NOTFIT,
-	FL_FITSOK,
+	FL_FITS_SIGNED,
+	FL_FITS_UNSIGN,
 	FL_FORCED,
 };
 enum asn1c_fitslong_e asn1c_type_fits_long(arg_t *arg, asn1p_expr_t *expr);