1 /* 2 * jsimd_arm64.c 3 * 4 * Copyright 2009 Pierre Ossman <ossman (at) cendio.se> for Cendio AB 5 * Copyright (C) 2009-2011, 2013-2014, 2016, D. R. Commander. 6 * Copyright (C) 2015-2016, Matthieu Darbois. 7 * 8 * Based on the x86 SIMD extension for IJG JPEG library, 9 * Copyright (C) 1999-2006, MIYASAKA Masaru. 10 * For conditions of distribution and use, see copyright notice in jsimdext.inc 11 * 12 * This file contains the interface between the "normal" portions 13 * of the library and the SIMD implementations when running on a 14 * 64-bit ARM architecture. 15 */ 16 17 #define JPEG_INTERNALS 18 #include "../jinclude.h" 19 #include "../jpeglib.h" 20 #include "../jsimd.h" 21 #include "../jdct.h" 22 #include "../jsimddct.h" 23 #include "jsimd.h" 24 25 #include <stdio.h> 26 #include <string.h> 27 #include <ctype.h> 28 29 #define JSIMD_FASTLD3 1 30 #define JSIMD_FASTST3 2 31 #define JSIMD_FASTTBL 4 32 33 static unsigned int simd_support = ~0; 34 static unsigned int simd_huffman = 1; 35 static unsigned int simd_features = JSIMD_FASTLD3 | JSIMD_FASTST3 | 36 JSIMD_FASTTBL; 37 38 #if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) 39 40 #define SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT (1024 * 1024) 41 42 LOCAL(int) 43 check_cpuinfo (char *buffer, const char *field, char *value) 44 { 45 char *p; 46 if (*value == 0) 47 return 0; 48 if (strncmp(buffer, field, strlen(field)) != 0) 49 return 0; 50 buffer += strlen(field); 51 while (isspace(*buffer)) 52 buffer++; 53 54 /* Check if 'value' is present in the buffer as a separate word */ 55 while ((p = strstr(buffer, value))) { 56 if (p > buffer && !isspace(*(p - 1))) { 57 buffer++; 58 continue; 59 } 60 p += strlen(value); 61 if (*p != 0 && !isspace(*p)) { 62 buffer++; 63 continue; 64 } 65 return 1; 66 } 67 return 0; 68 } 69 70 LOCAL(int) 71 parse_proc_cpuinfo (int bufsize) 72 { 73 char *buffer = (char *)malloc(bufsize); 74 FILE *fd; 75 76 if (!buffer) 77 return 0; 78 79 fd = fopen("/proc/cpuinfo", "r"); 80 if (fd) { 81 while (fgets(buffer, bufsize, fd)) { 82 if (!strchr(buffer, '\n') && !feof(fd)) { 83 /* "impossible" happened - insufficient size of the buffer! */ 84 fclose(fd); 85 free(buffer); 86 return 0; 87 } 88 if (check_cpuinfo(buffer, "CPU part", "0xd03") || 89 check_cpuinfo(buffer, "CPU part", "0xd07")) 90 /* The Cortex-A53 has a slow tbl implementation. We can gain a few 91 percent speedup by disabling the use of that instruction. The 92 speedup on Cortex-A57 is more subtle but still measurable. */ 93 simd_features &= ~JSIMD_FASTTBL; 94 else if (check_cpuinfo(buffer, "CPU part", "0x0a1")) 95 /* The SIMD version of Huffman encoding is slower than the C version on 96 Cavium ThunderX. Also, ld3 and st3 are abyssmally slow on that 97 CPU. */ 98 simd_huffman = simd_features = 0; 99 } 100 fclose(fd); 101 } 102 free(buffer); 103 return 1; 104 } 105 106 #endif 107 108 /* 109 * Check what SIMD accelerations are supported. 110 * 111 * FIXME: This code is racy under a multi-threaded environment. 112 */ 113 114 /* 115 * ARMv8 architectures support NEON extensions by default. 116 * It is no longer optional as it was with ARMv7. 117 */ 118 119 120 LOCAL(void) 121 init_simd (void) 122 { 123 char *env = NULL; 124 #if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) 125 int bufsize = 1024; /* an initial guess for the line buffer size limit */ 126 #endif 127 128 if (simd_support != ~0U) 129 return; 130 131 simd_support = 0; 132 133 simd_support |= JSIMD_ARM_NEON; 134 #if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) 135 while (!parse_proc_cpuinfo(bufsize)) { 136 bufsize *= 2; 137 if (bufsize > SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT) 138 break; 139 } 140 #endif 141 142 /* Force different settings through environment variables */ 143 env = getenv("JSIMD_FORCENEON"); 144 if ((env != NULL) && (strcmp(env, "1") == 0)) 145 simd_support = JSIMD_ARM_NEON; 146 env = getenv("JSIMD_FORCENONE"); 147 if ((env != NULL) && (strcmp(env, "1") == 0)) 148 simd_support = 0; 149 env = getenv("JSIMD_NOHUFFENC"); 150 if ((env != NULL) && (strcmp(env, "1") == 0)) 151 simd_huffman = 0; 152 env = getenv("JSIMD_FASTLD3"); 153 if ((env != NULL) && (strcmp(env, "1") == 0)) 154 simd_features |= JSIMD_FASTLD3; 155 if ((env != NULL) && (strcmp(env, "0") == 0)) 156 simd_features &= ~JSIMD_FASTLD3; 157 env = getenv("JSIMD_FASTST3"); 158 if ((env != NULL) && (strcmp(env, "1") == 0)) 159 simd_features |= JSIMD_FASTST3; 160 if ((env != NULL) && (strcmp(env, "0") == 0)) 161 simd_features &= ~JSIMD_FASTST3; 162 } 163 164 GLOBAL(int) 165 jsimd_can_rgb_ycc (void) 166 { 167 init_simd(); 168 169 /* The code is optimised for these values only */ 170 if (BITS_IN_JSAMPLE != 8) 171 return 0; 172 if (sizeof(JDIMENSION) != 4) 173 return 0; 174 if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4)) 175 return 0; 176 177 if (simd_support & JSIMD_ARM_NEON) 178 return 1; 179 180 return 0; 181 } 182 183 GLOBAL(int) 184 jsimd_can_rgb_gray (void) 185 { 186 init_simd(); 187 188 return 0; 189 } 190 191 GLOBAL(int) 192 jsimd_can_ycc_rgb (void) 193 { 194 init_simd(); 195 196 /* The code is optimised for these values only */ 197 if (BITS_IN_JSAMPLE != 8) 198 return 0; 199 if (sizeof(JDIMENSION) != 4) 200 return 0; 201 if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4)) 202 return 0; 203 204 if (simd_support & JSIMD_ARM_NEON) 205 return 1; 206 207 return 0; 208 } 209 210 GLOBAL(int) 211 jsimd_can_ycc_rgb565 (void) 212 { 213 init_simd(); 214 215 /* The code is optimised for these values only */ 216 if (BITS_IN_JSAMPLE != 8) 217 return 0; 218 if (sizeof(JDIMENSION) != 4) 219 return 0; 220 221 if (simd_support & JSIMD_ARM_NEON) 222 return 1; 223 224 return 0; 225 } 226 227 GLOBAL(void) 228 jsimd_rgb_ycc_convert (j_compress_ptr cinfo, 229 JSAMPARRAY input_buf, JSAMPIMAGE output_buf, 230 JDIMENSION output_row, int num_rows) 231 { 232 void (*neonfct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int); 233 234 switch(cinfo->in_color_space) { 235 case JCS_EXT_RGB: 236 if (simd_features & JSIMD_FASTLD3) 237 neonfct=jsimd_extrgb_ycc_convert_neon; 238 else 239 neonfct=jsimd_extrgb_ycc_convert_neon_slowld3; 240 break; 241 case JCS_EXT_RGBX: 242 case JCS_EXT_RGBA: 243 neonfct=jsimd_extrgbx_ycc_convert_neon; 244 break; 245 case JCS_EXT_BGR: 246 if (simd_features & JSIMD_FASTLD3) 247 neonfct=jsimd_extbgr_ycc_convert_neon; 248 else 249 neonfct=jsimd_extbgr_ycc_convert_neon_slowld3; 250 break; 251 case JCS_EXT_BGRX: 252 case JCS_EXT_BGRA: 253 neonfct=jsimd_extbgrx_ycc_convert_neon; 254 break; 255 case JCS_EXT_XBGR: 256 case JCS_EXT_ABGR: 257 neonfct=jsimd_extxbgr_ycc_convert_neon; 258 break; 259 case JCS_EXT_XRGB: 260 case JCS_EXT_ARGB: 261 neonfct=jsimd_extxrgb_ycc_convert_neon; 262 break; 263 default: 264 if (simd_features & JSIMD_FASTLD3) 265 neonfct=jsimd_extrgb_ycc_convert_neon; 266 else 267 neonfct=jsimd_extrgb_ycc_convert_neon_slowld3; 268 break; 269 } 270 271 neonfct(cinfo->image_width, input_buf, output_buf, output_row, num_rows); 272 } 273 274 GLOBAL(void) 275 jsimd_rgb_gray_convert (j_compress_ptr cinfo, 276 JSAMPARRAY input_buf, JSAMPIMAGE output_buf, 277 JDIMENSION output_row, int num_rows) 278 { 279 } 280 281 GLOBAL(void) 282 jsimd_ycc_rgb_convert (j_decompress_ptr cinfo, 283 JSAMPIMAGE input_buf, JDIMENSION input_row, 284 JSAMPARRAY output_buf, int num_rows) 285 { 286 void (*neonfct)(JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY, int); 287 288 switch(cinfo->out_color_space) { 289 case JCS_EXT_RGB: 290 if (simd_features & JSIMD_FASTST3) 291 neonfct=jsimd_ycc_extrgb_convert_neon; 292 else 293 neonfct=jsimd_ycc_extrgb_convert_neon_slowst3; 294 break; 295 case JCS_EXT_RGBX: 296 case JCS_EXT_RGBA: 297 neonfct=jsimd_ycc_extrgbx_convert_neon; 298 break; 299 case JCS_EXT_BGR: 300 if (simd_features & JSIMD_FASTST3) 301 neonfct=jsimd_ycc_extbgr_convert_neon; 302 else 303 neonfct=jsimd_ycc_extbgr_convert_neon_slowst3; 304 break; 305 case JCS_EXT_BGRX: 306 case JCS_EXT_BGRA: 307 neonfct=jsimd_ycc_extbgrx_convert_neon; 308 break; 309 case JCS_EXT_XBGR: 310 case JCS_EXT_ABGR: 311 neonfct=jsimd_ycc_extxbgr_convert_neon; 312 break; 313 case JCS_EXT_XRGB: 314 case JCS_EXT_ARGB: 315 neonfct=jsimd_ycc_extxrgb_convert_neon; 316 break; 317 default: 318 if (simd_features & JSIMD_FASTST3) 319 neonfct=jsimd_ycc_extrgb_convert_neon; 320 else 321 neonfct=jsimd_ycc_extrgb_convert_neon_slowst3; 322 break; 323 } 324 325 neonfct(cinfo->output_width, input_buf, input_row, output_buf, num_rows); 326 } 327 328 GLOBAL(void) 329 jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo, 330 JSAMPIMAGE input_buf, JDIMENSION input_row, 331 JSAMPARRAY output_buf, int num_rows) 332 { 333 jsimd_ycc_rgb565_convert_neon(cinfo->output_width, input_buf, input_row, 334 output_buf, num_rows); 335 } 336 337 GLOBAL(int) 338 jsimd_can_h2v2_downsample (void) 339 { 340 init_simd(); 341 342 /* The code is optimised for these values only */ 343 if (BITS_IN_JSAMPLE != 8) 344 return 0; 345 if (DCTSIZE != 8) 346 return 0; 347 if (sizeof(JDIMENSION) != 4) 348 return 0; 349 350 if (simd_support & JSIMD_ARM_NEON) 351 return 1; 352 353 return 0; 354 } 355 356 GLOBAL(int) 357 jsimd_can_h2v1_downsample (void) 358 { 359 init_simd(); 360 361 /* The code is optimised for these values only */ 362 if (BITS_IN_JSAMPLE != 8) 363 return 0; 364 if (DCTSIZE != 8) 365 return 0; 366 if (sizeof(JDIMENSION) != 4) 367 return 0; 368 369 if (simd_support & JSIMD_ARM_NEON) 370 return 1; 371 372 return 0; 373 } 374 375 GLOBAL(void) 376 jsimd_h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, 377 JSAMPARRAY input_data, JSAMPARRAY output_data) 378 { 379 jsimd_h2v2_downsample_neon(cinfo->image_width, cinfo->max_v_samp_factor, 380 compptr->v_samp_factor, compptr->width_in_blocks, 381 input_data, output_data); 382 } 383 384 GLOBAL(void) 385 jsimd_h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, 386 JSAMPARRAY input_data, JSAMPARRAY output_data) 387 { 388 jsimd_h2v1_downsample_neon(cinfo->image_width, cinfo->max_v_samp_factor, 389 compptr->v_samp_factor, compptr->width_in_blocks, 390 input_data, output_data); 391 } 392 393 GLOBAL(int) 394 jsimd_can_h2v2_upsample (void) 395 { 396 init_simd(); 397 398 return 0; 399 } 400 401 GLOBAL(int) 402 jsimd_can_h2v1_upsample (void) 403 { 404 init_simd(); 405 406 return 0; 407 } 408 409 GLOBAL(void) 410 jsimd_h2v2_upsample (j_decompress_ptr cinfo, 411 jpeg_component_info *compptr, 412 JSAMPARRAY input_data, 413 JSAMPARRAY *output_data_ptr) 414 { 415 } 416 417 GLOBAL(void) 418 jsimd_h2v1_upsample (j_decompress_ptr cinfo, 419 jpeg_component_info *compptr, 420 JSAMPARRAY input_data, 421 JSAMPARRAY *output_data_ptr) 422 { 423 } 424 425 GLOBAL(int) 426 jsimd_can_h2v2_fancy_upsample (void) 427 { 428 init_simd(); 429 430 return 0; 431 } 432 433 GLOBAL(int) 434 jsimd_can_h2v1_fancy_upsample (void) 435 { 436 init_simd(); 437 438 return 0; 439 } 440 441 GLOBAL(void) 442 jsimd_h2v2_fancy_upsample (j_decompress_ptr cinfo, 443 jpeg_component_info *compptr, 444 JSAMPARRAY input_data, 445 JSAMPARRAY *output_data_ptr) 446 { 447 } 448 449 GLOBAL(void) 450 jsimd_h2v1_fancy_upsample (j_decompress_ptr cinfo, 451 jpeg_component_info *compptr, 452 JSAMPARRAY input_data, 453 JSAMPARRAY *output_data_ptr) 454 { 455 } 456 457 GLOBAL(int) 458 jsimd_can_h2v2_merged_upsample (void) 459 { 460 init_simd(); 461 462 return 0; 463 } 464 465 GLOBAL(int) 466 jsimd_can_h2v1_merged_upsample (void) 467 { 468 init_simd(); 469 470 return 0; 471 } 472 473 GLOBAL(void) 474 jsimd_h2v2_merged_upsample (j_decompress_ptr cinfo, 475 JSAMPIMAGE input_buf, 476 JDIMENSION in_row_group_ctr, 477 JSAMPARRAY output_buf) 478 { 479 } 480 481 GLOBAL(void) 482 jsimd_h2v1_merged_upsample (j_decompress_ptr cinfo, 483 JSAMPIMAGE input_buf, 484 JDIMENSION in_row_group_ctr, 485 JSAMPARRAY output_buf) 486 { 487 } 488 489 GLOBAL(int) 490 jsimd_can_convsamp (void) 491 { 492 init_simd(); 493 494 /* The code is optimised for these values only */ 495 if (DCTSIZE != 8) 496 return 0; 497 if (BITS_IN_JSAMPLE != 8) 498 return 0; 499 if (sizeof(JDIMENSION) != 4) 500 return 0; 501 if (sizeof(DCTELEM) != 2) 502 return 0; 503 504 if (simd_support & JSIMD_ARM_NEON) 505 return 1; 506 507 return 0; 508 } 509 510 GLOBAL(int) 511 jsimd_can_convsamp_float (void) 512 { 513 init_simd(); 514 515 return 0; 516 } 517 518 GLOBAL(void) 519 jsimd_convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, 520 DCTELEM *workspace) 521 { 522 jsimd_convsamp_neon(sample_data, start_col, workspace); 523 } 524 525 GLOBAL(void) 526 jsimd_convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, 527 FAST_FLOAT *workspace) 528 { 529 } 530 531 GLOBAL(int) 532 jsimd_can_fdct_islow (void) 533 { 534 init_simd(); 535 536 /* The code is optimised for these values only */ 537 if (DCTSIZE != 8) 538 return 0; 539 if (sizeof(DCTELEM) != 2) 540 return 0; 541 542 if (simd_support & JSIMD_ARM_NEON) 543 return 1; 544 545 return 0; 546 } 547 548 GLOBAL(int) 549 jsimd_can_fdct_ifast (void) 550 { 551 init_simd(); 552 553 /* The code is optimised for these values only */ 554 if (DCTSIZE != 8) 555 return 0; 556 if (sizeof(DCTELEM) != 2) 557 return 0; 558 559 if (simd_support & JSIMD_ARM_NEON) 560 return 1; 561 562 return 0; 563 } 564 565 GLOBAL(int) 566 jsimd_can_fdct_float (void) 567 { 568 init_simd(); 569 570 return 0; 571 } 572 573 GLOBAL(void) 574 jsimd_fdct_islow (DCTELEM *data) 575 { 576 jsimd_fdct_islow_neon(data); 577 } 578 579 GLOBAL(void) 580 jsimd_fdct_ifast (DCTELEM *data) 581 { 582 jsimd_fdct_ifast_neon(data); 583 } 584 585 GLOBAL(void) 586 jsimd_fdct_float (FAST_FLOAT *data) 587 { 588 } 589 590 GLOBAL(int) 591 jsimd_can_quantize (void) 592 { 593 init_simd(); 594 595 /* The code is optimised for these values only */ 596 if (DCTSIZE != 8) 597 return 0; 598 if (sizeof(JCOEF) != 2) 599 return 0; 600 if (sizeof(DCTELEM) != 2) 601 return 0; 602 603 if (simd_support & JSIMD_ARM_NEON) 604 return 1; 605 606 return 0; 607 } 608 609 GLOBAL(int) 610 jsimd_can_quantize_float (void) 611 { 612 init_simd(); 613 614 return 0; 615 } 616 617 GLOBAL(void) 618 jsimd_quantize (JCOEFPTR coef_block, DCTELEM *divisors, 619 DCTELEM *workspace) 620 { 621 jsimd_quantize_neon(coef_block, divisors, workspace); 622 } 623 624 GLOBAL(void) 625 jsimd_quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors, 626 FAST_FLOAT *workspace) 627 { 628 } 629 630 GLOBAL(int) 631 jsimd_can_idct_2x2 (void) 632 { 633 init_simd(); 634 635 /* The code is optimised for these values only */ 636 if (DCTSIZE != 8) 637 return 0; 638 if (sizeof(JCOEF) != 2) 639 return 0; 640 if (BITS_IN_JSAMPLE != 8) 641 return 0; 642 if (sizeof(JDIMENSION) != 4) 643 return 0; 644 if (sizeof(ISLOW_MULT_TYPE) != 2) 645 return 0; 646 647 if (simd_support & JSIMD_ARM_NEON) 648 return 1; 649 650 return 0; 651 } 652 653 GLOBAL(int) 654 jsimd_can_idct_4x4 (void) 655 { 656 init_simd(); 657 658 /* The code is optimised for these values only */ 659 if (DCTSIZE != 8) 660 return 0; 661 if (sizeof(JCOEF) != 2) 662 return 0; 663 if (BITS_IN_JSAMPLE != 8) 664 return 0; 665 if (sizeof(JDIMENSION) != 4) 666 return 0; 667 if (sizeof(ISLOW_MULT_TYPE) != 2) 668 return 0; 669 670 if (simd_support & JSIMD_ARM_NEON) 671 return 1; 672 673 return 0; 674 } 675 676 GLOBAL(void) 677 jsimd_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr, 678 JCOEFPTR coef_block, JSAMPARRAY output_buf, 679 JDIMENSION output_col) 680 { 681 jsimd_idct_2x2_neon(compptr->dct_table, coef_block, output_buf, 682 output_col); 683 } 684 685 GLOBAL(void) 686 jsimd_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr, 687 JCOEFPTR coef_block, JSAMPARRAY output_buf, 688 JDIMENSION output_col) 689 { 690 jsimd_idct_4x4_neon(compptr->dct_table, coef_block, output_buf, 691 output_col); 692 } 693 694 GLOBAL(int) 695 jsimd_can_idct_islow (void) 696 { 697 init_simd(); 698 699 /* The code is optimised for these values only */ 700 if (DCTSIZE != 8) 701 return 0; 702 if (sizeof(JCOEF) != 2) 703 return 0; 704 if (BITS_IN_JSAMPLE != 8) 705 return 0; 706 if (sizeof(JDIMENSION) != 4) 707 return 0; 708 if (sizeof(ISLOW_MULT_TYPE) != 2) 709 return 0; 710 711 if (simd_support & JSIMD_ARM_NEON) 712 return 1; 713 714 return 0; 715 } 716 717 GLOBAL(int) 718 jsimd_can_idct_ifast (void) 719 { 720 init_simd(); 721 722 /* The code is optimised for these values only */ 723 if (DCTSIZE != 8) 724 return 0; 725 if (sizeof(JCOEF) != 2) 726 return 0; 727 if (BITS_IN_JSAMPLE != 8) 728 return 0; 729 if (sizeof(JDIMENSION) != 4) 730 return 0; 731 if (sizeof(IFAST_MULT_TYPE) != 2) 732 return 0; 733 if (IFAST_SCALE_BITS != 2) 734 return 0; 735 736 if (simd_support & JSIMD_ARM_NEON) 737 return 1; 738 739 return 0; 740 } 741 742 GLOBAL(int) 743 jsimd_can_idct_float (void) 744 { 745 init_simd(); 746 747 return 0; 748 } 749 750 GLOBAL(void) 751 jsimd_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr, 752 JCOEFPTR coef_block, JSAMPARRAY output_buf, 753 JDIMENSION output_col) 754 { 755 jsimd_idct_islow_neon(compptr->dct_table, coef_block, output_buf, 756 output_col); 757 } 758 759 GLOBAL(void) 760 jsimd_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr, 761 JCOEFPTR coef_block, JSAMPARRAY output_buf, 762 JDIMENSION output_col) 763 { 764 jsimd_idct_ifast_neon(compptr->dct_table, coef_block, output_buf, 765 output_col); 766 } 767 768 GLOBAL(void) 769 jsimd_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr, 770 JCOEFPTR coef_block, JSAMPARRAY output_buf, 771 JDIMENSION output_col) 772 { 773 } 774 775 GLOBAL(int) 776 jsimd_can_huff_encode_one_block (void) 777 { 778 init_simd(); 779 780 if (DCTSIZE != 8) 781 return 0; 782 if (sizeof(JCOEF) != 2) 783 return 0; 784 785 if (simd_support & JSIMD_ARM_NEON && simd_huffman) 786 return 1; 787 788 return 0; 789 } 790 791 GLOBAL(JOCTET*) 792 jsimd_huff_encode_one_block (void *state, JOCTET *buffer, JCOEFPTR block, 793 int last_dc_val, c_derived_tbl *dctbl, 794 c_derived_tbl *actbl) 795 { 796 if (simd_features & JSIMD_FASTTBL) 797 return jsimd_huff_encode_one_block_neon(state, buffer, block, last_dc_val, 798 dctbl, actbl); 799 else 800 return jsimd_huff_encode_one_block_neon_slowtbl(state, buffer, block, 801 last_dc_val, dctbl, actbl); 802 } 803