Files
Martin DisibioandGitHub 9aaf851965 Upgrade parquet-go (#6030)
* Upgrade parquet-go to latest for StructTag option

* Upgrade parquet-go to get latest alloc fix
2025-12-04 15:04:47 -05:00

944 lines
17 KiB
ArmAsm

//go:build !purego
#include "funcdata.h"
#include "textflag.h"
// func unpackInt64Default(dst []int64, src []byte, bitWidth uint)
TEXT ·unpackInt64Default(SB), NOSPLIT, $0-56
MOVD dst_base+0(FP), R0 // R0 = dst pointer
MOVD dst_len+8(FP), R1 // R1 = dst length
MOVD src_base+24(FP), R2 // R2 = src pointer
MOVD bitWidth+48(FP), R3 // R3 = bitWidth
// Initialize registers
MOVD $0, R5 // R5 = bitOffset
MOVD $0, R6 // R6 = index
// Check if length >= 4 for unrolled loop
CMP $4, R1
BLT scalar_loop_start
// Calculate bitMask = (1 << bitWidth) - 1
MOVD $1, R4
LSL R3, R4, R4
SUB $1, R4, R4 // R4 = bitMask
// Calculate unrolled iterations: (length / 4) * 4
LSR $2, R1, R16 // R16 = length / 4
CBZ R16, scalar_loop_start
LSL $2, R16, R16 // R16 = (length / 4) * 4
unrolled_loop:
// Process 4 elements with instruction-level parallelism
// Use 64-bit loads for better performance
// === Element 0 ===
LSR $6, R5, R7 // i = bitOffset / 64
AND $63, R5, R8 // j = bitOffset % 64
MOVD (R2)(R7<<3), R9 // load 64-bit word from src[i]
LSL R8, R4, R10
AND R10, R9, R9
LSR R8, R9, R9
// Check if value spans into next word
ADD R8, R3, R11
CMP $64, R11
BLE store0
MOVD $64, R12
SUB R8, R12, R12
ADD $1, R7, R13
MOVD (R2)(R13<<3), R14
LSR R12, R4, R15
AND R15, R14, R14
LSL R12, R14, R14
ORR R14, R9, R9
store0:
ADD R3, R5, R5 // bitOffset += bitWidth
MOVD R9, (R0)(R6<<3)
ADD $1, R6, R6
// === Element 1 ===
LSR $6, R5, R7
AND $63, R5, R8
MOVD (R2)(R7<<3), R9
LSL R8, R4, R10
AND R10, R9, R9
LSR R8, R9, R9
ADD R8, R3, R11
CMP $64, R11
BLE store1
MOVD $64, R12
SUB R8, R12, R12
ADD $1, R7, R13
MOVD (R2)(R13<<3), R14
LSR R12, R4, R15
AND R15, R14, R14
LSL R12, R14, R14
ORR R14, R9, R9
store1:
ADD R3, R5, R5
MOVD R9, (R0)(R6<<3)
ADD $1, R6, R6
// === Element 2 ===
LSR $6, R5, R7
AND $63, R5, R8
MOVD (R2)(R7<<3), R9
LSL R8, R4, R10
AND R10, R9, R9
LSR R8, R9, R9
ADD R8, R3, R11
CMP $64, R11
BLE store2
MOVD $64, R12
SUB R8, R12, R12
ADD $1, R7, R13
MOVD (R2)(R13<<3), R14
LSR R12, R4, R15
AND R15, R14, R14
LSL R12, R14, R14
ORR R14, R9, R9
store2:
ADD R3, R5, R5
MOVD R9, (R0)(R6<<3)
ADD $1, R6, R6
// === Element 3 ===
LSR $6, R5, R7
AND $63, R5, R8
MOVD (R2)(R7<<3), R9
LSL R8, R4, R10
AND R10, R9, R9
LSR R8, R9, R9
ADD R8, R3, R11
CMP $64, R11
BLE store3
MOVD $64, R12
SUB R8, R12, R12
ADD $1, R7, R13
MOVD (R2)(R13<<3), R14
LSR R12, R4, R15
AND R15, R14, R14
LSL R12, R14, R14
ORR R14, R9, R9
store3:
ADD R3, R5, R5
MOVD R9, (R0)(R6<<3)
ADD $1, R6, R6
CMP R16, R6
BLT unrolled_loop
// Check if done
CMP R1, R6
BEQ done
scalar_loop_start:
// Fallback scalar loop for remaining elements
MOVD $1, R4
LSL R3, R4, R4
SUB $1, R4, R4 // R4 = bitMask
scalar_loop:
LSR $6, R5, R7 // i = bitOffset / 64
AND $63, R5, R8 // j = bitOffset % 64
MOVD (R2)(R7<<3), R9 // load 64-bit word
LSL R8, R4, R10 // bitMask << j
AND R10, R9, R9
LSR R8, R9, R9 // extracted value
// Check for span
ADD R8, R3, R11
CMP $64, R11
BLE scalar_next
MOVD $64, R12
SUB R8, R12, R12 // k = 64 - j
ADD $1, R7, R13
MOVD (R2)(R13<<3), R14
LSR R12, R4, R15
AND R15, R14, R14
LSL R12, R14, R14
ORR R14, R9, R9
scalar_next:
MOVD R9, (R0)(R6<<3) // dst[index] = d
ADD R3, R5, R5 // bitOffset += bitWidth
ADD $1, R6, R6 // index++
scalar_test:
CMP R1, R6
BNE scalar_loop
done:
RET
// unpackInt64x1to32bitsARM64 implements optimized unpacking for bit widths 1-32
// Uses optimized scalar ARM64 operations with batched processing
//
// func unpackInt64x1to32bitsARM64(dst []int64, src []byte, bitWidth uint)
TEXT ·unpackInt64x1to32bitsARM64(SB), NOSPLIT, $0-56
MOVD dst_base+0(FP), R0 // R0 = dst pointer
MOVD dst_len+8(FP), R1 // R1 = dst length
MOVD src_base+24(FP), R2 // R2 = src pointer
MOVD bitWidth+48(FP), R3 // R3 = bitWidth
// Check if we have at least 4 values to process
CMP $4, R1
BLT scalar_fallback_int64
// Determine which path to use based on bitWidth
CMP $1, R3
BEQ int64_1bit
CMP $2, R3
BEQ int64_2bit
CMP $3, R3
BEQ int64_3bit
CMP $4, R3
BEQ int64_4bit
CMP $5, R3
BEQ int64_5bit
CMP $6, R3
BEQ int64_6bit
CMP $7, R3
BEQ int64_7bit
CMP $8, R3
BEQ int64_8bit
CMP $16, R3
BEQ int64_16bit
CMP $32, R3
BEQ int64_32bit
// For other bit widths, fall back to scalar
B scalar_fallback_int64
int64_1bit:
// BitWidth 1: 8 int64 values packed in 1 byte
// Process 8 values at a time
// Round down to multiple of 8 for processing
MOVD R1, R4
LSR $3, R4, R4 // R4 = len / 8
LSL $3, R4, R4 // R4 = aligned length (multiple of 8)
MOVD $0, R5
CMP $0, R4
BEQ scalar_fallback_int64
int64_1bit_loop:
// Load 1 byte (contains 8 values, 1 bit each)
MOVBU (R2), R6
// Extract 8 bits
AND $1, R6, R7
MOVD R7, (R0)
LSR $1, R6, R7
AND $1, R7, R7
MOVD R7, 8(R0)
LSR $2, R6, R7
AND $1, R7, R7
MOVD R7, 16(R0)
LSR $3, R6, R7
AND $1, R7, R7
MOVD R7, 24(R0)
LSR $4, R6, R7
AND $1, R7, R7
MOVD R7, 32(R0)
LSR $5, R6, R7
AND $1, R7, R7
MOVD R7, 40(R0)
LSR $6, R6, R7
AND $1, R7, R7
MOVD R7, 48(R0)
LSR $7, R6, R7
AND $1, R7, R7
MOVD R7, 56(R0)
ADD $1, R2, R2
ADD $64, R0, R0
ADD $8, R5, R5
CMP R4, R5
BLT int64_1bit_loop
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_2bit:
// BitWidth 2: 8 int64 values packed in 2 bytes
MOVD R1, R4
LSR $3, R4, R4
LSL $3, R4, R4
MOVD $0, R5
CMP $0, R4
BEQ scalar_fallback_int64
int64_2bit_loop:
MOVHU (R2), R6
AND $3, R6, R7
MOVD R7, (R0)
LSR $2, R6, R7
AND $3, R7, R7
MOVD R7, 8(R0)
LSR $4, R6, R7
AND $3, R7, R7
MOVD R7, 16(R0)
LSR $6, R6, R7
AND $3, R7, R7
MOVD R7, 24(R0)
LSR $8, R6, R7
AND $3, R7, R7
MOVD R7, 32(R0)
LSR $10, R6, R7
AND $3, R7, R7
MOVD R7, 40(R0)
LSR $12, R6, R7
AND $3, R7, R7
MOVD R7, 48(R0)
LSR $14, R6, R7
AND $3, R7, R7
MOVD R7, 56(R0)
ADD $2, R2, R2
ADD $64, R0, R0
ADD $8, R5, R5
CMP R4, R5
BLT int64_2bit_loop
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_3bit:
// BitWidth 3: 8 int64 values packed in 3 bytes
MOVD R1, R4
LSR $3, R4, R4
LSL $3, R4, R4
MOVD $0, R5
CMP $0, R4
BEQ scalar_fallback_int64
int64_3bit_loop:
MOVWU (R2), R6
AND $7, R6, R7
MOVD R7, (R0)
LSR $3, R6, R7
AND $7, R7, R7
MOVD R7, 8(R0)
LSR $6, R6, R7
AND $7, R7, R7
MOVD R7, 16(R0)
LSR $9, R6, R7
AND $7, R7, R7
MOVD R7, 24(R0)
LSR $12, R6, R7
AND $7, R7, R7
MOVD R7, 32(R0)
LSR $15, R6, R7
AND $7, R7, R7
MOVD R7, 40(R0)
LSR $18, R6, R7
AND $7, R7, R7
MOVD R7, 48(R0)
LSR $21, R6, R7
AND $7, R7, R7
MOVD R7, 56(R0)
ADD $3, R2, R2
ADD $64, R0, R0
ADD $8, R5, R5
CMP R4, R5
BLT int64_3bit_loop
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_4bit:
// BitWidth 4: 8 int64 values packed in 4 bytes
MOVD R1, R4
LSR $3, R4, R4
LSL $3, R4, R4
MOVD $0, R5
CMP $0, R4
BEQ scalar_fallback_int64
int64_4bit_loop:
MOVWU (R2), R6
AND $15, R6, R7
MOVD R7, (R0)
LSR $4, R6, R7
AND $15, R7, R7
MOVD R7, 8(R0)
LSR $8, R6, R7
AND $15, R7, R7
MOVD R7, 16(R0)
LSR $12, R6, R7
AND $15, R7, R7
MOVD R7, 24(R0)
LSR $16, R6, R7
AND $15, R7, R7
MOVD R7, 32(R0)
LSR $20, R6, R7
AND $15, R7, R7
MOVD R7, 40(R0)
LSR $24, R6, R7
AND $15, R7, R7
MOVD R7, 48(R0)
LSR $28, R6, R7
AND $15, R7, R7
MOVD R7, 56(R0)
ADD $4, R2, R2
ADD $64, R0, R0
ADD $8, R5, R5
CMP R4, R5
BLT int64_4bit_loop
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_5bit:
// BitWidth 5: 8 int64 values packed in 5 bytes
MOVD R1, R4
LSR $3, R4, R4
LSL $3, R4, R4
MOVD $0, R5
CMP $0, R4
BEQ scalar_fallback_int64
int64_5bit_loop:
MOVD (R2), R6
AND $31, R6, R7
MOVD R7, (R0)
LSR $5, R6, R7
AND $31, R7, R7
MOVD R7, 8(R0)
LSR $10, R6, R7
AND $31, R7, R7
MOVD R7, 16(R0)
LSR $15, R6, R7
AND $31, R7, R7
MOVD R7, 24(R0)
LSR $20, R6, R7
AND $31, R7, R7
MOVD R7, 32(R0)
LSR $25, R6, R7
AND $31, R7, R7
MOVD R7, 40(R0)
LSR $30, R6, R7
AND $31, R7, R7
MOVD R7, 48(R0)
LSR $35, R6, R7
AND $31, R7, R7
MOVD R7, 56(R0)
ADD $5, R2, R2
ADD $64, R0, R0
ADD $8, R5, R5
CMP R4, R5
BLT int64_5bit_loop
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_6bit:
// BitWidth 6: 8 int64 values packed in 6 bytes
MOVD R1, R4
LSR $3, R4, R4
LSL $3, R4, R4
MOVD $0, R5
CMP $0, R4
BEQ scalar_fallback_int64
int64_6bit_loop:
MOVD (R2), R6
AND $63, R6, R7
MOVD R7, (R0)
LSR $6, R6, R7
AND $63, R7, R7
MOVD R7, 8(R0)
LSR $12, R6, R7
AND $63, R7, R7
MOVD R7, 16(R0)
LSR $18, R6, R7
AND $63, R7, R7
MOVD R7, 24(R0)
LSR $24, R6, R7
AND $63, R7, R7
MOVD R7, 32(R0)
LSR $30, R6, R7
AND $63, R7, R7
MOVD R7, 40(R0)
LSR $36, R6, R7
AND $63, R7, R7
MOVD R7, 48(R0)
LSR $42, R6, R7
AND $63, R7, R7
MOVD R7, 56(R0)
ADD $6, R2, R2
ADD $64, R0, R0
ADD $8, R5, R5
CMP R4, R5
BLT int64_6bit_loop
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_7bit:
// BitWidth 7: 8 int64 values packed in 7 bytes
MOVD R1, R4
LSR $3, R4, R4
LSL $3, R4, R4
MOVD $0, R5
CMP $0, R4
BEQ scalar_fallback_int64
int64_7bit_loop:
MOVD (R2), R6
AND $127, R6, R7
MOVD R7, (R0)
LSR $7, R6, R7
AND $127, R7, R7
MOVD R7, 8(R0)
LSR $14, R6, R7
AND $127, R7, R7
MOVD R7, 16(R0)
LSR $21, R6, R7
AND $127, R7, R7
MOVD R7, 24(R0)
LSR $28, R6, R7
AND $127, R7, R7
MOVD R7, 32(R0)
LSR $35, R6, R7
AND $127, R7, R7
MOVD R7, 40(R0)
LSR $42, R6, R7
AND $127, R7, R7
MOVD R7, 48(R0)
LSR $49, R6, R7
AND $127, R7, R7
MOVD R7, 56(R0)
ADD $7, R2, R2
ADD $64, R0, R0
ADD $8, R5, R5
CMP R4, R5
BLT int64_7bit_loop
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_8bit:
// BitWidth 8: 8 int64 values packed in 8 bytes
// Process 8 values at a time
// Round down to multiple of 8 for processing
MOVD R1, R4
LSR $3, R4, R4 // R4 = len / 8
LSL $3, R4, R4 // R4 = aligned length (multiple of 8)
MOVD $0, R5 // R5 = index
CMP $0, R4
BEQ scalar_fallback_int64
int64_8bit_loop:
// Load 8 bytes (contains 8 values, 1 byte each)
MOVD (R2), R6
// Extract 8 bytes and store as int64
// Value 0: byte 0
AND $0xFF, R6, R7
MOVD R7, (R0)
// Value 1: byte 1
LSR $8, R6, R7
AND $0xFF, R7, R7
MOVD R7, 8(R0)
// Value 2: byte 2
LSR $16, R6, R7
AND $0xFF, R7, R7
MOVD R7, 16(R0)
// Value 3: byte 3
LSR $24, R6, R7
AND $0xFF, R7, R7
MOVD R7, 24(R0)
// Value 4: byte 4
LSR $32, R6, R7
AND $0xFF, R7, R7
MOVD R7, 32(R0)
// Value 5: byte 5
LSR $40, R6, R7
AND $0xFF, R7, R7
MOVD R7, 40(R0)
// Value 6: byte 6
LSR $48, R6, R7
AND $0xFF, R7, R7
MOVD R7, 48(R0)
// Value 7: byte 7
LSR $56, R6, R7
MOVD R7, 56(R0)
// Advance pointers
ADD $8, R2, R2 // src += 8 bytes (8 values)
ADD $64, R0, R0 // dst += 8 int64 (64 bytes)
ADD $8, R5, R5 // index += 8
CMP R4, R5
BLT int64_8bit_loop
// Handle tail with scalar
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_16bit:
// BitWidth 16: 4 int64 values packed in 8 bytes
// Process 4 values at a time
MOVD R1, R4
LSR $2, R4, R4 // R4 = len / 4
LSL $2, R4, R4 // R4 = aligned length (multiple of 4)
MOVD $0, R5 // R5 = index
CMP $0, R4
BEQ scalar_fallback_int64
int64_16bit_loop:
// Load 8 bytes as 4 uint16 values
MOVD (R2), R6
// Extract 16-bit values and write as int64
// Value 0 (bits 0-15)
AND $0xFFFF, R6, R7
MOVD R7, (R0)
// Value 1 (bits 16-31)
LSR $16, R6, R7
AND $0xFFFF, R7, R7
MOVD R7, 8(R0)
// Value 2 (bits 32-47)
LSR $32, R6, R7
AND $0xFFFF, R7, R7
MOVD R7, 16(R0)
// Value 3 (bits 48-63)
LSR $48, R6, R7
MOVD R7, 24(R0)
// Advance pointers
ADD $8, R2, R2 // src += 8 bytes (4 values)
ADD $32, R0, R0 // dst += 4 int64 (32 bytes)
ADD $4, R5, R5 // index += 4
CMP R4, R5
BLT int64_16bit_loop
// Handle tail with scalar
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_32bit:
// BitWidth 32: 2 int64 values packed in 8 bytes
// Process 2 values at a time
MOVD R1, R4
LSR $1, R4, R4 // R4 = len / 2
LSL $1, R4, R4 // R4 = aligned length (multiple of 2)
MOVD $0, R5 // R5 = index
CMP $0, R4
BEQ scalar_fallback_int64
int64_32bit_loop:
// Load 8 bytes as 2 uint32 values
MOVD (R2), R6
// Extract 32-bit values and write as int64
// Value 0 (bits 0-31)
AND $0xFFFFFFFF, R6, R7
MOVD R7, (R0)
// Value 1 (bits 32-63)
LSR $32, R6, R7
MOVD R7, 8(R0)
// Advance pointers
ADD $8, R2, R2 // src += 8 bytes (2 values)
ADD $16, R0, R0 // dst += 2 int64 (16 bytes)
ADD $2, R5, R5 // index += 2
CMP R4, R5
BLT int64_32bit_loop
// Handle tail with scalar
CMP R1, R5
BEQ int64_done
SUB R5, R1, R1
B scalar_fallback_entry_int64
int64_done:
RET
scalar_fallback_int64:
MOVD $0, R5 // Start from beginning
scalar_fallback_entry_int64:
// R0 = current dst position (already advanced)
// R1 = remaining elements
// R2 = current src position (already advanced)
// R3 = bitWidth
// R5 = elements already processed
// Fall back to optimized implementation for remaining elements
CMP $0, R1
BEQ scalar_done_int64 // No remaining elements
// Check if we can do 4-way unrolled loop
CMP $4, R1
BLT scalar_single_int64
// Calculate bitMask
MOVD $1, R4
LSL R3, R4, R4
SUB $1, R4, R4 // R4 = bitMask
// Calculate unrolled iterations: (remaining / 4) * 4
LSR $2, R1, R16
CBZ R16, scalar_single_int64
LSL $2, R16, R16 // R16 = (len / 4) * 4
MOVD $0, R6 // R6 = bitOffset
MOVD $0, R7 // R7 = index
scalar_unrolled_loop_int64:
// === Element 0 ===
LSR $6, R6, R8 // i = bitOffset / 64
AND $63, R6, R9 // j = bitOffset % 64
MOVD (R2)(R8<<3), R11 // load 64-bit word
LSL R9, R4, R12
AND R12, R11, R11
LSR R9, R11, R11
ADD R9, R3, R12
CMP $64, R12
BLE scalar_store0_int64
MOVD $64, R13
SUB R9, R13, R13
ADD $1, R8, R14
MOVD (R2)(R14<<3), R15
LSR R13, R4, R10
AND R10, R15, R15
LSL R13, R15, R15
ORR R15, R11, R11
scalar_store0_int64:
ADD R3, R6, R6
LSL $3, R7, R10
MOVD R11, (R0)(R10)
ADD $1, R7, R7
// === Element 1 ===
LSR $6, R6, R8
AND $63, R6, R9
MOVD (R2)(R8<<3), R11
LSL R9, R4, R12
AND R12, R11, R11
LSR R9, R11, R11
ADD R9, R3, R12
CMP $64, R12
BLE scalar_store1_int64
MOVD $64, R13
SUB R9, R13, R13
ADD $1, R8, R14
MOVD (R2)(R14<<3), R15
LSR R13, R4, R10
AND R10, R15, R15
LSL R13, R15, R15
ORR R15, R11, R11
scalar_store1_int64:
ADD R3, R6, R6
LSL $3, R7, R10
MOVD R11, (R0)(R10)
ADD $1, R7, R7
// === Element 2 ===
LSR $6, R6, R8
AND $63, R6, R9
MOVD (R2)(R8<<3), R11
LSL R9, R4, R12
AND R12, R11, R11
LSR R9, R11, R11
ADD R9, R3, R12
CMP $64, R12
BLE scalar_store2_int64
MOVD $64, R13
SUB R9, R13, R13
ADD $1, R8, R14
MOVD (R2)(R14<<3), R15
LSR R13, R4, R10
AND R10, R15, R15
LSL R13, R15, R15
ORR R15, R11, R11
scalar_store2_int64:
ADD R3, R6, R6
LSL $3, R7, R10
MOVD R11, (R0)(R10)
ADD $1, R7, R7
// === Element 3 ===
LSR $6, R6, R8
AND $63, R6, R9
MOVD (R2)(R8<<3), R11
LSL R9, R4, R12
AND R12, R11, R11
LSR R9, R11, R11
ADD R9, R3, R12
CMP $64, R12
BLE scalar_store3_int64
MOVD $64, R13
SUB R9, R13, R13
ADD $1, R8, R14
MOVD (R2)(R14<<3), R15
LSR R13, R4, R10
AND R10, R15, R15
LSL R13, R15, R15
ORR R15, R11, R11
scalar_store3_int64:
ADD R3, R6, R6
LSL $3, R7, R10
MOVD R11, (R0)(R10)
ADD $1, R7, R7
CMP R16, R7
BLT scalar_unrolled_loop_int64
// Check if done
CMP R1, R7
BEQ scalar_done_int64
// Preserve R6 (bitOffset), R4 (bitMask), and R7 (index) for tail processing
// R1 still contains total count, R7 has current index
B scalar_loop_single_int64
scalar_single_int64:
// Process remaining elements one at a time
MOVD $1, R4
LSL R3, R4, R4
SUB $1, R4, R4 // R4 = bitMask
MOVD $0, R6 // R6 = bitOffset
MOVD $0, R7 // R7 = index
scalar_loop_single_int64:
LSR $6, R6, R8 // i = bitOffset / 64
AND $63, R6, R9 // j = bitOffset % 64
MOVD (R2)(R8<<3), R11 // load 64-bit word
LSL R9, R4, R12
AND R12, R11, R11
LSR R9, R11, R11
ADD R9, R3, R12
CMP $64, R12
BLE scalar_next_single_int64
MOVD $64, R13
SUB R9, R13, R13
ADD $1, R8, R14
MOVD (R2)(R14<<3), R15
LSR R13, R4, R10
AND R10, R15, R15
LSL R13, R15, R15
ORR R15, R11, R11
scalar_next_single_int64:
LSL $3, R7, R10
MOVD R11, (R0)(R10)
ADD R3, R6, R6
ADD $1, R7, R7
CMP R1, R7
BLT scalar_loop_single_int64
scalar_done_int64:
RET
// Macro definitions for unsupported NEON instructions using WORD encodings
// USHLL Vd.8H, Vn.8B, #0 - widen 8x8-bit to 8x16-bit
#define USHLL_8H_8B(vd, vn) WORD $(0x2f08a400 | (vd) | ((vn)<<5))
// USHLL2 Vd.8H, Vn.16B, #0 - widen upper 8x8-bit to 8x16-bit
#define USHLL2_8H_16B(vd, vn) WORD $(0x6f08a400 | (vd) | ((vn)<<5))
// USHLL Vd.4S, Vn.4H, #0 - widen 4x16-bit to 4x32-bit
#define USHLL_4S_4H(vd, vn) WORD $(0x2f10a400 | (vd) | ((vn)<<5))
// USHLL2 Vd.4S, Vn.8H, #0 - widen upper 4x16-bit to 4x32-bit
#define USHLL2_4S_8H(vd, vn) WORD $(0x6f10a400 | (vd) | ((vn)<<5))
// USHLL Vd.2D, Vn.2S, #0 - widen 2x32-bit to 2x64-bit
#define USHLL_2D_2S(vd, vn) WORD $(0x2f20a400 | (vd) | ((vn)<<5))
// USHLL2 Vd.2D, Vn.4S, #0 - widen upper 2x32-bit to 2x64-bit
#define USHLL2_2D_4S(vd, vn) WORD $(0x6f20a400 | (vd) | ((vn)<<5))
// unpackInt64x1bitNEON implements table-based NEON unpacking for int64 bitWidth=1
// Similar to int32 version but with additional widening to 64-bit
//
// func unpackInt64x1bitNEON(dst []int64, src []byte, bitWidth uint)