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