On Tue, 20 Jan 2026 14:58:50 +0800, Feng Jiang wrote:
> diff --git a/arch/riscv/lib/strnlen.S b/arch/riscv/lib/strnlen.S

Branches that test maxlen can be replaced with Zbb minu instruction.
(see below)

> +     /*
> +      * Returns
> +      *   a0 - String length
> +      *
> +      * Parameters
> +      *   a0 - String to measure
> +      *   a1 - Max length of string
> +      *
> +      * Clobbers
> +      *   t0, t1, t2, t3, t4
> +      */
> +
> +     /* If maxlen is 0, return 0. */
> +     beqz    a1, 3f
> +
> +     /* Number of irrelevant bytes in the first word. */
> +     andi    t2, a0, SZREG-1
> +
> +     /* Align pointer. */
> +     andi    t0, a0, -SZREG
> +
> +     li      t3, SZREG
> +     sub     t3, t3, t2
> +     slli    t2, t2, 3
> +
> +     /* Aligned boundary. */
> +     add     t4, a0, a1
> +     andi    t4, t4, -SZREG
> +
> +     /* Get the first word.  */
> +     REG_L   t1, 0(t0)
> +
> +     /*
> +      * Shift away the partial data we loaded to remove the irrelevant bytes
> +      * preceding the string with the effect of adding NUL bytes at the
> +      * end of the string's first word.
> +      */
> +     SHIFT   t1, t1, t2
> +
> +     /* Convert non-NUL into 0xff and NUL into 0x00. */
> +     orc.b   t1, t1
> +
> +     /* Convert non-NUL into 0x00 and NUL into 0xff. */
> +     not     t1, t1
> +
> +     /*
> +      * Search for the first set bit (corresponding to a NUL byte in the
> +      * original chunk).
> +      */
> +     CZ      t1, t1
> +
> +     /*
> +      * The first chunk is special: compare against the number
> +      * of valid bytes in this chunk.
> +      */
> +     srli    a0, t1, 3
> +
> +     /* Limit the result by maxlen. */
> +     bleu    a1, a0, 3f

minu    a0, a0, a1

> +
> +     bgtu    t3, a0, 2f
> +
> +     /* Prepare for the word comparison loop. */
> +     addi    t2, t0, SZREG
> +     li      t3, -1
> +
> +     /*
> +      * Our critical loop is 4 instructions and processes data in
> +      * 4 byte or 8 byte chunks.
> +      */
> +     .p2align 3
> +1:
> +     REG_L   t1, SZREG(t0)
> +     addi    t0, t0, SZREG
> +     orc.b   t1, t1
> +     bgeu    t0, t4, 4f
> +     beq     t1, t3, 1b
> +4:
> +     not     t1, t1
> +     CZ      t1, t1
> +     srli    t1, t1, 3
> +
> +     /* Get number of processed bytes. */
> +     sub     t2, t0, t2
> +
> +     /* Add number of characters in the first word.  */
> +     add     a0, a0, t2
> +
> +     /* Add number of characters in the last word.  */
> +     add     a0, a0, t1
> +
> +     /* Ensure the final result does not exceed maxlen. */
> +     bgeu    a0, a1, 3f

minu    a0, a0, a1

> +2:
> +     ret
> +3:
> +     mv      a0, a1
> +     ret
> +
> +.option pop

--
Qingfang

Reply via email to