# 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 # longlong2str function for Intel 80x86 (gcc/gas syntax) # See longlong2str(dst,radix,val) description in longlong2str.c. .file "longlong2str.s" .version "1.01" .text .align 4 .globl longlong2str .type longlong2str,@function longlong2str: subl $80,%esp # Temporary buffer for up to 64 radix-2 digits pushl %ebp pushl %esi pushl %edi pushl %ebx movl 100(%esp),%esi # esi = Lower part of val movl 112(%esp),%ebx # ebx = Radix movl 104(%esp),%ebp # ebp = Higher part of val movl 108(%esp),%edi # edi -> dst testl %ebx,%ebx jge .L144 # (Radix >= 0) testl %ebp,%ebp jge .L146 # (Higher part of val >= 0) movb $45,(%edi) # Add '-' sign incl %edi negl %esi # Change val to positive adcl $0,%ebp negl %ebp .L146: negl %ebx # Change radix to positive .L144: cmpl $36,%ebx # Radix must be between 2 and 36 ja .Lerror # (Radix not in range) cmpl $2,%ebx jb .Lerror # (Radix not in range) movl %esi,%eax # eax = lower part of val ... orl %ebp,%eax # and it stays thus if ebp=0 je Lzero # (Treat zero as special case) leal 92(%esp),%ecx # ecx -> End of temporary buffer testl %ebp,%ebp je Llow # (Higher part of val = 0) Lhigh: #val in ebp:esi. div the high part by the radix, #then div remainder + low part by the radix. movl %ebp,%eax # edx=0,eax=high(from ebp) xorl %edx,%edx decl %ecx divl %ebx movl %eax,%ebp # edx=result of last, eax=low(from esi) movl %esi,%eax divl %ebx movl %eax,%esi # ebp:esi = quotient movb %dl,(%ecx) # store byte in temporary buffer testl %ebp,%ebp jne Lhigh # (Higher part of val still > 0) Llow: #val in 0:eax. div 0 + low part by the radix. xorl %edx,%edx decl %ecx divl %ebx movb %dl,(%ecx) # store byte in temporary buffer testl %eax,%eax jne Llow # (Lower part of val still <> 0) leal 92(%esp),%esi # esi -> End of temporary buffer Lmov: movb (%ecx),%dl # dl = byte from temporary buffer movb $-1,%bl cmpb $10,%dl # add 7 if dl > '9' adcb $0,%bl addb $48,%dl # add '0' andb $7,%bl addb %bl,%dl incl %ecx movb %dl,(%edi) # put dl in dst incl %edi cmpl %ecx,%esi ja Lmov # (more bytes exist in temporary buffer) movb $0,(%edi) # trailing '\0' in dst movl %edi,%eax # eax = return value = pointer to '\0' .Lret: popl %ebx popl %edi popl %esi popl %ebp addl $80,%esp ret .Lerror: xorl %eax,%eax # Wrong radix jmp .Lret Lzero: # Treat 0 as a special case. Unnecessary but we # expect 0 will be frequent. movl 108(%esp),%eax # eax = dst popl %ebx movb $48,(%eax) # '0' popl %edi incl %eax popl %esi popl %ebp addl $80,%esp movb $0,(%eax) # '\0' ret # # 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 # set %esi to 0xcccccccd .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 .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 .L10end: .size longlong10_to_str,.L10end-longlong10_to_str