#define GELU_MACROS_ONLY
#define GELU_WITH_BIAS
#include "gelu_f16.S"

// m2 output, m3 seed, m4 remote partials, m5 bias, m6 remote count,
// m7 rows, m8 columns. All partials use the same packed AMP-left order.
// Workers stride through quads within a 16-column panel; bias repeats per row.
.section .text.reduce_bias_gelu_f16,"ax",@progbits
.globl reduce_bias_gelu_f16
.p2align 2
.type reduce_bias_gelu_f16,@function
reduce_bias_gelu_f16:
.supervisor
add $m11, $m11, -64
st32 $m2, $m11, $m15, 0
st32 $m3, $m11, $m15, 1
st32 $m4, $m11, $m15, 2
st32 $m5, $m11, $m15, 3
st32 $m6, $m11, $m15, 4
shl $m7, $m7, 5 // bytes per panel
st32 $m7, $m11, $m15, 5
shr $m8, $m8, 4
st32 $m8, $m11, $m15, 6
mul $m7, $m7, $m8
shr $m7, $m7, 3 // remote stride in eight-byte units
st32 $m7, $m11, $m15, 7
STORE_GELU_BOUNDS
setzi $m0, .Lreduce_bias_gelu_worker
runall $m0, $m11, 0
sync SYNC_COMPUTE_SET
add $m11, $m11, 64
br $m10
.size reduce_bias_gelu_f16, .-reduce_bias_gelu_f16

.worker
.p2align 3
.Lreduce_bias_gelu_worker:
ldconst $a0, GELU_MIX_COEFFICIENTS_F16X2
uput $TAS, $a0
setzi $a0, 1 << CSR_W_FP_CLR__ZAACC__SHIFT
uput $FP_CLR, $a0
ldconst $a6, ONE_F16X2
ldconst $a7, HALF_F16X2
ld32 $m0, $mvertex_base, $m15, 4
ld32 $m1, $mvertex_base, $m15, 7
setzi $m7, 0 // panel index
.Lreduce_bias_gelu_panel:
ld32 $m2, $mvertex_base, $m15, 0
ld32 $m3, $mvertex_base, $m15, 1
ld32 $m4, $mvertex_base, $m15, 2
ld32 $m6, $mvertex_base, $m15, 5
mul $m8, $m6, $m7
get $m5, $WSR
and $m5, $m5, CSR_W_WSR__CTXTID_M1__MASK
shl $m9, $m5, 3
add $m8, $m8, $m9
add $m2, $m2, $m8
add $m3, $m3, $m8
add $m4, $m4, $m8
shr $m6, $m6, 3
cmpult $m8, $m5, $m6
brz $m8, .Lreduce_bias_gelu_next_panel
add $m6, $m6, 5
sub $m6, $m6, $m5
setzi $m8, 43691
mul $m6, $m6, $m8
shr $m6, $m6, 18
ld32 $m9, $mvertex_base, $m15, 3
shl $m8, $m7, 5
add $m9, $m9, $m8
and $m8, $m5, 3
shl $m8, $m8, 3
add $m9, $m9, $m8
// Striding six quads alternates between the two halves of the bias panel.
and $m5, $m5, 2
shl $m5, $m5, 1
setzi $m8, 2
sub $m5, $m8, $m5
brnzdec $m6, .Lreduce_bias_gelu_loop
.Lreduce_bias_gelu_loop:
ld64step $a0:1, $mzero, $m3+=, 6
mov $m10, $m4
sub $m8, $m0, 1
ld64step $a2:3, $mzero, $m4+=, $m1
.p2align 3
{ rpt $m8, 0
  fnop }
{ ld64step $a2:3, $mzero, $m4+=, $m1
  f16v4add $a0:1, $a0:1, $a2:3 }
{ add $m4, $m10, 48
  f16v4add $a0:1, $a0:1, $a2:3 }
GELU_TWO_PAIRS 0, 1, $m5
sub $m5, $mzero, $m5
st64step $a2:3, $mzero, $m2+=, 6
brnzdec $m6, .Lreduce_bias_gelu_loop
.Lreduce_bias_gelu_next_panel:
add $m7, $m7, 1
ld32 $m8, $mvertex_base, $m15, 6
cmpult $m8, $m7, $m8
brnz $m8, .Lreduce_bias_gelu_panel
exitz $m15
