Commit cb22b947 authored by Kevin Bracey's avatar Kevin Bracey

Improved strcmp and memset functions nicked from ARM's version of the library.

parent 01eff222
......@@ -236,7 +236,7 @@ EXPORTS = ${MODWRAP} \
#
ANSI_OBJS =\
o.alloc o.armprof o.armsys o.clib o.ctype o.error o.fpprintf \
o.kernel o.locale o.math o.memcpy o.overmgr o.printf o.scanf \
o.kernel o.locale o.math o.memcpset o.overmgr o.printf o.scanf \
o.signal o.sort o.stdio o.stdlib o.string o.swiv o.time
RM_OBJS =\
......@@ -250,7 +250,7 @@ RM_OBJS =\
rm_o.fpprintf \
rm_o.locale \
rm_o.math \
rm_o.memcpy \
rm_o.memcpset \
rm_o.printf \
rm_o.scanf \
rm_o.signal \
......@@ -615,8 +615,8 @@ rm_o_rl.rl_modbody: rlib.s.rl_mod_r
rm_o.k_modbody: kernel.s.k_mod_r
${OBJASM} ${AFLAGS} -from kernel.s.k_mod_r -to $@
rm_o.memcpy: s.memcpy s.h_regs
${OBJASM} ${AFLAGS} -from s.memcpy -to $@
rm_o.memcpset: s.memcpset s.h_regs
${OBJASM} ${AFLAGS} -from s.memcpset -to $@
rm_o.initmodule: clib.s.initmod_r
${OBJASM} ${AFLAGS} -from clib.s.initmod_r -to $@
......@@ -634,13 +634,13 @@ o.armprof: c.armprof
${CC} ${CFLAGS} -fah ${VLFLAGS} -pcc -o $@ c.armprof
o.string: c.string
${CC} ${CFLAGS} -fah -DSEPERATE_MEMCPY -o $@ c.string
${CC} ${CFLAGS} -fah -DSEPARATE_MEMCPY -DSEPARATE_MEMSET -o $@ c.string
rm_o.armsys: c.armsys
${CC} ${CFLAGS} -ffah ${DFLAGS} -zm1 ${CSFLAGS} ${VSFLAGS} -o $@ c.armsys
rm_o.string: c.string
${CC} ${CFLAGS} -ffah ${DFLAGS} -zm1 ${CSFLAGS} -DSEPERATE_MEMCPY -o $@ c.string
${CC} ${CFLAGS} -ffah ${DFLAGS} -zm1 ${CSFLAGS} -DSEPARATE_MEMCPY -DSEPARATE_MEMSET -o $@ c.string
#
# Special case: use "rom_defs" for ROM library (o_rm), "defs" for the others
......
......@@ -12,9 +12,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* string.c: ANSI draft (X3J11 Oct 86) library code, section 4.11 */
/* Copyright (C) A.C. Norman and A. Mycroft */
/* Copyright (C) Codemist Ltd., 1988 */
/* Copyright (C) Advanced Risc Machines Ltd., 1991 */
/* version 3a */
/* Also the routine 'strerror' is in 'perror.c' rather than here */
......@@ -57,7 +57,7 @@ extern void _set_strcoll(int territory);
/* copying functions */
#ifndef SEPERATE_MEMCPY
#ifndef SEPARATE_MEMCPY
void *memcpy(void *a, const void *b, size_t n)
/* copy memory (upwards) - it is an errof for args to overlap. */
......@@ -205,7 +205,8 @@ char *strncat(char *a, const char *b, size_t n)
/* comparison functions */
int memcmp(const void *a, const void *b, size_t n)
{ const unsigned char *ac = a, *bc = b;
{ const unsigned char *ac = (const unsigned char *)a,
*bc = (const unsigned char *)b;
#ifdef _copywords
if ((((int)ac | (int)bc) & 3) == 0)
{ while (n >= 4 && *(int *)ac == *(int *)bc)
......@@ -223,6 +224,36 @@ int memcmp(const void *a, const void *b, size_t n)
int strcmp(const char *a, const char *b) /* lexical comparison on strings */
{
#ifdef _copywords
#ifdef BYTESEX_EVEN
/* Improved little-endian ARM strcmp code by Ian Rickards, ARM Ltd. */
if ((((int)a | (int)b) & 3) == 0)
{ int w1, w2, res, rc;
nullbyte_prologue_();
do {
w1 = *(int *)a, a += 4;
w2 = *(int *)b, b += 4;
res = w1 - w2;
if (res != 0) goto strcmp_checkbytes;
} while (!word_has_nullbyte(w1));
return 0;
strcmp_checkbytes:
/* carry propagation in subtract means that no subtract-per-byte is needed */
rc = res << 24;
if (rc != 0) return rc;
if ((w1 & 0xff) == 0) return rc;
rc = res << 16;
if (rc != 0) return rc;
if ((w1 & 0xff00) == 0) return rc;
rc = res << 8;
if (rc != 0) return rc;
if ((w1 & 0xff0000) == 0) return rc;
return res;
#else
if ((((int)a | (int)b) & 3) == 0)
{ int w1, w2;
nullbyte_prologue_();
......@@ -230,15 +261,7 @@ int strcmp(const char *a, const char *b) /* lexical comparison on strings */
w1 = *(int *)a, a += 4;
w2 = *(int *)b, b += 4;
} while (w1 == w2 && !word_has_nullbyte(w1));
#ifdef BYTESEX_EVEN
for (;;)
{ char c1 = w1 & 0xff, c2 = w2 & 0xff;
int d = c1 - c2;
if (d != 0) return d;
if (c1 == 0) return 0;
w1 = w1 >> 8; w2 = w2 >> 8;
}
#else
for (;;)
{ char c1 = (w1 >> 24) & 0xff, c2 = (w2 >> 24) & 0xff;
int d = c1 - c2;
......@@ -249,11 +272,13 @@ int strcmp(const char *a, const char *b) /* lexical comparison on strings */
#endif
}
#endif
for (;;)
{ char c1 = *a++, c2 = *b++;
int d = c1 - c2;
if (d != 0) return d;
if (c1 == 0) return 0; /* no need to check c2 */
{ char const *ap = a; /* in order to move ap from reg a1 */
for (;;)
{ char c1 = *ap++, c2 = *b++;
int d = c1 - c2;
if (d != 0) return d;
if (c1 == 0) return d; /* no need to check c2 */
}
}
}
......@@ -303,14 +328,14 @@ size_t strxfrm(char *s1, const char *s2, size_t n)
int strcoll(const char *a, const char *b)
{
_kernel_swi_regs r;
int ret;
if (strcoll_territory == 0) return strcmp(a, b); /* C locale */
r.r[0] = strcoll_territory;
r.r[1] = (int)a;
r.r[2] = (int)b;
r.r[3] = 0;
if (_kernel_swi(Territory_Collate, &r, &r))
if (_swix(Territory_Collate, _INR(0,3)|_OUT(0),
strcoll_territory, a, b, 0,
&ret))
return 0;
return r.r[0];
}
......@@ -323,7 +348,7 @@ void _set_strcoll(int territory)
void *memchr(const void *s, _chararg ch, size_t n)
/* first instance of ch in s */
{ const unsigned char *t = s;
{ const unsigned char *t = (const unsigned char *)s;
unsigned char c1 = (unsigned char)ch;
while (n-- > 0) if (*t == c1) return (void *)t; else t++;
return 0;
......@@ -415,6 +440,8 @@ char *strtok(char *s1, const char *s2)
/* Miscellaneous functions */
#ifndef SEPARATE_MEMSET
void *memset(void *s, _chararg c, size_t n)
{
unsigned char *p = s;
......@@ -432,6 +459,8 @@ void *memset(void *s, _chararg c, size_t n)
return s;
}
#endif
size_t strlen(const char *a) /* find number of chars in a string */
{ const char *x = a + 1;
#ifdef _copywords
......
; Copyright 1997 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
;;; h_la_obj.s
;;; Copyright (C) Advanced RISC Machines Ltd., 1991
MACRO
DataArea
AREA |C$$data|, DATA
MEND
[ make <> "shared-library"
MACRO
CodeArea
AREA |C$$code|, CODE, READONLY
MEND
MACRO
LoadStaticAddress $Addr, $Reg, $Ignore
LDR $Reg, =$Addr
MEND
MACRO
LoadStaticBase $Reg, $Ignore
LoadStaticAddress StaticData, $Reg, $Ignore
MEND
MACRO
AdconTable
MEND
MACRO
Function $name, $type
LCLS Temps
Temps SETS VBar:CC:"$name":CC:VBar
EXPORT $Temps
$Temps
MEND
|
MACRO
CodeArea
AREA |C$$code|, CODE, READONLY, REENTRANT, PIC
MEND
MACRO
AdconTable
AREA |sb$$adcons|, DATA, READONLY, BASED sb
MEND
MACRO
Function $name, $type
LCLS Temps
Temps SETS VBar:CC:"$name":CC:VBar
[ "$type" = ""
EXPORT $Temps
|
EXPORT $Temps[$type]
]
$Temps
MEND
]
END
This diff is collapsed.
; Copyright 1997 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
;;; h_objmacro.s
;;; Copyright (C) Advanced RISC Machines Ltd., 1991
;;; RCS $Revision$
;;; Checkin $Date$
;;; Revising $Author$
[ :LNOT: :DEF: LDM_MAX
GBLA LDM_MAX
LDM_MAX SETA 16
]
[ :LNOT: :DEF: make
GBLS make
make SETS "all"
]
[ :LNOT: :DEF: FPIS
GBLA FPIS
FPIS SETA 2
]
GBLL FPE2
FPE2 SETL FPIS=2
GBLS VBar
GBLS UL
GBLS XXModuleName
VBar SETS "|"
UL SETS "_"
GET h_la_obj.s
MACRO
Module $name
XXModuleName SETS UL:CC:"$name":CC:UL
MEND
MACRO
$Label Variable $Size
LCLS Temps
LCLA Tempa
[ "$Size"=""
Tempa SETA 1
|
Tempa SETA $Size
]
Temps SETS VBar:CC:XXModuleName:CC:"$Label":CC:VBar
KEEP $Temps
ALIGN
O_$Label * .-StaticData
$Temps % &$Tempa*4
MEND
MACRO
$Label ExportedVariable $Size
LCLS Temps
LCLA Tempa
[ "$Size"=""
Tempa SETA 1
|
Tempa SETA $Size
]
Temps SETS VBar:CC:"$Label":CC:VBar
EXPORT $Temps
ALIGN
O_$Label * .-StaticData
$Temps % &$Tempa*4
MEND
MACRO
$Label ExportedWord $Value
LCLS Temps
Temps SETS VBar:CC:"$Label":CC:VBar
EXPORT $Temps
ALIGN
O_$Label * .-StaticData
$Temps & $Value
MEND
MACRO
$Label ExportedVariableByte $Size
LCLS Temps
LCLA Tempa
[ "$Size"=""
Tempa SETA 1
|
Tempa SETA $Size
]
Temps SETS VBar:CC:"$Label":CC:VBar
EXPORT $Temps
O_$Label * .-StaticData
$Temps % &$Tempa
MEND
MACRO
$Label VariableByte $Size
LCLS Temps
LCLA Tempa
[ "$Size"=""
Tempa SETA 1
|
Tempa SETA $Size
]
Temps SETS VBar:CC:XXModuleName:CC:"$Label":CC:VBar
KEEP $Temps
O_$Label * .-StaticData
$Temps % &$Tempa
MEND
MACRO
$Label InitByte $Value
$Label = $Value
MEND
MACRO
$Label InitWord $Value
$Label & $Value
MEND
MACRO
$Label Keep $Arg
LCLS Temps
$Label $Arg
Temps SETS VBar:CC:XXModuleName:CC:"$Label":CC:VBar
KEEP $Temps
$Temps
MEND
MACRO
PopFrame $Regs,$Caret,$CC,$Base
LCLS BaseReg
[ "$Base" = ""
BaseReg SETS "fp"
|
BaseReg SETS "$Base"
]
LCLA count
LCLS s
LCLS ch
s SETS "$Regs"
count SETA 1
WHILE s<>""
ch SETS s:LEFT:1
s SETS s:RIGHT:(:LEN:s-1)
[ ch = ","
count SETA count+1
|
[ ch = "-"
! 1, "Can't handle register list including '-'"
]
]
WEND
[ LDM_MAX < count
LCLA r
LCLS subs
s SETS "$Regs"
subs SETS ""
r SETA 0
SUB ip, $BaseReg, #4*&$count
WHILE s<>""
ch SETS s:LEFT:1
s SETS s:RIGHT:(:LEN:s-1)
[ ch = ","
r SETA r+1
[ r >= LDM_MAX
LDM$CC.FD ip!,{$subs}
subs SETS ""
r SETA 0
|
subs SETS subs:CC:ch
]
|
[ ch = "-"
! 1, "Push can't handle register list including '-'"
|
subs SETS subs:CC:ch
]
]
WEND
LDM$CC.FD ip,{$subs}$Caret
|
LDM$CC.DB $BaseReg, {$Regs}$Caret
]
MEND
MACRO
Pop $Regs,$Caret,$CC,$Base
LCLS BaseReg
[ "$Base" = ""
BaseReg SETS "sp"
|
BaseReg SETS "$Base"
]
[ LDM_MAX < 16
LCLA r
LCLS s
LCLS subs
LCLS ch
s SETS "$Regs"
subs SETS ""
r SETA 0
WHILE s<>""
ch SETS s:LEFT:1
s SETS s:RIGHT:(:LEN:s-1)
[ ch = ","
r SETA r+1
[ r >= LDM_MAX
LDM$CC.FD $BaseReg!,{$subs}
subs SETS ""
r SETA 0
|
subs SETS subs:CC:ch
]
|
[ ch = "-"
! 1, "Can't handle register list including '-'"
|
subs SETS subs:CC:ch
]
]
WEND
LDM$CC.FD $BaseReg!,{$subs}$Caret
|
LDM$CC.FD $BaseReg!, {$Regs}$Caret
]
MEND
MACRO
Return $UsesSb, $ReloadList, $Base, $CC
LCLS Temps
Temps SETS "$ReloadList"
[ "$UsesSb" <> "" :LAND: make="shared-library"
[ Temps = ""
Temps SETS "sb"
|
Temps SETS Temps:CC:", sb"
]
]
[ {CONFIG} = 26
[ "$Base" = "LinkNotStacked" :LAND: "$ReloadList"=""
MOV$CC.S pc, lr
|
[ Temps <> ""
Temps SETS Temps :CC: ","
]
[ "$Base" = "fpbased"
PopFrame "$Temps.fp,sp,pc",^,$CC
|
Pop "$Temps.pc",^,$CC
]
]
|
[ "$Base" = "LinkNotStacked" :LAND: "$ReloadList"=""
MOV$CC pc, lr
|
[ Temps <> ""
Temps SETS Temps :CC: ","
]
[ "$Base" = "fpbased"
PopFrame "$Temps.fp,sp,pc",,$CC
|
Pop "$Temps.pc",,$CC
]
]
]
MEND
MACRO
PushA $Regs,$Base
; Push registers on an empty ascending stack, with stack pointer $Base
; (no default for $Base, won't be sp)
[ LDM_MAX < 16
LCLA r
LCLS s
LCLS subs
LCLS ch
s SETS "$Regs"
subs SETS ""
r SETA 0
WHILE s<>""
ch SETS s:LEFT:1
s SETS s:RIGHT:(:LEN:s-1)
[ ch = ","
r SETA r+1
[ r >= LDM_MAX
STMIA $Base!,{$subs}
subs SETS ""
r SETA 0
|
subs SETS subs:CC:ch
]
|
[ ch = "-"
! 1, "Can't handle register list including '-'"
|
subs SETS subs:CC:ch
]
]
WEND
STMIA $Base!,{$subs}
|
STMIA $Base!, {$Regs}
]
MEND
MACRO
PopA $Regs,$Base
; Pop registers from an empty ascending stack, with stack pointer $Base
; (no default for $Base, won't be sp)
[ LDM_MAX < 16
LCLA n
LCLA r
LCLS s
LCLS subs
LCLS ch
s SETS "$Regs"
n SETA :LEN:s
subs SETS ""
r SETA 0
WHILE n<>0
n SETA n-1
ch SETS s:RIGHT:1
s SETS s:LEFT:n
[ ch = ","
r SETA r+1
[ r >= LDM_MAX
LDMDB $Base!,{$subs}
subs SETS ""
r SETA 0
|
subs SETS ch:CC:subs
]
|
[ ch = "-"
! 1, "Can't handle register list including '-'"
|
subs SETS ch:CC:subs
]
]
WEND
LDMDB $Base!,{$subs}
|
LDMDB $Base!, {$Regs}
]
MEND
MACRO
Push $Regs, $Base
LCLS BaseReg
[ "$Base" = ""
BaseReg SETS "sp"
|
BaseReg SETS "$Base"
]
[ LDM_MAX < 16
LCLA n
LCLA r
LCLS s
LCLS subs
LCLS ch
s SETS "$Regs"
n SETA :LEN:s
subs SETS ""
r SETA 0
WHILE n<>0
n SETA n-1
ch SETS s:RIGHT:1
s SETS s:LEFT:n
[ ch = ","
r SETA r+1
[ r >= LDM_MAX
STMFD $BaseReg!,{$subs}
subs SETS ""
r SETA 0
|
subs SETS ch:CC:subs
]
|
[ ch = "-"
! 1, "Can't handle register list including '-'"
|
subs SETS ch:CC:subs
]
]
WEND
STMFD $BaseReg!,{$subs}
|
STMFD $BaseReg!, {$Regs}
]
MEND
MACRO
FunctionEntry $UsesSb, $SaveList, $MakeFrame
LCLS Temps
LCLS TempsC
Temps SETS "$SaveList"
TempsC SETS ""
[ Temps <> ""
TempsC SETS Temps :CC: ","
]
[ "$UsesSb" <> "" :LAND: make="shared-library"
[ "$MakeFrame" = ""
MOV ip, sb ; intra-link-unit entry
Push "$TempsC.sb,lr"
MOV sb, ip
|
MOV ip, sb ; intra-link-unit entry
Push "sp,lr,pc"
ADD lr, sp, #8
Push "$TempsC.sb,fp"
MOV fp, lr
MOV sb, ip
]
|
[ "$MakeFrame" = ""
Push "$TempsC.lr"
|
MOV ip, sp
Push "$TempsC.fp,ip,lr,pc"
SUB fp, ip, #4
]
]
MEND
END
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment