~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
# Copyright (C) 2003 MySQL AB
2
#
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.
6
#
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.
11
#
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
15
16
# Implemention of my_strtoll():  Converting a string to a 64 bit integer.
17
# For documentation, check my_strtoll.c
18
	
19
	.file	"my_strtoll10-x86.s"
20
	.version "01.02"
21
	
22
.text
23
	.align 4
24
	
25
.globl my_strtoll10
26
	.type	 my_strtoll10,@function
27
28
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
38
	# ebp-36	Temp value
39
40
	# esi		Pointer to input string
41
	# ebx		End of string
42
	
43
my_strtoll10:
44
	pushl %ebp
45
	movl %esp,%ebp
46
	subl $48,%esp
47
	pushl %esi
48
	pushl %edi
49
	pushl %ebx
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)
54
	je .L110
55
56
# Fixed length string
57
	movl (%eax),%ebx	# bx= end-of-string
58
	.p2align 4,,7
59
.L100:
60
	cmpl %ebx,%esi
61
	je .Lno_conv
62
	movb (%esi), %al	# al= next byte
63
	incl %esi
64
	cmpb $32,%al		# Skip space
65
	je .L100
66
	cmpb $9,%al		# Skip tab
67
	je .L100
68
	jmp .L130
69
70
# String that ends with \0
71
72
.L110:
73
	leal -4(%ebp),%edi
74
	movl %edi,12(%ebp)	# endptr= &dummy, for easier end check
75
	.p2align 4,,7
76
.L120:
77
	movb (%esi), %al	# al= next byte
78
	incl %esi
79
	cmpb $32,%al
80
	je .L120
81
	cmpb $9,%al
82
	je .L120
83
	testb %al,%al		# Test if we found end \0
84
	je .Lno_conv
85
	leal 65535(%esi),%ebx	# ebx = end-of-string
86
87
.L130:
88
	cmpb $45,%al		# Test if '-'
89
	jne .Lpositive
90
91
	# negative number
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)
96
	movl $8,-32(%ebp)
97
	jmp .L460
98
99
	.p2align 4,,7
100
.Lpositive:
101
	movl $0,(%ecx)		# error=0
102
	movl $0,-20(%ebp)	# negative= 0
103
	movl $184467440,-24(%ebp)
104
	movl $737095516,-28(%ebp)
105
	movl $15,-32(%ebp)
106
	cmpb $43,%al		# Check if '+'
107
	jne .L462
108
109
.L460:
110
	cmpl %ebx,%esi		# Check if overflow
111
	je .Lno_conv
112
	movb (%esi), %al	# al= next byte after sign
113
	incl %esi
114
		
115
	# Remove pre zero to be able to handle a lot of pre-zero
116
.L462:
117
	cmpb $48,%al
118
	jne .L475		# Number doesn't start with 0
119
	decl %esi
120
	.p2align 4,,7
121
122
	# Skip pre zeros
123
.L481:	
124
	incl %esi		# Skip processed byte
125
	cmpl %ebx,%esi
126
	je .Lms_return_zero
127
	cmpb (%esi),%al		# Test if next byte is also zero
128
	je .L481
129
	leal 9(%esi),%ecx	# ecx = end-of-current-part
130
	xorl %edi,%edi		# Store first 9 digits in edi
131
	jmp .L482
132
	.p2align 4,,7
133
134
	# Check if first char is a valid number
135
.L475:
136
	addb $-48,%al
137
	cmpb $9,%al
138
	ja .Lno_conv
139
.L477:	
140
	movzbl %al,%edi		# edi = first digit
141
	leal 8(%esi),%ecx	# ecx = end-of-current-part
142
143
	# Handle first 8/9 digits and store them in edi
144
.L482:
145
	cmpl %ebx,%ecx
146
	jbe .L522
147
	movl %ebx,%ecx		# ecx = min(end-of-current-part, end-of-string)
148
	jmp .L522
149
150
	.p2align 4,,7
151
.L488:
152
	movb (%esi), %al	# al= next byte
153
	incl %esi
154
	addb $-48,%al
155
	cmpb $9,%al
156
	ja .Lend_i_dec_esi
157
158
	# Calculate edi= edi*10 + al
159
	leal (%edi,%edi,4),%edx
160
	movzbl %al,%eax
161
	leal (%eax,%edx,2),%edi
162
.L522:
163
	cmpl %ecx,%esi		# If more digits at this level
164
	jne .L488
165
	cmpl %ebx,%esi		# If end of string
166
	je .Lend_i
167
168
	movl %edi,-8(%ebp)	# Store first 9 digits
169
	movl %esi,-12(%ebp)	# store pos to first digit of second part
170
171
	# Calculate next 9 digits and store them in edi
172
173
	xorl %edi,%edi
174
	leal 9(%esi),%ecx	# ecx= end-of-current-part
175
	movl %ecx,-36(%ebp)	# Store max length
176
	cmpl %ebx,%ecx
177
	jbe .L498
178
	movl %ebx,%ecx		# ecx = min(end-of-current-part, end-of-string)
179
180
	.p2align 4,,7
181
.L498:
182
	movb (%esi), %al	# al= next byte
183
	incl %esi
184
	addb $-48,%al
185
	cmpb $9,%al
186
	ja .Lend_i_and_j_decl_esi
187
188
	# Calculate edi= edi*10 + al
189
	leal (%edi,%edi,4),%edx
190
	movzbl %al,%eax
191
	leal (%eax,%edx,2),%edi
192
193
	cmpl %ecx,%esi		# If end of current part
194
	jne .L498
195
	cmpl %ebx,%esi		# If end of string
196
	jne .L500
197
	cmpl -36(%ebp),%esi	# Test if string is less than 18 digits
198
	jne .Lend_i_and_j
199
.L499:	
200
	movl $1000000000,%eax	
201
	jmp .Lgot_factor	# 18 digit string
202
203
	# Handle the possible next to last digit and store in ecx
204
.L500:
205
	movb (%esi),%al
206
	addb $-48,%al
207
	cmpb $9,%al
208
	ja .L499		# 18 digit string
209
210
	incl %esi
211
	movzbl %al,%ecx
212
	cmpl %ebx,%esi		# If end of string
213
	je .Lend4
214
215
	movb (%esi),%al		# Read last digit
216
	addb $-48,%al
217
	cmpb $9,%al
218
	ja .Lend4
219
220
	# ecx= ecx*10 + al
221
	leal (%ecx,%ecx,4),%edx
222
	movzbl %al,%eax
223
	leal (%eax,%edx,2),%ecx
224
225
	movl 12(%ebp),%eax	# eax = endptr
226
	incl %esi
227
	movl %esi,(%eax)	# *endptr = end-of-string
228
	cmpl %ebx,%esi
229
	je .L505		# At end of string
230
231
	movb (%esi),%al		# check if extra digits
232
	addb $-48,%al
233
	cmpb $9,%al
234
	jbe .Loverflow
235
236
	# At this point we have:
237
	# -8(%ebp)	First 9 digits
238
	# edi		Next 9 digits
239
	# ecx		Last 2 digits
240
	# *endpos	end-of-string
241
	
242
.L505:	# Check that we are not going to get overflow for unsigned long long
243
	movl -8(%ebp),%eax	# First 9 digits
244
	cmpl -24(%ebp),%eax
245
	ja .Loverflow
246
	jne .L507
247
	cmpl -28(%ebp),%edi
248
	ja .Loverflow
249
	jne .L507
250
	cmpl -32(%ebp),%ecx
251
	ja .Loverflow
252
253
.L507:
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)
257
	mull %ecx
258
	imull $23,-8(%ebp),%ecx
259
	movl $0,-36(%ebp)
260
	movl %eax,%ebx
261
	imull $1215752192,-36(%ebp),%eax
262
	movl %edx,%edi
263
	addl %ecx,%edi
264
	addl %eax,%edi		# Temp in edi:ebx
265
266
	movl $100,%eax		# j= j*100
267
	mull -4(%ebp)
268
	addl %ebx,%eax		# edx:eax+= edi:ebx
269
	adcl %edi,%edx
270
	addl %esi,%eax
271
	adcl $0,%edx
272
	jmp .Lms_return
273
274
.Loverflow:
275
	# When we come here, *endptr is already updated
276
277
	movl 16(%ebp),%edx	# edx= error
278
	movl $34,(%edx)		# *error = 34
279
	movl $-1,%eax
280
	movl %eax,%edx
281
	cmpl $0,-20(%ebp)	# If negative
282
	je .Lms_return
283
	xor %eax,%eax		# edx:eax = LONGLONG_LMIN
284
	movl $-2147483648,%edx
285
	jmp .Lms_return
286
287
	# Return value that is in %edi as long long
288
	.p2align 4,,7
289
.Lend_i_dec_esi:
290
	decl %esi		# Fix so that it points at last digit
291
.Lend_i:
292
	xorl %edx,%edx
293
	movl %edi,%eax
294
	cmpl $0,-20(%ebp)
295
	je .Lreturn_save_endptr	# Positive number
296
	negl %eax
297
	cltd			# Neg result in edx:eax
298
	jmp .Lreturn_save_endptr
299
300
	# Return value (%ebp-8) * lfactor[(uint) (edx-start)] + edi
301
	.p2align 4,,7
302
.Lend_i_and_j_decl_esi:
303
	decl %esi		# Fix so that it points at last digit
304
.Lend_i_and_j:
305
	movl %esi,%ecx
306
	subl -12(%ebp),%ecx	# ecx= number of digits in second part
307
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)
313
314
	cmpb  $3,%cl
315
	ja    .L4_to_8
316
	movl  $1000, %eax
317
	je    .Lgot_factor	# %cl=3, eax= 1000
318
	movl  $10, %eax
319
	cmpb  $1,%cl		# %cl is here 0 - 2
320
	je    .Lgot_factor	# %cl=1, eax= 10
321
	movl  $100, %eax	
322
	ja    .Lgot_factor	# %cl=2, eax=100
323
	movl  $1, %eax		
324
	jmp   .Lgot_factor	# %cl=0, eax=1
325
326
.L4_to_8:			# %cl is here 4-8
327
	cmpb  $5,%cl
328
	movl  $100000, %eax
329
	je   .Lgot_factor	# %cl=5, eax=100000
330
	movl  $10000, %eax
331
	jbe  .Lgot_factor	# %cl=4, eax=10000
332
	movl  $10000000, %eax
333
	cmpb  $7,%cl
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
338
339
	# Return -8(%ebp) * %eax + edi
340
	.p2align 4,,7
341
.Lgot_factor:
342
	mull -8(%ebp)
343
	addl %edi,%eax
344
	adcl $0,%edx
345
	cmpl $0,-20(%ebp)	# if negative
346
	je .Lreturn_save_endptr
347
	negl %eax		# Neg edx:%eax
348
	adcl $0,%edx
349
	negl %edx
350
	jmp .Lreturn_save_endptr
351
352
	# Return -8(%ebp) * $10000000000 + edi*10 + ecx
353
	.p2align 4,,7
354
.Lend4:
355
	movl %ecx,-16(%ebp)	# store lowest digits
356
	movl 12(%ebp),%ebx
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)
360
	mull %ecx
361
	movl $0,-36(%ebp)
362
	movl %eax,%ebx		# Store lowest 32 byte from multiplication
363
	imull $1410065408,-36(%ebp),%eax
364
	movl -8(%ebp),%ecx	# First 9 digits
365
	movl %edx,%esi
366
	addl %ecx,%ecx
367
	addl %ecx,%esi
368
	addl %eax,%esi		# %esi:%ebx now has -8(%ebp) * $10000000000
369
370
	movl $10,%eax		# Calc edi*10
371
	mull %edi
372
	addl %ebx,%eax		# And add to result
373
	adcl %esi,%edx
374
	addl -16(%ebp),%eax	# Add lowest digit
375
	adcl $0,%edx
376
	cmpl $0,-20(%ebp)	# if negative
377
	je .Lms_return
378
379
	cmpl $-2147483648,%edx	# Test if too big signed integer
380
	ja .Loverflow
381
	jne .L516
382
	testl %eax,%eax
383
	ja .Loverflow
384
385
.L516:	
386
	negl %eax
387
	adcl $0,%edx
388
	negl %edx
389
	jmp .Lms_return
390
391
	.p2align 4,,7
392
.Lno_conv:			# Not a legal number
393
	movl 16(%ebp),%eax
394
	movl $33,(%eax)		# error= edom
395
396
.Lms_return_zero:
397
	xorl %eax,%eax		# Return zero
398
	xorl %edx,%edx
399
400
	.p2align 4,,7
401
.Lreturn_save_endptr:
402
	movl 12(%ebp),%ecx	# endptr= end-of-string
403
	movl %esi,(%ecx)	# *endptr= end-of-string
404
405
.Lms_return:
406
	popl %ebx
407
	popl %edi
408
	popl %esi
409
	movl %ebp,%esp
410
	popl %ebp
411
	ret
412
413
.my_strtoll10_end:
414
	.size	my_strtoll10,.my_strtoll10_end-my_strtoll10
415
        .comm   res,240,32
416
        .comm   end_ptr,120,32
417
        .comm   error,120,32
418
	.ident	"Monty"