bitXXgen: add osmo_loadXXbe_ext_2() to get right-adjusted values

As shown in the recently added bitgen_test.c, using osmo_loadXXbe_ext() with a
smaller n produces results aligned on the most significant bytes, which is
cumbersome, since it does not return a previously stored value. This problem
exists only for the big-endian functions, the little-endian osmo_loadXXle_ext()
properly return values adjusted on the least significant octets.

Add osmo_loadXXbe_ext_2() variants that properly right-adjust the returned
value. Prominently highlight this behavior in API doc. Test the new functions
in bitgen_test.c.

For example, this eases handling of 24bit integers (e.g. loaded from buffer to
uint32_t, and stored into buffer from uint32_t). Also explicitly show this 24
bit case in bitgen_test.c

Change-Id: I2806df6f0f7bf1ad705d52fa386d4525b892b928
diff --git a/include/osmocom/core/bitXXgen.h.tpl b/include/osmocom/core/bitXXgen.h.tpl
index 7e0ecd7..258fccb 100644
--- a/include/osmocom/core/bitXXgen.h.tpl
+++ b/include/osmocom/core/bitXXgen.h.tpl
@@ -24,7 +24,7 @@
 
 #include <osmocom/core/utils.h>
 
-/*! load unaligned n-byte integer (little-endian encoding) into uintXX_t
+/*! load unaligned n-byte integer (little-endian encoding) into uintXX_t, into the least significant octets.
  *  \param[in] p Buffer where integer is stored
  *  \param[in] n Number of bytes stored in p
  *  \returns XX bit unsigned integer
@@ -39,7 +39,9 @@
 	return r;
 }
 
-/*! load unaligned n-byte integer (big-endian encoding) into uintXX_t
+/*! load unaligned n-byte integer (big-endian encoding) into uintXX_t, into the MOST significant octets.
+ * WARNING: for n < sizeof(uintXX_t), the result is not returned in the least significant octets, as one might expect.
+ * To always return the same value as fed to osmo_storeXXbe_ext() before, use osmo_loadXXbe_ext_2().
  *  \param[in] p Buffer where integer is stored
  *  \param[in] n Number of bytes stored in p
  *  \returns XX bit unsigned integer
@@ -54,6 +56,21 @@
 	return r;
 }
 
+/*! load unaligned n-byte integer (big-endian encoding) into uintXX_t, into the least significant octets.
+ *  \param[in] p Buffer where integer is stored
+ *  \param[in] n Number of bytes stored in p
+ *  \returns XX bit unsigned integer
+ */
+static inline uintXX_t osmo_loadXXbe_ext_2(const void *p, uint8_t n)
+{
+	uint8_t i;
+	uintXX_t r = 0;
+	const uint8_t *q = (uint8_t *)p;
+	OSMO_ASSERT(n <= sizeof(r));
+	for(i = 0; i < n; r |= ((uintXX_t)q[i] << (XX - 8* (1 + i + (sizeof(r) - n)))), i++);
+	return r;
+}
+
 
 /*! store unaligned n-byte integer (little-endian encoding) from uintXX_t
  *  \param[in] x unsigned XX bit integer