# Copyright (C) 2000 MySQL AB
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# Optimized longlong2str function for Intel 80x86  (gcc/gas syntax) 
# Some set sequences are optimized for pentuimpro II 

	.file	"longlong2str-x86.s"
	.version "1.02"

.text
	.align 4

.globl	longlong2str_with_dig_vector
	.type	 longlong2str_with_dig_vector,@function
	
longlong2str_with_dig_vector:
	subl $80,%esp
	pushl %ebp
	pushl %esi
	pushl %edi
	pushl %ebx
	movl 100(%esp),%esi	# Lower part of val 
	movl 112(%esp),%ebx	# Radix 
	movl 104(%esp),%ebp	# Higher part of val 
	movl %ebx,%eax
	movl 108(%esp),%edi	# get dst 
	testl %eax,%eax
	jge .L144

	addl $36,%eax
	cmpl $34,%eax
	ja .Lerror		# Wrong radix 
	testl %ebp,%ebp
	jge .L146
	movb $45,(%edi)		# Add sign 
	incl %edi		# Change sign of val 
	negl %esi
	adcl $0,%ebp
	negl %ebp
.L146:
	negl %ebx		# Change radix to positive 
	jmp .L148
	.align 4
.L144:
	addl $-2,%eax
	cmpl $34,%eax
	ja .Lerror		# Radix in range 

.L148:
	movl %esi,%eax		# Test if zero (for easy loop) 
	orl %ebp,%eax
	jne .L150
	movb $48,(%edi)
	incl %edi
	jmp .L10_end
	.align 4

.L150:
	leal 92(%esp),%ecx	# End of buffer 
	movl %edi, 108(%esp)    # Store possible modified dest
	movl 116(%esp), %edi    # dig_vec_upper
	jmp  .L155
	.align 4

.L153:
	# val is stored in in ebp:esi 

	movl %ebp,%eax		# High part of value 
	xorl %edx,%edx
	divl %ebx
	movl %eax,%ebp
	movl %esi,%eax
	divl %ebx
	decl %ecx
	movl %eax,%esi		# quotent in ebp:esi 
	movb (%edx,%edi),%al    # al is faster than dl 
	movb %al,(%ecx)		# store value in buff 
	.align 4
.L155:
	testl %ebp,%ebp
	ja .L153
	testl %esi,%esi		# rest value 
	jl .L153
	je .L160		# Ready 
	movl %esi,%eax
	.align 4

.L154:				# Do rest with integer precision 
	cltd
	divl %ebx
	decl %ecx
	movb (%edx,%edi),%dl	# bh is always zero as ebx=radix < 36 
	testl %eax,%eax
	movb %dl,(%ecx)
	jne .L154

.L160:
	movl 108(%esp),%edi	# get dst 
	
.L10_mov:
	movl %ecx,%esi
	leal 92(%esp),%ecx	# End of buffer 
	subl %esi,%ecx
	rep
	movsb

.L10_end:
	movl %edi,%eax		# Pointer to end null 
	movb $0,(%edi)		# Store the end null 

.L165:
	popl %ebx
	popl %edi
	popl %esi
	popl %ebp
	addl $80,%esp
	ret

.Lerror:
	xorl %eax,%eax		# Wrong radix 
	jmp .L165

.Lfe3:
	.size	 longlong2str_with_dig_vector,.Lfe3-longlong2str_with_dig_vector

#
# This is almost equal to the above, except that we can do the final
# loop much more efficient	
#	

	.align 4
	
.globl	longlong10_to_str
	.type	 longlong10_to_str,@function
longlong10_to_str:
	subl $80,%esp
	pushl %ebp
	pushl %esi
	pushl %edi
	pushl %ebx
	movl 100(%esp),%esi	# Lower part of val 
	movl 104(%esp),%ebp	# Higher part of val 
	movl 108(%esp),%edi	# get dst 
	movl 112(%esp),%ebx	# Radix (10 or -10)
	testl %ebx,%ebx
	jge .L10_10		# Positive radix

	negl %ebx		# Change radix to positive (= 10)

	testl %ebp,%ebp		# Test if negative value
	jge .L10_10
	movb $45,(%edi)		# Add sign 
	incl %edi
	negl %esi		# Change sign of val (ebp:esi)
	adcl $0,%ebp
	negl %ebp
	.align 4

.L10_10:
	leal 92(%esp),%ecx	# End of buffer 
	movl %esi,%eax		# Test if zero (for easy loop) 
	orl %ebp,%eax
	jne .L10_30		# Not zero

	# Here when value is zero
	movb $48,(%edi)
	incl %edi
	jmp .L10_end
	.align 4

.L10_20:
	# val is stored in in ebp:esi 
	movl %ebp,%eax		# High part of value 
	xorl %edx,%edx
	divl %ebx		# Divide by 10
	movl %eax,%ebp
	movl %esi,%eax
	divl %ebx		# Divide by 10
	decl %ecx
	movl %eax,%esi		# quotent in ebp:esi 
	addl $48,%edx		# Convert to ascii
	movb %dl,(%ecx)		# store value in buff 

.L10_30:
	testl %ebp,%ebp
	ja .L10_20
	testl %esi,%esi		# rest value 
	jl .L10_20		# Unsigned, do ulonglong div once more
	je .L10_mov		# Ready
	movl %esi,%ebx		# Move val to %ebx

	# The following code uses some tricks to change division by 10 to
	# multiplication and shifts
	movl $0xcccccccd,%esi
		
.L10_40:
        movl %ebx,%eax
        mull %esi
        decl %ecx
        shrl $3,%edx
        leal (%edx,%edx,4),%eax
        addl %eax,%eax
        subb %al,%bl		# %bl now contains val % 10
        addb $48,%bl
        movb %bl,(%ecx)
        movl %edx,%ebx
        testl %ebx,%ebx
	jne .L10_40
	jmp .L10_mov		# Shared end with longlong10_to_str

.L10end:
	.size	 longlong10_to_str,.L10end-longlong10_to_str