/* Copyright (C) 2021,2022 fef . All rights reserved. */ #include /* void *memset(void *dest, int c, usize n) */ ENTRY(memset) pushq %rbp movq %rsp, %rbp cld movq %rdi, %r11 /* save original pointer to dest */ movl %esi, %eax /* move `c' into correct register for rep;stosq */ movq %rdx, %rcx /* move `n' into correct register for rep;stosq */ cmpq $16, %rcx jb out /* n < 16, not worth the effort */ testl $1, %edi jz 2f stosb decq %rcx /* 2-byte aligned */ 2: movl %eax, %edx shll $8, %eax orl %edx, %eax /* c |= (c << 8) */ testl $2, %edi jz 4f stosw subq $2, %rcx /* 4-byte aligned */ 4: movl %eax, %edx shll $16, %eax orl %edx, %eax /* c |= (c << 16) */ testl $4, %edi jz 8f stosl subq $4, %rcx /* 8-byte aligned, now we can fire stosq */ 8: movl %eax, %edx shlq $32, %rax orq %rdx, %rax /* c |= (c << 32) */ movl %ecx, %edx andl $7, %edx /* edx = n % 8 */ shrq $3, %rcx /* n /= 8 */ rep stosq movl %edx, %ecx /* write out remaining bytes (or do the whole memset, if n < 16) */ out: rep stosb movq %r11, %rax /* return original pointer to dest */ popq %rbp retq END(memset)