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 */
19 extern char *mystrncpy(char *dest, const char *src, size_t n);
20 asm(
21 ".text\n"
22 "\n"
23 VG_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 */
62 extern int __ltostr(char *s, unsigned int size, unsigned long i,
63 unsigned int base, int UpCase);
64 asm(
65 ".text\n"
66 VG_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
116 const char *it = "<UNSET>"; /* Routine name for message routines. */
117 size_t errors = 0;
118
119 /* Complain if condition is not true. */
120 static void
check(int thing,int number)121 check (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. */
131 static void
equal(const char * a,const char * b,int number)132 equal (const char *a, const char *b, int number)
133 {
134 check(a != NULL && b != NULL && STREQ (a, b), number);
135 }
136
137 char one[50];
138 char two[50];
139 char *cp;
140
141 static void
test_strncpy(void)142 test_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
main(void)184 int 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