mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-27 11:43:34 +08:00
New files, optimized for m68k.
This commit is contained in:
parent
2e92188db9
commit
c2df6ff9c7
228
sysdeps/m68k/memchr.S
Normal file
228
sysdeps/m68k/memchr.S
Normal file
@ -0,0 +1,228 @@
|
||||
/* memchr (str, ch, n) -- Return pointer to first occurrence of CH in the
|
||||
first N bytes of STR.
|
||||
For Motorola 68000.
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Andreas Schwab <schwab@gnu.org>.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include "asm-syntax.h"
|
||||
|
||||
TEXT
|
||||
ENTRY(memchr)
|
||||
/* Save the callee-saved registers we use. */
|
||||
moveml R(d2)-R(d4),MEM_PREDEC(sp)
|
||||
|
||||
/* Get string pointer, character and length. */
|
||||
movel MEM_DISP(sp,16),R(a0)
|
||||
moveb MEM_DISP(sp,23),R(d0)
|
||||
movel MEM_DISP(sp,24),R(d4)
|
||||
|
||||
/* Check if at least four bytes left to search. */
|
||||
moveql #4,R(d1)
|
||||
cmpl R(d1),R(d4)
|
||||
bcs L(L6)
|
||||
|
||||
/* Distribute the character to all bytes of a longword. */
|
||||
movel R(d0),R(d1)
|
||||
lsll #8,R(d1)
|
||||
moveb R(d0),R(d1)
|
||||
movel R(d1),R(d0)
|
||||
swap R(d0)
|
||||
movew R(d1),R(d0)
|
||||
|
||||
/* First search for the character one byte at a time until the
|
||||
pointer is aligned to a longword boundary. */
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
subql #1,R(d4)
|
||||
beq L(L7)
|
||||
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
subql #1,R(d4)
|
||||
beq L(L7)
|
||||
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
subql #1,R(d4)
|
||||
beq L(L7)
|
||||
|
||||
L(L1:)
|
||||
/* Load the magic bits. Unlike the generic implementation we can
|
||||
use the carry bit as the fourth hole. */
|
||||
movel #0xfefefeff,R(d3)
|
||||
|
||||
/* We exit the loop if adding MAGIC_BITS to LONGWORD fails to
|
||||
change any of the hole bits of LONGWORD.
|
||||
|
||||
1) Is this safe? Will it catch all the zero bytes?
|
||||
Suppose there is a byte with all zeros. Any carry bits
|
||||
propagating from its left will fall into the hole at its
|
||||
least significant bit and stop. Since there will be no
|
||||
carry from its most significant bit, the LSB of the
|
||||
byte to the left will be unchanged, and the zero will be
|
||||
detected.
|
||||
|
||||
2) Is this worthwhile? Will it ignore everything except
|
||||
zero bytes? Suppose every byte of LONGWORD has a bit set
|
||||
somewhere. There will be a carry into bit 8. If bit 8
|
||||
is set, this will carry into bit 16. If bit 8 is clear,
|
||||
one of bits 9-15 must be set, so there will be a carry
|
||||
into bit 16. Similarly, there will be a carry into bit
|
||||
24. If one of bits 24-31 is set, there will be a carry
|
||||
into bit 32 (=carry flag), so all of the hole bits will
|
||||
be changed.
|
||||
|
||||
3) But wait! Aren't we looking for C, not zero?
|
||||
Good point. So what we do is XOR LONGWORD with a longword,
|
||||
each of whose bytes is C. This turns each byte that is C
|
||||
into a zero. */
|
||||
|
||||
/* Still at least 4 bytes to search? */
|
||||
subql #4,R(d4)
|
||||
bcs L(L6)
|
||||
|
||||
L(L2:)
|
||||
/* Get the longword in question. */
|
||||
movel MEM_POSTINC(a0),R(d1)
|
||||
/* XOR with the byte we search for. */
|
||||
eorl R(d0),R(d1)
|
||||
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not C. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits. */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word equals
|
||||
C. */
|
||||
bne L(L8)
|
||||
|
||||
/* Still at least 4 bytes to search? */
|
||||
subql #4,R(d4)
|
||||
bcs L(L6)
|
||||
|
||||
/* Get the longword in question. */
|
||||
movel MEM_POSTINC(a0),R(d1)
|
||||
/* XOR with the byte we search for. */
|
||||
eorl R(d0),R(d1)
|
||||
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not C. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word equals
|
||||
C. */
|
||||
bne L(L8)
|
||||
|
||||
/* Still at least 4 bytes to search? */
|
||||
subql #4,R(d4)
|
||||
bcc L(L2)
|
||||
|
||||
L(L6:)
|
||||
/* Search one byte at a time in the remaining less than 4 bytes. */
|
||||
andw #3,R(d4)
|
||||
beq L(L7)
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
subqw #1,R(d4)
|
||||
beq L(L7)
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
subqw #1,R(d4)
|
||||
beq L(L7)
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
|
||||
L(L7:)
|
||||
/* Return NULL. */
|
||||
clrl R(d0)
|
||||
movel R(d0),R(a0)
|
||||
moveml MEM_POSTINC(sp),R(d2)-R(d4)
|
||||
rts
|
||||
|
||||
L(L8:)
|
||||
/* We have a hit. Check to see which byte it was. First
|
||||
compensate for the autoincrement in the loop. */
|
||||
subql #4,R(a0)
|
||||
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
/* Otherwise the fourth byte must equal C. */
|
||||
L(L9:)
|
||||
movel R(a0),R(d0)
|
||||
moveml MEM_POSTINC(sp),R(d2)-R(d4)
|
||||
rts
|
||||
END(strchr)
|
||||
|
||||
weak_alias (strchr, index)
|
179
sysdeps/m68k/rawmemchr.S
Normal file
179
sysdeps/m68k/rawmemchr.S
Normal file
@ -0,0 +1,179 @@
|
||||
/* rawmemchr (str, ch) -- Return pointer to first occurrence of CH in STR.
|
||||
For Motorola 68000.
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Andreas Schwab <schwab@gnu.org>.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include "asm-syntax.h"
|
||||
|
||||
TEXT
|
||||
ENTRY(__rawmemchr)
|
||||
/* Save the callee-saved registers we use. */
|
||||
movel R(d2),MEM_PREDEC(sp)
|
||||
movel R(d3),MEM_PREDEC(sp)
|
||||
|
||||
/* Get string pointer and character. */
|
||||
movel MEM_DISP(sp,12),R(a0)
|
||||
moveb MEM_DISP(sp,19),R(d0)
|
||||
|
||||
/* Distribute the character to all bytes of a longword. */
|
||||
movel R(d0),R(d1)
|
||||
lsll #8,R(d1)
|
||||
moveb R(d0),R(d1)
|
||||
movel R(d1),R(d0)
|
||||
swap R(d0)
|
||||
movew R(d1),R(d0)
|
||||
|
||||
/* First search for the character one byte at a time until the
|
||||
pointer is aligned to a longword boundary. */
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
L(L1:)
|
||||
/* Load the magic bits. Unlike the generic implementation we can
|
||||
use the carry bit as the fourth hole. */
|
||||
movel #0xfefefeff,R(d3)
|
||||
|
||||
/* We exit the loop if adding MAGIC_BITS to LONGWORD fails to
|
||||
change any of the hole bits of LONGWORD.
|
||||
|
||||
1) Is this safe? Will it catch all the zero bytes?
|
||||
Suppose there is a byte with all zeros. Any carry bits
|
||||
propagating from its left will fall into the hole at its
|
||||
least significant bit and stop. Since there will be no
|
||||
carry from its most significant bit, the LSB of the
|
||||
byte to the left will be unchanged, and the zero will be
|
||||
detected.
|
||||
|
||||
2) Is this worthwhile? Will it ignore everything except
|
||||
zero bytes? Suppose every byte of LONGWORD has a bit set
|
||||
somewhere. There will be a carry into bit 8. If bit 8
|
||||
is set, this will carry into bit 16. If bit 8 is clear,
|
||||
one of bits 9-15 must be set, so there will be a carry
|
||||
into bit 16. Similarly, there will be a carry into bit
|
||||
24. If one of bits 24-31 is set, there will be a carry
|
||||
into bit 32 (=carry flag), so all of the hole bits will
|
||||
be changed.
|
||||
|
||||
3) But wait! Aren't we looking for C, not zero?
|
||||
Good point. So what we do is XOR LONGWORD with a longword,
|
||||
each of whose bytes is C. This turns each byte that is C
|
||||
into a zero. */
|
||||
|
||||
L(L2:)
|
||||
/* Get the longword in question. */
|
||||
movel MEM_POSTINC(a0),R(d1)
|
||||
/* XOR with the byte we search for. */
|
||||
eorl R(d0),R(d1)
|
||||
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not C. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits. */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word equals
|
||||
C. */
|
||||
bne L(L8)
|
||||
|
||||
/* Get the longword in question. */
|
||||
movel MEM_POSTINC(a0),R(d1)
|
||||
/* XOR with the byte we search for. */
|
||||
eorl R(d0),R(d1)
|
||||
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not C. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word equals
|
||||
C. */
|
||||
beq L(L2)
|
||||
|
||||
L(L8:)
|
||||
/* We have a hit. Check to see which byte it was. First
|
||||
compensate for the autoincrement in the loop. */
|
||||
subql #4,R(a0)
|
||||
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
cmpb MEM(a0),R(d0)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
/* Otherwise the fourth byte must equal C. */
|
||||
L(L9:)
|
||||
movel R(a0),R(d0)
|
||||
movel MEM_POSTINC(sp),R(d3)
|
||||
movel MEM_POSTINC(sp),R(d2)
|
||||
rts
|
||||
END(__rawmemchr)
|
||||
|
||||
weak_alias (__rawmemchr, rawmemchr)
|
257
sysdeps/m68k/strchr.S
Normal file
257
sysdeps/m68k/strchr.S
Normal file
@ -0,0 +1,257 @@
|
||||
/* strchr (str, ch) -- Return pointer to first occurrence of CH in STR.
|
||||
For Motorola 68000.
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Andreas Schwab <schwab@gnu.org>.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include "asm-syntax.h"
|
||||
|
||||
TEXT
|
||||
ENTRY(strchr)
|
||||
/* Save the callee-saved registers we use. */
|
||||
movel R(d2),MEM_PREDEC(sp)
|
||||
movel R(d3),MEM_PREDEC(sp)
|
||||
|
||||
/* Get string pointer and character. */
|
||||
movel MEM_DISP(sp,12),R(a0)
|
||||
moveb MEM_DISP(sp,19),R(d0)
|
||||
|
||||
/* Distribute the character to all bytes of a longword. */
|
||||
movel R(d0),R(d1)
|
||||
lsll #8,R(d1)
|
||||
moveb R(d0),R(d1)
|
||||
movel R(d1),R(d0)
|
||||
swap R(d0)
|
||||
movew R(d1),R(d0)
|
||||
|
||||
/* First search for the character one byte at a time until the
|
||||
pointer is aligned to a longword boundary. */
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L3)
|
||||
addql #1,R(a0)
|
||||
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L3)
|
||||
addql #1,R(a0)
|
||||
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L3)
|
||||
addql #1,R(a0)
|
||||
|
||||
L(L1:)
|
||||
/* Load the magic bits. Unlike the generic implementation we can
|
||||
use the carry bit as the fourth hole. */
|
||||
movel #0xfefefeff,R(d3)
|
||||
|
||||
/* We exit the loop if adding MAGIC_BITS to LONGWORD fails to
|
||||
change any of the hole bits of LONGWORD.
|
||||
|
||||
1) Is this safe? Will it catch all the zero bytes?
|
||||
Suppose there is a byte with all zeros. Any carry bits
|
||||
propagating from its left will fall into the hole at its
|
||||
least significant bit and stop. Since there will be no
|
||||
carry from its most significant bit, the LSB of the
|
||||
byte to the left will be unchanged, and the zero will be
|
||||
detected.
|
||||
|
||||
2) Is this worthwhile? Will it ignore everything except
|
||||
zero bytes? Suppose every byte of LONGWORD has a bit set
|
||||
somewhere. There will be a carry into bit 8. If bit 8
|
||||
is set, this will carry into bit 16. If bit 8 is clear,
|
||||
one of bits 9-15 must be set, so there will be a carry
|
||||
into bit 16. Similarly, there will be a carry into bit
|
||||
24. If one of bits 24-31 is set, there will be a carry
|
||||
into bit 32 (=carry flag), so all of the hole bits will
|
||||
be changed.
|
||||
|
||||
3) But wait! Aren't we looking for C, not zero?
|
||||
Good point. So what we do is XOR LONGWORD with a longword,
|
||||
each of whose bytes is C. This turns each byte that is C
|
||||
into a zero. */
|
||||
|
||||
L(L2:)
|
||||
/* Get the longword in question. */
|
||||
movel MEM_POSTINC(a0),R(d1)
|
||||
/* XOR with the byte we search for. */
|
||||
eorl R(d0),R(d1)
|
||||
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not C. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits. */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word equals
|
||||
C. */
|
||||
bne L(L8)
|
||||
|
||||
/* Next look for a NUL byte.
|
||||
Restore original longword without reload. */
|
||||
eorl R(d0),R(d1)
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not NUL. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit, and return NULL. */
|
||||
bcc L(L3)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits. */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word was NUL
|
||||
and we return NULL. Otherwise continue with the next longword. */
|
||||
bne L(L3)
|
||||
|
||||
/* Get the longword in question. */
|
||||
movel MEM_POSTINC(a0),R(d1)
|
||||
/* XOR with the byte we search for. */
|
||||
eorl R(d0),R(d1)
|
||||
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not C. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word equals
|
||||
C. */
|
||||
bne L(L8)
|
||||
|
||||
/* Next look for a NUL byte.
|
||||
Restore original longword without reload. */
|
||||
eorl R(d0),R(d1)
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not NUL. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit, and return NULL. */
|
||||
bcc L(L3)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word was NUL
|
||||
and we return NULL. Otherwise continue with the next longword. */
|
||||
beq L(L2)
|
||||
|
||||
L(L3:)
|
||||
/* Return NULL. */
|
||||
clrl R(d0)
|
||||
movel R(d0),R(a0)
|
||||
movel MEM_POSTINC(sp),R(d3)
|
||||
movel MEM_POSTINC(sp),R(d2)
|
||||
rts
|
||||
|
||||
L(L8:)
|
||||
/* We have a hit. Check to see which byte it was. First
|
||||
compensate for the autoincrement in the loop. */
|
||||
subql #4,R(a0)
|
||||
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L3)
|
||||
addql #1,R(a0)
|
||||
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L3)
|
||||
addql #1,R(a0)
|
||||
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L3)
|
||||
addql #1,R(a0)
|
||||
|
||||
/* Otherwise the fourth byte must equal C. */
|
||||
L(L9:)
|
||||
movel R(a0),R(d0)
|
||||
movel MEM_POSTINC(sp),R(d3)
|
||||
movel MEM_POSTINC(sp),R(d2)
|
||||
rts
|
||||
END(strchr)
|
||||
|
||||
weak_alias (strchr, index)
|
250
sysdeps/m68k/strchrnul.S
Normal file
250
sysdeps/m68k/strchrnul.S
Normal file
@ -0,0 +1,250 @@
|
||||
/* strchrnul (str, ch) -- Return pointer to first occurrence of CH in STR
|
||||
or the final NUL byte.
|
||||
For Motorola 68000.
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Andreas Schwab <schwab@gnu.org>.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include "asm-syntax.h"
|
||||
|
||||
TEXT
|
||||
ENTRY(__strchrnul)
|
||||
/* Save the callee-saved registers we use. */
|
||||
movel R(d2),MEM_PREDEC(sp)
|
||||
movel R(d3),MEM_PREDEC(sp)
|
||||
|
||||
/* Get string pointer and character. */
|
||||
movel MEM_DISP(sp,12),R(a0)
|
||||
moveb MEM_DISP(sp,19),R(d0)
|
||||
|
||||
/* Distribute the character to all bytes of a longword. */
|
||||
movel R(d0),R(d1)
|
||||
lsll #8,R(d1)
|
||||
moveb R(d0),R(d1)
|
||||
movel R(d1),R(d0)
|
||||
swap R(d0)
|
||||
movew R(d1),R(d0)
|
||||
|
||||
/* First search for the character one byte at a time until the
|
||||
pointer is aligned to a longword boundary. */
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
movel R(a0),R(d1)
|
||||
andw #3,R(d1)
|
||||
beq L(L1)
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
L(L1:)
|
||||
/* Load the magic bits. Unlike the generic implementation we can
|
||||
use the carry bit as the fourth hole. */
|
||||
movel #0xfefefeff,R(d3)
|
||||
|
||||
/* We exit the loop if adding MAGIC_BITS to LONGWORD fails to
|
||||
change any of the hole bits of LONGWORD.
|
||||
|
||||
1) Is this safe? Will it catch all the zero bytes?
|
||||
Suppose there is a byte with all zeros. Any carry bits
|
||||
propagating from its left will fall into the hole at its
|
||||
least significant bit and stop. Since there will be no
|
||||
carry from its most significant bit, the LSB of the
|
||||
byte to the left will be unchanged, and the zero will be
|
||||
detected.
|
||||
|
||||
2) Is this worthwhile? Will it ignore everything except
|
||||
zero bytes? Suppose every byte of LONGWORD has a bit set
|
||||
somewhere. There will be a carry into bit 8. If bit 8
|
||||
is set, this will carry into bit 16. If bit 8 is clear,
|
||||
one of bits 9-15 must be set, so there will be a carry
|
||||
into bit 16. Similarly, there will be a carry into bit
|
||||
24. If one of bits 24-31 is set, there will be a carry
|
||||
into bit 32 (=carry flag), so all of the hole bits will
|
||||
be changed.
|
||||
|
||||
3) But wait! Aren't we looking for C, not zero?
|
||||
Good point. So what we do is XOR LONGWORD with a longword,
|
||||
each of whose bytes is C. This turns each byte that is C
|
||||
into a zero. */
|
||||
|
||||
L(L2:)
|
||||
/* Get the longword in question. */
|
||||
movel MEM_POSTINC(a0),R(d1)
|
||||
/* XOR with the byte we search for. */
|
||||
eorl R(d0),R(d1)
|
||||
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not C. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits. */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word equals
|
||||
C. */
|
||||
bne L(L8)
|
||||
|
||||
/* Next look for a NUL byte.
|
||||
Restore original longword without reload. */
|
||||
eorl R(d0),R(d1)
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not NUL. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits. */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word was
|
||||
NUL. Otherwise continue with the next longword. */
|
||||
bne L(L8)
|
||||
|
||||
/* Get the longword in question. */
|
||||
movel MEM_POSTINC(a0),R(d1)
|
||||
/* XOR with the byte we search for. */
|
||||
eorl R(d0),R(d1)
|
||||
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not C. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word equals
|
||||
C. */
|
||||
bne L(L8)
|
||||
|
||||
/* Next look for a NUL byte.
|
||||
Restore original longword without reload. */
|
||||
eorl R(d0),R(d1)
|
||||
/* Add the magic value. We get carry bits reported for each byte
|
||||
which is not NUL. */
|
||||
movel R(d3),R(d2)
|
||||
addl R(d1),R(d2)
|
||||
|
||||
/* Check the fourth carry bit before it is clobbered by the next
|
||||
XOR. If it is not set we have a hit. */
|
||||
bcc L(L8)
|
||||
|
||||
/* We are only interested in carry bits that change due to the
|
||||
previous add, so remove original bits */
|
||||
eorl R(d1),R(d2)
|
||||
|
||||
/* Now test for the other three overflow bits.
|
||||
Set all non-carry bits. */
|
||||
orl R(d3),R(d2)
|
||||
/* Add 1 to get zero if all carry bits were set. */
|
||||
addql #1,R(d2)
|
||||
|
||||
/* If we don't get zero then at least one byte of the word was
|
||||
NUL. Otherwise continue with the next longword. */
|
||||
beq L(L2)
|
||||
|
||||
L(L8:)
|
||||
/* We have a hit. Check to see which byte it was. First
|
||||
compensate for the autoincrement in the loop. */
|
||||
subql #4,R(a0)
|
||||
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
moveb MEM(a0),R(d1)
|
||||
cmpb R(d0),R(d1)
|
||||
beq L(L9)
|
||||
tstb R(d1)
|
||||
beq L(L9)
|
||||
addql #1,R(a0)
|
||||
|
||||
/* Otherwise the fourth byte must equal C or be NUL. */
|
||||
L(L9:)
|
||||
movel R(a0),R(d0)
|
||||
movel MEM_POSTINC(sp),R(d3)
|
||||
movel MEM_POSTINC(sp),R(d2)
|
||||
rts
|
||||
END(__strchrnul)
|
||||
|
||||
weak_alias (__strchrnul, strchrnul)
|
Loading…
Reference in New Issue
Block a user