mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
57edc61b06
mysql-test/r/create.result: Update for new error messages mysql-test/r/type_blob.result: Update for new error messages strings/my_strtoll10-x86.s: Faster str->longlong strings/my_strtoll10.c: Updated comments
402 lines
8.6 KiB
ArmAsm
402 lines
8.6 KiB
ArmAsm
# Copyright (C) 2003 MySQL AB
|
|
# This program is free software; you can resistribute 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
|
|
|
|
# Implemention of my_strtoll(): Converting a string to a 64 bit integer.
|
|
# For documentation, check my_strtoll.c
|
|
|
|
.file "my_strtoll10-x86.s"
|
|
.version "01.01"
|
|
.data
|
|
.align 32
|
|
.type lfactor,@object
|
|
.size lfactor,36
|
|
lfactor:
|
|
.long 1
|
|
.long 10
|
|
.long 100
|
|
.long 1000
|
|
.long 10000
|
|
.long 100000
|
|
.long 1000000
|
|
.long 10000000
|
|
.long 100000000
|
|
.text
|
|
.align 4
|
|
|
|
.globl my_strtoll10
|
|
.type my_strtoll10,@function
|
|
|
|
|
|
# Used stack variables
|
|
# ebp-4 dummy for storing endptr if endptr = 0
|
|
# ebp-8 First 9 digits of return values
|
|
# ebp-12 Pointer to first digit of second part
|
|
# ebp-16 Store lowest 2 digits
|
|
# ebp-20 != 0 if value was negative
|
|
# ebp-24 High max value
|
|
# ebp-28 Middle max value
|
|
# ebp-32 Low max value
|
|
# ebp-36 Temp value
|
|
|
|
# esi Pointer to input string
|
|
# ebx End of string
|
|
|
|
my_strtoll10:
|
|
pushl %ebp
|
|
movl %esp,%ebp
|
|
subl $48,%esp
|
|
pushl %esi
|
|
pushl %edi
|
|
pushl %ebx
|
|
movl 8(%ebp),%esi # esi= nptr
|
|
movl 16(%ebp),%ecx # ecx= error (Will be overwritten later)
|
|
movl 12(%ebp),%eax # eax= endptr
|
|
cmpl $0,%eax # if (endptr)
|
|
je .L110
|
|
|
|
# Fixed length string
|
|
movl (%eax),%ebx # bx= end-of-string
|
|
.p2align 4,,7
|
|
.L100:
|
|
cmpl %ebx,%esi
|
|
je .Lno_conv
|
|
movb (%esi), %al # al= next byte
|
|
incl %esi
|
|
cmpb $32,%al # Skip space
|
|
je .L100
|
|
cmpb $9,%al # Skip tab
|
|
je .L100
|
|
jmp .L130
|
|
|
|
# String that ends with \0
|
|
|
|
.L110:
|
|
leal -4(%ebp),%edi
|
|
movl %edi,12(%ebp) # endptr= &dummy, for easier end check
|
|
.p2align 4,,7
|
|
.L120:
|
|
movb (%esi), %al # al= next byte
|
|
incl %esi
|
|
cmpb $32,%al
|
|
je .L120
|
|
cmpb $9,%al
|
|
je .L120
|
|
testb %al,%al # Test if we found end \0
|
|
je .Lno_conv
|
|
leal 65535(%esi),%ebx # ebx = end-of-string
|
|
|
|
.L130:
|
|
cmpb $45,%al # Test if '-'
|
|
jne .Lpositive
|
|
|
|
# negative number
|
|
movl $-1,(%ecx) # error = -1 (mark that number is negative)
|
|
movl $1,-20(%ebp) # negative= 1
|
|
movl $92233720,-24(%ebp)
|
|
movl $368547758,-28(%ebp)
|
|
movl $8,-32(%ebp)
|
|
jmp .L460
|
|
|
|
.p2align 4,,7
|
|
.Lpositive:
|
|
movl $0,(%ecx) # error=0
|
|
movl $0,-20(%ebp) # negative= 0
|
|
movl $184467440,-24(%ebp)
|
|
movl $737095516,-28(%ebp)
|
|
movl $15,-32(%ebp)
|
|
cmpb $43,%al # Check if '+'
|
|
jne .L462
|
|
|
|
.L460:
|
|
cmpl %ebx,%esi # Check if overflow
|
|
je .Lno_conv
|
|
movb (%esi), %al # al= next byte after sign
|
|
incl %esi
|
|
|
|
# Remove pre zero to be able to handle a lot of pre-zero
|
|
.L462:
|
|
cmpb $48,%al
|
|
jne .L475 # Number doesn't start with 0
|
|
decl %esi
|
|
.p2align 4,,7
|
|
|
|
# Skip pre zeros
|
|
.L481:
|
|
incl %esi # Skip processed byte
|
|
cmpl %ebx,%esi
|
|
je .Lms_return_zero
|
|
cmpb (%esi),%al # Test if next byte is also zero
|
|
je .L481
|
|
leal 9(%esi),%ecx # ecx = end-of-current-part
|
|
xorl %edi,%edi # Store first 9 digits in edi
|
|
jmp .L482
|
|
.p2align 4,,7
|
|
|
|
# Check if first char is a valid number
|
|
.L475:
|
|
addb $-48,%al
|
|
cmpb $9,%al
|
|
ja .Lno_conv
|
|
.L477:
|
|
movzbl %al,%edi # edi = first digit
|
|
leal 8(%esi),%ecx # ecx = end-of-current-part
|
|
|
|
# Handle first 8/9 digits and store them in edi
|
|
.L482:
|
|
cmpl %ebx,%ecx
|
|
jbe .L522
|
|
movl %ebx,%ecx # ecx = min(end-of-current-part, end-of-string)
|
|
jmp .L522
|
|
|
|
.p2align 4,,7
|
|
.L488:
|
|
movb (%esi), %al # al= next byte
|
|
incl %esi
|
|
addb $-48,%al
|
|
cmpb $9,%al
|
|
ja .Lend_i_dec_esi
|
|
|
|
# Calculate edi= edi*10 + al
|
|
leal (%edi,%edi,4),%edx
|
|
movzbl %al,%eax
|
|
leal (%eax,%edx,2),%edi
|
|
.L522:
|
|
cmpl %ecx,%esi # If more digits at this level
|
|
jne .L488
|
|
cmpl %ebx,%esi # If end of string
|
|
je .Lend_i
|
|
|
|
movl %edi,-8(%ebp) # Store first 9 digits
|
|
movl %esi,-12(%ebp) # store pos to first digit of second part
|
|
|
|
# Calculate next 9 digits and store them in edi
|
|
|
|
xorl %edi,%edi
|
|
leal 9(%esi),%ecx # ecx= end-of-current-part
|
|
movl %ecx,-36(%ebp) # Store max length
|
|
cmpl %ebx,%ecx
|
|
jbe .L498
|
|
movl %ebx,%ecx # ecx = min(end-of-current-part, end-of-string)
|
|
|
|
.p2align 4,,7
|
|
.L498:
|
|
movb (%esi), %al # al= next byte
|
|
incl %esi
|
|
addb $-48,%al
|
|
cmpb $9,%al
|
|
ja .Lend_i_and_j_decl_esi
|
|
|
|
# Calculate edi= edi*10 + al
|
|
leal (%edi,%edi,4),%edx
|
|
movzbl %al,%eax
|
|
leal (%eax,%edx,2),%edi
|
|
|
|
cmpl %ecx,%esi # If end of current part
|
|
jne .L498
|
|
cmpl %ebx,%esi # If end of string
|
|
jne .L500
|
|
cmpl -36(%ebp),%esi # Test if string is less than 18 digits
|
|
jne .Lend_i_and_j
|
|
jmp .Lend3 # 18 digit string
|
|
|
|
# Handle the possible next to last digit and store in ecx
|
|
.L500:
|
|
movb (%esi),%al
|
|
addb $-48,%al
|
|
cmpb $9,%al
|
|
ja .Lend3
|
|
|
|
incl %esi
|
|
movzbl %al,%ecx
|
|
cmpl %ebx,%esi # If end of string
|
|
je .Lend4
|
|
|
|
movb (%esi),%al # Read last digit
|
|
addb $-48,%al
|
|
cmpb $9,%al
|
|
ja .Lend4
|
|
|
|
# ecx= ecx*10 + al
|
|
leal (%ecx,%ecx,4),%edx
|
|
movzbl %al,%eax
|
|
leal (%eax,%edx,2),%ecx
|
|
|
|
movl 12(%ebp),%eax # eax = endptr
|
|
incl %esi
|
|
movl %esi,(%eax) # *endptr = end-of-string
|
|
cmpl %ebx,%esi
|
|
je .L505 # At end of string
|
|
|
|
movb (%esi),%al # check if extra digits
|
|
addb $-48,%al
|
|
cmpb $9,%al
|
|
jbe .Loverflow
|
|
|
|
# At this point we have:
|
|
# -8(%ebp) First 9 digits
|
|
# edi Next 9 digits
|
|
# ecx Last 2 digits
|
|
# *endpos end-of-string
|
|
|
|
.L505: # Check that we are not going to get overflow for unsigned long long
|
|
movl -8(%ebp),%eax # First 9 digits
|
|
cmpl -24(%ebp),%eax
|
|
ja .Loverflow
|
|
jne .L507
|
|
cmpl -28(%ebp),%edi
|
|
ja .Loverflow
|
|
jne .L507
|
|
cmpl -32(%ebp),%ecx
|
|
ja .Loverflow
|
|
|
|
.L507:
|
|
movl %edi,-4(%ebp) # Save middle bytes
|
|
movl %ecx,%esi # esi = 2 last digits
|
|
movl $1215752192,%ecx # %ecx= lower_32_bits(100000000000)
|
|
mull %ecx
|
|
imull $23,-8(%ebp),%ecx
|
|
movl $0,-36(%ebp)
|
|
movl %eax,%ebx
|
|
imull $1215752192,-36(%ebp),%eax
|
|
movl %edx,%edi
|
|
addl %ecx,%edi
|
|
addl %eax,%edi # Temp in edi:ebx
|
|
|
|
movl $100,%eax # j= j*100
|
|
mull -4(%ebp)
|
|
addl %ebx,%eax # edx:eax+= edi:ebx
|
|
adcl %edi,%edx
|
|
addl %esi,%eax
|
|
adcl $0,%edx
|
|
jmp .Lms_return
|
|
|
|
.Loverflow:
|
|
# When we come here, *endptr is already updated
|
|
|
|
movl 16(%ebp),%edx # edx= error
|
|
movl $34,(%edx) # *error = 34
|
|
movl $-1,%eax
|
|
movl %eax,%edx
|
|
cmpl $0,-20(%ebp) # If negative
|
|
je .Lms_return
|
|
xor %eax,%eax # edx:eax = LONGLONG_LMIN
|
|
movl $-2147483648,%edx
|
|
jmp .Lms_return
|
|
|
|
# Return value that is in %edi as long long
|
|
.p2align 4,,7
|
|
.Lend_i_dec_esi:
|
|
decl %esi # Fix so that it points at last digit
|
|
.Lend_i:
|
|
xorl %edx,%edx
|
|
movl %edi,%eax
|
|
cmpl $0,-20(%ebp)
|
|
je .Lreturn_save_endptr # Positive number
|
|
negl %eax
|
|
cltd # Neg result in edx:eax
|
|
jmp .Lreturn_save_endptr
|
|
|
|
# Return value (%ebp-8) * lfactor[(uint) (edx-start)] + edi
|
|
.p2align 4,,7
|
|
.Lend_i_and_j_decl_esi:
|
|
decl %esi # Fix so that it points at last digit
|
|
.Lend_i_and_j:
|
|
movl %esi,%ecx
|
|
subl -12(%ebp),%ecx # ecx= number of digits in second part
|
|
movl lfactor(,%ecx,4),%eax
|
|
jmp .L523
|
|
|
|
# Return -8(%ebp) * $1000000000 + edi
|
|
.p2align 4,,7
|
|
.Lend3:
|
|
movl $1000000000,%eax
|
|
.L523:
|
|
mull -8(%ebp)
|
|
addl %edi,%eax
|
|
adcl $0,%edx
|
|
cmpl $0,-20(%ebp) # if negative
|
|
je .Lreturn_save_endptr
|
|
negl %eax # Neg edx:%eax
|
|
adcl $0,%edx
|
|
negl %edx
|
|
jmp .Lreturn_save_endptr
|
|
|
|
# Return -8(%ebp) * $10000000000 + edi*10 + ecx
|
|
.p2align 4,,7
|
|
.Lend4:
|
|
movl %ecx,-16(%ebp) # store lowest digits
|
|
movl 12(%ebp),%ebx
|
|
movl %esi,(%ebx) # *endpos = end-of-string
|
|
movl -8(%ebp),%eax # First 9 digits
|
|
movl $1410065408,%ecx # ecx= lower_32_bits(10000000000)
|
|
mull %ecx
|
|
movl $0,-36(%ebp)
|
|
movl %eax,%ebx # Store lowest 32 byte from multiplication
|
|
imull $1410065408,-36(%ebp),%eax
|
|
movl -8(%ebp),%ecx # First 9 digits
|
|
movl %edx,%esi
|
|
addl %ecx,%ecx
|
|
addl %ecx,%esi
|
|
addl %eax,%esi # %esi:%ebx now has -8(%ebp) * $10000000000
|
|
|
|
movl $10,%eax # Calc edi*10
|
|
mull %edi
|
|
addl %ebx,%eax # And add to result
|
|
adcl %esi,%edx
|
|
addl -16(%ebp),%eax # Add lowest digit
|
|
adcl $0,%edx
|
|
cmpl $0,-20(%ebp) # if negative
|
|
je .Lms_return
|
|
|
|
cmpl $-2147483648,%edx # Test if too big signed integer
|
|
ja .Loverflow
|
|
jne .L516
|
|
testl %eax,%eax
|
|
ja .Loverflow
|
|
|
|
.L516:
|
|
negl %eax
|
|
adcl $0,%edx
|
|
negl %edx
|
|
jmp .Lms_return
|
|
|
|
.p2align 4,,7
|
|
.Lno_conv: # Not a legal number
|
|
movl 16(%ebp),%eax
|
|
movl $33,(%eax) # error= edom
|
|
|
|
.Lms_return_zero:
|
|
xorl %eax,%eax # Return zero
|
|
xorl %edx,%edx
|
|
|
|
.p2align 4,,7
|
|
.Lreturn_save_endptr:
|
|
movl 12(%ebp),%ecx # endptr= end-of-string
|
|
movl %esi,(%ecx) # *endptr= end-of-string
|
|
|
|
.Lms_return:
|
|
popl %ebx
|
|
popl %edi
|
|
popl %esi
|
|
movl %ebp,%esp
|
|
popl %ebp
|
|
ret
|
|
|
|
my_strtoll10_end:
|
|
.size my_strtoll10,.my_strtoll10_end-my_strtoll10
|
|
.comm res,240,32
|
|
.comm end_ptr,120,32
|
|
.comm error,120,32
|
|
.ident "Monty"
|