Files
rdplib/protocol/pdu/ycbcr_arm64.s
T

80 lines
2.0 KiB
ArmAsm

// Scalar ARM64 implementation of ycoCgToBGRANEON.
// Processes one pixel per iteration (no chroma subsampling, alpha = 0xFF).
// Go arm64 assembler lacks SSHR (signed vector shift right), SSHL (by register),
// and SQXTUN (saturating narrow), so we use scalar GP instructions instead.
// Stack ABI (ABI0):
// pixels+0(FP) unsafe.Pointer
// yPlane+8(FP) unsafe.Pointer
// coPlane+16(FP) unsafe.Pointer
// cgPlane+24(FP) unsafe.Pointer
// count+32(FP) int
// shift+40(FP) int
#include "textflag.h"
// func ycoCgToBGRANEON(pixels, yPlane, coPlane, cgPlane unsafe.Pointer, count, shift int)
TEXT ·ycoCgToBGRANEON(SB),NOSPLIT,$0-48
MOVD pixels+0(FP), R0 // dst
MOVD yPlane+8(FP), R1 // Y plane
MOVD coPlane+16(FP), R2 // Co plane
MOVD cgPlane+24(FP), R3 // Cg plane
MOVD count+32(FP), R4 // pixel count
MOVD shift+40(FP), R5 // shift amount
CBZ R4, done
MOVD $0, R12 // const 0
MOVD $255, R13 // const 255
loop:
MOVBU (R1), R6 // y = Y[i]
MOVBU (R2), R7 // co = Co[i]
MOVBU (R3), R8 // cg = Cg[i]
ADD $1, R1
ADD $1, R2
ADD $1, R3
// coVal = int8(co << shift): shift left, then sign-extend low byte.
LSL R5, R7, R7 // R7 = co << shift (low 8 bits hold result)
SXTB R7, R7 // R7 = int64(int8(R7))
// cgVal = int8(cg << shift)
LSL R5, R8, R8
SXTB R8, R8
// B = clamp(y - co - cg)
SUB R7, R6, R9 // R9 = y - co
SUB R8, R9, R9 // R9 = y - co - cg
CMP R12, R9
CSEL LT, R12, R9, R9
CMP R13, R9
CSEL GT, R13, R9, R9
// G = clamp(y + cg)
ADD R8, R6, R10 // R10 = y + cg
CMP R12, R10
CSEL LT, R12, R10, R10
CMP R13, R10
CSEL GT, R13, R10, R10
// R = clamp(y + co - cg)
ADD R7, R6, R11 // R11 = y + co
SUB R8, R11, R11 // R11 = y + co - cg
CMP R12, R11
CSEL LT, R12, R11, R11
CMP R13, R11
CSEL GT, R13, R11, R11
// Store BGRA pixel.
MOVBU R9, 0(R0)
MOVBU R10, 1(R0)
MOVBU R11, 2(R0)
MOVBU R13, 3(R0) // alpha = 255
ADD $4, R0
SUBS $1, R4, R4
BNE loop
done:
RET