1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 /* 12 * This file contains the implementation of function 13 * WebRtcSpl_MaxAbsValueW16() 14 * 15 * The description header can be found in signal_processing_library.h. 16 * 17 */ 18 19 #include <assert.h> 20 21 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 22 23 // Maximum absolute value of word16 vector. 24 int16_t WebRtcSpl_MaxAbsValueW16_mips(const int16_t* vector, size_t length) { 25 int32_t totMax = 0; 26 int32_t tmp32_0, tmp32_1, tmp32_2, tmp32_3; 27 size_t i, loop_size; 28 29 assert(length > 0); 30 31 #if defined(MIPS_DSP_R1) 32 const int32_t* tmpvec32 = (int32_t*)vector; 33 loop_size = length >> 4; 34 35 for (i = 0; i < loop_size; i++) { 36 __asm__ volatile ( 37 "lw %[tmp32_0], 0(%[tmpvec32]) \n\t" 38 "lw %[tmp32_1], 4(%[tmpvec32]) \n\t" 39 "lw %[tmp32_2], 8(%[tmpvec32]) \n\t" 40 "lw %[tmp32_3], 12(%[tmpvec32]) \n\t" 41 42 "absq_s.ph %[tmp32_0], %[tmp32_0] \n\t" 43 "absq_s.ph %[tmp32_1], %[tmp32_1] \n\t" 44 "cmp.lt.ph %[totMax], %[tmp32_0] \n\t" 45 "pick.ph %[totMax], %[tmp32_0], %[totMax] \n\t" 46 47 "lw %[tmp32_0], 16(%[tmpvec32]) \n\t" 48 "absq_s.ph %[tmp32_2], %[tmp32_2] \n\t" 49 "cmp.lt.ph %[totMax], %[tmp32_1] \n\t" 50 "pick.ph %[totMax], %[tmp32_1], %[totMax] \n\t" 51 52 "lw %[tmp32_1], 20(%[tmpvec32]) \n\t" 53 "absq_s.ph %[tmp32_3], %[tmp32_3] \n\t" 54 "cmp.lt.ph %[totMax], %[tmp32_2] \n\t" 55 "pick.ph %[totMax], %[tmp32_2], %[totMax] \n\t" 56 57 "lw %[tmp32_2], 24(%[tmpvec32]) \n\t" 58 "cmp.lt.ph %[totMax], %[tmp32_3] \n\t" 59 "pick.ph %[totMax], %[tmp32_3], %[totMax] \n\t" 60 61 "lw %[tmp32_3], 28(%[tmpvec32]) \n\t" 62 "absq_s.ph %[tmp32_0], %[tmp32_0] \n\t" 63 "absq_s.ph %[tmp32_1], %[tmp32_1] \n\t" 64 "cmp.lt.ph %[totMax], %[tmp32_0] \n\t" 65 "pick.ph %[totMax], %[tmp32_0], %[totMax] \n\t" 66 67 "absq_s.ph %[tmp32_2], %[tmp32_2] \n\t" 68 "cmp.lt.ph %[totMax], %[tmp32_1] \n\t" 69 "pick.ph %[totMax], %[tmp32_1], %[totMax] \n\t" 70 "absq_s.ph %[tmp32_3], %[tmp32_3] \n\t" 71 "cmp.lt.ph %[totMax], %[tmp32_2] \n\t" 72 "pick.ph %[totMax], %[tmp32_2], %[totMax] \n\t" 73 74 "cmp.lt.ph %[totMax], %[tmp32_3] \n\t" 75 "pick.ph %[totMax], %[tmp32_3], %[totMax] \n\t" 76 77 "addiu %[tmpvec32], %[tmpvec32], 32 \n\t" 78 : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1), 79 [tmp32_2] "=&r" (tmp32_2), [tmp32_3] "=&r" (tmp32_3), 80 [totMax] "+r" (totMax), [tmpvec32] "+r" (tmpvec32) 81 : 82 : "memory" 83 ); 84 } 85 __asm__ volatile ( 86 "rotr %[tmp32_0], %[totMax], 16 \n\t" 87 "cmp.lt.ph %[totMax], %[tmp32_0] \n\t" 88 "pick.ph %[totMax], %[tmp32_0], %[totMax] \n\t" 89 "packrl.ph %[totMax], $0, %[totMax] \n\t" 90 : [tmp32_0] "=&r" (tmp32_0), [totMax] "+r" (totMax) 91 : 92 ); 93 loop_size = length & 0xf; 94 for (i = 0; i < loop_size; i++) { 95 __asm__ volatile ( 96 "lh %[tmp32_0], 0(%[tmpvec32]) \n\t" 97 "addiu %[tmpvec32], %[tmpvec32], 2 \n\t" 98 "absq_s.w %[tmp32_0], %[tmp32_0] \n\t" 99 "slt %[tmp32_1], %[totMax], %[tmp32_0] \n\t" 100 "movn %[totMax], %[tmp32_0], %[tmp32_1] \n\t" 101 : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1), 102 [tmpvec32] "+r" (tmpvec32), [totMax] "+r" (totMax) 103 : 104 : "memory" 105 ); 106 } 107 #else // #if defined(MIPS_DSP_R1) 108 int32_t v16MaxMax = WEBRTC_SPL_WORD16_MAX; 109 int32_t r, r1, r2, r3; 110 const int16_t* tmpvector = vector; 111 loop_size = length >> 4; 112 for (i = 0; i < loop_size; i++) { 113 __asm__ volatile ( 114 "lh %[tmp32_0], 0(%[tmpvector]) \n\t" 115 "lh %[tmp32_1], 2(%[tmpvector]) \n\t" 116 "lh %[tmp32_2], 4(%[tmpvector]) \n\t" 117 "lh %[tmp32_3], 6(%[tmpvector]) \n\t" 118 119 "abs %[tmp32_0], %[tmp32_0] \n\t" 120 "abs %[tmp32_1], %[tmp32_1] \n\t" 121 "abs %[tmp32_2], %[tmp32_2] \n\t" 122 "abs %[tmp32_3], %[tmp32_3] \n\t" 123 124 "slt %[r], %[totMax], %[tmp32_0] \n\t" 125 "movn %[totMax], %[tmp32_0], %[r] \n\t" 126 "slt %[r1], %[totMax], %[tmp32_1] \n\t" 127 "movn %[totMax], %[tmp32_1], %[r1] \n\t" 128 "slt %[r2], %[totMax], %[tmp32_2] \n\t" 129 "movn %[totMax], %[tmp32_2], %[r2] \n\t" 130 "slt %[r3], %[totMax], %[tmp32_3] \n\t" 131 "movn %[totMax], %[tmp32_3], %[r3] \n\t" 132 133 "lh %[tmp32_0], 8(%[tmpvector]) \n\t" 134 "lh %[tmp32_1], 10(%[tmpvector]) \n\t" 135 "lh %[tmp32_2], 12(%[tmpvector]) \n\t" 136 "lh %[tmp32_3], 14(%[tmpvector]) \n\t" 137 138 "abs %[tmp32_0], %[tmp32_0] \n\t" 139 "abs %[tmp32_1], %[tmp32_1] \n\t" 140 "abs %[tmp32_2], %[tmp32_2] \n\t" 141 "abs %[tmp32_3], %[tmp32_3] \n\t" 142 143 "slt %[r], %[totMax], %[tmp32_0] \n\t" 144 "movn %[totMax], %[tmp32_0], %[r] \n\t" 145 "slt %[r1], %[totMax], %[tmp32_1] \n\t" 146 "movn %[totMax], %[tmp32_1], %[r1] \n\t" 147 "slt %[r2], %[totMax], %[tmp32_2] \n\t" 148 "movn %[totMax], %[tmp32_2], %[r2] \n\t" 149 "slt %[r3], %[totMax], %[tmp32_3] \n\t" 150 "movn %[totMax], %[tmp32_3], %[r3] \n\t" 151 152 "lh %[tmp32_0], 16(%[tmpvector]) \n\t" 153 "lh %[tmp32_1], 18(%[tmpvector]) \n\t" 154 "lh %[tmp32_2], 20(%[tmpvector]) \n\t" 155 "lh %[tmp32_3], 22(%[tmpvector]) \n\t" 156 157 "abs %[tmp32_0], %[tmp32_0] \n\t" 158 "abs %[tmp32_1], %[tmp32_1] \n\t" 159 "abs %[tmp32_2], %[tmp32_2] \n\t" 160 "abs %[tmp32_3], %[tmp32_3] \n\t" 161 162 "slt %[r], %[totMax], %[tmp32_0] \n\t" 163 "movn %[totMax], %[tmp32_0], %[r] \n\t" 164 "slt %[r1], %[totMax], %[tmp32_1] \n\t" 165 "movn %[totMax], %[tmp32_1], %[r1] \n\t" 166 "slt %[r2], %[totMax], %[tmp32_2] \n\t" 167 "movn %[totMax], %[tmp32_2], %[r2] \n\t" 168 "slt %[r3], %[totMax], %[tmp32_3] \n\t" 169 "movn %[totMax], %[tmp32_3], %[r3] \n\t" 170 171 "lh %[tmp32_0], 24(%[tmpvector]) \n\t" 172 "lh %[tmp32_1], 26(%[tmpvector]) \n\t" 173 "lh %[tmp32_2], 28(%[tmpvector]) \n\t" 174 "lh %[tmp32_3], 30(%[tmpvector]) \n\t" 175 176 "abs %[tmp32_0], %[tmp32_0] \n\t" 177 "abs %[tmp32_1], %[tmp32_1] \n\t" 178 "abs %[tmp32_2], %[tmp32_2] \n\t" 179 "abs %[tmp32_3], %[tmp32_3] \n\t" 180 181 "slt %[r], %[totMax], %[tmp32_0] \n\t" 182 "movn %[totMax], %[tmp32_0], %[r] \n\t" 183 "slt %[r1], %[totMax], %[tmp32_1] \n\t" 184 "movn %[totMax], %[tmp32_1], %[r1] \n\t" 185 "slt %[r2], %[totMax], %[tmp32_2] \n\t" 186 "movn %[totMax], %[tmp32_2], %[r2] \n\t" 187 "slt %[r3], %[totMax], %[tmp32_3] \n\t" 188 "movn %[totMax], %[tmp32_3], %[r3] \n\t" 189 190 "addiu %[tmpvector], %[tmpvector], 32 \n\t" 191 : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1), 192 [tmp32_2] "=&r" (tmp32_2), [tmp32_3] "=&r" (tmp32_3), 193 [totMax] "+r" (totMax), [r] "=&r" (r), [tmpvector] "+r" (tmpvector), 194 [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3) 195 : 196 : "memory" 197 ); 198 } 199 loop_size = length & 0xf; 200 for (i = 0; i < loop_size; i++) { 201 __asm__ volatile ( 202 "lh %[tmp32_0], 0(%[tmpvector]) \n\t" 203 "addiu %[tmpvector], %[tmpvector], 2 \n\t" 204 "abs %[tmp32_0], %[tmp32_0] \n\t" 205 "slt %[tmp32_1], %[totMax], %[tmp32_0] \n\t" 206 "movn %[totMax], %[tmp32_0], %[tmp32_1] \n\t" 207 : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1), 208 [tmpvector] "+r" (tmpvector), [totMax] "+r" (totMax) 209 : 210 : "memory" 211 ); 212 } 213 214 __asm__ volatile ( 215 "slt %[r], %[v16MaxMax], %[totMax] \n\t" 216 "movn %[totMax], %[v16MaxMax], %[r] \n\t" 217 : [totMax] "+r" (totMax), [r] "=&r" (r) 218 : [v16MaxMax] "r" (v16MaxMax) 219 ); 220 #endif // #if defined(MIPS_DSP_R1) 221 return (int16_t)totMax; 222 } 223 224 #if defined(MIPS_DSP_R1_LE) 225 // Maximum absolute value of word32 vector. Version for MIPS platform. 226 int32_t WebRtcSpl_MaxAbsValueW32_mips(const int32_t* vector, size_t length) { 227 // Use uint32_t for the local variables, to accommodate the return value 228 // of abs(0x80000000), which is 0x80000000. 229 230 uint32_t absolute = 0, maximum = 0; 231 int tmp1 = 0, max_value = 0x7fffffff; 232 233 assert(length > 0); 234 235 __asm__ volatile ( 236 ".set push \n\t" 237 ".set noreorder \n\t" 238 239 "1: \n\t" 240 "lw %[absolute], 0(%[vector]) \n\t" 241 "absq_s.w %[absolute], %[absolute] \n\t" 242 "addiu %[length], %[length], -1 \n\t" 243 "slt %[tmp1], %[maximum], %[absolute] \n\t" 244 "movn %[maximum], %[absolute], %[tmp1] \n\t" 245 "bgtz %[length], 1b \n\t" 246 " addiu %[vector], %[vector], 4 \n\t" 247 "slt %[tmp1], %[max_value], %[maximum] \n\t" 248 "movn %[maximum], %[max_value], %[tmp1] \n\t" 249 250 ".set pop \n\t" 251 252 : [tmp1] "=&r" (tmp1), [maximum] "+r" (maximum), [absolute] "+r" (absolute) 253 : [vector] "r" (vector), [length] "r" (length), [max_value] "r" (max_value) 254 : "memory" 255 ); 256 257 return (int32_t)maximum; 258 } 259 #endif // #if defined(MIPS_DSP_R1_LE) 260 261 // Maximum value of word16 vector. Version for MIPS platform. 262 int16_t WebRtcSpl_MaxValueW16_mips(const int16_t* vector, size_t length) { 263 int16_t maximum = WEBRTC_SPL_WORD16_MIN; 264 int tmp1; 265 int16_t value; 266 267 assert(length > 0); 268 269 __asm__ volatile ( 270 ".set push \n\t" 271 ".set noreorder \n\t" 272 273 "1: \n\t" 274 "lh %[value], 0(%[vector]) \n\t" 275 "addiu %[length], %[length], -1 \n\t" 276 "slt %[tmp1], %[maximum], %[value] \n\t" 277 "movn %[maximum], %[value], %[tmp1] \n\t" 278 "bgtz %[length], 1b \n\t" 279 " addiu %[vector], %[vector], 2 \n\t" 280 ".set pop \n\t" 281 282 : [tmp1] "=&r" (tmp1), [maximum] "+r" (maximum), [value] "=&r" (value) 283 : [vector] "r" (vector), [length] "r" (length) 284 : "memory" 285 ); 286 287 return maximum; 288 } 289 290 // Maximum value of word32 vector. Version for MIPS platform. 291 int32_t WebRtcSpl_MaxValueW32_mips(const int32_t* vector, size_t length) { 292 int32_t maximum = WEBRTC_SPL_WORD32_MIN; 293 int tmp1, value; 294 295 assert(length > 0); 296 297 __asm__ volatile ( 298 ".set push \n\t" 299 ".set noreorder \n\t" 300 301 "1: \n\t" 302 "lw %[value], 0(%[vector]) \n\t" 303 "addiu %[length], %[length], -1 \n\t" 304 "slt %[tmp1], %[maximum], %[value] \n\t" 305 "movn %[maximum], %[value], %[tmp1] \n\t" 306 "bgtz %[length], 1b \n\t" 307 " addiu %[vector], %[vector], 4 \n\t" 308 309 ".set pop \n\t" 310 311 : [tmp1] "=&r" (tmp1), [maximum] "+r" (maximum), [value] "=&r" (value) 312 : [vector] "r" (vector), [length] "r" (length) 313 : "memory" 314 ); 315 316 return maximum; 317 } 318 319 // Minimum value of word16 vector. Version for MIPS platform. 320 int16_t WebRtcSpl_MinValueW16_mips(const int16_t* vector, size_t length) { 321 int16_t minimum = WEBRTC_SPL_WORD16_MAX; 322 int tmp1; 323 int16_t value; 324 325 assert(length > 0); 326 327 __asm__ volatile ( 328 ".set push \n\t" 329 ".set noreorder \n\t" 330 331 "1: \n\t" 332 "lh %[value], 0(%[vector]) \n\t" 333 "addiu %[length], %[length], -1 \n\t" 334 "slt %[tmp1], %[value], %[minimum] \n\t" 335 "movn %[minimum], %[value], %[tmp1] \n\t" 336 "bgtz %[length], 1b \n\t" 337 " addiu %[vector], %[vector], 2 \n\t" 338 339 ".set pop \n\t" 340 341 : [tmp1] "=&r" (tmp1), [minimum] "+r" (minimum), [value] "=&r" (value) 342 : [vector] "r" (vector), [length] "r" (length) 343 : "memory" 344 ); 345 346 return minimum; 347 } 348 349 // Minimum value of word32 vector. Version for MIPS platform. 350 int32_t WebRtcSpl_MinValueW32_mips(const int32_t* vector, size_t length) { 351 int32_t minimum = WEBRTC_SPL_WORD32_MAX; 352 int tmp1, value; 353 354 assert(length > 0); 355 356 __asm__ volatile ( 357 ".set push \n\t" 358 ".set noreorder \n\t" 359 360 "1: \n\t" 361 "lw %[value], 0(%[vector]) \n\t" 362 "addiu %[length], %[length], -1 \n\t" 363 "slt %[tmp1], %[value], %[minimum] \n\t" 364 "movn %[minimum], %[value], %[tmp1] \n\t" 365 "bgtz %[length], 1b \n\t" 366 " addiu %[vector], %[vector], 4 \n\t" 367 368 ".set pop \n\t" 369 370 : [tmp1] "=&r" (tmp1), [minimum] "+r" (minimum), [value] "=&r" (value) 371 : [vector] "r" (vector), [length] "r" (length) 372 : "memory" 373 ); 374 375 return minimum; 376 } 377