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