diff --git a/.gitignore b/.gitignore index 145c255..e43b81a 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ trainscript/tsvm *.tab.h *.l.h lex.yy.cpp + +depmake.exe* +docs/* diff --git a/Depfile b/Depfile new file mode 100644 index 0000000..d490594 --- /dev/null +++ b/Depfile @@ -0,0 +1,21 @@ +#Config +Artifact=kernel +TempDir=obj +SourceDir=asm src +Files=trainscript/trainscript.y trainscript/trainscript.l trainscript/tsvm.cpp + +# Tools +AS=gcc +CC=gcc +CXX=g++ +LD=g++ +LEX=flex +YACC=bison + +# Flags +FLAGS=-m32 -Dnullptr=0 +ASFLAGS= +CCFLAGS=-g -std=c11 -Dnullptr=0 -Wall -g -fno-stack-protector -ffreestanding -Iinclude +CXXFLAGS=-g -std=c++11 -Wall -g -fno-stack-protector -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -Wall -Wextra -ffreestanding -Wno-unused-function -Iinclude +LDFLAGS=-g -m32 -nostdlib -fno-builtin -Tkernel.ld + diff --git a/Makefile b/Makefile index c26c6b5..741b522 100644 --- a/Makefile +++ b/Makefile @@ -8,11 +8,11 @@ LEX=flex YACC=bison # define nullptr, but not NULL. -CFLAGS = -m32 -Dnullptr=0 +CFLAGS = -m32 ASFLAGS = -CCFLAGS = -g -std=c11 -Wall -g -fno-stack-protector -ffreestanding -Iinclude +CCFLAGS = -g -std=c11 -Wall -Dnullptr=0 -g -fno-stack-protector -ffreestanding -Iinclude CXXFLAGS = -g -std=c++11 -Wall -g -fno-stack-protector -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -Wall -Wextra -ffreestanding -Wno-unused-function -Iinclude -LDFLAGS = -g -m32 -Tkernel.ld +LDFLAGS = -g -m32 -nostdlib -fno-builtin -Tkernel.ld all: clean kernel diff --git a/Makefile.new b/Makefile.new new file mode 100644 index 0000000..f97c9a3 --- /dev/null +++ b/Makefile.new @@ -0,0 +1,109 @@ +# Makefile generated by makedep. + +# Tools +AS = gcc +CC = gcc +CXX = g++ +LD = g++ +LEX = flex +YACC = bison + +# File Lists +SRCS_AS = asm/intr_common_handler.S asm/multiboot.S asm/start.S +SRCS_CC = src/console.c src/init.c src/interrupts.c src/malloc.c src/pmm.c src/stdlib.c src/timer.c src/vmm.c +SRCS_CXX = trainscript/tsvm.cpp src/cplusplus.cpp src/vm.cpp obj/trainscript.yy.cpp obj/trainscript.tab.cpp +OBJS = obj/trainscript.o obj/trainscript.o obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o + +# Flags +FLAGS = -m32 -Dnullptr=0 +ASFLAGS = +CCFLAGS = -g -std=c11 -Dnullptr=0 -Wall -g -fno-stack-protector -ffreestanding -Iinclude +CXXFLAGS = -g -std=c++11 -Wall -g -fno-stack-protector -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -Wall -Wextra -ffreestanding -Wno-unused-function -Iinclude +LDFLAGS = -g -m32 -nostdlib -fno-builtin -Tkernel.ld + +# Targets +all: kernel + +kernel: obj/trainscript.o obj/trainscript.o obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o + $(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/trainscript.o obj/trainscript.o obj/tsvm.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o + +# src/console.c +obj/console.o: src/console.c include/console.h include/stdlib.h \ + include/varargs.h + $(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/console.c + +# src/init.c +obj/init.o: src/init.c include/kernel.h include/stdlib.h include/varargs.h \ + include/console.h include/interrupts.h include/cpustate.h include/pmm.h \ + include/multiboot.h include/vmm.h include/timer.h + $(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/init.c + +# src/interrupts.c +obj/interrupts.o: src/interrupts.c include/interrupts.h include/cpustate.h \ + include/console.h include/stdlib.h include/varargs.h include/io.h \ + src/intr_stubs.h + $(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/interrupts.c + +# src/malloc.c +obj/malloc.o: src/malloc.c include/stdlib.h include/varargs.h + $(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/malloc.c + +# src/pmm.c +obj/pmm.o: src/pmm.c include/pmm.h include/multiboot.h include/kernel.h \ + include/stdlib.h include/varargs.h include/console.h + $(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/pmm.c + +# src/stdlib.c +obj/stdlib.o: src/stdlib.c include/stdlib.h include/varargs.h \ + include/kernel.h + $(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/stdlib.c + +# src/timer.c +obj/timer.o: src/timer.c include/timer.h include/interrupts.h \ + include/cpustate.h + $(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/timer.c + +# src/vmm.c +obj/vmm.o: src/vmm.c include/vmm.h include/pmm.h include/multiboot.h \ + include/stdlib.h include/varargs.h include/console.h include/kernel.h + $(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/vmm.c + +# trainscript/tsvm.cpp +obj/tsvm.o: trainscript/tsvm.cpp include/stdlib.h include/varargs.h \ + include/console.h trainscript/common.h trainscript/tsvm.hpp \ + include/ker/string.hpp include/ker/vector.hpp include/ker/new.hpp \ + include/ker/dictionary.hpp include/ker/pair.hpp trainscript/typeid.hpp \ + trainscript/trainscript.tab.hpp trainscript/trainscript.l.h \ + include/string.h + $(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c trainscript/tsvm.cpp + +# src/cplusplus.cpp +obj/cplusplus.o: src/cplusplus.cpp include/stdlib.h include/varargs.h \ + include/console.h include/ker/new.hpp + $(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/cplusplus.cpp + +# src/vm.cpp +obj/vm.o: src/vm.cpp include/stdlib.h include/varargs.h \ + src/../trainscript/tsvm.hpp include/console.h include/ker/string.hpp \ + include/ker/vector.hpp include/ker/new.hpp include/ker/dictionary.hpp \ + include/ker/pair.hpp src/../trainscript/typeid.hpp + $(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp + +# obj/trainscript.yy.cpp + $(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c obj/trainscript.yy.cpp + +# obj/trainscript.tab.cpp + $(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c obj/trainscript.tab.cpp + +# asm/intr_common_handler.S +obj/intr_common_handler.o: asm/intr_common_handler.S + $(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/intr_common_handler.S + +# asm/multiboot.S +obj/multiboot.o: asm/multiboot.S + $(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/multiboot.S + +# asm/start.S +obj/start.o: asm/start.S + $(AS) $(FLAGS) $(ASFLAGS) -o $@ -c asm/start.S + diff --git a/src/console.c b/src/console.c index a82dda3..0ffcee4 100644 --- a/src/console.c +++ b/src/console.c @@ -183,6 +183,7 @@ void kprintf(const char *format, ...) { c = *(format++); int i; + float f; char *str; switch(c) { @@ -200,6 +201,10 @@ void kprintf(const char *format, ...) i = va_arg(vl, int); kputs(itoa(i, buffer, 16)); break; + case 'f': + f = va_arg(vl, float); + kputs(ftoa(f, buffer, 3)); + break; case 'c': c = va_arg(vl, int); kputc(c); diff --git a/src/stdlib.c b/src/stdlib.c index 75425bc..a44b3ee 100644 --- a/src/stdlib.c +++ b/src/stdlib.c @@ -97,6 +97,54 @@ double atod(const char *str) return 42.0; } +// Converts a given integer x to string str[]. d is the number +// of digits required in output. If d is more than the number +// of digits in x, then 0s are added at the beginning. +static int intToStr(int x, char str[], int d) +{ + int i = 0; + while (x) + { + str[i++] = (x%10) + '0'; + x = x/10; + } + + // If number of digits required is more, then + // add 0s at the beginning + while (i < d) + str[i++] = '0'; + + reverse(str, i); + str[i] = '\0'; + return i; +} + +// Converts a floating point number to string. +void ftoa(float n, char *res, int afterpoint) +{ + // Extract integer part + int ipart = (int)n; + + // Extract floating part + float fpart = n - (float)ipart; + + // convert integer part to string + int i = intToStr(ipart, res, 0); + + // check for display option after point + if (afterpoint != 0) + { + res[i] = '.'; // add dot + + // Get the value of fraction part upto given no. + // of points after dot. The third parameter is needed + // to handle cases like 233.007 + //fpart = fpart * pow(10, afterpoint); + + intToStr((int)fpart, res + i + 1, afterpoint); + } +} + void *memmove( void *destination, const void *source, size_t num) { diff --git a/src/vm.cpp b/src/vm.cpp index 19f5883..1d981d5 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -15,12 +15,18 @@ VAR global : INT; PUB main() | i : INT BEGIN print(10, 20, 30); + afraid(15.0, 34) → i; + print(40, i, 60); 0 -> i; - REPEAT + WHILE i < 5 DO BEGIN print(i); i + 1 -> i; END + REPEAT + BEGIN + + END END)code"; void cpp_test(); @@ -32,6 +38,21 @@ public: Variable invoke(Vector arguments) override; }; +class NativeMethod : + public Method +{ +private: + void *function; +public: + NativeMethod(void *fn) : + function(fn) + { + + } + + Variable invoke(Vector arguments) override; +}; + Variable PrintMethod::invoke(Vector arguments) { for(auto &var : arguments) @@ -43,6 +64,95 @@ Variable PrintMethod::invoke(Vector arguments) return Variable::Void; } +static void copyCode(uint8_t **ptr, const uint8_t *src, size_t length) +{ + for(size_t i = 0; i < length; i++) { + // Copy byte + **ptr = src[i]; + // Iterate + (*ptr)++; + } +} + +/** + * @brief Invokes a cdecl function + * @param arguments Arguments passed to the c function + * @return uint32_t return value of the c function + */ +Variable NativeMethod::invoke(Vector arguments) +{ + if(this->function == nullptr) { + return Variable::Invalid; + } + + // ASM code: + // push ebp + // mov ebp, esp + // (push imm32) * num + // call [function] + // add esp, 4 * num + // ret + + uint8_t headerCode[] = { + 0x55, // push ebp + 0x89, 0xE5, // mov ebp, esp + }; + uint8_t tailCode[] = { + 0xB8, 0x42, 0x00, 0x00, 0x00, // mov eax,0x42 + 0xFF, 0xD0, // call eax + 0x83, 0xC4, 0x08, // add esp, 0x00 + 0xC9, // leave + // 0x5D, // pop ebp + 0xC3, // ret + }; + + // Store some memory for a function + uint8_t pushCode[] = { + 0x68, 0x00, 0x00, 0x00, 0x00 // push 0x00 + }; + + size_t stackSize = 4 * arguments.length(); + + // Copy target address to mov eax, 0x42 + *reinterpret_cast(&tailCode[1]) = reinterpret_cast(this->function); + // Copy stack size to add esp, 0x00 + *reinterpret_cast(&tailCode[9]) = static_cast(stackSize); + + uint8_t code[128]; + // Built the function + { + uint8_t *codePtr = &code[0]; + // Copy function header + copyCode(&codePtr, headerCode, sizeof(headerCode)); + + // Copy arguments + for(int i = arguments.length() - 1; i >= 0; i--) { + + // Copy argument value to push 0x00 + *reinterpret_cast(&pushCode[1]) = reinterpret_cast(arguments[i].integer); + + // Copy push code + copyCode(&codePtr, pushCode, sizeof(pushCode)); + } + + // Copy function end + copyCode(&codePtr, tailCode, sizeof(tailCode)); + } + + // Call some crazy + uint32_t (*func)() = (uint32_t(*)())code; + + uint32_t result = func(); + + return mkvar((Int)result); +} + +extern "C" uint32_t __attribute__((cdecl)) cCodeFunction(float a, int b) +{ + kprintf("a=%d, b=%d\n", a, b); + return 666; +} + extern "C" void vm_start() { // cpp_test(); @@ -58,6 +168,8 @@ extern "C" void vm_start() module->methods.add("print", new PrintMethod()); + module->methods.add("afraid", new NativeMethod(reinterpret_cast(&cCodeFunction))); + for(const auto &var : module->variables) { kprintf("Variable: '%s' => '", var.first.str()); diff --git a/trainOS.pro b/trainOS.pro index 0e22042..31e85d1 100644 --- a/trainOS.pro +++ b/trainOS.pro @@ -51,7 +51,8 @@ DISTFILES += \ trainscript/Makefile \ trainscript/trainscript.y \ trainscript/file02.ts \ - kernel.ld + kernel.ld \ + Depfile QMAKE_INCDIR = diff --git a/trainscript/tsvm.hpp b/trainscript/tsvm.hpp index 61197b0..f941eb8 100644 --- a/trainscript/tsvm.hpp +++ b/trainscript/tsvm.hpp @@ -19,7 +19,7 @@ extern "C" { namespace trainscript { using Int = int32_t; - using Real = double; + using Real = float; using Void = void; using Bool = bool;