Unsigned integer division macro example
You can use a macro to perform unsigned integer division.
The macro takes the following parameters:
$Bot
The register that holds the divisor.
$Top
The register that holds the dividend before the instructions are executed. After the instructions are executed, it holds the remainder.
$Div
The register where the quotient of the division is placed. It can be
NULL
(""
) if only the remainder is required.$Temp
A temporary register used during the calculation.
Example unsigned integer division with a macro
MACRO $Lab DivMod $Div,$Top,$Bot,$Temp ASSERT $Top <> $Bot ; Produce an error message if the ASSERT $Top <> $Temp ; registers supplied are ASSERT $Bot <> $Temp ; not all different IF "$Div" <> "" ASSERT $Div <> $Top ; These three only matter if $Div ASSERT $Div <> $Bot ; is not null ("") ASSERT $Div <> $Temp ; ENDIF $Lab MOV $Temp, $Bot ; Put divisor in $Temp CMP $Temp, $Top, LSR #1 ; double it until 90 MOVLS $Temp, $Temp, LSL #1 ; 2 * $Temp > $Top CMP $Temp, $Top, LSR #1 BLS %b90 ; The b means search backwards IF "$Div" <> "" ; Omit next instruction if $Div ; is null MOV $Div, #0 ; Initialize quotient ENDIF 91 CMP $Top, $Temp ; Can we subtract $Temp? SUBCS $Top, $Top,$Temp ; If we can, do so IF "$Div" <> "" ; Omit next instruction if $Div ; is null ADC $Div, $Div, $Div ; Double $Div ENDIF MOV $Temp, $Temp, LSR #1 ; Halve $Temp, CMP $Temp, $Bot ; and loop until BHS %b91 ; less than divisor MEND
The macro checks that no two parameters use the same register. It also optimizes the code produced if only the remainder is required.
To avoid multiple definitions of labels if DivMod
is used more than once
in the assembler source, the macro uses numeric local labels (90, 91).
The following example shows the code that this macro produces if it is invoked as follows:
ratio DivMod R0,R5,R4,R2
Output from the example division macro
ASSERT r5 <> r4 ; Produce an error if the ASSERT r5 <> r2 ; registers supplied are ASSERT r4 <> r2 ; not all different ASSERT r0 <> r5 ; These three only matter if $Div ASSERT r0 <> r4 ; is not null ("") ASSERT r0 <> r2 ; ratio MOV r2, r4 ; Put divisor in $Temp CMP r2, r5, LSR #1 ; double it until 90 MOVLS r2, r2, LSL #1 ; 2 * r2 > r5 CMP r2, r5, LSR #1 BLS %b90 ; The b means search backwards MOV r0, #0 ; Initialize quotient 91 CMP r5, r2 ; Can we subtract r2? SUBCS r5, r5, r2 ; If we can, do so ADC r0, r0, r0 ; Double r0 MOV r2, r2, LSR #1 ; Halve r2, CMP r2, r4 ; and loop until BHS %b91 ; less than divisor