[go: nahoru, domu]

Skip to content

Commit

Permalink
add some standard libc functions
Browse files Browse the repository at this point in the history
  • Loading branch information
PauloMigAlmeida committed Dec 16, 2021
1 parent 83061e8 commit b540e29
Show file tree
Hide file tree
Showing 12 changed files with 248 additions and 3 deletions.
1 change: 1 addition & 0 deletions include/libc/internals/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ long syscall(long nr_number, ...);
#define __NR_read 0
#define __NR_write 1
#define __NR_getpid 39
#define __NR_time 201

#endif /* INCLUDE_LIBC_INTERNAL_SYSCALL_H_ */
5 changes: 5 additions & 0 deletions include/libc/stdlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@ int rand(void);
int rand_r(unsigned int *seedp);
void srand(unsigned int s);

char* ltoa(long value, char *str, int radix);

int abs(int value);


#endif /* INCLUDE_LIBC_STDLIB_H_ */
19 changes: 19 additions & 0 deletions include/libc/string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* string.h
*
* Created on: 16/12/2021
* Author: Paulo Almeida
*/

#ifndef INCLUDE_LIBC_STRING_H_
#define INCLUDE_LIBC_STRING_H_

#include "libc/compiler/freestanding.h"

void* memcpy(void *dst, const void *src, size_t size);
void* memset(void *buf, char value, size_t size);
void* memmove(void *dst, void *src, size_t size);
size_t strlen(const char *buf);
void strrev(char *str, size_t length);

#endif /* INCLUDE_LIBC_STRING_H_ */
6 changes: 3 additions & 3 deletions src/libc/stdlib/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#----------------------------------------------------------------------------
# AlmeidaOS libc/rand makefile
# AlmeidaOS libc/stdlib makefile
#----------------------------------------------------------------------------

DIR_ROOT := $(CURDIR)/../../../
Expand All @@ -10,15 +10,15 @@ include $(DIR_ROOT)/scripts/config.mk
ASFLAGS := -f elf64

DIR_SRC_SUBSYSTEMS := $(shell find $(CURDIR)/* -maxdepth 1 -type d)
DIR_TARGET := $(DIR_BUILD)/libc/rand
DIR_TARGET := $(DIR_BUILD)/libc/stdlib

SRC_C_FILES := $(wildcard *.c)
BIN_C_FILES := $(SRC_C_FILES:%.c=$(DIR_TARGET)/%.o)

SRC_ASM_FILES := $(wildcard *.asm)
BIN_ASM_FILES := $(SRC_ASM_FILES:%.asm=$(DIR_TARGET)/%.o)

TAG := [libc/rand]
TAG := [libc/stdlib]

all: mkdir compile
@echo "$(TAG) Compiled successfully"
Expand Down
17 changes: 17 additions & 0 deletions src/libc/stdlib/abs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* abs.c
*
* Created on: 16/12/2021
* Author: Paulo Almeida
*/

#include "libc/stdlib.h"

int abs(int value) {
/*
* C99 abs:"if the result cannot be represented, the behavior is undefined."
* So I decided not to handle 2-complement's edge case such as -2147483648
*/
int const mask = value >> (sizeof(int) * CHAR_BIT - 1);
return (value + mask) ^ mask;
}
47 changes: 47 additions & 0 deletions src/libc/stdlib/ltoa.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* ltoa.c
*
* Created on: 16/12/2021
* Author: Paulo Almeida
*/

#include "libc/stdlib.h"
#include "libc/string.h"

char* ltoa(long value, char *str, int radix) {
// Check for supported base.
if (radix != 8 && radix != 10 && radix != 16) {
*str = '\0';
return str;
}

int i = 0;
bool is_negative = false;

/* handle edge case */
if (value == 0) {
str[i++] = '0';
str[i] = '\0';
return str;
}

/* negative numbers are handled only with base 10 */
if (value < 0 && radix == 10) {
is_negative = true;
value = abs(value);
}

while (value != 0) {
int rem = value % radix;
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
value = value / radix;
}

if (is_negative)
str[i++] = '-';

str[i] = '\0';
strrev(str, i);

return str;
}
49 changes: 49 additions & 0 deletions src/libc/string/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#----------------------------------------------------------------------------
# AlmeidaOS libc/string makefile
#----------------------------------------------------------------------------

DIR_ROOT := $(CURDIR)/../../../

include $(DIR_ROOT)/scripts/config.mk

# override AS flags from $(DIR_ROOT)/scripts/config.mk
ASFLAGS := -f elf64

DIR_SRC_SUBSYSTEMS := $(shell find $(CURDIR)/* -maxdepth 1 -type d)
DIR_TARGET := $(DIR_BUILD)/libc/string

SRC_C_FILES := $(wildcard *.c)
BIN_C_FILES := $(SRC_C_FILES:%.c=$(DIR_TARGET)/%.o)

SRC_ASM_FILES := $(wildcard *.asm)
BIN_ASM_FILES := $(SRC_ASM_FILES:%.asm=$(DIR_TARGET)/%.o)

TAG := [libc/string]

all: mkdir compile
@echo "$(TAG) Compiled successfully"

.PHONY: mkdir
mkdir:
@mkdir -p $(DIR_TARGET)

.PHONY: clean
clean:
@rm -f $(BIN_C_FILES)

.PHONY: compile
compile: $(BIN_C_FILES) $(BIN_ASM_FILES) $(DIR_SRC_SUBSYSTEMS)

$(BIN_C_FILES): $(DIR_TARGET)/%.o: %.c
@echo "$(TAG) Compiling $<"
@$(CC) $(CCFLAGS) -I$(DIR_INCLUDE) -c $< -o $@

$(BIN_ASM_FILES): $(DIR_TARGET)/%.o: %.asm
@echo "$(TAG) Assembling $<"
@$(AS) $(ASFLAGS) $< -o $@

.PHONY: $(DIR_SRC_SUBSYSTEMS)
$(DIR_SRC_SUBSYSTEMS):
@$(MAKE) $(MAKE_FLAGS) --directory=$@


23 changes: 23 additions & 0 deletions src/libc/string/memcpy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* memcpy.c
*
* Created on: 16/12/2021
* Author: Paulo Almeida
*/

#include "libc/string.h"

void* memcpy(void *dst, const void *src, size_t size) {

long d0, d1, d2;
asm volatile(
"rep movsq \n\t"
"movq rcx, %[remainder] \n\t"
"rep movsb \n\t"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
: "0" (size >> 3), [remainder] "g" (size & 7), "1" (dst), "2" (src)
: "memory"
);

return dst;
}
30 changes: 30 additions & 0 deletions src/libc/string/memmove.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* memmove.c
*
* Created on: 16/12/2021
* Author: Paulo Almeida
*/

#include "libc/string.h"

void* memmove(void *dst, void *src, size_t size) {
char *t_dst = dst;
char *t_src = src;

/* sanity check */
if (t_src == t_dst)
return dst;

memcpy(t_dst, t_src, size);

if ((t_dst > t_src && (t_src + size) < t_dst) || (t_src > t_dst && (t_dst + size) < t_src)) {
/* they don't interset */
memset(t_src, 0, size);
} else if (t_dst > t_src) {
memset(t_src, 0, size - (t_dst - t_src));
} else {
memset(t_src + ((t_src + size) - (t_dst + size)), 0, (t_src + size) - (t_dst + size));
}

return dst;
}
18 changes: 18 additions & 0 deletions src/libc/string/memset.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* memset.c
*
* Created on: 16/12/2021
* Author: Paulo Almeida
*/

#include "libc/string.h"

void* memset(void *buf, char value, size_t size) {
asm volatile(
"rep stosb \n\t"
: "=&D" (buf)
: "a" (value), "c"(size)
: "memory"
);
return buf;
}
16 changes: 16 additions & 0 deletions src/libc/string/strlen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* strlen.c
*
* Created on: 16/12/2021
* Author: Paulo Almeida
*/

#include "libc/string.h"

size_t strlen(const char *buf) {
/* we don't count NUL-terminator */
size_t len = 0;
for (; *(buf + len) != '\0'; len++)
/* nothing */ ;
return len;
}
20 changes: 20 additions & 0 deletions src/libc/string/strrev.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* strrev.c
*
* Created on: 16/12/2021
* Author: Paulo Almeida
*/

#include "libc/string.h"

void strrev(char *str, size_t length) {
/* str is expected to be NUL-terminated */
if (length < 2)
return;

for (size_t start = 0, end = length - 1; start < length / 2; start++, end--) {
char tmp = *(str + start);
*(str + start) = *(str + end);
*(str + end) = tmp;
}
}

0 comments on commit b540e29

Please sign in to comment.