This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: Update RX assembler files to conditionally avoid string instructions


Hi Guys,

  A problem has come to light with the RX string instructions (SMOVF,
  SUNTIL, etc).  They must not be used in the I/O address space as they 
  prefetch data from addresses that might be invalid.  So the attached
  patch adds alternative versions to all of the RX assembler source
  files that use these instructions, predicated on a C preprocessor
  macro called __RX_DISALLOW_STRING_INSNS__.  (A future patch to GCC
  will allow it to set this macro and create a multilib for it, but that
  has to wait until the gcc sources are unfrozen).

  Tested with no regressions on an rx-elf toolchain.

  OK to apply ?

Cheers
  Nick

newlib/ChangeLog
2015-04-08  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.

libgloss/ChangeLog
2015-04-08  Nick Clifton  <nickc@redhat.com>

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

diff --git a/libgloss/rx/crt0.S b/libgloss/rx/crt0.S
index 2227423..6d7089d 100644
--- a/libgloss/rx/crt0.S
+++ b/libgloss/rx/crt0.S
@@ -40,11 +40,24 @@ _start:
 	mov	#__stack, r0
 	mvtc	#__vectors, intb
 
+	/* Copy the .data section from ROM into RAM.  */
 	mov	#__datastart, r1
 	mov	#__romdatastart, r2
 	mov	#__romdatacopysize, r3
+#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	#0, r2
 	mov	#__bsssize, r3
diff --git a/newlib/libc/machine/rx/memchr.S b/newlib/libc/machine/rx/memchr.S
index 937753c..cdc97c8 100644
--- a/newlib/libc/machine/rx/memchr.S
+++ b/newlib/libc/machine/rx/memchr.S
@@ -5,9 +5,28 @@
 	.global  _memchr
 	.type	 _memchr,@function
 _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...
 	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.
 	stnz	#1, r1		; If no match was found return NULL.
 	sub	#1, r1		; suntil.b leaves r1 pointing at the address *after* the match.
 	rts
+#endif
+
+	.size _memchr, . - _memchr
+	
diff --git a/newlib/libc/machine/rx/memcpy.S b/newlib/libc/machine/rx/memcpy.S
index 3e0d500..eb671c0 100644
--- a/newlib/libc/machine/rx/memcpy.S
+++ b/newlib/libc/machine/rx/memcpy.S
@@ -4,7 +4,28 @@
 	.global  _memcpy
 	.type	 _memcpy,@function
 _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
 	smovf	    		; Copy R2 (source) to R1 (dest).  Stop after R3 bytes.
 	mov	r4, r1		; Return DEST
 	rts
+#endif
+	.size _memcpy, . - _memcpy
diff --git a/newlib/libc/machine/rx/memmove.S b/newlib/libc/machine/rx/memmove.S
index 4b126ba..60b7683 100644
--- a/newlib/libc/machine/rx/memmove.S
+++ b/newlib/libc/machine/rx/memmove.S
@@ -4,6 +4,39 @@
 	.global  _memmove
 	.type	 _memmove,@function
 _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
 	cmp	r1, r2
 	blt	2f		; If SRC (r2) is less than DEST (r1) then copy backwards
@@ -18,3 +51,7 @@ _memmove:
 	sub	#1, r1		; additions and subtractions.
 	smovb
 	bra	1b
+
+#endif /* SMOVF allowed.  */
+
+	.size _memmove, . - _memmove
diff --git a/newlib/libc/machine/rx/mempcpy.S b/newlib/libc/machine/rx/mempcpy.S
index c679d04..f824524 100644
--- a/newlib/libc/machine/rx/mempcpy.S
+++ b/newlib/libc/machine/rx/mempcpy.S
@@ -4,5 +4,22 @@
 	.global  _mempcpy
 	.type	 _mempcpy,@function
 _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
 	rts
+#endif
+	.size _mempcpy, . - _mempcpy
diff --git a/newlib/libc/machine/rx/memset.S b/newlib/libc/machine/rx/memset.S
index edab446..5ce7a3b 100644
--- a/newlib/libc/machine/rx/memset.S
+++ b/newlib/libc/machine/rx/memset.S
@@ -8,3 +8,6 @@ _memset:
 	sstr.b
 	mov	r4, r1
 	rts
+
+	.size _memset, . - _memset
+	
diff --git a/newlib/libc/machine/rx/strcat.S b/newlib/libc/machine/rx/strcat.S
index 7ceffb7..22533fc 100644
--- a/newlib/libc/machine/rx/strcat.S
+++ b/newlib/libc/machine/rx/strcat.S
@@ -6,6 +6,22 @@
 _strcat:
 	;; On entry: r1 => Destination
 	;;           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 	r2, r5		; Save a copy of the source pointer.
 	
@@ -20,3 +36,6 @@ _strcat:
 
 	mov	r4, r1		; Return the original dest pointer.
 	rts
+#endif
+	.size _strcat, . - _strcat
+	
diff --git a/newlib/libc/machine/rx/strcmp.S b/newlib/libc/machine/rx/strcmp.S
index 397415b..6a06e6c 100644
--- a/newlib/libc/machine/rx/strcmp.S
+++ b/newlib/libc/machine/rx/strcmp.S
@@ -5,6 +5,21 @@
 	.global  _strcmp
 	.type	 _strcmp,@function
 _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.
 	scmpu			; Perform the string comparison
 	bnc	1f		; If Carry is not set skip over
@@ -13,3 +28,6 @@ _strcmp:
 1:				;
 	mov	#-1,r1		; Carry not set, result should be negative
 	rts			;
+#endif
+	.size _strcmp, . - _strcmp
+	
diff --git a/newlib/libc/machine/rx/strcpy.S b/newlib/libc/machine/rx/strcpy.S
index a2dc174..05766cc 100644
--- a/newlib/libc/machine/rx/strcpy.S
+++ b/newlib/libc/machine/rx/strcpy.S
@@ -4,8 +4,22 @@
 	.global  _strcpy
 	.type	 _strcpy,@function
 _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	#-1, r3		; Strictly speaking this is incorrect, but I doubt if anyone will ever know.
 	smovu
 	mov	r4, r1
 	rts
+#endif
+	.size _strcpy, . - _strcpy
diff --git a/newlib/libc/machine/rx/strlen.S b/newlib/libc/machine/rx/strlen.S
index c07b429..bf12c0c 100644
--- a/newlib/libc/machine/rx/strlen.S
+++ b/newlib/libc/machine/rx/strlen.S
@@ -5,6 +5,17 @@
 	.global  _strlen
 	.type	 _strlen,@function
 _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.
 	beq     null_string	; Test for a NULL pointer.
 	mov	#-1, r3		; Set a limit on the number of bytes examined.
@@ -14,3 +25,5 @@ _strlen:
 null_string:
 	sub	r4, r1		; Compute the length.
 	rts
+#endif
+	.size _strlen, . - _strlen
diff --git a/newlib/libc/machine/rx/strncat.S b/newlib/libc/machine/rx/strncat.S
index 3bc6b75..ba544a4 100644
--- a/newlib/libc/machine/rx/strncat.S
+++ b/newlib/libc/machine/rx/strncat.S
@@ -7,7 +7,27 @@ _strncat:
 	;; On entry: r1 => Destination
 	;;           r2 => Source
 	;; 	     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 	r2, r5		; Save a copy of the source pointer.
 	mov 	r3, r14		; Save a copy of the byte count.
@@ -33,3 +53,6 @@ _strncat:
 1:	
 	mov	r4, r1		; Return the original dest pointer.
 	rts
+#endif
+	.size _strncat, . - _strncat
+	
diff --git a/newlib/libc/machine/rx/strncmp.S b/newlib/libc/machine/rx/strncmp.S
index 929e9cb..4be8076 100644
--- a/newlib/libc/machine/rx/strncmp.S
+++ b/newlib/libc/machine/rx/strncmp.S
@@ -4,6 +4,32 @@
 	.global  _strncmp
 	.type	 _strncmp,@function
 _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
 	bnc	1f		; If Carry is not set skip over
 	scne.L	r1		; Set result based on Z flag
@@ -11,3 +37,5 @@ _strncmp:
 1:				;
 	mov	#-1,r1		; Carry not set, result should be negative
 	rts			;
+#endif
+	.size _strncmp, . - _strncmp
diff --git a/newlib/libc/machine/rx/strncpy.S b/newlib/libc/machine/rx/strncpy.S
index e04922a..e5b6a83 100644
--- a/newlib/libc/machine/rx/strncpy.S
+++ b/newlib/libc/machine/rx/strncpy.S
@@ -4,6 +4,26 @@
 	.global  _strncpy
 	.type	 _strncpy,@function
 _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	r3, r5		; Save a copy of the byte count
 	smovu	    		; Copy the bytes
@@ -16,3 +36,6 @@ _strncpy:
 1:
 	mov	r4, r1		; Return the destination pointer
 	rts
+#endif
+	.size _strncpy, . - _strncpy
+	

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]