diff --git a/.vscode/settings.json b/.vscode/settings.json index eb3723e9..df26bf8e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -103,7 +103,8 @@ "stddef.h": "c", "spinlock.h": "c", "stat.h": "c", - "video.h": "c" + "video.h": "c", + "libm.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "" diff --git a/kernel/common/Makefile b/kernel/common/Makefile index 5c02fa28..c1740c59 100644 --- a/kernel/common/Makefile +++ b/kernel/common/Makefile @@ -1,7 +1,7 @@ CFLAGS += -I . -kernel_common_subdirs:=libELF +kernel_common_subdirs:=libELF math all: glib.o @list='$(kernel_common_subdirs)'; for subdir in $$list; do \ diff --git a/kernel/common/math.h b/kernel/common/math.h new file mode 100644 index 00000000..9d76645a --- /dev/null +++ b/kernel/common/math.h @@ -0,0 +1,3 @@ +#pragma once +#include "stddef.h" +int64_t pow(int64_t x, int y); \ No newline at end of file diff --git a/kernel/common/math/Makefile b/kernel/common/math/Makefile new file mode 100644 index 00000000..996d4fed --- /dev/null +++ b/kernel/common/math/Makefile @@ -0,0 +1,14 @@ + + +CFLAGS += -I . + +all: fabs.o round.o pow.o + +fabs.o: fabs.c + gcc $(CFLAGS) -c fabs.c -o fabs.o + +round.o: round.c + gcc $(CFLAGS) -c round.c -o round.o + +pow.o: pow.c + gcc $(CFLAGS) -c pow.c -o pow.o \ No newline at end of file diff --git a/kernel/common/math/fabs.c b/kernel/common/math/fabs.c new file mode 100644 index 00000000..9eb5374c --- /dev/null +++ b/kernel/common/math/fabs.c @@ -0,0 +1,30 @@ +#include +#include +#include "libm.h" + +double fabs(double x) +{ + union + { + double f; + uint64_t i; + } u = {x}; + u.i &= -1ULL / 2; + return u.f; +} + + +#if __LDBL_MANT_DIG__ == 53 && __LDBL_MAX_EXP__ == 1024 +long double fabsl(long double x) +{ + return fabs(x); +} +#elif (__LDBL_MANT_DIG__ == 64 || __LDBL_MANT_DIG__ == 113) && __LDBL_MAX_EXP__ == 16384 +long double fabsl(long double x) +{ + union ldshape u = {x}; + + u.i.se &= 0x7fff; + return u.f; +} +#endif \ No newline at end of file diff --git a/kernel/common/math/libm.h b/kernel/common/math/libm.h new file mode 100644 index 00000000..29249a6a --- /dev/null +++ b/kernel/common/math/libm.h @@ -0,0 +1,75 @@ +#pragma once +#include + +// ===== 描述long double 的数据比特结构 +#if __LDBL_MANT_DIG__ == 53 && __LDBL_MAX_EXP__ == 1024 +#elif __LDBL_MANT_DIG__ == 64 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +union ldshape +{ + long double f; + struct + { + uint64_t m; + uint16_t se; + } i; +}; +#elif __LDBL_MANT_DIG__ == 113 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +union ldshape +{ + long double f; + struct + { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct + { + uint64_t lo; + uint64_t hi; + } i2; +}; +#elif __LDBL_MANT_DIG__ == 113 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __BIG_ENDIAN +union ldshape +{ + long double f; + struct + { + uint16_t se; + uint16_t top; + uint32_t mid; + uint64_t lo; + } i; + struct + { + uint64_t hi; + uint64_t lo; + } i2; +}; +#else +#error Unsupported long double representation +#endif + +#define FORCE_EVAL(x) \ + do \ + { \ + if (sizeof(x) == sizeof(float)) \ + { \ + volatile float __x; \ + __x = (x); \ + (void)__x; \ + } \ + else if (sizeof(x) == sizeof(double)) \ + { \ + volatile double __x; \ + __x = (x); \ + (void)__x; \ + } \ + else \ + { \ + volatile long double __x; \ + __x = (x); \ + (void)__x; \ + } \ + } while (0) diff --git a/kernel/common/math/pow.c b/kernel/common/math/pow.c new file mode 100644 index 00000000..9d2ee308 --- /dev/null +++ b/kernel/common/math/pow.c @@ -0,0 +1,10 @@ +#include +#include + +int64_t pow(int64_t x, int y) +{ + int64_t res = 1; + for (int i = 0; i < y; ++i) + res *= x; + return res; +} \ No newline at end of file diff --git a/kernel/common/math/round.c b/kernel/common/math/round.c new file mode 100644 index 00000000..120cd90f --- /dev/null +++ b/kernel/common/math/round.c @@ -0,0 +1,43 @@ + + +#include "libm.h" + +#if __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1 +#define EPS __DBL_EPSILON__ +#elif __FLT_EVAL_METHOD__ == 2 +#define EPS __LDBL_EPSILON__ +#endif +static const double toint = 1 / EPS; + +double round(double x) +{ + union + { + double f; + uint64_t i; + } u = {x}; + + int e = u.i >> 52 & 0x7ff; + double y; + + if (e >= 0x3ff + 52) + return x; + if (u.i >> 63) + x = -x; + if (e < 0x3ff - 1) + { + /* raise inexact if x!=0 */ + FORCE_EVAL(x + toint); + return 0 * u.f; + } + y = x + toint - toint - x; + if (y > 0.5) + y = y + x - 1; + else if (y <= -0.5) + y = y + x + 1; + else + y = y + x; + if (u.i >> 63) + y = -y; + return y; +} \ No newline at end of file diff --git a/kernel/common/printk.c b/kernel/common/printk.c index 63ec2993..2d836dc2 100644 --- a/kernel/common/printk.c +++ b/kernel/common/printk.c @@ -9,7 +9,7 @@ #include #include - +#include "math.h" //#include "linkage.h" struct printk_screen_info pos; @@ -535,6 +535,7 @@ static char *write_num(char *str, ul num, int base, int field_width, int precisi return str; } + static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags) { /** @@ -572,11 +573,11 @@ static char *write_float_point_num(char *str, double num, int field_width, int p if (sign) --field_width; - int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度 - ul num_z = (ul)(num); // 获取整数部分 - ul num_decimal = (ul)(round((num - num_z) * precision)); // 获取小数部分 + int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度 + uint64_t num_z = (uint64_t)(num); // 获取整数部分 + uint64_t num_decimal = (uint64_t)(round(1.0*(num - num_z) * pow(10, precision))); // 获取小数部分 - if (num == 0) + if (num == 0 || num_z == 0) tmp_num_z[js_num_z++] = '0'; else { @@ -605,18 +606,23 @@ static char *write_float_point_num(char *str, double num, int field_width, int p *str++ = sign; // 输出整数部分 - while (js_num_z-- > 0) - *str++ = tmp_num_z[js_num_z]; - + // while (js_num_z-- > 0) + // *str++ = tmp_num_z[js_num_z]; + while (js_num_z > 0) + { + *str++ = tmp_num_z[js_num_z - 1]; + --js_num_z; + } *str++ = '.'; // 输出小数部分 - while (js_num_d-- > 0) + int total_dec_count = js_num_d; + for (int i = 0; i < precision && js_num_d-- > 0; ++i) *str++ = tmp_num_d[js_num_d]; - while (js_num_d < precision) + while (total_dec_count < precision) { - --precision; + ++total_dec_count; *str++ = '0'; } diff --git a/run.sh b/run.sh index 9578a20f..36265580 100644 --- a/run.sh +++ b/run.sh @@ -107,7 +107,7 @@ if [ $flag_can_run -eq 1 ]; then else qemu-system-x86_64 -cdrom ${iso} -m 512M -smp 2,cores=2,threads=1,sockets=1 \ -boot order=d \ - -monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm -s -S -cpu "IvyBridge,+apic,+x2apic,check,${allflags}" --enable-kvm -rtc clock=host,base=localtime -serial file:serial_opt.txt \ + -monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm -s -S -cpu "IvyBridge,+apic,+x2apic,+fpu,check,${allflags}" --enable-kvm -rtc clock=host,base=localtime -serial file:serial_opt.txt \ -drive id=disk,file=bin/disk.img,if=none \ -device ahci,id=ahci \ -device ide-hd,drive=disk,bus=ahci.0 \ diff --git a/user/apps/about/about.c b/user/apps/about/about.c index 0cd69f8b..4738044f 100644 --- a/user/apps/about/about.c +++ b/user/apps/about/about.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include void print_ascii_logo() { @@ -26,11 +28,11 @@ int main() { // printf("Hello World!\n"); print_ascii_logo(); - usleep(500000); - usleep(500000); + print_copyright(); // exit(0); // while (1) // ; + return 0; } \ No newline at end of file diff --git a/user/libs/libc/math.h b/user/libs/libc/math.h index ef470a48..e7d2a9df 100644 --- a/user/libs/libc/math.h +++ b/user/libs/libc/math.h @@ -1,5 +1,5 @@ #pragma once - +#include "stddef.h" double fabs(double x); float fabsf(float x); @@ -7,4 +7,6 @@ long double fabsl(long double x); double round(double x); float roundf(float x); -long double roundl(long double x); \ No newline at end of file +long double roundl(long double x); + +int64_t pow(int64_t x, int y); \ No newline at end of file diff --git a/user/libs/libc/math/Makefile b/user/libs/libc/math/Makefile index 1e62c359..996d4fed 100644 --- a/user/libs/libc/math/Makefile +++ b/user/libs/libc/math/Makefile @@ -1,11 +1,14 @@ -all: fabs.o round.o CFLAGS += -I . +all: fabs.o round.o pow.o fabs.o: fabs.c gcc $(CFLAGS) -c fabs.c -o fabs.o round.o: round.c - gcc $(CFLAGS) -c round.c -o round.o \ No newline at end of file + gcc $(CFLAGS) -c round.c -o round.o + +pow.o: pow.c + gcc $(CFLAGS) -c pow.c -o pow.o \ No newline at end of file diff --git a/user/libs/libc/math/fabs.c b/user/libs/libc/math/fabs.c index c64b1670..39a8eb50 100644 --- a/user/libs/libc/math/fabs.c +++ b/user/libs/libc/math/fabs.c @@ -1,6 +1,7 @@ #include #include #include "libm.h" + double fabs(double x) { union diff --git a/user/libs/libc/math/pow.c b/user/libs/libc/math/pow.c new file mode 100644 index 00000000..5cabe645 --- /dev/null +++ b/user/libs/libc/math/pow.c @@ -0,0 +1,10 @@ +#include "math.h" +#include + +int64_t pow(int64_t x, int y) +{ + int64_t res = 1; + for (int i = 0; i < y; ++i) + res *= x; + return res; +} \ No newline at end of file diff --git a/user/libs/libc/printf.c b/user/libs/libc/printf.c index a1ca5fdf..4ad15c5d 100644 --- a/user/libs/libc/printf.c +++ b/user/libs/libc/printf.c @@ -9,7 +9,6 @@ static char *write_num(char *str, uint64_t num, int base, int field_width, int precision, int flags); static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags); - static int skip_and_atoi(const char **s) { /** @@ -323,10 +322,6 @@ int vsprintf(char *buf, const char *fmt, va_list args) break; case 'f': // 默认精度为3 - // printk("1111\n"); - // va_arg(args, double); - // printk("222\n"); - if (precision < 0) precision = 3; @@ -497,11 +492,11 @@ static char *write_float_point_num(char *str, double num, int field_width, int p if (sign) --field_width; - int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度 - uint64_t num_z = (uint64_t)(num); // 获取整数部分 - uint64_t num_decimal = (uint64_t)(round((num - num_z) * precision)); // 获取小数部分 + int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度 + uint64_t num_z = (uint64_t)(num); // 获取整数部分 + uint64_t num_decimal = (uint64_t)(round(1.0*(num - num_z) * pow(10, precision))); // 获取小数部分 - if (num == 0) + if (num == 0 || num_z == 0) tmp_num_z[js_num_z++] = '0'; else { @@ -530,18 +525,23 @@ static char *write_float_point_num(char *str, double num, int field_width, int p *str++ = sign; // 输出整数部分 - while (js_num_z-- > 0) - *str++ = tmp_num_z[js_num_z]; - + // while (js_num_z-- > 0) + // *str++ = tmp_num_z[js_num_z]; + while (js_num_z > 0) + { + *str++ = tmp_num_z[js_num_z - 1]; + --js_num_z; + } *str++ = '.'; // 输出小数部分 - while (js_num_d-- > 0) + int total_dec_count = js_num_d; + for (int i = 0; i < precision && js_num_d-- > 0; ++i) *str++ = tmp_num_d[js_num_d]; - while (js_num_d < precision) + while (total_dec_count < precision) { - --precision; + ++total_dec_count; *str++ = '0'; }