diff --git a/include/elf/rx.h b/include/elf/rx.h index 83980853e..c17128c48 100644 --- a/include/elf/rx.h +++ b/include/elf/rx.h @@ -120,6 +120,11 @@ END_RELOC_NUMBERS (R_RX_max) #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_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. */ #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. */ diff --git a/libgloss/ChangeLog b/libgloss/ChangeLog index fc3674ebc..37cb4a581 100644 --- a/libgloss/ChangeLog +++ b/libgloss/ChangeLog @@ -1,3 +1,8 @@ +2015-04-09 Nick Clifton + + * rx/crt0.S (_start): If string instructions are not allowed, + avoid using SMOVF. + 2015-04-08 Nick Clifton * rx/rx.ld: Add .note and DWARF3 sections. diff --git a/libgloss/rx/crt0.S b/libgloss/rx/crt0.S index 222742352..6d7089d4d 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 - 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 #0, r2 mov #__bsssize, r3 diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 470978d48..bca127755 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,17 @@ +2015-04-09 Nick Clifton + + * 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 * libc/include/stdint.h: Throughout add parens around MIN/MAX values. diff --git a/newlib/libc/machine/rx/memchr.S b/newlib/libc/machine/rx/memchr.S index 937753cef..cdc97c874 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 3e0d50001..eb671c0ae 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 4b126bafc..60b76836b 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 c679d04ce..f82452462 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 edab44620..5ce7a3bca 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 7ceffb744..22533fc8d 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 397415bb4..6a06e6c9d 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 a2dc17464..05766ccef 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 c07b429b2..bf12c0ce1 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 3bc6b75ae..ba544a43a 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 929e9cb0a..4be8076db 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 e04922a59..e5b6a83ac 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 +