Milán Major

netscape-revival

1 branch
Code

nspr-/src/md_Mac/mdmac.s

						EXPORT 	.ll_udivmod32
						EXPORT 	.CountLeadingZeros
						EXPORT 	.memset
						EXPORT	.LL_MUL32

################################################################################
#
#	ll_udivmod32
#
################################################################################

.ll_udivmod32:			
						cmpi		cr1, r7, 0
	
						li			r11, 0
						li			r9, 32
						
						#	If someone tried to divide by zero, then they lose
						#	big time.
						
						beqlr		cr1

						#	If the denominator has the high-bit set, we need
						#	to do some fancy foot work.  Otherwise, procede
						#	with division as usual.

						bge			cr1, repeatdivide

highbitset:
						#	Shift the denominator down by a power of two.  
						#	This will allow us to proceed with the 
						#	normal division algorithm, and just clean up
						#	at the end.  Also remember if the low bit 
						#	of the denominator is set.

						andi.		r8, r7, 1
						cmpi		cr0, r8, 1
						
						srwi		r7, r7, 1
						
						#	Keep both pieces of information that we need
						#	about the denominator (i.e. whether it's low and
						#	bits were set) in CR1... we will need them 
						#	later.
						
						crand		6, 2, 2
						
repeatdivide:			
						cntlzw		r10, r5
						
						cmplw		r10, r9
						ble			dontpinshift
				
						mr			r10, r9
						
dontpinshift:			
						slw			r5, r5, r10
						
						li			r8, 32
						sub			r8, r8, r10

						srw			r8, r6, r8
						slw			r6, r6, r10
						
						or			r6, r6, r8
						or			r5, r5, r8
						
						divwu		r12, r5, r7

						mullw		r8, r7, r12
						sub			r5, r5, r8

						sub.		r9, r9, r10
						slw			r12, r12, r9
						add			r11, r11, r12
						
						bne			repeatdivide

finishup:

						#	If the high bit of the denominator was not
						#	originally set, then we are done.  If it was,
						#	then we need to adjust the result for the 
						#	fact that we shifted the denominator down by one
						#	bit.

						bge			cr1, highBitWasntSet
						
						#	If the low bit of the result.hi was set, make
						#	sure to add the shifted denominator back into the
						#	remainder once before we shift result.hi down
						#	to compensate for the fact that we shifted 
						#	the it down originally.
						
						andi.		r10, r11, 1
						beq			dontAddShiftedDivisorToRemainder
						
						add			r5, r5, r7
						
dontAddShiftedDivisorToRemainder:

						#	Finally shift result.lo down. 

						srwi		r11, r11, 1
						
						#	If the low bit of our denominator was originally
						#	set, then we are still not done.  We may have
						#	overestimated how many times the it could
						#	go into the numerator
						
						bne			cr1, lowBitWasntSet
						
						#	Restore the denominator to its original glory
						
						slwi		r7, r7, 1
						ori			r7, r7, 1
						
						#	Subtract result.hi from result.lo.  This will
						#	give us an adjusted remainder that includes the
						#	lowest significant bit of the denominator
						
						sub.		r10, r5, r11
						
						#	It is possible that the remainder will no longer
						#	be in the proper range (it went below zero)
						#	Add the denominator to it until
						#	it goes possible (this can only happen twice),
						#	each time decrementing result.hi
						
						cmplw		r10, r5
						ble			noMoreAdjustments
						
						subi		r11, r11, 1
						add.		r5, r10, r7
						
						cmplw		r5, r10
						ble			noMoreAdjustments2
						
						subi		r11, r11, 1
						add.		r10, r5, r7
												
noMoreAdjustments:
						mr			r5, r10
						
noMoreAdjustments2:
highBitWasntSet:
lowBitWasntSet:

						stw			r11, 0(r3)
						stw			r5, 0(r4)
						
						blr


################################################################################
#
#	CountLeadingZeros
#
################################################################################

.LL_MUL32	
						mullw	r6, r3, r4 
						stw		r6, 4(r5)
						mulhwu	r6, r3, r4
						stw		r6, 0(r5)
						blr

################################################################################
#
#	CountLeadingZeros
#
################################################################################

.CountLeadingZeros:		
						cntlzw		r3, r3
						blr
						
						
################################################################################
#
#	.memset
#
################################################################################
					
.memset

						cmplwi   	r5, 0
						mr			r7, r3
						li			r8, 0
						li			r6, 0
						beqlr
						
						#	If we are filling with zeros, then we donÕt have
						#	to create a four-byte copy of the fill byte,
						#	we already have it:  0x00000000.
						
						rlwinm.  	r0,r4,0,24,31
						beq			checkalignment
						
						#	Create a four-byte copy of the fill byte, put
						#	it in r6.
						
						rlwinm   	r0,r4,0,24,31
						extsh    	r0,r0
						rlwinm   	r6,r4,0,24,31
						rlwinm   	r0,r0,8,0,23
						or       	r8,r6,r0
						rlwinm   	r0,r8,0,16,31
						rlwinm   	r6,r8,0,16,31
						rlwinm   	r0,r0,16,0,15
						or       	r6,r6,r0
						
						b			checkalignment

alignbegin:
						#	Try to align the destination pointer to a 
						#	word boundary.

						stb      	r4,0(r7)
						subi     	r5,r5,1
						addi     	r7,r7,1
						
checkalignment:

						cmplwi   	r5,$0000
						beq      	alignedfillheader
						
						rlwinm.  	r0,r7,0,30,31
						bne      	alignbegin
						
alignedfillheader:

						rlwinm.  	r0,r5,27,5,31
						beq			alignend
						
alignedfill:			stw      	r6,0(r7)
						stwu    	r6,4(r7)
						stwu    	r6,4(r7)
						stwu    	r6,4(r7)
						stwu    	r6,4(r7)
						stwu     	r6,4(r7)
						stwu     	r6,4(r7)
						stwu    	r6,4(r7)
						addi     	r7,r7,4
						subic.   	r0,r0,1
						bne			alignedfill

alignend:
						rlwinm   	r0,r5,0,27,31
						rlwinm.  	r0,r0,30,2,31
						beq			fillLongsAtEndSkip
						
fillLongsAtEnd:
						stw      	r6,0(r7)
						addi 		r7,r7,4
						subic.   	r0,r0,1
						bne			fillLongsAtEnd
						
fillLongsAtEndSkip:

						rlwinm.  	r0,r5,0,30,30
						beq			fillWordAtEndSkip

fillWordsAtEnd:

						sth      	r8,0(r7)
						addi     	r7,r7,2

fillWordAtEndSkip:
						rlwinm.  	r0,r5,0,31,31
						beqlr
						
						stb      	r4,0(r7)
						blr