In article <
2018Mar2...@mips.complang.tuwien.ac.at>,
Anton Ertl <
an...@mips.complang.tuwien.ac.at> wrote:
>
minf...@arcor.de writes:
>>The 128/64 bit division was tough though. It's the
>>classic binary shift-subtract-algorithm. I didn't find any simpler method
>>in the web.
>>
>>Perhaps some good fellow could give me a hint how the 128/64 division could
>>be composed of simple 64/32 bit division elements? =20
>
>It's already bad enough if the element is 64/64. With 64/32, the
>shift-and-subtract variant may be fastest; and it's certainly the
>simplest. Another option is to use the 64/32 in combination with
>shifts to get an approximate result, and then refine that.
C is like assembler with no flag registers.
E.g. Z80 code for shit-and-subtract is easy to find, but it uses flags.
Dec alpha assembler is also like that and it has no basic divide
instruction.
Instead a register that I called compare is used.
This is my shift-and-subtract code for the DEC alpha.
The macro processor is used to give registers a name.
CW is the cell width
CODE_HEADER({UM/MOD},{USLAS})
define({divisor},{SR1})
define({dividend},{SR3})
define({modulus},{SR3})
define({quotient},{SR0})
define({compare},{SR2})
define({mask},{{$}{5}})
LDQ divisor, _CELLS(0)(SPO) #{LSW OF DIVISOR}
LDQ quotient, _CELLS(1)(SPO) #{MSW OF DIVIDEND}
LDQ dividend, _CELLS(2)(SPO) #{LSW OF DIVIDEND}
ADDQ SPO, _CELLS(3), SPO
BEQ divisor, DZERO /* div by zero */
BIS $31,1,mask
/* shift divisor left */
USLAS1: CMPULT divisor,modulus,compare
BLT divisor, USLAS3
ADDQ divisor,divisor,divisor
ADDQ mask,mask,mask
BNE compare,USLAS1
/* ok, start to go right again.. */
USLAS2: SRL divisor,1,divisor
BEQ mask, USLAS9
SRL mask,1,mask
USLAS3: CMPULE divisor,modulus,compare
BEQ compare,USLAS2
ADDQ quotient,mask,quotient
BEQ mask,USLAS9
SUBQ modulus,divisor,modulus
BR USLAS2
USLAS9:
_2PUSH
undefine({divisor})
undefine({dividend})
undefine({modulus})
undefine({quotient})
undefine({compare})
undefine({mask})
#
#{ DIVIDE BY ZERO ERROR - SHOW MAX NUMBERS}
DZERO: SUBQ $31, 1, SR0
ADDQ SR0, 0, SR3
_2PUSH #{STORE QUOT/REM}
#
\--------------- after macro ------------------------------
X_USLAS:
LDQ $1, (CW*(0))($29) #LSW OF DIVISOR
LDQ $0, (CW*(1))($29) #MSW OF DIVIDEND
LDQ $3, (CW*(2))($29) #LSW OF DIVIDEND
ADDQ $29, (CW*(3)), $29
BEQ $1, DZERO /* div by zero */
BIS $31,1,$5
/* $1 left */
USLAS1: CMPULT $1,$3,$2
BLT $1, USLAS3
ADDQ $1,$1,$1
ADDQ $5,$5,$5
BNE $2,USLAS1
/* ok, start to go right again.. */
USLAS2: SRL $1,1,$1
BEQ $5, USLAS9
SRL $5,1,$5
USLAS3: CMPULE $1,$3,$2
BEQ $2,USLAS2
ADDQ $0,$5,$0
BEQ $5,USLAS9
SUBQ $3,$1,$3
BR USLAS2
USLAS9:
SUBQ $29, 2*CW, $29
STQ $3, CW($29)
STQ $0, 0($29)
LDQ $0, 0($30)
ADDQ $30, CW, $30
LDQ $1, 0($0)
JMP $31, ($1), 0
#
# DIVIDE BY ZERO ERROR - SHOW MAX NUMBERS
DZERO: SUBQ $31, 1, $0
ADDQ $0, 0, $3
SUBQ $29, 2*CW, $29
STQ $3, CW($29)
STQ $0, 0($29)
LDQ $0, 0($30)
ADDQ $30, CW, $30
LDQ $1, 0($0)
JMP $31, ($1), 0 #STORE QUOT/REM
\----------------------------------------------------------
(You can also look at the dec alpha Forth on my side below)
This is of course tricky code.
>
>- anton