bug126147-x86.c revision e739ac0589b4fb43561f801c4faba8c1b89f8680
1#include "tests/asm.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <assert.h>
6
7/* These fns taken from dietlibc-0.30 (is GPL v2'd) */
8
9/*
10  Copyright (C) 2002 Thomas M. Ogrisegg
11
12  This is free software. You can redistribute and
13  modify it under the terms of the GNU General Public
14  Public License.
15
16  strncpy.S
17    i386 assembler implementation of strncpy(3)
18*/
19extern char *mystrncpy(char *dest, const char *src, size_t n);
20asm(
21".text\n"
22"\n"
23VG_SYM(mystrncpy) ":\n"
24"	pushl %esi\n"
25"	pushl %edi\n"
26"	movl %esp, %ecx\n"
27"	movl  0x0c(%ecx), %edi\n"
28"	movl  0x10(%ecx), %esi\n"
29"	movl  0x14(%ecx), %ecx\n"
30"\n"
31"	movl %edi, %edx\n"
32"	cld\n"
33"0:\n"
34"	dec %ecx\n"
35"	js 1f\n"
36"	lodsb\n"
37"	stosb\n"
38"	or %al, %al\n"
39"	jnz 0b\n"
40"	repnz stosb\n"
41"1:\n"
42"	movl %edx, %eax\n"
43"	popl %edi\n"
44"	popl %esi\n"
45"	ret\n"
46"\n"
47);
48
49
50/*
51   Copyright (C) 2002 Thomas M. Ogrisegg
52
53   __ltostr.S -- convert an integer into a string
54
55 %eax = dividend
56 %ebx = divisor
57 %ecx = size of output-buffer
58 %edi = output-buffer
59 %ebp = if uppercase is set, then %ebp is 'A'-10 else %ebp is 'a'-10
60
61*/
62extern int __ltostr(char *s, unsigned int size, unsigned long i,
63                             unsigned int base, int UpCase);
64asm(
65".text\n"
66VG_SYM(__ltostr) ":\n"
67"        pushl %esi\n"
68"        pushl %edi              # destination\n"
69"        pushl %ebp\n"
70"        pushl %ebx\n"
71"        movl %esp, %eax\n"
72"        movl 0x14(%eax), %edi\n"
73"        movl 0x18(%eax), %ecx   # size\n"
74"        movl 0x20(%eax), %ebx   # divisor\n"
75"        movl 0x1c(%eax), %eax   # dividend\n"
76"        decl %ecx\n"
77"        movl %ecx, %esi\n"
78"        movl $55, %ebp          # 55 == char(A)-10\n"
79"        xorl %edx, %edx         # must be 0 -- used by idiv\n"
80"        cmpl $0x0, 36(%esp)     # check for uppercase\n"
81"        jnz 0f\n"
82"        addl $0x20, %ebp        # set lowercase\n"
83"0:\n"
84"        idiv %ebx, %eax\n"
85"        cmpb $0x9, %dl\n"
86"        jg 1f\n"
87"        addb $48, %dl           # 48 == '0'\n"
88"        jmp 2f\n"
89"1:\n"
90"        addl %ebp, %edx\n"
91"2:\n"
92"        movb %dl, (%edi, %ecx)\n"
93"        xorl %edx, %edx\n"
94"        decl %ecx\n"
95"        jz 3f\n"
96"        orl %eax, %eax\n"
97"        jnz 0b\n"
98"3:\n"
99"        cld\n"
100"        movl %esi, %ebx\n"
101"        leal 1(%edi, %ecx), %esi\n"
102"        subl %ebx, %ecx\n"
103"        negl %ecx\n"
104"        movl %ecx, %eax\n"
105"        repnz movsb\n"
106"        movb $0x0, (%edi)\n"
107"        popl %ebx\n"
108"        popl %ebp\n"
109"        popl %edi\n"
110"        popl %esi\n"
111"        ret\n"
112);
113
114#define STREQ(a, b)     (strcmp((a), (b)) == 0)
115
116const char *it = "<UNSET>";     /* Routine name for message routines. */
117size_t errors = 0;
118
119/* Complain if condition is not true.  */
120static void
121check (int thing, int number)
122{
123  if (!thing)
124    {
125      printf("%s flunked test %d\n", it, number);
126      ++errors;
127    }
128}
129
130/* Complain if first two args don't strcmp as equal.  */
131static void
132equal (const char *a, const char *b, int number)
133{
134  check(a != NULL && b != NULL && STREQ (a, b), number);
135}
136
137char one[50];
138char two[50];
139char *cp;
140
141static void
142test_strncpy (void)
143{
144  /* Testing is a bit different because of odd semantics.  */
145  it = "strncpy";
146  check (mystrncpy (one, "abc", 4) == one, 1);    /* Returned value. */
147  equal (one, "abc", 2);                        /* Did the copy go right? */
148
149  (void) strcpy (one, "abcdefgh");
150  (void) mystrncpy (one, "xyz", 2);
151  equal (one, "xycdefgh", 3);                   /* Copy cut by count. */
152
153  (void) strcpy (one, "abcdefgh");
154  (void) mystrncpy (one, "xyz", 3);               /* Copy cut just before NUL. */
155  equal (one, "xyzdefgh", 4);
156
157  (void) strcpy (one, "abcdefgh");
158  (void) mystrncpy (one, "xyz", 4);               /* Copy just includes NUL. */
159  equal (one, "xyz", 5);
160  equal (one+4, "efgh", 6);                     /* Wrote too much? */
161
162  (void) strcpy (one, "abcdefgh");
163  (void) mystrncpy (one, "xyz", 5);               /* Copy includes padding. */
164  equal (one, "xyz", 7);
165  equal (one+4, "", 8);
166  equal (one+5, "fgh", 9);
167
168  (void) strcpy (one, "abc");
169  (void) mystrncpy (one, "xyz", 0);               /* Zero-length copy. */
170  equal (one, "abc", 10);
171
172  (void) mystrncpy (one, "", 2);          /* Zero-length source. */
173  equal (one, "", 11);
174  equal (one+1, "", 12);
175  equal (one+2, "c", 13);
176
177  (void) strcpy (one, "hi there");
178  (void) mystrncpy (two, one, 9);
179  equal (two, "hi there", 14);          /* Just paranoia. */
180  equal (one, "hi there", 15);          /* Stomped on source? */
181}
182
183
184int main ( void )
185{
186  char buf[1024];
187
188  /* test strncpy, hence repnz stosb */
189  test_strncpy();
190    if (errors == 0)
191    {
192      printf("No errors.\n");
193    }
194  else
195    {
196      printf("%d errors.\n", (int)errors);
197    }
198
199    /* test __ltostr, hence repnz stosb */
200  assert(__ltostr(buf,10,1723,10,0)==4); assert(!strcmp(buf,"1723"));
201  assert(__ltostr(buf,3,1723,10,0)==2); assert(!strcmp(buf,"23"));
202  assert(__ltostr(buf,2,0x1234,16,0)==1); assert(!strcmp(buf,"4"));
203  assert(__ltostr(buf,3,0xFEFE,16,1)==2); assert(!strcmp(buf,"FE"));
204
205 return 0;
206}
207