linux/arch/hexagon/mm/strnlen_user.S
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * User string length functions for kernel
   4 *
   5 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
   6 */
   7
   8#define isrc    r0
   9#define max     r1      /*  Do not change!  */
  10
  11#define end     r2
  12#define tmp1    r3
  13
  14#define obo     r6      /*  off-by-one  */
  15#define start   r7
  16#define mod8    r8
  17#define dbuf    r15:14
  18#define dcmp    r13:12
  19
  20/*
  21 * The vector mask version of this turned out *really* badly.
  22 * The hardware loop version also turned out *really* badly.
  23 * Seems straight pointer arithmetic basically wins here.
  24 */
  25
  26#define fname __strnlen_user
  27
  28        .text
  29        .global fname
  30        .type fname, @function
  31        .p2align 5  /*  why?  */
  32fname:
  33        {
  34                mod8 = and(isrc,#7);
  35                end = add(isrc,max);
  36                start = isrc;
  37        }
  38        {
  39                P0 = cmp.eq(mod8,#0);
  40                mod8 = and(end,#7);
  41                dcmp = #0;
  42                if (P0.new) jump:t dw_loop;     /*  fire up the oven  */
  43        }
  44
  45alignment_loop:
  46fail_1: {
  47                tmp1 = memb(start++#1);
  48        }
  49        {
  50                P0 = cmp.eq(tmp1,#0);
  51                if (P0.new) jump:nt exit_found;
  52                P1 = cmp.gtu(end,start);
  53                mod8 = and(start,#7);
  54        }
  55        {
  56                if (!P1) jump exit_error;  /*  hit the end  */
  57                P0 = cmp.eq(mod8,#0);
  58        }
  59        {
  60                if (!P0) jump alignment_loop;
  61        }
  62
  63
  64
  65dw_loop:
  66fail_2: {
  67                dbuf = memd(start);
  68                obo = add(start,#1);
  69        }
  70        {
  71                P0 = vcmpb.eq(dbuf,dcmp);
  72        }
  73        {
  74                tmp1 = P0;
  75                P0 = cmp.gtu(end,start);
  76        }
  77        {
  78                tmp1 = ct0(tmp1);
  79                mod8 = and(end,#7);
  80                if (!P0) jump end_check;
  81        }
  82        {
  83                P0 = cmp.eq(tmp1,#32);
  84                if (!P0.new) jump:nt exit_found;
  85                if (!P0.new) start = add(obo,tmp1);
  86        }
  87        {
  88                start = add(start,#8);
  89                jump dw_loop;
  90        }       /*  might be nice to combine these jumps...   */
  91
  92
  93end_check:
  94        {
  95                P0 = cmp.gt(tmp1,mod8);
  96                if (P0.new) jump:nt exit_error; /*  neverfound!  */
  97                start = add(obo,tmp1);
  98        }
  99
 100exit_found:
 101        {
 102                R0 = sub(start,isrc);
 103                jumpr R31;
 104        }
 105
 106exit_error:
 107        {
 108                R0 = add(max,#1);
 109                jumpr R31;
 110        }
 111
 112        /*  Uh, what does the "fixup" return here?  */
 113        .falign
 114fix_1:
 115        {
 116                R0 = #0;
 117                jumpr R31;
 118        }
 119
 120        .size fname,.-fname
 121
 122
 123.section __ex_table,"a"
 124.long fail_1,fix_1
 125.long fail_2,fix_1
 126.previous
 127