INSTRUCTION SET
S3C4510B
GENERAL PURPOSE SIGNED DIVIDE
This example shows a general purpose signed divide and remainder routine in both Thumb and ARM code.
Thumb code
;signed_divide
; Signed divide of R1 by R0: returns quotient in R0,
; remainder in R1
;Get abs value of R0 into R3
ASR
EOR
SUB
R2, R0, #31
R0, R2
R3, R0, R2
; Get 0 or -1 in R2 depending on sign of R0
; EOR with -1 (0xFFFFFFFF) if negative
; and ADD 1 (SUB -1) to get abs value
;SUB always sets flag so go & report division by 0 if necessary
BEQ divide_by_zero
;Get abs value of R1 by xoring with 0xFFFFFFFF and adding 1 if negative
ASR
EOR
SUB
R0, R1, #31
R1, R0
R1, R0
; Get 0 or -1 in R3 depending on sign of R1
; EOR with -1 (0xFFFFFFFF) if negative
; and ADD 1 (SUB -1) to get abs value
;Save signs (0 or -1 in R0 & R2) for later use in determining ; sign of quotient & remainder.
PUSH {R0, R2}
;Justification, shift 1 bit at a time until divisor (R0 value) ; is just <= than dividend (R1 value). To do this shift
dividend ; right by 1 and stop as soon as shifted value becomes >.
LSR
MOV
B
R0, R1, #1
R2, R3
%FT0
just_l
0
LSL
CMP
BLS
MOV
B
R2, #1
R2, R0
just_l
R0, #0
%FT0
; Set accumulator to 0
; Branch into division loop
div_l
0
LSR
CMP
BCC
SUB
ADC
CMP
BNE
R2, #1
R1, R2
%FT0
R1, R2
R0, R0
R2, R3
div_l
; Test subtract
; If successful do a real subtract
0
; Shift result and add 1 if subtract succeeded
; Terminate when R2 == R3 (ie we have just
; tested subtracting the 'ones' value).
;Now fix up the signs of the quotient (R0) and remainder (R1)
POP
EOR
EOR
SUB
EOR
SUB
MOV
{R2, R3}
R3, R2
R0, R3
R0, R3
R1, R2
R1, R2
pc, lr
; Get dividend/divisor signs back
; Result sign
; Negate if result sign = -1
; Negate remainder if dividend sign = -1
3-98