Fast Integer Division Intrinsics

The intrinsics listed in Table 7-9 perform faster division using hardware fast integer division support. These intrinsics are enabled if the --idiv_support=idiv0 compiler option is used.

In order to use these intrinsics, your code must include the stdlib.h header file and the --float_support option must be set to fpu32 or fpu64. Fast integer division support is available for EABI only.

These intrinsics follow the format of the ldiv and lldiv standard library functions. They take as input the dividend and divisor, and return a structure containing both the quotient and remainder in the fields quot and rem, respectively. The __uldiv_t and __ulldiv_t types are unsigned equivalents to ldiv and lldiv provided by stdlib.h. In addition, the following additional structure types are provided to return long long quotients with a long remainder:

typedef struct { long long quot; long rem; } __llldiv_t; typedef struct { unsigned long long quot; unsigned long rem; } __ullldiv_t;

These intrinsics support three types of integer division:

For all three types of division, the dividend is exactly equal to quotient * divisor + remainder. All three types of division compute the same quotient and remainder if the remainder is zero or if the dividend and divisor are positive.

Since the results of division between two unsigned values do not vary for the traditional, Euclidean, and modulo versions, only the traditional versions are provided for unsigned inputs.

In general, if the dividend and divisor are of different types, the divisor is converted to the type of the dividend before division. However, in cases where the dividend type is signed, the divisor type is unsigned, and the dividend type is not larger than the divisor type—that is, for the *_div_i32byu32 and *_div_i64byu64 intrinsics—division is carried out using a signed type larger than both the dividend and divisor, and then converted to the type of the dividend.

Division by 0 is always undefined.

In addition to these intrinsics, when the --idiv_support=idiv0 compiler option is used, the built-in integer division and modulo operators ("/" and "%") use the appropriate faster instructions as described in Section 7.8.2. The faster versions of these built-in operators are used whether or not the stdlib.h header file is included.

Table 7-9 C/C++ Compiler Intrinsics for Fast Integer Division (--idiv_support=idiv0)

Intrinsic Assembly Instruction(s) Description
16-bit by 16-bit
ldiv_t __traditional_div_i16byi16( int dividend, int divisor); I16TOF32 R3H,@Den F32TOI32 R3H,R3H I16TOF32 R1H,@Num MPYF32 R1H,R1H,#65536.0 NOP F32TOI32 R1H,R1H ABSI32DIV32 R2H, R1H, R3H .loop #4 {SUBC4UI32 R2H, R1H, R3H} NEGI32DIV32 R1H, R2H Return the result of traditional 16-bit by 16-bit division.
ldiv_t __euclidean_div_i16byi16( int dividend, int divisor); I16TOF32 R3H,@Den F32TOI32 R3H,R3H I16TOF32 R1H,@Num MPYF32 R1H,R1H,#65536.0 NOP F32TOI32 R1H,R1H ABSI32DIV32 R2H, R1H, R3H .loop #4 {SUBC4UI32 R2H, R1H, R3H} ENEGI32DIV32 R1H, R2H, R3H Return the result of Eucildean 16-bit by 16-bit division.
ldiv_t __modulo_div_i16byi16( int dividend, int divisor); I16TOF32 R3H,@Den F32TOI32 R3H,R3H I16TOF32 R1H,@Num MPYF32 R1H,R1H,#65536.0 NOP F32TOI32 R1H,R1H ABSI32DIV32 R2H, R1H, R3H .loop #4 {SUBC4UI32 R2H, R1H, R3H} MNEGI32DIV32 R1H, R2H, R3H Return the result of modulo 16-bit by 16-bit division.
__uldiv_t __traditional_div_u16byu16( unsigned int dividend, unsigned int divisor); UI16TOF32 R3H,@Den F32TOUI32 R3H,R3H UI16TOF32 R1H,@Num MPYF32 R1H,R1H,#65536.0 NOP F32TOUI32 R1H,R1H .loop #4{SUBC4UI32 R2H, R1H, R3H} Return the unsigned result of traditional 16-bit by 16-bit division, when the dividend and divisor are unsigned.
32-bit by 32-bit
ldiv_t __traditional_div_i32byi32( long dividend, long divisor); MOV32 R3H @DEN MOV32 R1H @NUM ABSI32DIV32 R2H, R1H, R3H .loop #8 {SUBC4UI32 R2H, R1H, R3H} NEGI32DIV32 R1H, R2H Return the result of traditional 32-bit by 32-bit division.
ldiv_t __euclidean_div_i32byi32( long dividend, long divisor); MOV32 R3H @DEN MOV32 R1H @NUM ABSI32DIV32 R2H, R1H, R3H .loop #8 {SUBC4UI32 R2H, R1H, R3H} ENEGI32DIV32 R1H, R2H, R3H Return the result of Eucildean 32-bit by 32-bit division.
ldiv_t __modulo_div_i32byi32( long dividend, long divisor); MOV32 R3H @DEN MOV32 R1H @NUM ABSI32DIV32 R2H, R1H, R3H .loop #8 {SUBC4UI32 R2H, R1H, R3H} MNEGI32DIV32 R1H, R2H, R3H Return the result of modulo 32-bit by 32-bit division.
ldiv_t __traditional_div_i32byu32( long dividend, unsigned long divisor); MOV32 R3H @DEN MOV32 R1H @NUM ABSI32DIV32U R2H, R1H .loop #8 {SUBC4UI32 R2H, R1H, R3H} NEGI32DIV32 R1H, R2H Return the result of traditional 32-bit by 32-bit division, when the divisor is unsigned.
ldiv_t __euclidean_div_i32byu32( long dividend, unsigned long divisor); MOV32 R3H @DEN MOV32 R1H @NUM ABSI32DIV32U R2H, R1H .loop #8 {SUBC4UI32 R2H, R1H, R3H} ENEGI32DIV32 R1H, R2H, R3H Return the result of Eucildean 32-bit by 32-bit division, when the divisor is unsigned.
ldiv_t __modulo_div_i32byu32( long dividend, unsigned long divisor); MOV32 R3H @DEN MOV32 R1H @NUM ABSI32DIV32U R2H, R1H .loop #8 {SUBC4UI32 R2H, R1H, R3H} MNEGI32DIV32 R1H, R2H, R3H Return the result of modulo 32-bit by 32-bit division, when the divisor is unsigned.
__uldiv_t __traditional_div_u32byu32( unsigned long dividend, unsigned long divisor); MOV32 R3H @DEN MOV32 R1H @NUM ZERO R2 .loop #8 {SUBC4UI32 R2H, R1H, R3H} Return the unsigned result of traditional 32-bit by 32-bit division, when the dividend and divisor are unsigned.
32-bit by 16-bit
ldiv_t __traditional_div_i32byi16( long dividend, int divisor); I16TOF32 R3H,@Den F32TOI32 R3H,R3H MOV R1H, @NUM .loop #3 {NOP} ABSI32DIV32 R2H, R1H, R3H .loop #8 {SUBC4UI32 R2H, R1H, R3H} NEGI32DIV32 R1H, R2H Return the result of traditional 32-bit by 16-bit division.
ldiv_t __euclidean_div_i32byi16( long dividend, int divisor); I16TOF32 R3H,@Den F32TOI32 R3H,R3H MOV R1H, @NUM .loop #3 {NOP} ABSI32DIV32 R2H, R1H, R3H .loop #8 {SUBC4UI32 R2H, R1H, R3H} ENEGI32DIV32 R1H, R2H, R3H Return the result of Eucildean 32-bit by 16-bit division.
ldiv_t __modulo_div_i32byi16( long dividend, int divisor); I16TOF32 R3H,@Den F32TOI32 R3H,R3H MOV R1H, @NUM .loop #3 {NOP} ABSI32DIV32 R2H, R1H, R3H .loop #8 {SUBC4UI32 R2H, R1H, R3H} MNEGI32DIV32 R1H, R2H, R3H Return the result of modulo 32-bit by 16-bit division.
__uldiv_t __traditional_div_u32byu16( unsigned long dividend, unsigned int divisor); I16TOF32 R3H,@Den F32TOI32 R3H,R3H MOV R1H, @NUM ZERO R2 .loop #2 {NOP} .loop #8 {SUBC4UI32 R2H, R1H, R3H} Return the unsigned result of traditional 32-bit by 16-bit division, when the dividend and divisor are unsigned.
64-bit by 64-bit
lldiv_t __traditional_div_i64byi64( long long dividend, long long divisor); MOV32 R5H @DEN_L MOV32 R3H @DEN_H MOV32 R0H @NUM_L MOV32 R1H @NUM_H ABSI64DIV64 R2H:R4H, R1H:R0H, R3H:R5H .loop #32 {SUBC2UI64 R2H:R4H, R1H:R0H, R3H:R5H} NEGI64DIV64 R1H:R0H, R2H:R4H Return the result of traditional 64-bit by 64-bit division.
lldiv_t __euclidean_div_i64byi64( long long dividend, long long divisor); MOV32 R5H @DEN_L MOV32 R3H @DEN_H MOV32 R0H @NUM_L MOV32 R1H @NUM_H ABSI64DIV64 R2H:R4H, R1H:R0H, R3H:R5H .loop #32 {SUBC2UI64 R2H:R4H, R1H:R0H, R3H:R5H} ENEGI64DIV64 R1H:R0H, R2H:R4H, R3H:R5H Return the result of Eucildean 64-bit by 64-bit division.
lldiv_t __modulo_div_i64byi64( long long dividend, long long divisor); MOV32 R5H @DEN_L MOV32 R3H @DEN_H MOV32 R0H @NUM_L MOV32 R1H @NUM_H ABSI64DIV64 R2H:R4H, R1H:R0H, R3H:R5H .loop #32 {SUBC2UI64 R2H:R4H, R1H:R0H, R3H:R5H} MNEGI64DIV64 R1H:R0H, R2H:R4H, R3H:R5H Return the result of modulo 64-bit by 64-bit division.
lldiv_t __traditional_div_i64byu64( long long dividend, unsigned long long divisor); MOV32 R5H @DEN_L MOV32 R3H @DEN_H MOV32 R0H @NUM_L MOV32 R1H @NUM_H ABSI64DIV64U R2H:R4H, R1H:R0H .loop #32 {SUBC2UI64 R2H:R4H, R1H:R0H, R3H:R5H} NEGI64DIV64 R1H:R0H, R2H:R4H Return the result of traditional 64-bit by 64-bit division, when the divisor is unsigned.
lldiv_t __euclidean_div_i64byu64( long long dividend, unsigned long long divisor); MOV32 R5H @DEN_L MOV32 R3H @DEN_H MOV32 R0H @NUM_L MOV32 R1H @NUM_H ABSI64DIV64U R2H:R4H, R1H:R0H .loop #32 {SUBC2UI64 R2H:R4H, R1H:R0H, R3H:R5H} ENEGI64DIV64 R1H:R0H, R2H:R4H, R3H:R5H Return the result of Eucildean 64-bit by 64-bit division, when the divisor is unsigned.
lldiv_t __modulo_div_i64byu64( long long dividend, unsigned long long divisor); MOV32 R5H @DEN_L MOV32 R3H @DEN_H MOV32 R0H @NUM_L MOV32 R1H @NUM_H ABSI64DIV64U R2H:R4H, R1H:R0H .loop #32 {SUBC2UI64 R2H:R4H, R1H:R0H, R3H:R5H} MNEGI64DIV64 R1H:R0H, R2H:R4H, R3H:R5H Return the result of modulo 64-bit by 64-bit division, when the divisor is unsigned.
__ulldiv_t __traditional_div_u64byu64( unsigned long long dividend, unsigned long long divisor); ZERO R2 ZERO R4 MOV32 R5H @DEN_L MOV32 R3H @DEN_H MOV32 R0H @NUM_L MOV32 R1H @NUM_H .loop #32 {SUBC2UI64 R2H:R4H, R1H:R0H, R3H:R5H} Return the unsigned result of traditional 64-bit by 64-bit division, when the dividend and divisor are unsigned.
64-bit by 32-bit
__llldiv_t __traditional_div_i64byi32( signed long long dividend, long divisor); ABSI64DIV32 R2H, R1H:R0H, R3H .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 NEGI64DIV32 R1H:R0H, R2H LRETR Return the result of traditional 64-bit by 32-bit division.
__llldiv_t __euclidean_div_i64byi32( signed long long dividend, long divisor); ABSI64DIV32 R2H, R1H:R0H, R3H .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 ENEGI64DIV32 R1H:R0H, R2H, R3H LRETR Return the result of Eucildean 64-bit by 32-bit division.
__llldiv_t __modulo_div_i64byi32( signed long long dividend, long divisor); ABSI64DIV32 R2H, R1H:R0H, R3H .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 MNEGI64DIV32 R1H:R0H, R2H, R3H LRETR Return the result of modulo 64-bit by 32-bit division.
__llldiv_t __traditional_div_i64byu32( signed long long dividend, unsigned long divisor); ABSI64DIV32U R2H, R1H:R0H .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 ZERO R4 SWAPF R4, R2 NEGI64DIV64 R1H:R0H, R2H:R4H LRETR Return the result of traditional 64-bit by 32-bit division, when the divisor is unsigned.
__llldiv_t __euclidean_div_i64byu32( signed long long dividend, unsigned long divisor); ABSI64DIV32U R2H, R1H:R0H .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 ENEGI64DIV32 R1H:R0H, R2H, R3H LRETR Return the result of Eucildean 64-bit by 32-bit division, when the divisor is unsigned.
__llldiv_t __modulo_div_i64byu32( unsigned long long dividend, unsigned long divisor); ABSI64DIV32U R2H, R1H:R0H .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 MNEGI64DIV32 R1H:R0H, R2H, R3H LRETR Return the result of modulo 64-bit by 32-bit division, when the divisor is unsigned.
__ullldiv_t __traditional_div_u64byu32( unsigned long long dividend, unsigned long divisor); ZERO R2 ZERO R4 .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 .loop 8 SUBC4UI32 R2H, R1H, R3H .endloop SWAPF R1, R0 LRETR Return the unsigned result of traditional 64-bit by 32-bit division, when the dividend and divisor are unsigned.