@@ -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