root/arch/hexagon/mm/strnlen_user.S

/* [<][>][^][v][top][bottom][index][help] */
   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?  */
  32 fname:
  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 
  45 alignment_loop:
  46 fail_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 
  65 dw_loop:
  66 fail_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 
  93 end_check:
  94         {
  95                 P0 = cmp.gt(tmp1,mod8);
  96                 if (P0.new) jump:nt exit_error; /*  neverfound!  */
  97                 start = add(obo,tmp1);
  98         }
  99 
 100 exit_found:
 101         {
 102                 R0 = sub(start,isrc);
 103                 jumpr R31;
 104         }
 105 
 106 exit_error:
 107         {
 108                 R0 = add(max,#1);
 109                 jumpr R31;
 110         }
 111 
 112         /*  Uh, what does the "fixup" return here?  */
 113         .falign
 114 fix_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

/* [<][>][^][v][top][bottom][index][help] */