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