The DS has accelerators for division and square-root computations. This section explains the Divider.
Registers for Division
Data registers have been prepared for the dividend, the divisor, the quotient and the remainder.
The relationship between these registers is as follows:
Also, a control register is provided to control the Divider.
Operations of the Divider
To perform calculations, the Divider sets the dividend and the divisor in the data registers DIV_NUMER and DIV_DENOM. After the control register DIVCNT is appropriately set, the results of the division are saved in DIV_RESULT and DIVREM_RESULT. (In actuality, the calculation begins right after a value has been set in either DIV_NUMER, DIV_DENOM, or DIVCNT. If data is written to the registers during the calculation, the calculation begins all over again.)
There are three modes for division:
You can switch between modes by changing the value set in the MODE bit of the DIVCNT register.
When the Divider begins a division calculation, the DIVCNT register's BUSY bit becomes 1. The bit retains that value until the result are computed. When this bit changes to 0, the values in the DIV_RESULT and DIVREM_RESULT registers hold the completed computation result.
When the divisor is 0, the DIVCNT register's DIV0 bit becomes 1. When this is the case, the calculation result is undefined.
Calculation Cycles
The number of cycles required by the Divider to perform a division calculation varies, depending on the division mode.
To make more efficient use of the Divider, you can perform another task while waiting for the results after setting the parameters in the Divider's data registers.
Setting the Parameters
Use CP_SetDivImm*() and CP_SetDiv*() to set the parameters for the Divider. Both functions can set both the dividend and the divisor. The CP_SetDiv*() function can also be used to set the DIVCNT register's division mode.
CP_SetDivImm32_32(), CP_SetDivImm64_32(), CP_SetDivImm_64_64()
CP_SetDiv32_32(), CP_SetDiv64_32, CP_SetDivImm64_64()
Thus, if you plan to perform a succession of division calculations in the same division mode, you can use CP_SetDiv*() the first time and then use CP_SetDivImm*() for all subsequent calculations.
Waiting for Calculation to End
To check whether or not the calculation has ended, call CP_IsDivBusy().
To wait for the calculation to end, call CP_WaitDiv().
Getting the Calculation Result
To get the quotient of the division calculation, call either CP_GetDivResult*() or CP_GetDivResultImm*().
The former waits until the DIVCNT register is no longer in the BUSY state before fetching the result. The latter acts immediately.
To get the remainder, call CP_GetDivRemainder() or CP_GetDivRemainderImm*().
The former waits until the DIVCNT register is no longer in the BUSY state before fetching the result. The latter acts immediately.
Notes
When the division mode is "32bit divided by 32bit" or "64bit divided by 32bit," the upper 32 bits in data registers for which only 32 bits are being used need to be filled with zeros. The NitroSDK functions do this automatically. However, don't forget to do this when your application directly sets values in the registers.
If you are using the thread system, the Divider calculations are thread safe by default.
Example
The following is an example using the Divider to conduct a division calculation and then displaying the result.
u32 quotient;
u32 remainder;
//---- set parameter and div-mode
CP_SetDiv( 0x12345678, 0x300, CP_DIV_32_32BIT_MODE );
//---- wait for division to finish
CP_WaitDiv();
//---- display result
quotient = CP_GetDivResultImm32();
remainder = CP_GetDivRemainderImm32();
OS_Printf( "quotient=%x, remainder=%x\n", quotient, remainder );
Precautions On Use Inside Interrupts
When using a divider or square root calculator inside an interrupt, there is a chance for the calculation result of the interrupt source to be destroyed.
Be sure to backup/restore the status of any divider or square root calculator used inside an interrupt with CP_SaveContext and CP_RestoreContext.
The contents of dividers are also automatically restored from thread context when threads are switched.
void intr_func( void )
{
CPContext context;
CP_SaveContext( &context );
CP_SetDiv32_32( 1000, 5 );
CP_WaitDiv();
result = CP_GetDivResult();
CP_RestoreContext( &context );
}
08/07/2006 Changed calculation cycles to CPU cycles and added a note regarding the use of dividers inside interrupts.
12/27/2004 Initial version.
CONFIDENTIAL