summaryrefslogtreecommitdiffstats
path: root/src/tests/math_test.c
diff options
context:
space:
mode:
authorMichael Brown2014-04-25 01:04:25 +0200
committerMichael Brown2014-04-25 02:45:13 +0200
commitad7d5af5e19a016e484188a2c75818bb2d0a35db (patch)
tree69fdf23ec65cbe67e3791302697d62dbeca38f37 /src/tests/math_test.c
parent[libc] Add inline assembly implementation of flsl() using BSR instruction (diff)
downloadipxe-ad7d5af5e19a016e484188a2c75818bb2d0a35db.tar.gz
ipxe-ad7d5af5e19a016e484188a2c75818bb2d0a35db.tar.xz
ipxe-ad7d5af5e19a016e484188a2c75818bb2d0a35db.zip
[test] Add tests for 64-bit division
On a 32-bit system, 64-bit division is implemented using the libgcc functions provided in __udivmoddi4.c etc. Calls to these functions are generated automatically by gcc, with a calling convention that is somewhat empirical in nature. Add these self-tests primarily as a check that we are using the correct calling convention. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/tests/math_test.c')
-rw-r--r--src/tests/math_test.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/tests/math_test.c b/src/tests/math_test.c
index 3967e620..fe61e29c 100644
--- a/src/tests/math_test.c
+++ b/src/tests/math_test.c
@@ -44,6 +44,54 @@ __attribute__ (( noinline )) int flsl_var ( long value ) {
}
/**
+ * Force a use of runtime 64-bit unsigned integer division
+ *
+ * @v dividend Dividend
+ * @v divisor Divisor
+ * @ret quotient Quotient
+ */
+__attribute__ (( noinline )) uint64_t u64div_var ( uint64_t dividend,
+ uint64_t divisor ) {
+ return ( dividend / divisor );
+}
+
+/**
+ * Force a use of runtime 64-bit unsigned integer modulus
+ *
+ * @v dividend Dividend
+ * @v divisor Divisor
+ * @ret remainder Remainder
+ */
+__attribute__ (( noinline )) uint64_t u64mod_var ( uint64_t dividend,
+ uint64_t divisor ) {
+ return ( dividend % divisor );
+}
+
+/**
+ * Force a use of runtime 64-bit signed integer division
+ *
+ * @v dividend Dividend
+ * @v divisor Divisor
+ * @ret quotient Quotient
+ */
+__attribute__ (( noinline )) int64_t s64div_var ( int64_t dividend,
+ int64_t divisor ) {
+ return ( dividend / divisor );
+}
+
+/**
+ * Force a use of runtime 64-bit unsigned integer modulus
+ *
+ * @v dividend Dividend
+ * @v divisor Divisor
+ * @ret remainder Remainder
+ */
+__attribute__ (( noinline )) int64_t s64mod_var ( int64_t dividend,
+ int64_t divisor ) {
+ return ( dividend % divisor );
+}
+
+/**
* Report a flsl() test result
*
* @v value Value
@@ -63,6 +111,60 @@ flsl_okx ( long value, int msb, const char *file, unsigned int line ) {
#define flsl_ok( value, msb ) flsl_okx ( value, msb, __FILE__, __LINE__ )
/**
+ * Report a 64-bit unsigned integer division test result
+ *
+ * @v dividend Dividend
+ * @v divisor Divisor
+ * @v quotient Quotient
+ * @v remainder Remainder
+ * @v file Test code file
+ * @v line Test code line
+ */
+static void u64divmod_okx ( uint64_t dividend, uint64_t divisor,
+ uint64_t quotient, uint64_t remainder,
+ const char *file, unsigned int line ) {
+
+ /* Sanity check */
+ okx ( ( ( divisor * quotient ) + remainder ) == dividend, file, line );
+
+ /* Check division */
+ okx ( u64div_var ( dividend, divisor ) == quotient, file, line );
+
+ /* Check modulus */
+ okx ( u64mod_var ( dividend, divisor ) == remainder, file, line );
+}
+#define u64divmod_ok( dividend, divisor, quotient, remainder ) \
+ u64divmod_okx ( dividend, divisor, quotient, remainder, \
+ __FILE__, __LINE__ )
+
+/**
+ * Report a 64-bit signed integer division test result
+ *
+ * @v dividend Dividend
+ * @v divisor Divisor
+ * @v quotient Quotient
+ * @v remainder Remainder
+ * @v file Test code file
+ * @v line Test code line
+ */
+static void s64divmod_okx ( int64_t dividend, int64_t divisor,
+ int64_t quotient, int64_t remainder,
+ const char *file, unsigned int line ) {
+
+ /* Sanity check */
+ okx ( ( ( divisor * quotient ) + remainder ) == dividend, file, line );
+
+ /* Check division */
+ okx ( s64div_var ( dividend, divisor ) == quotient, file, line );
+
+ /* Check modulus */
+ okx ( s64mod_var ( dividend, divisor ) == remainder, file, line );
+}
+#define s64divmod_ok( dividend, divisor, quotient, remainder ) \
+ s64divmod_okx ( dividend, divisor, quotient, remainder, \
+ __FILE__, __LINE__ )
+
+/**
* Perform mathematical self-tests
*
*/
@@ -77,6 +179,26 @@ static void math_test_exec ( void ) {
flsl_ok ( 0x69505845, 31 );
flsl_ok ( -1U, ( 8 * sizeof ( int ) ) );
flsl_ok ( -1UL, ( 8 * sizeof ( long ) ) );
+
+ /* Test 64-bit arithmetic
+ *
+ * On a 64-bit machine, these tests are fairly meaningless.
+ *
+ * On a 32-bit machine, these tests verify the correct
+ * operation of our libgcc functions __udivmoddi4()
+ * etc. (including checking that the implicit calling
+ * convention assumed by gcc matches our expectations).
+ */
+ u64divmod_ok ( 0x2b90ddccf699f765ULL, 0xed9f5e73ULL,
+ 0x2eef6ab4ULL, 0x0e12f089ULL );
+ s64divmod_ok ( 0x2b90ddccf699f765ULL, 0xed9f5e73ULL,
+ 0x2eef6ab4ULL, 0x0e12f089ULL );
+ u64divmod_ok ( 0xc09e00dcb9e34b54ULL, 0x35968185cdc744f3ULL,
+ 3, 0x1fda7c4b508d7c7bULL );
+ s64divmod_ok ( -0x3f61ff23461cb4acLL, 0x35968185cdc744f3ULL,
+ -1LL, -0x9cb7d9d78556fb9LL );
+ u64divmod_ok ( 0, 0x5b2f2737f4ffULL, 0, 0 );
+ s64divmod_ok ( 0, 0xbb00ded72766207fULL, 0, 0 );
}
/** Mathematical self-tests */