iPXE
Macros | Functions | Variables
math_test.c File Reference

Mathematical self-tests. More...

#include <string.h>
#include <strings.h>
#include <assert.h>
#include <ipxe/test.h>
#include <ipxe/isqrt.h>

Go to the source code of this file.

Macros

#define check_divmod(dividend, divisor, OP)
 Check division/modulus operation. More...
 
#define ffsl_ok(value, lsb)   ffsl_okx ( value, lsb, __FILE__, __LINE__ )
 
#define ffsll_ok(value, lsb)   ffsll_okx ( value, lsb, __FILE__, __LINE__ )
 
#define flsl_ok(value, msb)   flsl_okx ( value, msb, __FILE__, __LINE__ )
 
#define flsll_ok(value, msb)   flsll_okx ( value, msb, __FILE__, __LINE__ )
 
#define u64divmod_ok(dividend, divisor, quotient, remainder)
 
#define s64divmod_ok(dividend, divisor, quotient, remainder)
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
int ffsl_var (long value)
 Force a call to the non-constant implementation of ffsl() More...
 
int ffsll_var (long long value)
 Force a call to the non-constant implementation of ffsll() More...
 
int flsl_var (long value)
 Force a call to the non-constant implementation of flsl() More...
 
int flsll_var (long long value)
 Force a call to the non-constant implementation of flsll() More...
 
static void * stack_check (void)
 Check current stack pointer. More...
 
uint64_t u64div_var (uint64_t dividend, uint64_t divisor)
 Force a use of runtime 64-bit unsigned integer division. More...
 
uint64_t u64mod_var (uint64_t dividend, uint64_t divisor)
 Force a use of runtime 64-bit unsigned integer modulus. More...
 
int64_t s64div_var (int64_t dividend, int64_t divisor)
 Force a use of runtime 64-bit signed integer division. More...
 
int64_t s64mod_var (int64_t dividend, int64_t divisor)
 Force a use of runtime 64-bit unsigned integer modulus. More...
 
static void ffsl_okx (long value, int lsb, const char *file, unsigned int line)
 Report a ffsl() test result. More...
 
static void ffsll_okx (long long value, int lsb, const char *file, unsigned int line)
 Report a ffsll() test result. More...
 
static void flsl_okx (long value, int msb, const char *file, unsigned int line)
 Report a flsl() test result. More...
 
static void flsll_okx (long long value, int msb, const char *file, unsigned int line)
 Report a flsll() test result. More...
 
static void u64divmod_okx (uint64_t dividend, uint64_t divisor, uint64_t quotient, uint64_t remainder, const char *file, unsigned int line)
 Report a 64-bit unsigned integer division test result. More...
 
static void s64divmod_okx (int64_t dividend, int64_t divisor, int64_t quotient, int64_t remainder, const char *file, unsigned int line)
 Report a 64-bit signed integer division test result. More...
 
static void math_test_exec (void)
 Perform mathematical self-tests. More...
 

Variables

struct self_test math_test __self_test
 Mathematical self-tests. More...
 

Detailed Description

Mathematical self-tests.

Definition in file math_test.c.

Macro Definition Documentation

◆ check_divmod

#define check_divmod (   dividend,
  divisor,
  OP 
)
Value:
( { \
uint64_t result; \
int count = 2; \
void *check = NULL; \
\
/* Prevent compiler from unrolling the loop */ \
__asm__ ( "\n" : "=g" ( count ) : "0" ( count ) ); \
\
do { \
/* Check that stack pointer does not change between \
* loop iterations. \
*/ \
if ( check ) { \
assert ( check == stack_check() ); \
} else { \
check = stack_check(); \
} \
\
/* Perform division, preventing the compiler from \
* moving the division out of the loop. \
*/ \
__asm__ ( "\n" : "=g" ( dividend ), "=g" ( divisor ) \
: "0" ( dividend ), "1" ( divisor ) ); \
result = ( dividend OP divisor ); \
__asm__ ( "\n" : "=g" ( result ) : "0" ( result ) ); \
\
} while ( --count ); \
result; } )
static const void const void void * result
Definition: crypto.h:335
static void * stack_check(void)
Check current stack pointer.
Definition: math_test.c:88
uint16_t count
Number of entries.
Definition: ena.h:22
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

Check division/modulus operation.

One aspect of the calling convention for the implicit arithmetic functions (__udivmoddi4() etc) is whether the caller or the callee is expected to pop any stack-based arguments. This distinction can be masked if the compiler chooses to uses a frame pointer in the caller, since the caller will then reload the stack pointer from the frame pointer and so can mask an error in the value of the stack pointer.

We run the division operation in a loop, and check that the stack pointer does not change value on the second iteration. To prevent the compiler from performing various optimisations which might invalidate our intended test (such as unrolling the loop, or moving the division operation outside the loop), we include some dummy inline assembly code.

Definition at line 118 of file math_test.c.

◆ ffsl_ok

#define ffsl_ok (   value,
  lsb 
)    ffsl_okx ( value, lsb, __FILE__, __LINE__ )

Definition at line 216 of file math_test.c.

◆ ffsll_ok

#define ffsll_ok (   value,
  lsb 
)    ffsll_okx ( value, lsb, __FILE__, __LINE__ )

Definition at line 235 of file math_test.c.

◆ flsl_ok

#define flsl_ok (   value,
  msb 
)    flsl_okx ( value, msb, __FILE__, __LINE__ )

Definition at line 254 of file math_test.c.

◆ flsll_ok

#define flsll_ok (   value,
  msb 
)    flsll_okx ( value, msb, __FILE__, __LINE__ )

Definition at line 273 of file math_test.c.

◆ u64divmod_ok

#define u64divmod_ok (   dividend,
  divisor,
  quotient,
  remainder 
)
Value:
u64divmod_okx ( dividend, divisor, quotient, remainder, \
__FILE__, __LINE__ )
static void u64divmod_okx(uint64_t dividend, uint64_t divisor, uint64_t quotient, uint64_t remainder, const char *file, unsigned int line)
Report a 64-bit unsigned integer division test result.
Definition: math_test.c:285

Definition at line 298 of file math_test.c.

◆ s64divmod_ok

#define s64divmod_ok (   dividend,
  divisor,
  quotient,
  remainder 
)
Value:
s64divmod_okx ( dividend, divisor, quotient, remainder, \
__FILE__, __LINE__ )
static void s64divmod_okx(int64_t dividend, int64_t divisor, int64_t quotient, int64_t remainder, const char *file, unsigned int line)
Report a 64-bit signed integer division test result.
Definition: math_test.c:312

Definition at line 325 of file math_test.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ ffsl_var()

int ffsl_var ( long  value)

Force a call to the non-constant implementation of ffsl()

Parameters
valueValue
Return values
lsbLeast significant bit set in value (LSB=1), or zero

Definition at line 47 of file math_test.c.

47  {
48  return ffsl ( value );
49 }
#define ffsl(x)
Find first (i.e.
Definition: strings.h:131
pseudo_bit_t value[0x00020]
Definition: arbel.h:13

References ffsl, and value.

Referenced by ffsl_okx().

◆ ffsll_var()

int ffsll_var ( long long  value)

Force a call to the non-constant implementation of ffsll()

Parameters
valueValue
Return values
lsbLeast significant bit set in value (LSB=1), or zero

Definition at line 57 of file math_test.c.

57  {
58  return ffsll ( value );
59 }
#define ffsll(x)
Find first (i.e.
Definition: strings.h:122
pseudo_bit_t value[0x00020]
Definition: arbel.h:13

References ffsll, and value.

Referenced by ffsll_okx().

◆ flsl_var()

int flsl_var ( long  value)

Force a call to the non-constant implementation of flsl()

Parameters
valueValue
Return values
msbMost significant bit set in value (LSB=1), or zero

Definition at line 67 of file math_test.c.

67  {
68  return flsl ( value );
69 }
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
#define flsl(x)
Find last (i.e.
Definition: strings.h:157

References flsl, and value.

Referenced by flsl_okx().

◆ flsll_var()

int flsll_var ( long long  value)

Force a call to the non-constant implementation of flsll()

Parameters
valueValue
Return values
msbMost significant bit set in value (LSB=1), or zero

Definition at line 77 of file math_test.c.

77  {
78  return flsll ( value );
79 }
#define flsll(x)
Find last (i.e.
Definition: strings.h:148
pseudo_bit_t value[0x00020]
Definition: arbel.h:13

References flsll, and value.

Referenced by flsll_okx().

◆ stack_check()

static void* stack_check ( void  )
static

Check current stack pointer.

Return values
stackA value at a fixed offset from the current stack pointer

Used by check_divmod()

Definition at line 88 of file math_test.c.

88  {
89  int a;
90  void *ret;
91 
92  /* Hide the fact that we are returning the address of a local
93  * variable, to prevent a compiler warning.
94  */
95  __asm__ ( "\n" : "=g" ( ret ) : "0" ( &a ) );
96 
97  return ret;
98 }
uint32_t a
Definition: md4.c:28
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")

References __asm__(), and a.

◆ u64div_var()

uint64_t u64div_var ( uint64_t  dividend,
uint64_t  divisor 
)

Force a use of runtime 64-bit unsigned integer division.

Parameters
dividendDividend
divisorDivisor
Return values
quotientQuotient

Definition at line 154 of file math_test.c.

155  {
156 
157  return check_divmod ( dividend, divisor, / );
158 }
#define check_divmod(dividend, divisor, OP)
Check division/modulus operation.
Definition: math_test.c:118

References check_divmod.

Referenced by u64divmod_okx().

◆ u64mod_var()

uint64_t u64mod_var ( uint64_t  dividend,
uint64_t  divisor 
)

Force a use of runtime 64-bit unsigned integer modulus.

Parameters
dividendDividend
divisorDivisor
Return values
remainderRemainder

Definition at line 167 of file math_test.c.

168  {
169 
170  return check_divmod ( dividend, divisor, % );
171 }
#define check_divmod(dividend, divisor, OP)
Check division/modulus operation.
Definition: math_test.c:118

References check_divmod.

Referenced by u64divmod_okx().

◆ s64div_var()

int64_t s64div_var ( int64_t  dividend,
int64_t  divisor 
)

Force a use of runtime 64-bit signed integer division.

Parameters
dividendDividend
divisorDivisor
Return values
quotientQuotient

Definition at line 180 of file math_test.c.

181  {
182 
183  return check_divmod ( dividend, divisor, / );
184 }
#define check_divmod(dividend, divisor, OP)
Check division/modulus operation.
Definition: math_test.c:118

References check_divmod.

Referenced by s64divmod_okx().

◆ s64mod_var()

int64_t s64mod_var ( int64_t  dividend,
int64_t  divisor 
)

Force a use of runtime 64-bit unsigned integer modulus.

Parameters
dividendDividend
divisorDivisor
Return values
remainderRemainder

Definition at line 193 of file math_test.c.

194  {
195 
196  return check_divmod ( dividend, divisor, % );
197 }
#define check_divmod(dividend, divisor, OP)
Check division/modulus operation.
Definition: math_test.c:118

References check_divmod.

Referenced by s64divmod_okx().

◆ ffsl_okx()

static void ffsl_okx ( long  value,
int  lsb,
const char *  file,
unsigned int  line 
)
inlinestatic

Report a ffsl() test result.

Parameters
valueValue
lsbExpected LSB
fileTest code file
lineTest code line

Definition at line 208 of file math_test.c.

208  {
209 
210  /* Verify as a constant (requires to be inlined) */
211  okx ( ffsl ( value ) == lsb, file, line );
212 
213  /* Verify as a non-constant */
214  okx ( ffsl_var ( value ) == lsb, file, line );
215 }
#define ffsl(x)
Find first (i.e.
Definition: strings.h:131
#define okx(success, file, line)
Report test result.
Definition: test.h:44
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
int ffsl_var(long value)
Force a call to the non-constant implementation of ffsl()
Definition: math_test.c:47

References ffsl, ffsl_var(), okx, and value.

◆ ffsll_okx()

static void ffsll_okx ( long long  value,
int  lsb,
const char *  file,
unsigned int  line 
)
inlinestatic

Report a ffsll() test result.

Parameters
valueValue
lsbExpected LSB
fileTest code file
lineTest code line

Definition at line 227 of file math_test.c.

227  {
228 
229  /* Verify as a constant (requires to be inlined) */
230  okx ( ffsll ( value ) == lsb, file, line );
231 
232  /* Verify as a non-constant */
233  okx ( ffsll_var ( value ) == lsb, file, line );
234 }
int ffsll_var(long long value)
Force a call to the non-constant implementation of ffsll()
Definition: math_test.c:57
#define okx(success, file, line)
Report test result.
Definition: test.h:44
#define ffsll(x)
Find first (i.e.
Definition: strings.h:122
pseudo_bit_t value[0x00020]
Definition: arbel.h:13

References ffsll, ffsll_var(), okx, and value.

◆ flsl_okx()

static void flsl_okx ( long  value,
int  msb,
const char *  file,
unsigned int  line 
)
inlinestatic

Report a flsl() test result.

Parameters
valueValue
msbExpected MSB
fileTest code file
lineTest code line

Definition at line 246 of file math_test.c.

246  {
247 
248  /* Verify as a constant (requires to be inlined) */
249  okx ( flsl ( value ) == msb, file, line );
250 
251  /* Verify as a non-constant */
252  okx ( flsl_var ( value ) == msb, file, line );
253 }
#define okx(success, file, line)
Report test result.
Definition: test.h:44
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
#define flsl(x)
Find last (i.e.
Definition: strings.h:157
int flsl_var(long value)
Force a call to the non-constant implementation of flsl()
Definition: math_test.c:67

References flsl, flsl_var(), okx, and value.

◆ flsll_okx()

static void flsll_okx ( long long  value,
int  msb,
const char *  file,
unsigned int  line 
)
inlinestatic

Report a flsll() test result.

Parameters
valueValue
msbExpected MSB
fileTest code file
lineTest code line

Definition at line 265 of file math_test.c.

265  {
266 
267  /* Verify as a constant (requires to be inlined) */
268  okx ( flsll ( value ) == msb, file, line );
269 
270  /* Verify as a non-constant */
271  okx ( flsll_var ( value ) == msb, file, line );
272 }
#define flsll(x)
Find last (i.e.
Definition: strings.h:148
#define okx(success, file, line)
Report test result.
Definition: test.h:44
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
int flsll_var(long long value)
Force a call to the non-constant implementation of flsll()
Definition: math_test.c:77

References flsll, flsll_var(), okx, and value.

◆ u64divmod_okx()

static void u64divmod_okx ( uint64_t  dividend,
uint64_t  divisor,
uint64_t  quotient,
uint64_t  remainder,
const char *  file,
unsigned int  line 
)
static

Report a 64-bit unsigned integer division test result.

Parameters
dividendDividend
divisorDivisor
quotientQuotient
remainderRemainder
fileTest code file
lineTest code line

Definition at line 285 of file math_test.c.

287  {
288 
289  /* Sanity check */
290  okx ( ( ( divisor * quotient ) + remainder ) == dividend, file, line );
291 
292  /* Check division */
293  okx ( u64div_var ( dividend, divisor ) == quotient, file, line );
294 
295  /* Check modulus */
296  okx ( u64mod_var ( dividend, divisor ) == remainder, file, line );
297 }
uint64_t u64div_var(uint64_t dividend, uint64_t divisor)
Force a use of runtime 64-bit unsigned integer division.
Definition: math_test.c:154
#define okx(success, file, line)
Report test result.
Definition: test.h:44
uint64_t u64mod_var(uint64_t dividend, uint64_t divisor)
Force a use of runtime 64-bit unsigned integer modulus.
Definition: math_test.c:167

References okx, u64div_var(), and u64mod_var().

◆ s64divmod_okx()

static void s64divmod_okx ( int64_t  dividend,
int64_t  divisor,
int64_t  quotient,
int64_t  remainder,
const char *  file,
unsigned int  line 
)
static

Report a 64-bit signed integer division test result.

Parameters
dividendDividend
divisorDivisor
quotientQuotient
remainderRemainder
fileTest code file
lineTest code line

Definition at line 312 of file math_test.c.

314  {
315 
316  /* Sanity check */
317  okx ( ( ( divisor * quotient ) + remainder ) == dividend, file, line );
318 
319  /* Check division */
320  okx ( s64div_var ( dividend, divisor ) == quotient, file, line );
321 
322  /* Check modulus */
323  okx ( s64mod_var ( dividend, divisor ) == remainder, file, line );
324 }
int64_t s64div_var(int64_t dividend, int64_t divisor)
Force a use of runtime 64-bit signed integer division.
Definition: math_test.c:180
#define okx(success, file, line)
Report test result.
Definition: test.h:44
int64_t s64mod_var(int64_t dividend, int64_t divisor)
Force a use of runtime 64-bit unsigned integer modulus.
Definition: math_test.c:193

References okx, s64div_var(), and s64mod_var().

◆ math_test_exec()

static void math_test_exec ( void  )
static

Perform mathematical self-tests.

Definition at line 333 of file math_test.c.

333  {
334 
335  /* Test ffsl() */
336  ffsl_ok ( 0, 0 );
337  ffsl_ok ( 1, 1 );
338  ffsl_ok ( 255, 1 );
339  ffsl_ok ( 256, 9 );
340  ffsl_ok ( 257, 1 );
341  ffsl_ok ( 0x54850596, 2 );
342  ffsl_ok ( 0x80000000, 32 );
343 
344  /* Test ffsll() */
345  ffsll_ok ( 0, 0 );
346  ffsll_ok ( 1, 1 );
347  ffsll_ok ( 0x6d63623330ULL, 5 );
348  ffsll_ok ( 0x80000000UL, 32 );
349  ffsll_ok ( 0x8000000000000000ULL, 64 );
350 
351  /* Test flsl() */
352  flsl_ok ( 0, 0 );
353  flsl_ok ( 1, 1 );
354  flsl_ok ( 255, 8 );
355  flsl_ok ( 256, 9 );
356  flsl_ok ( 257, 9 );
357  flsl_ok ( 0x69505845, 31 );
358  flsl_ok ( -1U, ( 8 * sizeof ( int ) ) );
359  flsl_ok ( -1UL, ( 8 * sizeof ( long ) ) );
360 
361  /* Test flsll() */
362  flsll_ok ( 0, 0 );
363  flsll_ok ( 1, 1 );
364  flsll_ok ( 0x6d63623330ULL, 39 );
365  flsll_ok ( -1U, ( 8 * sizeof ( int ) ) );
366  flsll_ok ( -1UL, ( 8 * sizeof ( long ) ) );
367  flsll_ok ( -1ULL, ( 8 * sizeof ( long long ) ) );
368 
369  /* Test 64-bit arithmetic
370  *
371  * On a 64-bit machine, these tests are fairly meaningless.
372  *
373  * On a 32-bit machine, these tests verify the correct
374  * operation of our libgcc functions __udivmoddi4()
375  * etc. (including checking that the implicit calling
376  * convention assumed by gcc matches our expectations).
377  */
378  u64divmod_ok ( 0x2b90ddccf699f765ULL, 0xed9f5e73ULL,
379  0x2eef6ab4ULL, 0x0e12f089ULL );
380  s64divmod_ok ( 0x2b90ddccf699f765ULL, 0xed9f5e73ULL,
381  0x2eef6ab4ULL, 0x0e12f089ULL );
382  u64divmod_ok ( 0xc09e00dcb9e34b54ULL, 0x35968185cdc744f3ULL,
383  3, 0x1fda7c4b508d7c7bULL );
384  s64divmod_ok ( -0x3f61ff23461cb4acLL, 0x35968185cdc744f3ULL,
385  -1LL, -0x9cb7d9d78556fb9LL );
386  u64divmod_ok ( 0, 0x5b2f2737f4ffULL, 0, 0 );
387  s64divmod_ok ( 0, 0xbb00ded72766207fULL, 0, 0 );
388 
389  /* Test integer square root */
390  ok ( isqrt ( 0 ) == 0 );
391  ok ( isqrt ( 1 ) == 1 );
392  ok ( isqrt ( 255 ) == 15 );
393  ok ( isqrt ( 256 ) == 16 );
394  ok ( isqrt ( 257 ) == 16 );
395  ok ( isqrt ( 0xa53df2adUL ) == 52652 );
396  ok ( isqrt ( 0x123793c6UL ) == 17482 );
397  ok ( isqrt ( -1UL ) == ( -1UL >> ( 8 * sizeof ( unsigned long ) / 2 )));
398 }
#define s64divmod_ok(dividend, divisor, quotient, remainder)
Definition: math_test.c:325
#define ffsl_ok(value, lsb)
Definition: math_test.c:216
unsigned long isqrt(unsigned long value)
Find integer square root.
Definition: isqrt.c:40
#define u64divmod_ok(dividend, divisor, quotient, remainder)
Definition: math_test.c:298
#define ffsll_ok(value, lsb)
Definition: math_test.c:235
#define flsll_ok(value, msb)
Definition: math_test.c:273
#define ok(success)
Definition: test.h:46
#define flsl_ok(value, msb)
Definition: math_test.c:254

References ffsl_ok, ffsll_ok, flsl_ok, flsll_ok, isqrt(), ok, s64divmod_ok, and u64divmod_ok.

Variable Documentation

◆ __self_test

struct self_test math_test __self_test
Initial value:
= {
.name = "math",
.exec = math_test_exec,
}
static void math_test_exec(void)
Perform mathematical self-tests.
Definition: math_test.c:333

Mathematical self-tests.

Definition at line 401 of file math_test.c.