Skip to content

Commit bf3c828

Browse files
author
Robert Schöftner
committed
add hal_extend_int function
helper function to deal with wrap around and extension of lower-width counters to 64bit ints.
1 parent fcd8ed1 commit bf3c828

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

src/hal/hal.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,18 @@ extern int hal_get_signal_value_by_name(
692692
extern int hal_get_param_value_by_name(
693693
const char *name, hal_type_t *type, hal_data_u **data);
694694

695+
/***********************************************************************
696+
* MISC HELPER FUNCTIONS *
697+
************************************************************************/
698+
699+
/** hal_extend_int() extends a counter value with nbits to 64 bits.
700+
Increments between updates need to be less than 2**(nbits-1).
701+
Call with current 64bit counter value to be updated, new
702+
lower-bit counter value and number of bits of counter.
703+
@returns new counter value.
704+
Code by Jeff Epler. */
705+
extern rtapi_s64 hal_extend_int(rtapi_s64 old, int newlow, int nbits);
706+
695707
/***********************************************************************
696708
* EXECUTION RELATED FUNCTIONS *
697709
************************************************************************/

src/hal/hal_lib.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,33 @@ int hal_get_param_value_by_name(
18721872
}
18731873

18741874

1875+
/***********************************************************************
1876+
* MISC HELPER FUNCTIONS *
1877+
************************************************************************/
1878+
1879+
rtapi_s64 hal_extend_int(rtapi_s64 old, rtapi_s64 newlow, int nbits)
1880+
{
1881+
/* see https://github.com/LinuxCNC/linuxcnc/pull/3932#issuecomment-4239206615
1882+
This code avoids branches and undefined behaviour due to signed overflow
1883+
Idea from MicroPython.
1884+
1885+
The shift left operations get the sign bit in the right place, the diff
1886+
is calculated and shifted back as a signed quantity. That assures the sign
1887+
is extended properly. Addition as unsigned avoids signed overflow, which
1888+
would be undefined behaviour.
1889+
1890+
Attention has to be paied that the magnitude of increments / decrements
1891+
of the counter stay within 1<<(nshift-1) between calls to this function,
1892+
else the wrap around will be counted in the wrong direction.
1893+
*/
1894+
int nshift = 64 - nbits;
1895+
rtapi_u64 oldlow_shifted = ((rtapi_u64)old << nshift);
1896+
rtapi_u64 newlow_shifted = ((rtapi_u64)newlow << nshift);
1897+
rtapi_s64 diff_shifted = newlow_shifted - oldlow_shifted;
1898+
return (rtapi_u64)old + (diff_shifted >> nshift);
1899+
}
1900+
1901+
18751902
/***********************************************************************
18761903
* EXECUTION RELATED FUNCTIONS *
18771904
************************************************************************/

0 commit comments

Comments
 (0)