1
# Copyright (C) 2003 MySQL AB
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; version 2 of the License.
7
# This program is distributed in the hope that it will be useful,
8
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
# GNU General Public License for more details.
12
# You should have received a copy of the GNU General Public License
13
# along with this program; if not, write to the Free Software
14
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
# Implemention of my_strtoll(): Converting a string to a 64 bit integer.
17
# For documentation, check my_strtoll.c
19
.file "my_strtoll10-x86.s"
26
.type my_strtoll10,@function
29
# Used stack variables
30
# ebp-4 dummy for storing endptr if endptr = 0
31
# ebp-8 First 9 digits of return values
32
# ebp-12 Pointer to first digit of second part
33
# ebp-16 Store lowest 2 digits
34
# ebp-20 != 0 if value was negative
35
# ebp-24 High max value
36
# ebp-28 Middle max value
37
# ebp-32 Low max value
40
# esi Pointer to input string
50
movl 8(%ebp),%esi # esi= nptr
51
movl 16(%ebp),%ecx # ecx= error (Will be overwritten later)
52
movl 12(%ebp),%eax # eax= endptr
53
cmpl $0,%eax # if (endptr)
57
movl (%eax),%ebx # bx= end-of-string
62
movb (%esi), %al # al= next byte
64
cmpb $32,%al # Skip space
66
cmpb $9,%al # Skip tab
70
# String that ends with \0
74
movl %edi,12(%ebp) # endptr= &dummy, for easier end check
77
movb (%esi), %al # al= next byte
83
testb %al,%al # Test if we found end \0
85
leal 65535(%esi),%ebx # ebx = end-of-string
88
cmpb $45,%al # Test if '-'
92
movl $-1,(%ecx) # error = -1 (mark that number is negative)
93
movl $1,-20(%ebp) # negative= 1
94
movl $92233720,-24(%ebp)
95
movl $368547758,-28(%ebp)
101
movl $0,(%ecx) # error=0
102
movl $0,-20(%ebp) # negative= 0
103
movl $184467440,-24(%ebp)
104
movl $737095516,-28(%ebp)
106
cmpb $43,%al # Check if '+'
110
cmpl %ebx,%esi # Check if overflow
112
movb (%esi), %al # al= next byte after sign
115
# Remove pre zero to be able to handle a lot of pre-zero
118
jne .L475 # Number doesn't start with 0
124
incl %esi # Skip processed byte
127
cmpb (%esi),%al # Test if next byte is also zero
129
leal 9(%esi),%ecx # ecx = end-of-current-part
130
xorl %edi,%edi # Store first 9 digits in edi
134
# Check if first char is a valid number
140
movzbl %al,%edi # edi = first digit
141
leal 8(%esi),%ecx # ecx = end-of-current-part
143
# Handle first 8/9 digits and store them in edi
147
movl %ebx,%ecx # ecx = min(end-of-current-part, end-of-string)
152
movb (%esi), %al # al= next byte
158
# Calculate edi= edi*10 + al
159
leal (%edi,%edi,4),%edx
161
leal (%eax,%edx,2),%edi
163
cmpl %ecx,%esi # If more digits at this level
165
cmpl %ebx,%esi # If end of string
168
movl %edi,-8(%ebp) # Store first 9 digits
169
movl %esi,-12(%ebp) # store pos to first digit of second part
171
# Calculate next 9 digits and store them in edi
174
leal 9(%esi),%ecx # ecx= end-of-current-part
175
movl %ecx,-36(%ebp) # Store max length
178
movl %ebx,%ecx # ecx = min(end-of-current-part, end-of-string)
182
movb (%esi), %al # al= next byte
186
ja .Lend_i_and_j_decl_esi
188
# Calculate edi= edi*10 + al
189
leal (%edi,%edi,4),%edx
191
leal (%eax,%edx,2),%edi
193
cmpl %ecx,%esi # If end of current part
195
cmpl %ebx,%esi # If end of string
197
cmpl -36(%ebp),%esi # Test if string is less than 18 digits
200
movl $1000000000,%eax
201
jmp .Lgot_factor # 18 digit string
203
# Handle the possible next to last digit and store in ecx
208
ja .L499 # 18 digit string
212
cmpl %ebx,%esi # If end of string
215
movb (%esi),%al # Read last digit
221
leal (%ecx,%ecx,4),%edx
223
leal (%eax,%edx,2),%ecx
225
movl 12(%ebp),%eax # eax = endptr
227
movl %esi,(%eax) # *endptr = end-of-string
229
je .L505 # At end of string
231
movb (%esi),%al # check if extra digits
236
# At this point we have:
237
# -8(%ebp) First 9 digits
240
# *endpos end-of-string
242
.L505: # Check that we are not going to get overflow for unsigned long long
243
movl -8(%ebp),%eax # First 9 digits
254
movl %edi,-4(%ebp) # Save middle bytes
255
movl %ecx,%esi # esi = 2 last digits
256
movl $1215752192,%ecx # %ecx= lower_32_bits(100000000000)
258
imull $23,-8(%ebp),%ecx
261
imull $1215752192,-36(%ebp),%eax
264
addl %eax,%edi # Temp in edi:ebx
266
movl $100,%eax # j= j*100
268
addl %ebx,%eax # edx:eax+= edi:ebx
275
# When we come here, *endptr is already updated
277
movl 16(%ebp),%edx # edx= error
278
movl $34,(%edx) # *error = 34
281
cmpl $0,-20(%ebp) # If negative
283
xor %eax,%eax # edx:eax = LONGLONG_LMIN
284
movl $-2147483648,%edx
287
# Return value that is in %edi as long long
290
decl %esi # Fix so that it points at last digit
295
je .Lreturn_save_endptr # Positive number
297
cltd # Neg result in edx:eax
298
jmp .Lreturn_save_endptr
300
# Return value (%ebp-8) * lfactor[(uint) (edx-start)] + edi
302
.Lend_i_and_j_decl_esi:
303
decl %esi # Fix so that it points at last digit
306
subl -12(%ebp),%ecx # ecx= number of digits in second part
308
# Calculate %eax= 10 ** %cl, where %cl <= 8
309
# With an array one could do this with:
310
# movl 10_factor_table(,%ecx,4),%eax
311
# We calculate the table here to avoid problems in
312
# position independent code (gcc -pic)
317
je .Lgot_factor # %cl=3, eax= 1000
319
cmpb $1,%cl # %cl is here 0 - 2
320
je .Lgot_factor # %cl=1, eax= 10
322
ja .Lgot_factor # %cl=2, eax=100
324
jmp .Lgot_factor # %cl=0, eax=1
326
.L4_to_8: # %cl is here 4-8
329
je .Lgot_factor # %cl=5, eax=100000
331
jbe .Lgot_factor # %cl=4, eax=10000
334
je .Lgot_factor # %cl=7, eax=10000000
335
movl $100000000, %eax
336
ja .Lgot_factor # %cl=8, eax=100000000
337
movl $1000000, %eax # %cl=6, eax=1000000
339
# Return -8(%ebp) * %eax + edi
345
cmpl $0,-20(%ebp) # if negative
346
je .Lreturn_save_endptr
347
negl %eax # Neg edx:%eax
350
jmp .Lreturn_save_endptr
352
# Return -8(%ebp) * $10000000000 + edi*10 + ecx
355
movl %ecx,-16(%ebp) # store lowest digits
357
movl %esi,(%ebx) # *endpos = end-of-string
358
movl -8(%ebp),%eax # First 9 digits
359
movl $1410065408,%ecx # ecx= lower_32_bits(10000000000)
362
movl %eax,%ebx # Store lowest 32 byte from multiplication
363
imull $1410065408,-36(%ebp),%eax
364
movl -8(%ebp),%ecx # First 9 digits
368
addl %eax,%esi # %esi:%ebx now has -8(%ebp) * $10000000000
370
movl $10,%eax # Calc edi*10
372
addl %ebx,%eax # And add to result
374
addl -16(%ebp),%eax # Add lowest digit
376
cmpl $0,-20(%ebp) # if negative
379
cmpl $-2147483648,%edx # Test if too big signed integer
392
.Lno_conv: # Not a legal number
394
movl $33,(%eax) # error= edom
397
xorl %eax,%eax # Return zero
401
.Lreturn_save_endptr:
402
movl 12(%ebp),%ecx # endptr= end-of-string
403
movl %esi,(%ecx) # *endptr= end-of-string
414
.size my_strtoll10,.my_strtoll10_end-my_strtoll10