summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@mishka.local>2005-08-08 13:18:18 +0300
committerunknown <monty@mishka.local>2005-08-08 13:18:18 +0300
commit38b4ccf5d338bfd146e78bfdb3c4500fb6eeae69 (patch)
treebaad3e26d98c222f43035b30b43cc76b7db788af
parent4456ae328d5d9b1cf7077ff1eb7707ebf03472dc (diff)
downloadmariadb-git-38b4ccf5d338bfd146e78bfdb3c4500fb6eeae69.tar.gz
Fix for BUG #11642: [Patch]es x86 Assembler and text relocations
Changed assembler functions to not access global variables or variables in text segement Added wrapper function in C to longlong2str() to pass _dig_vec_upper as an argument mysql-test/r/bigint.result: More tests for parsing of bigint's More tests for different values to conv() mysql-test/t/bigint.test: More tests for parsing of bigint's More tests for different values to conv() strings/Makefile.am: Added longlong2str_asm.c strings/longlong2str-x86.s: Changed functions to not access variables in text segment Fixed this by adding global variable '_dig_vec_upper' as an argument to longlong2str_with_dig_vector() strings/my_strtoll10-x86.s: Removd array lfactor by calculating the value in code (this is to to make the code position independent) strings/longlong2str_asm.c: New BitKeeper file ``strings/longlong2str_asm.c''
-rw-r--r--mysql-test/r/bigint.result9
-rw-r--r--mysql-test/t/bigint.test3
-rw-r--r--strings/Makefile.am4
-rw-r--r--strings/longlong2str-x86.s35
-rw-r--r--strings/longlong2str_asm.c33
-rw-r--r--strings/my_strtoll10-x86.s62
6 files changed, 104 insertions, 42 deletions
diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index eb3d0da3f23..e9a457c9dfa 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -17,6 +17,15 @@ select 9223372036854775808+1;
select -(0-3),round(-(0-3)), round(9999999999999999999);
-(0-3) round(-(0-3)) round(9999999999999999999)
3 3 10000000000000000000
+select 1,11,101,1001,10001,100001,1000001,10000001,100000001,1000000001,10000000001,100000000001,1000000000001,10000000000001,100000000000001,1000000000000001,10000000000000001,100000000000000001,1000000000000000001,10000000000000000001;
+1 11 101 1001 10001 100001 1000001 10000001 100000001 1000000001 10000000001 100000000001 1000000000001 10000000000001 100000000000001 1000000000000001 10000000000000001 100000000000000001 1000000000000000001 10000000000000000001
+1 11 101 1001 10001 100001 1000001 10000001 100000001 1000000001 10000000001 100000000001 1000000000001 10000000000001 100000000000001 1000000000000001 10000000000000001 100000000000000001 1000000000000000001 10000000000000000001
+select -1,-11,-101,-1001,-10001,-100001,-1000001,-10000001,-100000001,-1000000001,-10000000001,-100000000001,-1000000000001,-10000000000001,-100000000000001,-1000000000000001,-10000000000000001,-100000000000000001,-1000000000000000001,-10000000000000000001;
+-1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000001
+-1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000000
+select conv(1,10,16),conv((1<<2)-1,10,16),conv((1<<10)-2,10,16),conv((1<<16)-3,10,16),conv((1<<25)-4,10,16),conv((1<<31)-5,10,16),conv((1<<36)-6,10,16),conv((1<<47)-7,10,16),conv((1<<48)-8,10,16),conv((1<<55)-9,10,16),conv((1<<56)-10,10,16),conv((1<<63)-11,10,16);
+conv(1,10,16) conv((1<<2)-1,10,16) conv((1<<10)-2,10,16) conv((1<<16)-3,10,16) conv((1<<25)-4,10,16) conv((1<<31)-5,10,16) conv((1<<36)-6,10,16) conv((1<<47)-7,10,16) conv((1<<48)-8,10,16) conv((1<<55)-9,10,16) conv((1<<56)-10,10,16) conv((1<<63)-11,10,16)
+1 3 3FE FFFD 1FFFFFC 7FFFFFFB FFFFFFFFA 7FFFFFFFFFF9 FFFFFFFFFFF8 7FFFFFFFFFFFF7 FFFFFFFFFFFFF6 7FFFFFFFFFFFFFF5
create table t1 (a bigint unsigned not null, primary key(a));
insert into t1 values (18446744073709551615), (0xFFFFFFFFFFFFFFFE), (18446744073709551613), (18446744073709551612);
select * from t1;
diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test
index 741c7ec360b..8a238d33e08 100644
--- a/mysql-test/t/bigint.test
+++ b/mysql-test/t/bigint.test
@@ -14,6 +14,9 @@ select +9999999999999999999,-9999999999999999999;
select cast(9223372036854775808 as unsigned)+1;
select 9223372036854775808+1;
select -(0-3),round(-(0-3)), round(9999999999999999999);
+select 1,11,101,1001,10001,100001,1000001,10000001,100000001,1000000001,10000000001,100000000001,1000000000001,10000000000001,100000000000001,1000000000000001,10000000000000001,100000000000000001,1000000000000000001,10000000000000000001;
+select -1,-11,-101,-1001,-10001,-100001,-1000001,-10000001,-100000001,-1000000001,-10000000001,-100000000001,-1000000000001,-10000000000001,-100000000000001,-1000000000000001,-10000000000000001,-100000000000000001,-1000000000000000001,-10000000000000000001;
+select conv(1,10,16),conv((1<<2)-1,10,16),conv((1<<10)-2,10,16),conv((1<<16)-3,10,16),conv((1<<25)-4,10,16),conv((1<<31)-5,10,16),conv((1<<36)-6,10,16),conv((1<<47)-7,10,16),conv((1<<48)-8,10,16),conv((1<<55)-9,10,16),conv((1<<56)-10,10,16),conv((1<<63)-11,10,16);
#
# In 3.23 we have to disable the test of column to bigint as
diff --git a/strings/Makefile.am b/strings/Makefile.am
index 3f954f3c6a0..97b35075277 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -23,7 +23,7 @@ pkglib_LIBRARIES = libmystrings.a
# Exact one of ASSEMBLER_X
if ASSEMBLER_x86
ASRCS = strings-x86.s longlong2str-x86.s my_strtoll10-x86.s
-CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c
+CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c longlong2str_asm.c
else
if ASSEMBLER_sparc32
# These file MUST all be on the same line!! Otherwise automake
@@ -46,7 +46,7 @@ EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-win1
ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-utf8.c \
ctype-ucs2.c ctype-uca.c ctype-tis620.c ctype-ujis.c \
xml.c strto.c strings-x86.s \
- longlong2str.c longlong2str-x86.s \
+ longlong2str.c longlong2str-x86.s longlong2str_asm.c \
my_strtoll10.c my_strtoll10-x86.s \
strxmov.c bmove_upp.c strappend.c strcont.c strend.c \
strfill.c strcend.c is_prefix.c strstr.c strinstr.c \
diff --git a/strings/longlong2str-x86.s b/strings/longlong2str-x86.s
index fcc57810224..1840bab3f47 100644
--- a/strings/longlong2str-x86.s
+++ b/strings/longlong2str-x86.s
@@ -16,26 +16,26 @@
# Optimized longlong2str function for Intel 80x86 (gcc/gas syntax)
# Some set sequences are optimized for pentuimpro II
- .file "longlong2str.s"
- .version "1.01"
+ .file "longlong2str-x86.s"
+ .version "1.02"
.text
.align 4
-.globl longlong2str
- .type longlong2str,@function
+.globl longlong2str_with_dig_vector
+ .type longlong2str_with_dig_vector,@function
-longlong2str:
+longlong2str_with_dig_vector:
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
+ movl 104(%esp),%ebp # Higher part of val
movl %ebx,%eax
+ movl 108(%esp),%edi # get dst
testl %eax,%eax
jge .L144
@@ -69,6 +69,8 @@ longlong2str:
.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
@@ -83,7 +85,7 @@ longlong2str:
divl %ebx
decl %ecx
movl %eax,%esi # quotent in ebp:esi
- movb _dig_vec_upper(%edx),%al # al is faster than dl
+ movb (%edx,%edi),%al # al is faster than dl
movb %al,(%ecx) # store value in buff
.align 4
.L155:
@@ -91,20 +93,22 @@ longlong2str:
ja .L153
testl %esi,%esi # rest value
jl .L153
- je .L10_mov # Ready
+ je .L160 # Ready
movl %esi,%eax
- movl $_dig_vec_upper,%ebp
.align 4
.L154: # Do rest with integer precision
cltd
divl %ebx
decl %ecx
- movb (%edx,%ebp),%dl # bh is always zero as ebx=radix < 36
+ 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
@@ -129,7 +133,7 @@ longlong2str:
jmp .L165
.Lfe3:
- .size longlong2str,.Lfe3-longlong2str
+ .size longlong2str_with_dig_vector,.Lfe3-longlong2str_with_dig_vector
#
# This is almost equal to the above, except that we can do the final
@@ -137,9 +141,6 @@ longlong2str:
#
.align 4
-.Ltmp:
- .long 0xcccccccd
- .align 4
.globl longlong10_to_str
.type longlong10_to_str,@function
@@ -202,8 +203,8 @@ longlong10_to_str:
# The following code uses some tricks to change division by 10 to
# multiplication and shifts
- movl .Ltmp,%esi # set %esi to 0xcccccccd
-
+ movl $0xcccccccd,%esi
+
.L10_40:
movl %ebx,%eax
mull %esi
diff --git a/strings/longlong2str_asm.c b/strings/longlong2str_asm.c
new file mode 100644
index 00000000000..e38a8328b91
--- /dev/null
+++ b/strings/longlong2str_asm.c
@@ -0,0 +1,33 @@
+/* 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 */
+
+/*
+ Wrapper for longlong2str.s
+
+ We need this because the assembler code can't access the local variable
+ _dig_vector in a portable manner.
+*/
+
+#include <my_global.h>
+#include "m_string.h"
+
+extern char *longlong2str_with_dig_vector(longlong val,char *dst,int radix,
+ const char *dig_vector);
+
+char *longlong2str(longlong val,char *dst,int radix)
+{
+ return longlong2str_with_dig_vector(val, dst, radix, _dig_vec_upper);
+}
diff --git a/strings/my_strtoll10-x86.s b/strings/my_strtoll10-x86.s
index c04384667a7..1d8b8f2bbce 100644
--- a/strings/my_strtoll10-x86.s
+++ b/strings/my_strtoll10-x86.s
@@ -17,21 +17,8 @@
# 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
+ .version "01.02"
+
.text
.align 4
@@ -209,14 +196,16 @@ my_strtoll10:
jne .L500
cmpl -36(%ebp),%esi # Test if string is less than 18 digits
jne .Lend_i_and_j
- jmp .Lend3 # 18 digit string
+.L499:
+ movl $1000000000,%eax
+ jmp .Lgot_factor # 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
+ ja .L499 # 18 digit string
incl %esi
movzbl %al,%ecx
@@ -315,14 +304,41 @@ my_strtoll10:
.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
+ # Calculate %eax= 10 ** %cl, where %cl <= 8
+ # With an array one could do this with:
+ # movl 10_factor_table(,%ecx,4),%eax
+ # We calculate the table here to avoid problems in
+ # position independent code (gcc -pic)
+
+ cmpb $3,%cl
+ ja .L4_to_8
+ movl $1000, %eax
+ je .Lgot_factor # %cl=3, eax= 1000
+ movl $10, %eax
+ cmpb $1,%cl # %cl is here 0 - 2
+ je .Lgot_factor # %cl=1, eax= 10
+ movl $100, %eax
+ ja .Lgot_factor # %cl=2, eax=100
+ movl $1, %eax
+ jmp .Lgot_factor # %cl=0, eax=1
+
+.L4_to_8: # %cl is here 4-8
+ cmpb $5,%cl
+ movl $100000, %eax
+ je .Lgot_factor # %cl=5, eax=100000
+ movl $10000, %eax
+ jbe .Lgot_factor # %cl=4, eax=10000
+ movl $10000000, %eax
+ cmpb $7,%cl
+ je .Lgot_factor # %cl=7, eax=10000000
+ movl $100000000, %eax
+ ja .Lgot_factor # %cl=8, eax=100000000
+ movl $1000000, %eax # %cl=6, eax=1000000
+
+ # Return -8(%ebp) * %eax + edi
.p2align 4,,7
-.Lend3:
- movl $1000000000,%eax
-.L523:
+.Lgot_factor:
mull -8(%ebp)
addl %edi,%eax
adcl $0,%edx