Non-Confidential | PDF version | DUI0773J | ||

| ||||

Home > Coding Considerations > Integer division-by-zero errors in C code |

For targets that do not support hardware division instructions (for example `SDIV`

and `UDIV`

), you can trap and identify integer division-by-zero errors with the appropriate C library helper functions, `__aeabi_idiv0()`

and `__rt_raise()`

.

You can trap integer division-by-zero errors with the C library helper function
`__aeabi_idiv0()`

so that division by zero returns some standard result,
for example zero.

Integer division is implemented in code through the C library helper functions
`__aeabi_idiv()`

and `__aeabi_uidiv()`

. Both functions check
for division by zero.

When integer division by zero is detected, a branch to `__aeabi_idiv0()`

is
made. To trap the division by zero, therefore, you only have to place a breakpoint on
`__aeabi_idiv0()`

.

The library provides two implementations of `__aeabi_idiv0()`

. The default
one does nothing, so if division by zero is detected, the division function returns zero.
However, if you use signal handling, an alternative implementation is selected that calls
`__rt_raise(SIGFPE, DIVBYZERO)`

.

If you provide your own version of `__aeabi_idiv0()`

, then the division
functions call this function. The function prototype for `__aeabi_idiv0()`

is:

`int`

__aeabi_idiv0(`void`

);

If `__aeabi_idiv0()`

returns a value, that value is used as the quotient
returned by the division function.

On entry into `__aeabi_idiv0()`

, the link register `LR`

contains the address of the instruction after the call to
the `__aeabi_uidiv()`

division routine in your application code.

The offending line in the source code
can be identified by looking up the line of C code in the debugger
at the address given by `LR`

.

If you want to examine parameters and save them for postmortem debugging when trapping
`__aeabi_idiv0`

, you can use the
`$Super$$`

and `$Sub$$`

mechanism:

Prefix

`__aeabi_idiv0()`

with`$Super$$`

to identify the original unpatched function`__aeabi_idiv0()`

.Use

`__aeabi_idiv0()`

prefixed with`$Super$$`

to call the original function directly.Prefix

`__aeabi_idiv0()`

with`$Sub$$`

to identify the new function to be called in place of the original version of`__aeabi_idiv0()`

.Use

`__aeabi_idiv0()`

prefixed with`$Sub$$`

to add processing before or after the original function`__aeabi_idiv0()`

.

The following example shows how to intercept `__aeabi_div0`

using the
`$Super$$`

and `$Sub$$`

mechanism.

extern void $Super$$__aeabi_idiv0(void); /* this function is called instead of the original __aeabi_idiv0() */ void $Sub$$__aeabi_idiv0() { // insert code to process a divide by zero ... // call the original __aeabi_idiv0 function $Super$$__aeabi_idiv0(); }

By default, integer division by zero returns zero. If you want to intercept division by
zero, you can re-implement the C library helper function
`__rt_raise()`

.

The function prototype for `__rt_raise()`

is:

`void`

__rt_raise(`int`

signal,`int`

type);

If you re-implement `__rt_raise()`

, then the library automatically provides
the signal-handling library version of `__aeabi_idiv0()`

, which calls
`__rt_raise()`

, then that library version of
`__aeabi_idiv0()`

is included in the final image.

In that case, when a divide-by-zero error occurs, `__aeabi_idiv0()`

calls
`__rt_raise(SIGFPE, DIVBYZERO)`

. Therefore, if you re-implement
`__rt_raise()`

, you must check ```
(signal == SIGFPE) && (type
== DIVBYZERO)
```

to determine if division by zero has occurred.