fidget-jit 0.5.1

Native JIT compiler for Fidget
Documentation
b0VIM 9.0���j6]�.mkeetercfarm14~mkeeter/fidget/fidget-jit/src/x86_64/float_slice.rsutf-8
3210#"! UtpJdL	>�i�\gyj�+Jad6vJ��}z:9����x?�
�
�
@


�����C��Y�
o
!
�	�	7	��M��c�y+��A��W	�vuO&���|aV
���wvTS            ; xor rcx, rcx // set            ; xor rcx, rcx // set the array offset (rcx) to 0            // TODO should there be a `vzeroupper` in here?        dynasm!(out.ops        out.prepare_stack(slot_count, STACK_SIZE_UPPER + STACK_SIZE_LOWER);        );            ; mov rbp, rsp            ; push rbp        dynasm!(out.ops        let mut out = AssemblerData::new(mmap);    fn init(mmap: Mmap, slot_count: usize) -> Self {    type Data = f32;impl Assembler for FloatSliceAssembler {#[expect(clippy::useless_conversion)]const STACK_SIZE_LOWER: usize = 0x220; // Positions relative to `rsp`const STACK_SIZE_UPPER: usize = 0x28; // Positions relative to `rbp`/// ```/// | 0x00     | ymm4         |                                             |/// | 0x20     | ymm5         |                                             |/// | 0x40     | ymm6         |                                             |/// | 0x60     | ymm7         |                                             |/// | 0x80     | ymm8         |                                             |/// | 0xa0     | ymm9         |                                             |/// | 0xc0     | ymm10        |                                             |/// | 0xe0     | ymm11        |                                             |/// | 0x100    | ymm12        |                                             |/// | 0x120    | ymm13        |                                             |/// | 0x140    | ymm14        | calls are placed here, then restored        |/// | 0x160    | ymm15        | Caller-saved registers during functions     |/// |----------|--------------|---------------------------------------------|/// | 0x180    | function i/o | Inputs and outputs for function calls       |/// | 0x200    | function in  | Stashed arguments for function calls        |/// |----------|--------------|---------------------------------------------|/// | 0x220    | ...          |                                             |/// | ...      | ...          | Register spills live up here                |/// |----------|--------------|---------------------------------------------|/// | -0x28    | `r15`        |                                             |/// | -0x20    | `rcx`        |                                             |/// | -0x18    | `rdx`        | previous values on the stack                |/// | -0x10    | `rsi`        | as temporary storage so must preserve their |/// | -0x08    | `rdi`        | During functions calls, we use these        |/// |----------|--------------|---------------------------------------------|/// | 0x00     | `rbp`        | Previous value for base pointer             |/// |----------|--------------|---------------------------------------------|/// | Position | Value        | Notes                                       |/// ```text////// The stack is configured as follows////// During evaluation, `rcx` is used to track offset within `vars`.////// 256-bit wide operations for everything./// The arrays must be an even multiple of 8 floats, since we're using AVX2 and////// | size     | `rdx`    | `u64`                      |/// | out      | `rsi`    | `*const *mut [f32; 8]`     |/// | vars     | `rdi`    | `*const *const [f32; 8]`   |/// | ---------|----------|----------------------------|/// | Argument | Register | Type                       |////// Arguments are passed as follows:////// Assembler for SIMD point-wise evaluation on `x86_64`pub const SIMD_WIDTH: usize = 8;use dynasmrt::{DynasmApi, DynasmError, DynasmLabelApi, dynasm};};    float_slice::FloatSliceAssembler, mmap::Mmap, reg,    Assembler, AssemblerData, IMM_REG, OFFSET, REGISTER_LIMIT,use crate::{ad�	h
+���tM&����\5�
�
�
�
�
]
4

���e:����ON.�
�
�
{
p
j
h
g
}    }        );            ; mov r15, [rbp - 0x28]            ; mov rcx, [rbp - 0x20]            ; mov rdx, [rbp - 0x18]            ; mov rsi, [rbp - 0x10]            ; mov rdi, [rbp - 0x8]            // Restore pointers            ; vmovups Ry(reg(out_reg)), [rsp + 0x180]            // Get the output value from the stack            ; vmovups ymm15, [rsp + 0x160]            ; vmovups ymm14, [rsp + 0x140]            ; vmovups ymm13, [rsp + 0x120]            ; vmovups ymm12, [rsp + 0x100]            ; vmovups ymm11, [rsp + 0xe0]            ; vmovups ymm10, [rsp + 0xc0]            ; vmovups ymm9, [rsp + 0xa0]            ; vmovups ymm8, [rsp + 0x80]            ; vmovups ymm7, [rsp + 0x60]            ; vmovups ymm6, [rsp + 0x40]            ; vmovups ymm5, [rsp + 0x20]            ; vmovups ymm4, [rsp]            // Restore float registers            ; movd [rsp + 0x19c], xmm0            ; call r15            ; movd xmm1, [rsp + 0x21c]            ; movd xmm0, [rsp + 0x19c]            ; movd [rsp + 0x198], xmm0            ; call r15            ; movd xmm1, [rsp + 0x218]            ; movd xmm0, [rsp + 0x198]            ; movd [rsp + 0x194], xmm0            ; call r15            ; movd xmm1, [rsp + 0x214]            ; movd xmm0, [rsp + 0x194]            ; movd [rsp + 0x190], xmm0            ; call r15            ; movd xmm1, [rsp + 0x210]            ; movd xmm0, [rsp + 0x190]ad�Qd����7,��lE-�
�
�
�
u
?

����\QKJ��q+ �
�
�
=


�	�	�	�	�	v	l	3	-	����hb*�����^'���XC9����tj0*���N���qpI)����wQ(����            ; vmovd                     ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, eax                                                          ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, r10d            ; mov     r10d, 4            ; vpsrld  ymm2, ymm3, 28            ; vpaddd  ymm3, ymm3, ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, r8d            ; mov     r8d, -1403630843            ; vpmulld ymm3, Ry(reg(rhs_reg)), ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, eax            ; mov     eax, 747796405            //================================================            // Round 1: H(rhs) + lhs, result left in out_reg            //================================================        dynasm!(self.0.ops    fn build_mix(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        self.call_fn_unary(out_reg, lhs_reg, float_atan);        }            f.atan()        extern "sysv64" fn float_atan(f: f32) -> f32 {    fn build_atan(&mut self, out_reg: u8, lhs_reg: u8) {    }        self.call_fn_unary(out_reg, lhs_reg, float_acos);        }            f.acos()        extern "sysv64" fn float_acos(f: f32) -> f32 {    fn build_acos(&mut self, out_reg: u8, lhs_reg: u8) {    }        self.call_fn_unary(out_reg, lhs_reg, float_asin);        }            f.asin()        extern "sysv64" fn float_asin(f: f32) -> f32 {    fn build_asin(&mut self, out_reg: u8, lhs_reg: u8) {    }        self.call_fn_unary(out_reg, lhs_reg, float_tan);        }            f.tan()        extern "sysv64" fn float_tan(f: f32) -> f32 {    fn build_tan(&mut self, out_reg: u8, lhs_reg: u8) {    }        self.call_fn_unary(out_reg, lhs_reg, float_cos);        }            f.cos()        extern "sysv64" fn float_cos(f: f32) -> f32 {    fn build_cos(&mut self, out_reg: u8, lhs_reg: u8) {    }        self.call_fn_unary(out_reg, lhs_reg, float_sin);        }            f.sin()        extern "sysv64" fn float_sin(f: f32) -> f32 {    fn build_sin(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vmovups [r8 + rcx], Ry(reg(arg_reg))            ; mov r8, [rsi + pos]   // read the *mut float from the array        dynasm!(self.0.ops        let pos = 8 * i32::try_from(out_index).unwrap();    fn build_output(&mut self, arg_reg: u8, out_index: u32) {    }        );            ; vmovups Ry(reg(out_reg)), [r8 + rcx] // offset by array            ; mov r8, [rdi + pos]   // read the *const float from the array        dynasm!(self.0.ops        let pos = 8 * i32::try_from(src_arg).unwrap();    fn build_input(&mut self, out_reg: u8, src_arg: u32) {    }        );            ; vmovups [rsp + sp_offset], Ry(reg(src_reg))        dynasm!(self.0.ops            .unwrap();            .try_into()            + STACK_SIZE_LOWER as u32)        let sp_offset: i32 = (self.0.stack_pos(dst_mem)        assert!((src_reg as usize) < REGISTER_LIMIT);    fn build_store(&mut self, dst_mem: u32, src_reg: u8) {    }        );            ; vmovups Ry(reg(dst_reg)), [rsp + sp_offset]        dynasm!(self.0.ops            .unwrap();            .try_into()            + STACK_SIZE_LOWER as u32)        let sp_offset: i32 = (self.0.stack_pos(src_mem)        assert!((dst_reg as usize) < REGISTER_LIMIT);    fn build_load(&mut self, dst_reg: u8, src_mem: u32) {    }        Self(out)        );            ; jz ->X // jump to the exit if we're done, otherwise fallthrough            ; test rdx, rdx            ; ->L:            // The loop returns here, and we check whether to keep loopingad,�i���p?"����R�
�
�
�
k
j
9

����uU/�����s4)#�
�
�
�
b
\
#

�	�	�	�	k	C		����jB���x]6���~x?$�����:/)(�����L1����z_3���rL&��            ; vaddps Ry(reg(out_reg)), ymm1, Ry(reg(lhs_reg))            ; vorps  ymm1, ymm1, ymm2            ; vbroadcastss ymm2, xmm2            ; vmovd xmm2, eax            ; mov eax, 0x3effffffu32 as i32            ; vandps  ymm1, ymm1, Ry(reg(lhs_reg))            ; vbroadcastss ymm1, xmm1            ; vmovd xmm1, eax            ; mov eax, 0x80000000u32 as i32        dynasm!(self.0.ops        // Shenanigans figured through Godbolt    fn build_round(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vroundps Ry(reg(out_reg)), Ry(reg(lhs_reg)), 2        dynasm!(self.0.ops    fn build_ceil(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vroundps Ry(reg(out_reg)), Ry(reg(lhs_reg)), 1        dynasm!(self.0.ops    fn build_floor(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vmulps Ry(reg(out_reg)), Ry(reg(lhs_reg)), Ry(reg(lhs_reg))        dynasm!(self.0.ops    fn build_square(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vsqrtps Ry(reg(out_reg)), Ry(reg(lhs_reg))        dynasm!(self.0.ops    fn build_sqrt(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vdivps Ry(reg(out_reg)), ymm0, Ry(reg(lhs_reg))            ; vpsrld ymm0, ymm0, 2            ; vpslld ymm0, ymm0, 25            ; vpcmpeqw ymm0, ymm0, ymm0            // Build [1.0 x 8] in ymm0        dynasm!(self.0.ops    fn build_recip(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vpand Ry(reg(out_reg)), ymm0, Ry(reg(lhs_reg))            ; vpsrld ymm0, ymm0, 1 // everything but the sign bit            ; vpcmpeqw ymm0, ymm0, ymm0        dynasm!(self.0.ops    fn build_abs(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vpxor Ry(reg(out_reg)), ymm0, Ry(reg(lhs_reg))            ; vpslld ymm0, ymm0, 31 // set the sign bit            ; vpcmpeqw ymm0, ymm0, ymm0        dynasm!(self.0.ops    fn build_neg(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vmovups Ry(reg(out_reg)), Ry(reg(lhs_reg))        dynasm!(self.0.ops    fn build_copy(&mut self, out_reg: u8, lhs_reg: u8) {    }        self.call_fn_unary(out_reg, lhs_reg, float_ln);        }            f.ln()        extern "sysv64" fn float_ln(f: f32) -> f32 {    fn build_ln(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vaddps  Ry(reg(out_reg)), Ry(reg(out_reg)), ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, eax            ; mov     rax, 0xbf800000            // subtract 1.0            ; vpor    Ry(reg(out_reg)), ymm2, ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, eax            ; mov     eax, 0x3f800000            // pack into float bits in [1,2)            ; vpxor   ymm2, ymm2, ymm3            ; vpsrld  ymm2, ymm2, 9            ; vpsrld  ymm3, ymm2, 31            // word = (word >> 9) ^ (word >> 31)            ; vpmulld ymm2, ymm2, ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, eax            ; mov     eax, 277803737            // word *= 277803737            ; vpxor   ymm2, ymm2, Ry(reg(out_reg))            ; vpsrlvd ymm2, Ry(reg(out_reg)), ymm1            // word = (state >> shift) ^ state            ; vpaddd  ymm1, ymm1, ymm2            ; vpbroadcastd ymm2, xmm2            ; vmovd   xmm2, eax            ; mov     eax, 4            ; vpsrld  ymm1, Ry(reg(out_reg)), 28            // shift = (state >> 28) + 4             ; vpaddd  Ry(reg(out_reg)), Ry(reg(out_reg)), ymm1            ; vpbroadcastd ymm1, xmm1ad/�\����lQ����LA;�
�
�
�
�
;
 
���~>'���r/�
�
�
�
N


�	�	�	�	P	5	��lGF���Z=����nF���pJ����N!��{pj%
��f4����            ; vandpd ymm1, ymm1, Ry(reg(lhs_reg))            ; vxorpd ymm2, ymm1, ymm2 // 1 ^ b = !b, so this inverts ymm1            ; vpcmpeqd ymm2, ymm2, ymm2 // All 1s            ; vcmpeqps ymm1, ymm1, Ry(reg(lhs_reg))            ; vxorps ymm1, ymm1, ymm1            // Build the (lhs == 0) mask in ymm1 and the opposite in ymm2        dynasm!(self.0.ops    fn build_and(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vandpd Ry(reg(out_reg)), Ry(reg(out_reg)), ymm1            ; vbroadcastss Ry(reg(out_reg)), Rx(reg(out_reg))            ; vmovd Rx(reg(out_reg)), eax            ; mov eax, 1f32.to_bits() as i32            ; vcmpeqps ymm1, ymm1, Ry(reg(arg_reg))            ; vxorps ymm1, ymm1, ymm1        dynasm!(self.0.ops    fn build_not(&mut self, out_reg: u8, arg_reg: u8) {    }        );            ; vsubps Ry(reg(out_reg)), Ry(reg(lhs_reg)), ymm2            ; vmulps ymm2, ymm2, ymm1            ; vroundps ymm2, ymm2, 0b1 // floor            ; vdivps ymm2, Ry(reg(lhs_reg)), ymm1            ; vpand ymm1, ymm2, Ry(reg(rhs_reg))            ; vpsrld ymm2, ymm2, 1 // everything but the sign bit            ; vpcmpeqw ymm2, ymm2, ymm2            // Take abs(rhs_reg)        dynasm!(self.0.ops    fn build_mod(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vorps Ry(reg(out_reg)), Ry(reg(out_reg)), ymm1            // matter here!)            // (note that we leave other bits unchanged, because it doesn't            // Set the NAN bits            ; vminps Ry(reg(out_reg)), Ry(reg(lhs_reg)), Ry(reg(rhs_reg))            // Calculate the min, which ignores NANs            ; vorps ymm1, ymm2, ymm1            ; vcmpunordps ymm2, Ry(reg(rhs_reg)), Ry(reg(rhs_reg))            ; vcmpunordps ymm1, Ry(reg(lhs_reg)), Ry(reg(lhs_reg))            // Build a mask of NANs; conveniently, all 1s is a NAN        dynasm!(self.0.ops    fn build_min(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vorps Ry(reg(out_reg)), Ry(reg(out_reg)), ymm1            // Set the NAN bits            ; vmaxps Ry(reg(out_reg)), Ry(reg(lhs_reg)), Ry(reg(rhs_reg))            // Calculate the max, which ignores NANs            ; vorps ymm1, ymm2, ymm1            ; vcmpunordps ymm2, Ry(reg(rhs_reg)), Ry(reg(rhs_reg))            ; vcmpunordps ymm1, Ry(reg(lhs_reg)), Ry(reg(lhs_reg))            // Build a mask of NANs; conveniently, all 1s is a NAN        dynasm!(self.0.ops    fn build_max(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        self.call_fn_binary(out_reg, lhs_reg, rhs_reg, float_atan2);        }            y.atan2(x)        extern "sysv64" fn float_atan2(y: f32, x: f32) -> f32 {    fn build_atan2(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vdivps Ry(reg(out_reg)), Ry(reg(lhs_reg)), Ry(reg(rhs_reg))        dynasm!(self.0.ops    fn build_div(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vmulps Ry(reg(out_reg)), Ry(reg(lhs_reg)), Ry(reg(rhs_reg))        dynasm!(self.0.ops    fn build_mul(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vsubps Ry(reg(out_reg)), Ry(reg(lhs_reg)), Ry(reg(rhs_reg))        dynasm!(self.0.ops    fn build_sub(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vaddps Ry(reg(out_reg)), Ry(reg(lhs_reg)), Ry(reg(rhs_reg))        dynasm!(self.0.ops    fn build_add(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vroundps Ry(reg(out_reg)), Ry(reg(out_reg)), 3ad�g����H-���W
�
�
w
l
f
e


�{8���f&%�
�
�
W
V

�	�	�	t	V	0	
	���od^1����a["����lYN4.,+�����ldE*����c?>����X/���\1��            // Put the function pointer into a caller-saved register            ; vmovups [rsp + 0x160], ymm15            ; vmovups [rsp + 0x140], ymm14            ; vmovups [rsp + 0x120], ymm13            ; vmovups [rsp + 0x100], ymm12            ; vmovups [rsp + 0xe0], ymm11            ; vmovups [rsp + 0xc0], ymm10            ; vmovups [rsp + 0xa0], ymm9            ; vmovups [rsp + 0x80], ymm8            ; vmovups [rsp + 0x60], ymm7            ; vmovups [rsp + 0x40], ymm6            ; vmovups [rsp + 0x20], ymm5            ; vmovups [rsp], ymm4            // Back up register values to the stack, saving all 128 bits            ; mov [rbp - 0x28], r15            ; mov [rbp - 0x20], rcx            ; mov [rbp - 0x18], rdx            ; mov [rbp - 0x10], rsi            ; mov [rbp - 0x8], rdi            // Back up all of our pointers to the stack        dynasm!(self.0.ops        let addr = f as usize;    ) {        f: extern "sysv64" fn(f32) -> f32,        arg_reg: u8,        out_reg: u8,        &mut self,    fn call_fn_unary(impl FloatSliceAssembler {#[expect(clippy::useless_conversion)]}    }        self.0.finalize()        );            ; ->X:            // Finalization code, which happens after all evaluation is complete            ; jmp ->L            ; add rcx, 32            ; sub rdx, 8        dynasm!(self.0.ops    fn finalize(mut self) -> Result<Mmap, DynasmError> {    }        IMM_REG.wrapping_sub(OFFSET)        );            ; vbroadcastss Ry(IMM_REG), Rx(IMM_REG)            ; vmovd Rx(IMM_REG), eax            ; mov eax, imm.to_bits() as i32        dynasm!(self.0.ops    fn load_imm(&mut self, imm: f32) -> u8 {    }        );            ; vorps Ry(reg(out_reg)), Ry(reg(out_reg)), ymm1            // Set the NAN bits            ; vorps Ry(reg(out_reg)), Ry(reg(out_reg)), ymm2            ; vandps ymm2, ymm2, ymm3            ; vbroadcastss ymm2, xmm2            ; vmovd xmm2, eax            ; mov eax, 1f32.to_bits() as i32            // Build and apply [1.0 x N] & greater-than            ; vandps Ry(reg(out_reg)), Ry(reg(out_reg)), ymm2            // Apply the less-than mask to the [-1.0 x N] reg            ; vbroadcastss Ry(reg(out_reg)), Rx(reg(out_reg))            ; vmovd Rx(reg(out_reg)), eax            ; mov eax, (-1f32).to_bits() as i32            // Put [-1.0; N] into the output register            ; vcmpgtps ymm3, Ry(reg(lhs_reg)), Ry(reg(rhs_reg))            // Calculate the greater-than mask in ymm2            ; vcmpltps ymm2, Ry(reg(lhs_reg)), Ry(reg(rhs_reg))            // Calculate the less-than mask in ymm2            ; vorps ymm1, ymm2, ymm1            ; vcmpunordps ymm2, Ry(reg(rhs_reg)), Ry(reg(rhs_reg))            ; vcmpunordps ymm1, Ry(reg(lhs_reg)), Ry(reg(lhs_reg))            // Build a mask of NANs; conveniently, all 1s is a NAN        dynasm!(self.0.ops    fn build_compare(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vorpd Ry(reg(out_reg)), ymm1, ymm2            ; vandpd ymm2, ymm2, Ry(reg(lhs_reg))            ; vandpd ymm1, ymm1, Ry(reg(rhs_reg))            ; vxorpd ymm2, ymm1, ymm2 // 1 ^ b = !b, so this inverts ymm1            ; vpcmpeqd ymm2, ymm2, ymm2 // All 1s            ; vcmpeqps ymm1, ymm1, Ry(reg(lhs_reg))            ; vxorps ymm1, ymm1, ymm1            // Build the (lhs == 0) mask in ymm1 and the opposite in ymm2        dynasm!(self.0.ops    fn build_or(&mut self, out_reg: u8, lhs_reg: u8, rhs_reg: u8) {    }        );            ; vorpd Ry(reg(out_reg)), ymm1, ymm2            ; vandpd ymm2, ymm2, Ry(reg(rhs_reg))ad�j���{d=����sL5�
�
�
�
k
D


���zyR0���c9�
�
�
c
b
/
�	�	�	�	�	m	I	%			�����{sT9���rNM���g>���k@���a+�����hA���wP)��            ; movd [rsp + 0x18c], xmm0            ; call r15            ; movd xmm1, [rsp + 0x20c]            ; movd xmm0, [rsp + 0x18c]            ; movd [rsp + 0x188], xmm0            ; call r15            ; movd xmm1, [rsp + 0x208]            ; movd xmm0, [rsp + 0x188]            ; movd [rsp + 0x184], xmm0            ; call r15            ; movd xmm1, [rsp + 0x204]            ; movd xmm0, [rsp + 0x184]            ; movd [rsp + 0x180], xmm0            ; call r15            ; movd xmm1, [rsp + 0x200]            ; movd xmm0, [rsp + 0x180]            ; vmovups [rsp + 0x200], Ry(reg(rhs_reg))            ; vmovups [rsp + 0x180], Ry(reg(lhs_reg))            // Copy our input arguments to the stack for safe-keeping            ; mov r15, QWORD addr as _            // Put the function pointer into a caller-saved register            ; vmovups [rsp + 0x160], ymm15            ; vmovups [rsp + 0x140], ymm14            ; vmovups [rsp + 0x120], ymm13            ; vmovups [rsp + 0x100], ymm12            ; vmovups [rsp + 0xe0], ymm11            ; vmovups [rsp + 0xc0], ymm10            ; vmovups [rsp + 0xa0], ymm9            ; vmovups [rsp + 0x80], ymm8            ; vmovups [rsp + 0x60], ymm7            ; vmovups [rsp + 0x40], ymm6            ; vmovups [rsp + 0x20], ymm5            ; vmovups [rsp], ymm4            // Back up register values to the stack, saving all 128 bits            ; mov [rbp - 0x28], r15            ; mov [rbp - 0x20], rcx            ; mov [rbp - 0x18], rdx            ; mov [rbp - 0x10], rsi            ; mov [rbp - 0x8], rdi            // Back up all of our pointers to the stack        dynasm!(self.0.ops        let addr = f as usize;    ) {        f: extern "sysv64" fn(f32, f32) -> f32,        rhs_reg: u8,        lhs_reg: u8,        out_reg: u8,        &mut self,    fn call_fn_binary(    }        );            ; mov r15, [rbp - 0x28]            ; mov rcx, [rbp - 0x20]            ; mov rdx, [rbp - 0x18]            ; mov rsi, [rbp - 0x10]            ; mov rdi, [rbp - 0x8]            // Restore pointers            ; vmovups Ry(reg(out_reg)), [rsp + 0x180]            // Get the output value from the stack            ; vmovups ymm15, [rsp + 0x160]            ; vmovups ymm14, [rsp + 0x140]            ; vmovups ymm13, [rsp + 0x120]            ; vmovups ymm12, [rsp + 0x100]            ; vmovups ymm11, [rsp + 0xe0]            ; vmovups ymm10, [rsp + 0xc0]            ; vmovups ymm9, [rsp + 0xa0]            ; vmovups ymm8, [rsp + 0x80]            ; vmovups ymm7, [rsp + 0x60]            ; vmovups ymm6, [rsp + 0x40]            ; vmovups ymm5, [rsp + 0x20]            ; vmovups ymm4, [rsp]            // Restore float registers            ; movd [rsp + 0x19c], xmm0            ; call r15            ; movd xmm0, [rsp + 0x19c]            ; movd [rsp + 0x198], xmm0            ; call r15            ; movd xmm0, [rsp + 0x198]            ; movd [rsp + 0x194], xmm0            ; call r15            ; movd xmm0, [rsp + 0x194]            ; movd [rsp + 0x190], xmm0            ; call r15            ; movd xmm0, [rsp + 0x190]            ; movd [rsp + 0x18c], xmm0            ; call r15            ; movd xmm0, [rsp + 0x18c]            ; movd [rsp + 0x188], xmm0            ; call r15            ; movd xmm0, [rsp + 0x188]            ; movd [rsp + 0x184], xmm0            ; call r15            ; movd xmm0, [rsp + 0x184]            ; movd [rsp + 0x180], xmm0            ; call r15            ; movd xmm0, [rsp + 0x180]            ; vmovups [rsp + 0x180], Ry(reg(arg_reg))            ; mov r15, QWORD addr as _ad��>�����dD����~^�
�
j
J
$
����_^-����XW7�
�
�
�
b
W
Q

�	�	�	�	�	M	2	
	���cb*�����a���            ; vmovd   xmm1, eax            ; mov     eax, -14            ; vmovd                        ; vmovd   xmm1, eax            ; mov     eax, -14                                                   ; vmovd   xmm1, eax                   ; vmovd   xmm1, eax                 ; vmovd   xmm1, e            ; vmovd   xmm            ; vmovd   xmm1, eax            ; mov     eax, -1403630843            // state += 2891336453 (-1403630843 as i32)            ; vpmulld Ry(reg(out_reg)), Ry(reg(arg_reg)), ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, eax            ; mov     eax, 747796405            // state = v * 747796405        dynasm!(self.0.ops    fn build_rand(&mut self, out_reg: u8, arg_reg: u8) {    }        self.call_fn_unary(out_reg, lhs_reg, float_exp);        }            f.exp()        extern "sysv64" fn float_exp(f: f32) -> f32 {    fn build_exp(&mut self, out_reg: u8, lhs_reg: u8) {    }        );            ; vpxor   Ry(reg(out_reg)), ymm1, ymm3            ; vpsrld  ymm1, ymm3, 22            // result = (word >> 22) ^ word --            ; vpmulld ymm3, ymm3, ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, r9d            ; vpxor   ymm3, ymm3, Ry(reg(out_reg))            ; vpsrlvd ymm3, Ry(reg(out_reg)), ymm2            ; vpaddd  ymm2, ymm2, ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, r10d            ; vpsrld  ymm2, Ry(reg(out_reg)), 28            ; vpaddd  Ry(reg(out_reg)), Ry(reg(out_reg)), ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, r8d            ; vpmulld Ry(reg(out_reg)), Ry(reg(out_reg)), ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, eax            //================================================            // Round 2: H(x2), result left in out_reg            //================================================            ; vpaddd  Ry(reg(out_reg)), ymm1, Ry(reg(lhs_reg))            // x2 = hash1 + lhs            ; vpxor   ymm1, ymm1, ymm2            ; vpsrld  ymm1, ymm2, 22            // hash1 = (word >> 22) ^ word            ; vpmulld ymm2, ymm2, ymm1            ; vpbroadcastd ymm1, xmm1            ; vmovd   xmm1, r9d            ; mov     r9d, 277803737            ; vpxor   ymm2, ymm2, ymm3            ; vpsrlvd ymm2, ymm3, ymm2            ; vpaddd  ymm2, ymm2, ymm1