Retro68/gcc/newlib/libc/machine/hppa/strlen.S
2012-03-27 01:51:53 +02:00

80 lines
3.3 KiB
ArmAsm

/*
* (c) Copyright 1986 HEWLETT-PACKARD COMPANY
*
* To anyone who acknowledges that this file is provided "AS IS"
* without any express or implied warranty:
* permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies, and that the name of Hewlett-Packard Company not be
* used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission.
* Hewlett-Packard Company makes no representations about the
* suitability of this software for any purpose.
*/
/* HPUX_ID = "@(#) $Revision: 1.1 $" */
/* strlen(s): Return length of string s */
#define start arg0
#define end ret0
#define tmp1 arg1
#define tmp2 arg2
#include "DEFS.h"
ENTRY(strlen)
movb,=,n start,end,$null_ptr
depi 0,31,2,end
comb,<> start,end,$not_aligned
ldws,ma 4(end),tmp1
comib,tr 0,0,$loop /* avoid INDIGO two register interlock */
uxor,nbz 0,tmp1,0
$not_aligned:
/*
; Tricky code. The problem is that the value of of the word
; including the start of the string has some garbage bytes that
; may be 0. We don't want them to stop the string scan. So
; we make those bytes non-zero (and any old non-zero value
; will do). Notice that the end pointer has been rounded
; down to a word boundary, and then incremented to the next
; word by the time we get here. Therefore, (start-end) has
; one of the values (-3, -2, or -1). Use uaddcm to do the
; subtraction (instead of sub), and the result will be
; (-4, -3, or -2). Multiply this by 8, and put into the
; shift register (which truncates to the last 5 bits) and
; the value will be (0, 8, or 16). Use this as a bit position,
; and drop a mask down into tmp1. All the garbage bytes will
; have at least 1 bit affected by the vdepi, so all the garbage
; in this first word will be non-zero garbage.
*/
uaddcm start,end,tmp2 /* tmp2 <- { -4, -3, -2 } */
sh3add tmp2,0,tmp2 /* tmp2 <- { -32, -24, -16 } */
mtsar tmp2 /* sar <- { 0, 8, 16 } */
vdepi -1,32,tmp1
uxor,nbz 0,tmp1,0
$loop:
b,n $end_loop
ldws,ma 4(end),tmp1
comib,tr 0,0,$loop /* avoid INDIGO two register interlock */
uxor,nbz 0,tmp1,0
$end_loop:
/* adjust the end pointer to one past the end of the string */
extru,<> tmp1,7,8,0
addib,tr,n -3,end,$out
extru,<> tmp1,15,8,0
addib,tr,n -2,end,$out
extru,<> tmp1,23,8,0
addi -1,end,end
$out:
bv 0(rp)
/*
; tricky code. the end pointer is just beyond the terminating
; null byte, so the length is (end-start-1). use uaddcm
; to do this in 1 instruction
*/
uaddcm end,start,ret0
$null_ptr:
EXIT(strlen)