//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Authors: spectral` // // NeoX // // // // Desc: mem*() functions // //----------------------------------------------------------------------------// #include #include //------------------------------------------// // memset() family // //------------------------------------------// // // Set "bytes"-many bytes starting from ptr to val // void *memset(void *ptr, int val, size_t bytes) { uchar *uptr = (uchar *)ptr; // deal with bytes before start of the first aligned qword while (((ulong)uptr % QWORD_ALIGN) > 0 && bytes--) { *uptr++ = (uchar)val; } // we're qword-aligned now if (bytes > QWORD_SIZE) { const ulong uval = ((ulong)val << 56) | ((ulong)val << 48) | ((ulong)val << 40) | ((ulong)val << 32) | ((ulong)val << 24) | ((ulong)val << 16) | ((ulong)val << 8) | ((ulong)val); ulong *uqptr = (ulong *)ptr; // move qword by qword while (bytes > QWORD_SIZE) { *uqptr++ = uval; bytes -= QWORD_SIZE; } uptr = (uchar *)(ulong)uqptr; } // deal with what's left while (bytes--) *uptr++ = (uchar)val; return ptr; } // // Set "words"-many words starting from ptr to val // void *memsetw(void *ptr, int val, size_t words) { ushort *uptr = (ushort *)ptr; // can't we do this an aligned way? if unlikely (((ulong)uptr % WORD_ALIGN) > 0) { while (words--) *uptr++ = (ushort)val; return uptr; } // deal with words before start of the first aligned qword while (((ulong)uptr % QWORD_ALIGN) > 0 && words--) { *uptr++ = (ushort)val; } // we're aligned for sure if (words > QWORDS_TO_WORDS(1)) { const ulong uval = ((ulong)val << 48) | ((ulong)val << 32) | ((ulong)val << 16) | ((ulong)val); ulong *uqptr = (ulong *)uptr; // move qword by qword while (words > QWORDS_TO_WORDS(1)) { words -= QWORDS_TO_WORDS(1); *uqptr++ = uval; } uptr = (ushort *)(ulong)uqptr; } // deal with what's left while (words--) *uptr++ = (ushort)val; return ptr; } // // Set "dwords"-many dwords starting from ptr to val // XXX unimplemented // void *memsetd(void *ptr, int val, size_t dwords) { (void)val; (void)dwords; return ptr; } // // Set "qwords"-many qwords starting from ptr to val // void *memsetq(void *ptr, long val, size_t qwords) { ulong *uptr = (ulong *)ptr; while (qwords--) *uptr++ = (ulong)val; return ptr; } // // Set "bytes"-many bytes starting from ptr to 0 // // WARNING // Assume "bytes" is large, for small sizes // use memset(ptr, 0, bytes) directly // void *memzero(void *ptr, size_t bytes) { return memsetb(ptr, 0, bytes); } // // Copy "bytes"-many bytes of src to dst // Does not deal with overlapping blocks (memmove's job) // void *memcpy(void *dst, const void *src, size_t bytes) { const ulong *usrc = (const ulong *)src; ulong *udst = (ulong *)dst; if unlikely (bytes == 0) return dst; // can we align them both at once? if unlikely ((ulong)src % WORD_ALIGN == 1 && (ulong)dst % WORD_ALIGN == 1) { const uchar *ubsrc = (const uchar *)usrc; uchar *ubdst = (uchar *)udst; *ubdst++ = *ubsrc++; bytes--; udst = (ulong *)ubdst; usrc = (ulong *)ubsrc; } const ushort *uwsrc = (const ushort *)usrc; ushort *uwdst = (ushort *)udst; // align either dst or src for qword access while ((ulong)dst % QWORD_ALIGN > 0 && (ulong)src % QWORD_ALIGN > 0 && bytes > WORD_SIZE) { *uwdst++ = *uwsrc++; bytes -= WORD_SIZE; } udst = (ulong *)uwdst; usrc = (ulong *)uwsrc; // should be most of the job while (bytes > QWORD_SIZE) { *udst++ = *usrc++; bytes -= QWORD_SIZE; } const uchar *ubsrc = (const uchar *)usrc; ushort *ubdst = (ushort *)udst; // deal with what's left while (bytes--) *ubdst ++ = *ubsrc++; return dst; } // // Move memory from src to dest // To be made more efficient // void *memmove(void *dst, const void *src, size_t bytes) { const uchar *usrc = src; uchar *udst = dst; if (udst < usrc) { while (bytes--) *udst++ = *usrc++; return dst; } uchar *usrc_end = (uchar *)usrc + bytes - 1; uchar *udst_end = udst + bytes - 1; while (bytes--) *udst_end-- = *usrc_end--; return dst; } // // Compare memory areas // int memcmp(const void *ptr1, const void *ptr2, size_t bytes) { const uchar *uptr1 = ptr1; const uchar *uptr2 = ptr2; while (bytes--) { if (*uptr1++ != *uptr2++) { return uptr1[-1] < uptr2[-1] ? -1 : 1; } } return 0; }