For the RX port, avoid using string instructions when __RX_DISALLOW_STRING_INSNS__ is defined.

* rx/crt0.S (_start): If string instructions are not allowed,
	avoid using SMOVF.

	* libc/machine/rx/memchr.S: Add non-string insn using version.
	* libc/machine/rx/memcpy.S: Likewise.
	* libc/machine/rx/memmove.S: Likewise.
	* libc/machine/rx/mempcpy.S: Likewise.
	* libc/machine/rx/strcat.S: Likewise.
	* libc/machine/rx/strcmp.S: Likewise.
	* libc/machine/rx/strcpy.S: Likewise.
	* libc/machine/rx/strlen.S: Likewise.
	* libc/machine/rx/strncat.S: Likewise.
	* libc/machine/rx/strncmp.S: Likewise.
	* libc/machine/rx/strncpy.S: Likewise.
This commit is contained in:
Nick Clifton 2015-04-09 09:20:00 +01:00 committed by Corinna Vinschen
parent 45d0b17928
commit cd0d459135
16 changed files with 273 additions and 1 deletions

View File

@ -120,6 +120,11 @@ END_RELOC_NUMBERS (R_RX_max)
#define E_FLAG_RX_PID (1 << 2) /* Unofficial - DJ */ #define E_FLAG_RX_PID (1 << 2) /* Unofficial - DJ */
#define E_FLAG_RX_ABI (1 << 3) /* Binary passes stacked arguments using natural alignment. Unofficial - NC. */ #define E_FLAG_RX_ABI (1 << 3) /* Binary passes stacked arguments using natural alignment. Unofficial - NC. */
#define E_FLAG_RX_SINSNS_SET (1 << 6) /* Set if bit-5 is significant. */
#define E_FLAG_RX_SINSNS_YES (1 << 7) /* Set if string instructions are used in the binary. */
#define E_FLAG_RX_SINSNS_NO 0 /* Bit-5 if this binary must not be linked with a string instruction using binary. */
#define E_FLAG_RX_SINSNS_MASK (3 << 6) /* Mask of bits used to determine string instruction use. */
/* These define the addend field of R_RX_RH_RELAX relocations. */ /* These define the addend field of R_RX_RH_RELAX relocations. */
#define RX_RELAXA_IMM6 0x00000010 /* Imm8/16/24/32 at bit offset 6. */ #define RX_RELAXA_IMM6 0x00000010 /* Imm8/16/24/32 at bit offset 6. */
#define RX_RELAXA_IMM12 0x00000020 /* Imm8/16/24/32 at bit offset 12. */ #define RX_RELAXA_IMM12 0x00000020 /* Imm8/16/24/32 at bit offset 12. */

View File

@ -1,3 +1,8 @@
2015-04-09 Nick Clifton <nickc@redhat.com>
* rx/crt0.S (_start): If string instructions are not allowed,
avoid using SMOVF.
2015-04-08 Nick Clifton <nickc@redhat.com> 2015-04-08 Nick Clifton <nickc@redhat.com>
* rx/rx.ld: Add .note and DWARF3 sections. * rx/rx.ld: Add .note and DWARF3 sections.

View File

@ -40,11 +40,24 @@ _start:
mov #__stack, r0 mov #__stack, r0
mvtc #__vectors, intb mvtc #__vectors, intb
/* Copy the .data section from ROM into RAM. */
mov #__datastart, r1 mov #__datastart, r1
mov #__romdatastart, r2 mov #__romdatastart, r2
mov #__romdatacopysize, r3 mov #__romdatacopysize, r3
smovf #ifdef __RX_DISALLOW_STRING_INSNS__
cmp #0, r3
beq 2f
1: mov.b [r2+], r5
mov.b r5, [r1+]
sub #1, r3
bne 1b
2:
#else
smovf
#endif
/* Initialise the contents of the .bss section. */
mov #__bssstart, r1 mov #__bssstart, r1
mov #0, r2 mov #0, r2
mov #__bsssize, r3 mov #__bsssize, r3

View File

@ -1,3 +1,17 @@
2015-04-09 Nick Clifton <nickc@redhat.com>
* libc/machine/rx/memchr.S: Add non-string insn using version.
* libc/machine/rx/memcpy.S: Likewise.
* libc/machine/rx/memmove.S: Likewise.
* libc/machine/rx/mempcpy.S: Likewise.
* libc/machine/rx/strcat.S: Likewise.
* libc/machine/rx/strcmp.S: Likewise.
* libc/machine/rx/strcpy.S: Likewise.
* libc/machine/rx/strlen.S: Likewise.
* libc/machine/rx/strncat.S: Likewise.
* libc/machine/rx/strncmp.S: Likewise.
* libc/machine/rx/strncpy.S: Likewise.
2015-04-01 Corinna Vinschen <vinschen@redhat.com> 2015-04-01 Corinna Vinschen <vinschen@redhat.com>
* libc/include/stdint.h: Throughout add parens around MIN/MAX values. * libc/include/stdint.h: Throughout add parens around MIN/MAX values.

View File

@ -5,9 +5,28 @@
.global _memchr .global _memchr
.type _memchr,@function .type _memchr,@function
_memchr: _memchr:
;; R1: string pointer
;; R2: byte sought
;; R3: max number to scan
#ifdef __RX_DISALLOW_STRING_INSNS__
mov.b r2, r2 ; The mov.b below sign extends as it loads, so make sure that r2 is sign-extended as well.
2: cmp #0, r3
beq 1f
sub #1, r3
mov.b [r1+], r5
cmp r5, r2
bne 2b
sub #1, r1 ; We have found a match, bit now R1 points to the byte after the match.
1: rts
#else
cmp #0, r3 ; If r3 is 0 suntil.b will do nothing and not set any flags... cmp #0, r3 ; If r3 is 0 suntil.b will do nothing and not set any flags...
stz #1, r1 ; ...so store 1 into r1. It will be decremented by the SUB later. stz #1, r1 ; ...so store 1 into r1. It will be decremented by the SUB later.
suntil.b ; Search until *r1 == r2 or r3 bytes have been examined. suntil.b ; Search until *r1 == r2 or r3 bytes have been examined.
stnz #1, r1 ; If no match was found return NULL. stnz #1, r1 ; If no match was found return NULL.
sub #1, r1 ; suntil.b leaves r1 pointing at the address *after* the match. sub #1, r1 ; suntil.b leaves r1 pointing at the address *after* the match.
rts rts
#endif
.size _memchr, . - _memchr

View File

@ -4,7 +4,28 @@
.global _memcpy .global _memcpy
.type _memcpy,@function .type _memcpy,@function
_memcpy: _memcpy:
#ifdef __RX_DISALLOW_STRING_INSNS__
/* Do not use the string instructions - they might prefetch
bytes from outside of valid memory. This is particularly
dangerous in I/O space. */
;; FIXME: It would be more space efficient to just branch to _memmove...
cmp #0, r3 ; If the count is zero, do nothing
beq 1f
mov r1, r14 ; Save a copy of DEST
2: mov.b [r2+], r5
mov.b r5, [r14+]
sub #1, r3
bne 2b
1: rts
#else
mov r1, r4 ; Save a copy of DEST mov r1, r4 ; Save a copy of DEST
smovf ; Copy R2 (source) to R1 (dest). Stop after R3 bytes. smovf ; Copy R2 (source) to R1 (dest). Stop after R3 bytes.
mov r4, r1 ; Return DEST mov r4, r1 ; Return DEST
rts rts
#endif
.size _memcpy, . - _memcpy

View File

@ -4,6 +4,39 @@
.global _memmove .global _memmove
.type _memmove,@function .type _memmove,@function
_memmove: _memmove:
;; R1: DEST
;; R2: SRC
;; R3: COUNT
#ifdef __RX_DISALLOW_STRING_INSNS__
/* Do not use the string instructions - they might prefetch
bytes from outside of valid memory. This is particularly
dangerous in I/O space. */
cmp #0, r3 ; If the count is zero, do nothing
beq 4f
cmp r1, r2
blt 3f ; If SRC < DEST copy backwards
mov r1, r14 ; Save a copy of DEST
5: mov.b [r2+], r5
mov.b r5, [r14+]
sub #1, r3
bne 5b
4: rts
3: add r3, r1
add r3, r2
6: mov.b [-r2], r5
mov.b r5, [-r1]
sub #1, r3
bne 6b
rts
#else
mov r1, r4 ; Save a copy of DEST mov r1, r4 ; Save a copy of DEST
cmp r1, r2 cmp r1, r2
blt 2f ; If SRC (r2) is less than DEST (r1) then copy backwards blt 2f ; If SRC (r2) is less than DEST (r1) then copy backwards
@ -18,3 +51,7 @@ _memmove:
sub #1, r1 ; additions and subtractions. sub #1, r1 ; additions and subtractions.
smovb smovb
bra 1b bra 1b
#endif /* SMOVF allowed. */
.size _memmove, . - _memmove

View File

@ -4,5 +4,22 @@
.global _mempcpy .global _mempcpy
.type _mempcpy,@function .type _mempcpy,@function
_mempcpy: _mempcpy:
#ifdef __RX_DISALLOW_STRING_INSNS__
/* Do not use the string instructions - they might prefetch
bytes from outside of valid memory. This is particularly
dangerous in I/O space. */
cmp #0, r3 ; If the count is zero, do nothing
beq 2f
1: mov.b [r2+], r5
mov.b r5, [r1+]
sub #1, r3
bne 1b
2: rts
#else
smovf smovf
rts rts
#endif
.size _mempcpy, . - _mempcpy

View File

@ -8,3 +8,6 @@ _memset:
sstr.b sstr.b
mov r4, r1 mov r4, r1
rts rts
.size _memset, . - _memset

View File

@ -6,6 +6,22 @@
_strcat: _strcat:
;; On entry: r1 => Destination ;; On entry: r1 => Destination
;; r2 => Source ;; r2 => Source
#ifdef __RX_DISALLOW_STRING_INSNS__
mov r1, r4 ; Save a copy of the dest pointer.
1: mov.b [r4+], r5 ; Find the NUL byte at the end of R4.
cmp #0, r5
bne 1b
sub #1, r4 ; Move R4 back to point at the NUL byte.
2: mov.b [r2+], r5 ; Copy bytes from R2 to R4 until we reach a NUL byte.
mov.b r5, [r4+]
cmp #0, r5
bne 2b
rts
#else
mov r1, r4 ; Save a copy of the dest pointer. mov r1, r4 ; Save a copy of the dest pointer.
mov r2, r5 ; Save a copy of the source pointer. mov r2, r5 ; Save a copy of the source pointer.
@ -20,3 +36,6 @@ _strcat:
mov r4, r1 ; Return the original dest pointer. mov r4, r1 ; Return the original dest pointer.
rts rts
#endif
.size _strcat, . - _strcat

View File

@ -5,6 +5,21 @@
.global _strcmp .global _strcmp
.type _strcmp,@function .type _strcmp,@function
_strcmp: _strcmp:
#ifdef __RX_DISALLOW_STRING_INSNS__
2: mov.b [r1+], r4
mov.b [r2+], r5
cmp #0, r4
beq 3f
cmp #0, r5
beq 3f
cmp r4, r5
beq 2b
3: and #0xff, r4 ; We need to perform an unsigned comparison of the bytes.
and #0xff, r5
sub r5, r4, r1
rts
#else
mov #-1, r3 ; Strictly speaking this is incorrect, but I doubt if anyone will ever know. mov #-1, r3 ; Strictly speaking this is incorrect, but I doubt if anyone will ever know.
scmpu ; Perform the string comparison scmpu ; Perform the string comparison
bnc 1f ; If Carry is not set skip over bnc 1f ; If Carry is not set skip over
@ -13,3 +28,6 @@ _strcmp:
1: ; 1: ;
mov #-1,r1 ; Carry not set, result should be negative mov #-1,r1 ; Carry not set, result should be negative
rts ; rts ;
#endif
.size _strcmp, . - _strcmp

View File

@ -4,8 +4,22 @@
.global _strcpy .global _strcpy
.type _strcpy,@function .type _strcpy,@function
_strcpy: _strcpy:
;; R1: dest
;; R2: source
#ifdef __RX_DISALLOW_STRING_INSNS__
mov r1, r4 ; Leave the destination address unchanged in the result register.
1: mov.b [r2+], r5
mov.b r5, [r4+]
cmp #0, r5
bne 1b
rts
#else
mov r1, r4 mov r1, r4
mov #-1, r3 ; Strictly speaking this is incorrect, but I doubt if anyone will ever know. mov #-1, r3 ; Strictly speaking this is incorrect, but I doubt if anyone will ever know.
smovu smovu
mov r4, r1 mov r4, r1
rts rts
#endif
.size _strcpy, . - _strcpy

View File

@ -5,6 +5,17 @@
.global _strlen .global _strlen
.type _strlen,@function .type _strlen,@function
_strlen: _strlen:
#ifdef __RX_DISALLOW_STRING_INSNS__
mov r1, r4
1: mov.b [r1+], r5
cmp #0, r5
bne 1b
sub #1, r1
sub r4, r1
rts
#else
add #0, r1, r4 ; Save a copy of the string start address and set the condition flags. add #0, r1, r4 ; Save a copy of the string start address and set the condition flags.
beq null_string ; Test for a NULL pointer. beq null_string ; Test for a NULL pointer.
mov #-1, r3 ; Set a limit on the number of bytes examined. mov #-1, r3 ; Set a limit on the number of bytes examined.
@ -14,3 +25,5 @@ _strlen:
null_string: null_string:
sub r4, r1 ; Compute the length. sub r4, r1 ; Compute the length.
rts rts
#endif
.size _strlen, . - _strlen

View File

@ -7,7 +7,27 @@ _strncat:
;; On entry: r1 => Destination ;; On entry: r1 => Destination
;; r2 => Source ;; r2 => Source
;; r3 => Max number of bytes to copy ;; r3 => Max number of bytes to copy
#ifdef __RX_DISALLOW_STRING_INSNS__
cmp #0, r3 ; If max is zero we have nothing to do.
beq 2f
mov r1, r4 ; Leave the desintation pointer intact for the return value.
1: mov.b [r4+], r5 ; Find the NUL byte at the end of the destination.
cmp #0, r5
bne 1b
sub #1, r4
3: mov.b [r2+], r5 ; Copy bytes from the source into the destination ...
mov.b r5, [r4+]
cmp #0, r5 ; ... until we reach a NUL byte ...
beq 2f
sub #1, r3
bne 3b ; ... or we have copied N bytes.
2: rts
#else
mov r1, r4 ; Save a copy of the dest pointer. mov r1, r4 ; Save a copy of the dest pointer.
mov r2, r5 ; Save a copy of the source pointer. mov r2, r5 ; Save a copy of the source pointer.
mov r3, r14 ; Save a copy of the byte count. mov r3, r14 ; Save a copy of the byte count.
@ -33,3 +53,6 @@ _strncat:
1: 1:
mov r4, r1 ; Return the original dest pointer. mov r4, r1 ; Return the original dest pointer.
rts rts
#endif
.size _strncat, . - _strncat

View File

@ -4,6 +4,32 @@
.global _strncmp .global _strncmp
.type _strncmp,@function .type _strncmp,@function
_strncmp: _strncmp:
;; R1: string1
;; R2: string2
;; R3: max number of bytes to compare
#ifdef __RX_DISALLOW_STRING_INSNS__
cmp #0, r3 ; For a length of zero, return zero
beq 4f
2: mov.b [r1+], r4
mov.b [r2+], r5
cmp #0, r4
beq 3f
cmp #0, r5
beq 3f
sub #1, r3
beq 3f
cmp r4, r5
beq 2b
3: and #0xff, r4 ; We need to perform an unsigned comparison of the bytes.
and #0xff, r5
sub r5, r4, r1
rts
4: mov #0, r1
rts
#else
scmpu ; Perform the string comparison scmpu ; Perform the string comparison
bnc 1f ; If Carry is not set skip over bnc 1f ; If Carry is not set skip over
scne.L r1 ; Set result based on Z flag scne.L r1 ; Set result based on Z flag
@ -11,3 +37,5 @@ _strncmp:
1: ; 1: ;
mov #-1,r1 ; Carry not set, result should be negative mov #-1,r1 ; Carry not set, result should be negative
rts ; rts ;
#endif
.size _strncmp, . - _strncmp

View File

@ -4,6 +4,26 @@
.global _strncpy .global _strncpy
.type _strncpy,@function .type _strncpy,@function
_strncpy: _strncpy:
#ifdef __RX_DISALLOW_STRING_INSNS__
cmp #0, r3
beq 3f
mov r1, r4 ; Preserve R1 for the return value.
2: mov.b [r2+], r5 ; Copy bytes until...
mov.b r5, [r4+]
sub #1, r3
beq 3f ; ... our count reaches zero
cmp #0, r5
bne 2b ; ... or we have written a NUL byte
4: mov.b r5, [r4+] ; Continue to write further NUL bytes
sub #1, r3
bne 4b ; until the count reaches zero.
3: rts
#else
mov r1, r4 ; Save a copy of the dest pointer. mov r1, r4 ; Save a copy of the dest pointer.
mov r3, r5 ; Save a copy of the byte count mov r3, r5 ; Save a copy of the byte count
smovu ; Copy the bytes smovu ; Copy the bytes
@ -16,3 +36,6 @@ _strncpy:
1: 1:
mov r4, r1 ; Return the destination pointer mov r4, r1 ; Return the destination pointer
rts rts
#endif
.size _strncpy, . - _strncpy