Espresso 0.0.1f
This commit is contained in:
4
Makefile
4
Makefile
@ -41,13 +41,11 @@ INTERNAL_OBJS := $(CRTI_OBJ) $(OBJS) $(CRTN_OBJ)
|
|||||||
build: all iso run
|
build: all iso run
|
||||||
|
|
||||||
# === Build all targets and clean ===
|
# === Build all targets and clean ===
|
||||||
buildc: test all iso run clean
|
buildc: all iso run clean
|
||||||
|
|
||||||
# === Default target ===
|
# === Default target ===
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
test:
|
|
||||||
printf $(CRTI_OBJ)
|
|
||||||
|
|
||||||
# === Linking ===
|
# === Linking ===
|
||||||
$(TARGET): ./arch/x86/boot/boot.o $(filter-out boot.o, $(OBJ_LINK_LIST))
|
$(TARGET): ./arch/x86/boot/boot.o $(filter-out boot.o, $(OBJ_LINK_LIST))
|
||||||
|
|||||||
10
README.md
Normal file
10
README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<--- Espresso. --->
|
||||||
|
|
||||||
|
Espresso is a simple operating system built with C and i686(IA32) assembler.
|
||||||
|
|
||||||
|
== BUILDING ==
|
||||||
|
|
||||||
|
First, you need a cross-compiler and toolchain built, see https://wiki.osdev.org/GCC_Cross-Compiler for instructions.
|
||||||
|
|
||||||
|
then, `cd` into the directory with the code (you should see the `kernel`, `include`, and `lib` directories if you're in the right place.) and type `make build`.
|
||||||
|
this will also run the OS. type `make clean` after every change to rebuild everything.
|
||||||
@ -45,30 +45,9 @@ doesn't make sense to return from this function as the bootloader is gone.
|
|||||||
|
|
||||||
.global _start
|
.global _start
|
||||||
.global _kernel_early
|
.global _kernel_early
|
||||||
/*.global loadPageDirectory
|
|
||||||
.global enablePaging*/
|
|
||||||
|
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
|
|
||||||
/*load_page_directory:
|
|
||||||
push %ebp
|
|
||||||
mov %esp, %ebp
|
|
||||||
mov 8(%esp), %eax
|
|
||||||
mov %eax, %cr3
|
|
||||||
mov %ebp, %esp
|
|
||||||
pop %ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
enable_paging:
|
|
||||||
push %ebp
|
|
||||||
mov %esp, %ebp
|
|
||||||
mov %cr0, %eax
|
|
||||||
or $0x80000000, %eax
|
|
||||||
mov %eax, %cr0
|
|
||||||
mov %ebp, %esp
|
|
||||||
pop %ebp
|
|
||||||
ret*/
|
|
||||||
|
|
||||||
enable_sse_asm:
|
enable_sse_asm:
|
||||||
push %eax
|
push %eax
|
||||||
push %ebx
|
push %ebx
|
||||||
@ -138,7 +117,7 @@ enable_sse_asm:
|
|||||||
.no_sse:
|
.no_sse:
|
||||||
.no_cpuid:
|
.no_cpuid:
|
||||||
lea sse_initialized, %edi
|
lea sse_initialized, %edi
|
||||||
mov $0, (%edi)
|
movl $0, (%edi)
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
pop %edi
|
pop %edi
|
||||||
@ -203,9 +182,8 @@ _start:
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Call _kernel_early, early low-level initialization will happen there;
|
Call _kernel_early, early low-level initialization will happen there.
|
||||||
please note that while _kernel_early is written in assembler,
|
NOTE: I don't use 'jmp' because it doesn't work. Nice try.
|
||||||
kernel_early is written in C. (kernel_early is called by _kernel_early, don't be confused. ;) )
|
|
||||||
*/
|
*/
|
||||||
call _kernel_early
|
call _kernel_early
|
||||||
|
|
||||||
|
|||||||
16
arch/x86/new_intrin.c
Normal file
16
arch/x86/new_intrin.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#ifdef __NEW_INTRINSICS_
|
||||||
|
|
||||||
|
bool cpu_supports_sse2(void)
|
||||||
|
{
|
||||||
|
int k = __buildin_cpu_supports("sse2");
|
||||||
|
return k > 0 ? true : false
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cpu_supports_sse(void)
|
||||||
|
{
|
||||||
|
return __buildin_cpu_supports("sse") > 0 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
248
drivers/fs/sfs.c
248
drivers/fs/sfs.c
@ -5,7 +5,12 @@
|
|||||||
#include <fs/sfs.h>
|
#include <fs/sfs.h>
|
||||||
|
|
||||||
|
|
||||||
#define SFS_BEGINNING_LBA 8
|
#define SFS_HEADER_START_LBA 8
|
||||||
|
#define SFS_HEADER_REGION_SECTORS 1024
|
||||||
|
#define SFS_HEADERS_PER_SECTOR 8
|
||||||
|
#define TOTAL_SECTORS 32768
|
||||||
|
#define SFS_DATA_START_LBA (TOTAL_SECTORS / 4)
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct sfs_file_header {
|
typedef struct sfs_file_header {
|
||||||
@ -24,37 +29,38 @@ typedef struct sfs_file_header {
|
|||||||
} sfs_file_header_t;
|
} sfs_file_header_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
static sfs_file_header_t* base;
|
|
||||||
|
uint8_t buffer[512] = { 0 };
|
||||||
|
|
||||||
|
/* Global allocator pointer to the next free sector in the data region */
|
||||||
|
uint64_t sfs_next_free_data_sector = SFS_DATA_START_LBA;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int32_t sfs_init(void)
|
||||||
int32_t sfs_init(bool format)
|
|
||||||
{
|
{
|
||||||
uint8_t buffer[512] = { 0 };
|
uint8_t sector_buf[512];
|
||||||
|
|
||||||
int32_t kl = read_sector(SFS_BEGINNING_LBA, buffer);
|
for (uint64_t lba = SFS_HEADER_START_LBA; lba < SFS_HEADER_START_LBA + SFS_HEADER_REGION_SECTORS; ++lba)
|
||||||
|
|
||||||
if (kl != 0)
|
|
||||||
{
|
{
|
||||||
return -1;
|
if (read_sector(lba, sector_buf) != 0)
|
||||||
}
|
|
||||||
|
|
||||||
volatile sfs_file_header_t null_file;
|
|
||||||
memcpy(&null_file, buffer, sizeof(sfs_file_header_t));
|
|
||||||
|
|
||||||
if ((&null_file)->magic != 0xBEEF)
|
|
||||||
{
|
|
||||||
if (!format)
|
|
||||||
{
|
{
|
||||||
return -2;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//sfs_format();
|
sfs_file_header_t* hdr = (sfs_file_header_t*)sector_buf;
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(base, &null_file, sizeof(sfs_file_header_t));
|
if (hdr->magic == 0xBEEF)
|
||||||
|
{
|
||||||
|
uint64_t end = hdr->data_beginning + hdr->num_sectors;
|
||||||
|
if (end > sfs_next_free_data_sector)
|
||||||
|
{
|
||||||
|
sfs_next_free_data_sector = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: support multiple headers per sector, loop through all 512/64 = 8 headers here */
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -75,20 +81,210 @@ bool sfs_get_formatted_name(const char* raw_name, char output[37])
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t sfs_create_file(const char* _name, int32_t size_bytes)
|
||||||
|
{
|
||||||
|
if (size_bytes < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char name[37];
|
||||||
|
if (!sfs_get_formatted_name(_name, name))
|
||||||
|
{
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t sectors_needed = (size_bytes + 511) / 512;
|
||||||
|
uint8_t sector_buf[512];
|
||||||
|
|
||||||
|
for (uint64_t lba = SFS_HEADER_START_LBA; lba < SFS_HEADER_START_LBA + SFS_HEADER_REGION_SECTORS; ++lba)
|
||||||
|
{
|
||||||
|
if (read_sector(lba, sector_buf) != 0)
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < SFS_HEADERS_PER_SECTOR; ++i)
|
||||||
|
{
|
||||||
|
sfs_file_header_t* hdr = ((sfs_file_header_t*)sector_buf) + i;
|
||||||
|
|
||||||
|
if (hdr->magic != 0xBEEF)
|
||||||
|
{
|
||||||
|
hdr->magic = 0xBEEF;
|
||||||
|
memcpy(hdr->filename, name, 37);
|
||||||
|
hdr->data_beginning = sfs_next_free_data_sector;
|
||||||
|
hdr->num_sectors = sectors_needed;
|
||||||
|
|
||||||
|
sfs_next_free_data_sector += sectors_needed;
|
||||||
|
|
||||||
|
if (write_sector(lba, sector_buf) != 0)
|
||||||
|
{
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
num is number of bytes
|
||||||
Note: if a negative value is passed for num, then read the whole file
|
Note: if a negative value is passed for num, then read the whole file
|
||||||
*/
|
*/
|
||||||
int32_t sfs_read_file(char* _name, void* buffer, uint32_t num)
|
int32_t sfs_read_file(char* _name, void* buffer, int32_t num)
|
||||||
{
|
{
|
||||||
char name[37] = { '\0' };
|
char name[37] = { '\0' };
|
||||||
|
|
||||||
if (sfs_get_formatted_name(_name, name))
|
if (!sfs_get_formatted_name(_name, name))
|
||||||
{
|
{
|
||||||
return -128;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s", name);
|
memclr(buffer, sizeof(buffer)); /* Zero out buffer */
|
||||||
|
|
||||||
|
uint64_t j = SFS_HEADER_START_LBA;
|
||||||
|
|
||||||
|
if (read_sector(j, buffer) != 0)
|
||||||
|
{
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
sfs_file_header_t file;
|
||||||
|
|
||||||
|
memcpy(&file, buffer, sizeof(file));
|
||||||
|
|
||||||
|
if (file.magic != 0xBEEF)
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (strncmp(file.filename, name, 37) != 0)
|
||||||
|
{
|
||||||
|
memclr(buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
if (read_sector(++j, buffer) != 0)
|
||||||
|
{
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&file, buffer, sizeof(file));
|
||||||
|
|
||||||
|
if (file.magic != 0xBEEF)
|
||||||
|
{
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* File found, now to read data */
|
||||||
|
|
||||||
|
uint32_t sectors_to_read = file.num_sectors;
|
||||||
|
if (num >= 0)
|
||||||
|
{
|
||||||
|
uint32_t max_sectors = (num + 511) / 512;
|
||||||
|
|
||||||
|
if (max_sectors < sectors_to_read)
|
||||||
|
{
|
||||||
|
sectors_to_read = max_sectors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < sectors_to_read; ++i)
|
||||||
|
{
|
||||||
|
if (read_sector((uint64_t)(file.data_beginning) + i, (uint8_t*)buffer + i * 512) != 0)
|
||||||
|
{
|
||||||
|
return -6; /* read error */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors_to_read * 512;
|
||||||
|
|
||||||
|
memclr(buffer, sizeof(buffer));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Writes num bytes to an existing file.
|
||||||
|
If the file exists, it will be resized (grown/shrunk) to fit num bytes.
|
||||||
|
Returns number of bytes written (rounded up to sectors), or a negative error code.
|
||||||
|
*/
|
||||||
|
int32_t sfs_write_file(char* _name, const void* buffer, int32_t num)
|
||||||
|
{
|
||||||
|
if (num < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char name[37] = { '\0' };
|
||||||
|
if (!sfs_get_formatted_name(_name, name))
|
||||||
|
{
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sector_buf[512];
|
||||||
|
uint64_t header_lba = SFS_HEADER_START_LBA;
|
||||||
|
sfs_file_header_t file;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (read_sector(header_lba, sector_buf) != 0)
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&file, sector_buf, sizeof(file));
|
||||||
|
|
||||||
|
if (file.magic != 0xBEEF)
|
||||||
|
{
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(file.filename, name, 37) == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++header_lba;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t sectors_needed = (num + 511) / 512;
|
||||||
|
|
||||||
|
if (sectors_needed != file.num_sectors)
|
||||||
|
{
|
||||||
|
file.num_sectors = sectors_needed;
|
||||||
|
file.data_beginning = sfs_next_free_data_sector;
|
||||||
|
sfs_next_free_data_sector += sectors_needed;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.magic = 0xBEEF;
|
||||||
|
memcpy(sector_buf, &file, sizeof(file));
|
||||||
|
|
||||||
|
if (write_sector(header_lba, sector_buf) != 0)
|
||||||
|
{
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < sectors_needed; ++i)
|
||||||
|
{
|
||||||
|
uint8_t temp[512] = {0};
|
||||||
|
|
||||||
|
if (i == sectors_needed - 1 && (num % 512 != 0))
|
||||||
|
{
|
||||||
|
memcpy(temp, (const uint8_t*)buffer + i * 512, num % 512);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(temp, (const uint8_t*)buffer + i * 512, 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_sector(file.data_beginning + i, temp) != 0)
|
||||||
|
{
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors_needed * 512;
|
||||||
|
}
|
||||||
|
|||||||
@ -3,10 +3,13 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
int32_t sfs_init(bool format);
|
int32_t sfs_init(void);
|
||||||
|
|
||||||
bool sfs_get_formatted_name(const char* raw_name, char output[37]);
|
bool sfs_get_formatted_name(const char* raw_name, char output[37]);
|
||||||
|
|
||||||
int32_t sfs_read_file(char* name, void* buffer, uint32_t num);
|
int32_t sfs_create_file(const char* _name, int32_t size_bytes);
|
||||||
|
|
||||||
|
int32_t sfs_read_file(char* name, void* buffer, int32_t num);
|
||||||
|
int32_t sfs_write_file(char* _name, const void* buffer, int32_t num);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -13,6 +13,13 @@ extern "C" {
|
|||||||
//#define ENABLE_USB
|
//#define ENABLE_USB
|
||||||
//#define ENABLE_NETWORK
|
//#define ENABLE_NETWORK
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool enable_debug;
|
||||||
|
bool enable_fs;
|
||||||
|
bool enable_ide;
|
||||||
|
bool enable_usb;
|
||||||
|
bool enable_networking;
|
||||||
|
} kconf_t;
|
||||||
|
|
||||||
static inline kconf_t get_kconfig(void)
|
static inline kconf_t get_kconfig(void)
|
||||||
{
|
{
|
||||||
|
|||||||
6
include/kincl.h
Normal file
6
include/kincl.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _KERNEL_INCLUDES_H
|
||||||
|
#define _KERNEL_INCLUDES_H
|
||||||
|
|
||||||
|
#define KERNEL_VERSION "0.0.1e"
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,30 +0,0 @@
|
|||||||
#ifndef _KERNEL_PANIC_H
|
|
||||||
#define _KERNEL_PANIC_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <tty.h>
|
|
||||||
|
|
||||||
void panic(const char* arr)
|
|
||||||
{
|
|
||||||
|
|
||||||
uint8_t color = 0x1F;
|
|
||||||
uint8_t blank = 0xFF;
|
|
||||||
|
|
||||||
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
|
||||||
{
|
|
||||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
|
||||||
{
|
|
||||||
const size_t index = y * VGA_WIDTH + x;
|
|
||||||
VGA_MEMORY[index] = (uint16_t) ' ' | (uint16_t) blank << 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 75; i += 2)
|
|
||||||
{
|
|
||||||
VGA_MEMORY[i] = arr[i];
|
|
||||||
VGA_MEMORY[i + 1] = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
#ifndef _SYSCALL_H
|
|
||||||
#define _SYSCALL_H
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -45,6 +45,15 @@
|
|||||||
extern void _hang_asm(void);
|
extern void _hang_asm(void);
|
||||||
extern void _sti_asm(void);
|
extern void _sti_asm(void);
|
||||||
|
|
||||||
|
char* espresso_str = ""
|
||||||
|
"####### ##### ###### ###### ####### ##### ##### #######\n"
|
||||||
|
"# # # # # # # # # # # # # #\n"
|
||||||
|
"# # # # # # # # # # #\n"
|
||||||
|
"##### ##### ###### ###### ##### ##### ##### # #\n"
|
||||||
|
"# # # # # # # # # #\n"
|
||||||
|
"# # # # # # # # # # # # #\n"
|
||||||
|
"####### ##### # # # ####### ##### ##### #######\n";
|
||||||
|
|
||||||
|
|
||||||
void kernel_main(multiboot_info_t* mbd, uint32_t magic)
|
void kernel_main(multiboot_info_t* mbd, uint32_t magic)
|
||||||
{
|
{
|
||||||
@ -142,16 +151,23 @@ void kernel_main(multiboot_info_t* mbd, uint32_t magic)
|
|||||||
/*pit_sleep(4000);
|
/*pit_sleep(4000);
|
||||||
begin_anim(espresso_kernel_version);*/
|
begin_anim(espresso_kernel_version);*/
|
||||||
|
|
||||||
/*printf("here\n");
|
printf("Guten tag and welcome to Espresso %s\n", espresso_kernel_version);
|
||||||
|
|
||||||
printf("%i\n", sfs_init(false));
|
printf("%s\n", espresso_str);
|
||||||
|
|
||||||
printf("here\n");*/
|
char buffer[512] = { 0 };
|
||||||
|
|
||||||
printf("Guten tag and welcome to Espresso\n");
|
int32_t i = sfs_read_file("test.txt", buffer, -1);
|
||||||
|
|
||||||
|
printf("%i\n", i);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
printf("%s\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
/* Loop infinitely. We only do something when a syscall happens now. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ void paging_init(void)
|
|||||||
page_directory = (page_directory_entry_t*)alloc_page();
|
page_directory = (page_directory_entry_t*)alloc_page();
|
||||||
memset(page_directory, 0, PAGE_SIZE);
|
memset(page_directory, 0, PAGE_SIZE);
|
||||||
|
|
||||||
/* Allocate and set up the first identity-mapped page table (0–4MB) */
|
/* Allocate and set up the first identity-mapped page table (0-4MB) */
|
||||||
page_tables[0] = (page_table_entry_t*)alloc_page();
|
page_tables[0] = (page_table_entry_t*)alloc_page();
|
||||||
memset(page_tables[0], 0, PAGE_SIZE);
|
memset(page_tables[0], 0, PAGE_SIZE);
|
||||||
for (uint32_t i = 0; i < PAGE_TABLE_ENTRIES; i++)
|
for (uint32_t i = 0; i < PAGE_TABLE_ENTRIES; i++)
|
||||||
|
|||||||
@ -99,41 +99,43 @@ void sse2_add_int32_arrays(int32_t *dst, const int32_t *a, const int32_t *b, siz
|
|||||||
__attribute__((force_align_arg_pointer))
|
__attribute__((force_align_arg_pointer))
|
||||||
void *sse2_memcpy(void *dst, const void *src, uint32_t n)
|
void *sse2_memcpy(void *dst, const void *src, uint32_t n)
|
||||||
{
|
{
|
||||||
uintptr_t i;
|
uint8_t *d = (uint8_t *)dst;
|
||||||
|
const uint8_t *s = (const uint8_t *)src;
|
||||||
|
uintptr_t i = 0;
|
||||||
|
|
||||||
/* Align to 16 bytes if necessary */
|
/* Align destination to 16 bytes */
|
||||||
while (((uintptr_t)dst & 15) && n > 0)
|
while (((uintptr_t)d & 15) && n > 0)
|
||||||
{
|
{
|
||||||
*((uint8_t*)dst) = *((uint8_t*)src);
|
*d++ = *s++;
|
||||||
dst = (uint8_t*)dst + 1;
|
|
||||||
src = (uint8_t*)src + 1;
|
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy 16-byte chunks with SSE2 */
|
/* Use SSE2 for 16-byte aligned blocks */
|
||||||
for (i = 0; i + 15 < n; i += 16)
|
for (; i + 15 < n; i += 16)
|
||||||
{
|
{
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"movdqa (%1), %%xmm0\n\t" /* Load 16 bytes from source into xmm0 */
|
"movdqa (%1), %%xmm0\n\t"
|
||||||
"movdqa %%xmm0, (%0)\n\t" /* Store 16 bytes to destination */
|
"movdqa %%xmm0, (%0)\n\t"
|
||||||
:
|
:
|
||||||
: "r"(dst + i), "r"(src + i)
|
: "r"(d + i), "r"(s + i)
|
||||||
: "xmm0", "memory"
|
: "xmm0", "memory"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle remaining bytes (less than 16) */
|
d += i;
|
||||||
while (n > 0)
|
s += i;
|
||||||
|
n -= i;
|
||||||
|
|
||||||
|
/* Copy any remaining bytes */
|
||||||
|
while (n--)
|
||||||
{
|
{
|
||||||
*((uint8_t*)dst) = *((uint8_t*)src);
|
*d++ = *s++;
|
||||||
dst = (uint8_t*)dst + 1;
|
|
||||||
src = (uint8_t*)src + 1;
|
|
||||||
n--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst; /* Return pointer to destination */
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__attribute__((force_align_arg_pointer))
|
__attribute__((force_align_arg_pointer))
|
||||||
char *sse2_strncpy(char *dest, const char *src, uint32_t n)
|
char *sse2_strncpy(char *dest, const char *src, uint32_t n)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user