From d221e17ec9072d6bd0b9b221646ea4e99f7deaed Mon Sep 17 00:00:00 2001 From: julianb0 Date: Wed, 21 Aug 2019 19:10:55 +0200 Subject: [PATCH] ppc --- vm/ob/command.ppc | 1655 --------------------------------------------- vm/ob/doskrnl.ppc | 1629 -------------------------------------------- vm/ob/hello.ppc | 995 --------------------------- 3 files changed, 4279 deletions(-) delete mode 100644 vm/ob/command.ppc delete mode 100644 vm/ob/doskrnl.ppc delete mode 100644 vm/ob/hello.ppc diff --git a/vm/ob/command.ppc b/vm/ob/command.ppc deleted file mode 100644 index 93b4c21..0000000 --- a/vm/ob/command.ppc +++ /dev/null @@ -1,1655 +0,0 @@ -# 1 "command.k" -# 1 "" -# 1 "" -# 31 "" -# 1 "/usr/include/stdc-predef.h" 1 3 4 -# 32 "" 2 -# 1 "command.k" -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -cmdstart: - jmp start - -# 1 "crt/crt.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; Limits -; -# 31 "crt/crt.k" -; -; Magic numbers -; - - - - -; -; CRT librairies -; - -# 1 "./crt/sys.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; SHUTDOWN syscall -; -; End virtual machine -; -Sys.Shutdown := 0x00 - -; -; EXIT syscall -; -; Return to COMMAND.COM -; -Sys.Exit := 0x01 - -; -; EXEC syscall -; -; IN -; ax0 = new RIP to load -; ax1 = frame ID to switch to -; -; New frame ID must be higher than current -; frame ID, and cannot be below 5 -; -; New CR1 is set so that new RIP corresponds to 1MB -; -Sys.ExecuteInFrame := 0x02 - -; FIND syscalls -; -; Find file on disk -; -; IN -; ax0 = address of name buffer -; ax1 = size of name buffer -; -; OUT -; rax = # of bytes written in name buffer -; rdx = size of file -; -; -Sys.FindFirst := 0x20 -Sys.FindNext := 0x21 - -; -; OPEN syscall -; -; IN -; ax0 = name string -; -; OUT -; rax = handle of file, or <0 if couldn't open -; -Sys.OpenFile := 0x30 - -; -; CREATE syscall -; -; IN -; ax0 = name string -; -; OUT -; rax = 0 on success, or <0 if couldn't open -; -Sys.CreateFile := 0x31 - -; -; REMOVE syscall -; -; IN -; ax0 = name string -; -; OUT -; rax = 0 on success, or <0 if couldn't open -; -Sys.RemoveFile := 0x32 - -; -; CLOSE syscall -; -; IN -; ax0 = file handle -; -Sys.CloseFile := 0x35 - -; -; READ syscall -; -; IN -; ax0 = file handle -; ax1 = buffer address -; ax2 = buffer size -; -; OUT -; rax = number of bytes read, <0 on error -; -Sys.ReadFile := 0x38 - -; Halt mode -Sys.EnterHaltMode := 0x999 -# 43 "crt/crt.k" 2 -# 1 "./crt/str.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; int strnlen(char *, int) -; -strnlen: - mov rcx, ax1 - scasb ax0, zero - - sub rax, ax1, rcx - ret - -; -; int strlen(char *) -; -strlen: - mov rcx, 0x7AFFFFFF - mov rdx, rcx - scasb ax0, zero - - sub rax, rdx, rcx - ret - -; -; void strcpy(char *, const char *) -; -strcpy: -.l: - mov rcx, b[ax1] - mov b[ax0], rcx - - jrcxz .r - - inc ax0 - inc ax1 - - jmp .l - -.r: - ret - -; -; void strncpy(char *, const char *, int) -; -strncpy: - mov rcx, ax2 - jrcxz .r - -.l: - mov b[ax0], b[ax1] - - inc ax0 - inc ax1 - - loop .l - -.r: - ret - -; -; void strnzcpy(char *, const char *, int) -; -strnzcpy: - mov rcx, ax2 - jrcxz .r - -.l: - mov rax, b[ax1] - mov b[ax0], rax - - jraxz .r - - inc ax0 - inc ax1 - - loop .l - -.z: - nul b[ax0] - -.r: - ret - -; -; int strcmp(const char *str1, const char *str2) -; -; Returns: -; 0 if the contents of both strings are equal -; >0 if the first character that does not match has a greater value in str1 than in str2 -; <0 if the first character that does not match has a lower value in str1 than in str2 -; -strcmp: - nul rsi -.l: - movzx rax, b[ax0+rsi] - movzx rdx, b[ax1+rsi] - - bne rax, rdx, .r - - ; both zero? - add rcx, rax, rdx - jrcxz .r - - inc rsi - jmp .l - -.r: - sub rax, rdx - ret - -; -; int strncmp(const char *str1, const char *str2, int maxn) -; -strncmp: - mov rcx, ax2 - jrcxz .r - -.l: - movzx rax, b[ax0] - movzx rdx, b[ax1] - - bne rax, rdx, .r - - inc ax0 - inc ax1 - loop .l - -.r: - sub rax, rdx - ret - -; -; char *strchrnul(const char *str, int ch) -; -strchrnul: - mov rcx, 0x7AFFFFFF - scasb ax0, ax1 - - mov rax, ax0 - ret - -; -; char *strchr(const char *str, int ch) -; -strchr: - mov rcx, 0x7AFFFFFF - scasb ax0, ax1 - - bnz b[ax0], .r - nul rax - ret - -.r: - mov rax, ax0 - ret - -; -; void strrev(char *buf, const char *str) -; -; buf and src must NOT overlap -; -strrev: - bzr b[ax1], .z - - ; save str's location - mov rsi, ax1 - - ; go to str's end, just before - ; the null terminator - mov rcx, 0x7AFFFFFF - scasb ax1, zero - dec ax1 - -.l: - ; copy, going backward though str - ; and forward through buf - mov b[ax0], b[ax1] - - beq ax1, rsi, .r - - inc ax0 - dec ax1 - jmp .l - -.r: - nul b[ax0+1] - ret - -.z: - nul b[ax0] - ret - -; -; void strrev2(char *str) -; -; Inverses str -; -strrev2: - bzr b[ax0], .r - - mov ax1, ax0 - - ; go to str's end, just before - ; the null terminator - mov rcx, 0x7AFFFFFF - scasb ax1, zero - dec ax1 - - ; increase ax0 while decreasing ax1, performing exchanges -.l: - blteu ax1, ax0, .r - - xchg b[ax0], b[ax1] - - inc ax0 - dec ax1 - jmp .l - -.r: - ret -# 44 "crt/crt.k" 2 -# 1 "./crt/mem.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; void memcpy(void *, const void *, int) -; -memcpy: - mov rcx, ax2 - jrcxz .r - -.l: - sub rdx, ax2, rcx - mov b[ax0+rdx], b[ax1+rdx] - loop .l - -.r: - ret - -; -; void memzero(void *, int) -; -memzero: - mov rcx, ax1 - jrcxz .r - -.l: - nul b[ax0] - inc ax0 - loop .l - -.r: - ret -# 45 "crt/crt.k" 2 -# 1 "./crt/time.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; struct TIME -; { -; byte sec; +0 (0-59) -; byte min; +1 (0-59) -; byte hour; +2 (0-23) -; byte mday; +3 (0-31) -; byte month; +4 (0-11) -; byte; +5 (pad) -; word year; +6 (0-65536) -; word yday; +8 (0-365) -; word; +10 (pad) -; dword; +12 (pad) -; } 16 bytes -; - -; -; int DaysInYear(int year) -; -DaysInYear: - mov rax, 365 - - ; divisible by 4? - rem rcx, ax0, 4 - jrcxnz .end - - ; divisible by 100? - rem rcx, ax0, 100 - jrcxnz .leap - - ; divisible by 400? - rem rcx, ax0, 400 - jrcxnz .end - -.leap: - inc rax, 1 - -.end: - ret - -; -; TIME *GetTimeUTC(void) -; -GetTimeUTC: - ytime - - mov rdi, .buf - - ; seconds - rem rsi, rax, 60 - mov b[rdi], rsi - - ; minutes - div rsi, rax, 60 - rem rsi, 60 - mov b[rdi+1], rsi - - ; hours - div rsi, rax, 3600 - rem rsi, 24 - mov b[rdi+2], rsi - - ; month days - div rsi, rax, 3600*24 - mov b[rdi+3], rsi - - ; month - mov b[rdi+4], rbx - - ; years - mov w[rdi+6], rcx - - ; - ; ydays (TODO) - ; - - mov rax, .buf - ret - -.buf = [24] -# 46 "crt/crt.k" 2 - -# 1 "./crt/fmt/ltostr.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; void itoa(char *buf, int num, int base) -; -itoa: - mov ax3, 1 - jmp ltostr - -; -; void utoa(char *buf, int num, int base) -; -utoa: - nul ax3 - jmp ltostr - -; -; void ltostr(char *buf, int num, int base, bool signed) -; -ltostr: - mov rax, ax0 - nul rcx - - ; make sure base is in [2, 32] - bltu ax2, 2, .bad - bltu 36, ax2, .bad - - ; deal with zero - bzr ax1, .is_zero - - ; deal with base 10 signedness - - bzr ax3, .conv - bne ax2, 10, .conv ; base 10 - - shr rcx, ax1, 63 ; extract ax1 sign - jrcxz .conv - - neg ax1 ; NEG if negative - - ; main loop -.conv: - bzr ax1, .fini - - rem rdx, ax1, ax2 ; ax1 % base - - blt 9, rdx, .nondec ; rdx > 9 ? - - inc rdx, '0' - jmp .next - -.nondec: - inc rdx, 55 ; 'A' - 10 - -.next: - mov b[ax0], rdx - - inc ax0 - - div ax1, ax2 - jmp .conv - - ; add minus flag, null-terminate and reverse -.fini: - jrcxz .cxz - mov b[ax0], '-' - inc ax0 - -.cxz: - nul b[ax0] - - call strrev2, rax - ret - -; -; exceptional cases -; -.bad: - mov b[ax0], 0 - ret - -.is_zero: - mov b[ax0], 48 ; '0' - mov b[ax0+1], 0 - ret -# 48 "crt/crt.k" 2 -# 1 "./crt/fmt/strtol.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; int strtol(const char *str, int base) -; -; rax = integer extracted from str -; rdx = pointer to first invalid byte -; -strtol: - mov ax2, 1 - jmp strtoq - -; -; int strtoul(const char *str, int base) -; -; rax = integer extracted from str -; rdx = pointer to first invalid byte -; -strtoul: - nul ax2 - jmp strtoq - -; -; int strtoq(const char *str, int base, bool signed) -; -; guesses base when 'base'=0 -; -strtoq: - nul rax, rsi - mov rdx, ax0 - - ; make sure base is in [2, 32] - beq ax1, 1, .bad - bltu 36, ax1, .bad - - ; empty string? - bzr b[rdx], .done - -.skip_spc: - bne b[rdx], ' ', .no_spc - inc rdx - jmp .skip_spc - -.no_spc: - ; skip + - bne b[rdx], '+', .no_plus - inc rdx - -.no_plus: - ; unsigned? - bzr ax2, .unsigned - - ; parse '-' - bne b[rdx], '-', .unsigned - inc rdx - mov rsi, 1 - -.unsigned: - ; base 0 - bzr ax1, .base_0 - - ; base prefix? - bne b[rdx], '0', .main_loop - - inc rdx - movzx rcx, b[rdx] - - ; "0x"/"0b" prefix - jrcxz .done ; "0" - beq rcx, 'x', .parsed_0x - beq rcx, 'b', .parsed_0b - - ; may be octal, but we don't care - ; we accept "0110101010" (despite base=2) for instance - jmp .main_loop - -.parsed_0x: - ; are we in base 16? - ; if not, leave rax = 0 and *rdx = 'x' - bne ax1, 16, .done - ; else - inc rdx, 1 - jmp .main_loop - -.parsed_0b: - ; are we in base 2? - ; if not, leave rax = 0 and *rdx = 'b' - bne ax1, 2, .done - ; else - inc rdx - jmp .main_loop - -.base_0: - ; guess base - - beq b[rdx], '0', .b0_not10 - - ; must be base 10 - mov ax1, 10 - jmp .main_loop - -.b0_not10: - inc rdx - - bne b[rdx], 'x', .b0_not16 - inc rdx - mov ax1, 16 - jmp .main_loop - -.b0_not16: - bne b[rdx], 'b', .b0_not2 - inc rdx - mov ax1, 2 - jmp .main_loop - -.b0_not2: - ; take octal by default - mov ax1, 8 - -.main_loop: - movzx rcx, b[rdx] - inc rdx - - ; between 0 and 9? - bltu rcx, '0', .done - bltu '9', rcx, .not_digit10 - - ; yes - sub rcx, '0' - jmp .next - -.not_digit10: - bltu rcx, 'A', .done - bltu 'Z', rcx, .not_digitAZ - - sub rcx, 55 ; 'A' - 10 - jmp .next - -.not_digitAZ: - bltu rcx, 'a', .done - bltu 'z', rcx, .done - - sub rcx, 87 ; 'a' - 10 - jmp .next - -.next: - ; too large for base? - blteu ax1, rcx, .done - - mul rax, ax1 - inc rax, rcx - jmp .main_loop - -.done: - ; negative? - bzr rsi, .r - - ; yes - neg rax - -.r: - ret - -.bad: - ret -# 49 "crt/crt.k" 2 -# 1 "./crt/fmt/doprnt.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; typedef int (*PUTC)(int ch) -; int doprnt(PUTC putc, int n, const char *fmt, va_list ap) -; -doprnt: - push rbp - mov rbp, rsp - - push r12, r13, r14 - push r15, r16, r17 - - mov r12, ax2 ; fmt - mov r14, ax3 ; va_list - mov r15, ax1 ; n - mov r17, ax0 ; putc - nul r16 ; return value - -.main_loop: - ; find '%' or null-terminator - mov rcx, 0x7AFFFFFF - mov r13, r12 - scasb r13, '%' - - ; everything below r13 is a regular character; print it -.print_regular: - beq r12, r13, .check_modf - - call .doput, b[r12] - - inc r12, 1 - jmp .print_regular - -.check_modf: - ; did we find a '%' ? - ; if not, then we found fmt's null-terminator; we're done - bne b[r12], '%', .epilogue - - ; we did find a modifier / '%' - mov rax, b[r12+1] - inc r12, 2 - - beq rax, 's', .modf_s - beq rax, 'c', .modf_c - beq rax, 'p', .modf_p - beq rax, 'x', .modf_x - beq rax, 'd', .modf_d - beq rax, 'o', .modf_o - beq rax, 'b', .modf_b - beq rax, '%', .modf_percent - - ; unrecognized - jmp .bad_modifier - -.modf_s: - ; get string address - mov r13, q[r14] - inc r14, 8 - - bzr r13, .nullstring - -.print_string: - movzx ax0, b[r13] - bzr ax0, .main_loop - - inc r13 - call .doput - - jmp .print_string - -.modf_c: - call .doput, q[r14] - inc r14, 8 - - jmp .main_loop - -.modf_p: - call .doput, '0' - call .doput, 'x' - ; Fallthrough - -.modf_x: - mov ax2, 16 - jmp .print_number - -.modf_d: - mov ax2, 10 - jmp .print_number - -.modf_o: - mov ax2, 8 - jmp .print_number - -.modf_b: - mov ax2, 2 - jmp .print_number - -.print_number: - ; allocate itoa conversion buffer - sub rsp, 80 - mov r13, rsp - - ; assume modifier already set up ax2 - call itoa, rsp, q[r14] - inc r14, 8 - -.print_itoa_buf: - movzx ax0, b[r13] - - bzr ax0, .pib_end_loop - inc r13 - - call .doput - jmp .print_itoa_buf - -.pib_end_loop: - inc rsp, 80 - jmp .main_loop - -.modf_percent: - call .doput, '%' - jmp .main_loop - -.bad_modifier: - ; print "%?" to clearly indicate that something is wrong - call .doput, '%' - call .doput, '?' - - jmp .main_loop - -.nullstring: - ; %s was passed a NULL - call .doput, '(' - call .doput, 'n' - call .doput, 'u' - call .doput, 'l' - call .doput, 'l' - call .doput, ')' - - jmp .main_loop - -.epilogue: - mov rax, r16 - - pop r17, r16 - pop r15, r14 - pop r13, r12 - - leave - ret -; -; prints ax0 -; -.doput: - ; update print count - inc r16 - - ; if n==0, don't print - ; we follow the C convention that sprintf()-like functions - ; should return the number of characters that would have - ; been printed/written if 'n' were big enough - bzr r15, .r - - ; decrement n and print - dec r15 - call r17 - - ; did putc fail? - jraxz .r - - ; yes, so artificially set n=0 - nul r15 - -.r: - ret -# 50 "crt/crt.k" 2 -# 1 "./crt/fmt/printf.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; int putc(int ch) -; -putc: - prn ax0 - nul rax - ret - -; -; int printf(const char *fmt, ...) -; -printf: - mov ax2, ax0 - mov ax0, putc - mov ax1, 0x7AFFFFFF - add ax3, rsp, 8 - jmp doprnt - -; -; int nprintf(const char *fmt, int n, ...) -; -nprintf: - mov ax2, ax0 - mov ax0, putc - add ax3, rsp, 8 - jmp doprnt - -; -; Print a string -; Guaranteed to only affect rcx and ax0 -; -print: -.l: - movzx rax, b[ax0] - jraxz .r - - prn rax - inc ax0 - - jmp .l - -.r: - ret - -; -; Print exactly ax1 characters -; -nprint: - mov rcx, ax1 - jrcxz .r - -.l: - prn b[ax0] - inc ax0 - loop .l -.r: - ret -# 51 "crt/crt.k" 2 - -exit: - mov rax, Sys.Exit - trap 0 - -abort: - crash -# 8 "command.k" 2 - - - - -; COMMAND.COM guarantees that programs -; are always loaded on a 16KB boundary -; This is guaranteed to be the case -; in all future versions as well - - -start: - mov rsp, 0x104000 ; + 16KB - mov rbp, zero - - call main - - mov rax, Sys.EnterHaltMode - trap 0 - - crash - -cmd.versionstr = "COMMAND.COM, version 0.1 (KVISC)\nCopyright (C) 2019, The OS/K Team\nMIT license (permissive), see LICENCE file in source tree" - -argbuf.size := 256 -argbuf = [argbuf.size] -argv0 = [argbuf.size] -argv1pos = 0 - -stdin_echoing = 1 - -prompt = [32] - -main: - mov rsi, prompt - mov b[rsi+0], 'C' - mov b[rsi+1], ':' - mov b[rsi+2], '\' - mov b[rsi+3], '>' - mov b[rsi+4], ' ' - -.print_prompt: - call print, prompt - - ; empty stuff - call memzero, argbuf, argbuf.size - call memzero, argv0, argbuf.size - nul q[argv1pos] - - ; call nprint, argv0, argbuf.size - - ; iterator through argbuf - nul rcx - -.input_loop: - pause - pause - pause - - ; Fill .buf with user input - scan rax - jraxz .input_loop - - ; ESC key pressed? - beq rax, 0x1B, .handle_EXIT - - ; backspace character? - bne rax, 8, .handle_input - - ; anything to delete? - jrcxz .input_loop ; no - - ; yes, delete it - dec rcx - add rdx, rcx, argbuf - nul b[rdx] - - ; update screen - bzr b[stdin_echoing], .input_loop - prn 8 - - jmp .input_loop - -.handle_input: - bzr b[stdin_echoing], .se.z - prn rax - -.se.z: - beq rax, 10, .extract_argv0 - - ; when max line length is reached, - ; force a newline - beq rcx, argbuf.size, .extract_argv0 - - ; add character to buffer and increase iterator (rcx) - add rdx, rcx, argbuf - mov b[rdx], rax - inc rcx - - ; another one - jmp .input_loop - -.extract_argv0: - ; did we read anything at all? - ; if not, just go back to waiting input - jrcxz .print_prompt - - ; find first whitespace or null-terminator - mov rcx, argbuf.size - mov rdx, argbuf - scasb rdx, ' ' - - ; argv1 exists? if so, save its position - mov rsi, rdx - -.next_space: - mov rcx, b[rsi] - jrcxz .do_extract - - ; skip spaces - bne rcx, ' ', .not_a_space - inc rsi - jmp .next_space - -.not_a_space: - ; if we're here, we found a - ; non-zero non-space character - mov q[argv1pos], rsi - - ; fallthrough - -.do_extract: - ; how much do we copy? - sub rcx, rdx, argbuf - jrcxz .detect_builtin - dec rcx - - mov rdi, argbuf - mov rsi, argv0 - -.copy_loop: - mov b[rsi], b[rdi] - - inc rdi - inc rsi - - loop .copy_loop - -.detect_builtin: - -.builtin_cls = "cls" - call strcmp, argv0, .builtin_cls - jraxz .handle_CLS - -.builtin_crash = "crash" - call strcmp, argv0, .builtin_crash - jraxz .handle_CRASH - -.builtin_date = "date" - call strcmp, argv0, .builtin_date - jraxz .handle_DATE - -.builtin_dir = "dir" - call strcmp, argv0, .builtin_dir - jraxz .handle_DIR - -.builtin_dump = "dump" - call strcmp, argv0, .builtin_dump - jraxz .handle_DUMP - -.builtin_echo = "echo" - call strcmp, argv0, .builtin_echo - jraxz .handle_ECHO - -.builtin_erase = "erase" - call strcmp, argv0, .builtin_erase - jraxz .handle_ERASE - -.builtin_exit = "exit" - call strcmp, argv0, .builtin_exit - jraxz .handle_EXIT - -.builtin_help = "help" - call strcmp, argv0, .builtin_help - jraxz .handle_HELP - -.builtin_halt = "halt" - call strcmp, argv0, .builtin_halt - jraxz .handle_HALT - -.builtin_make = "make" - call strcmp, argv0, .builtin_make - jraxz .handle_MAKE - -.builtin_print = "print" - call strcmp, argv0, .builtin_print - jraxz .handle_PRINT - -.builtin_prompt = "prompt" - call strcmp, argv0, .builtin_prompt - jraxz .handle_PROMPT - -.builtin_remove = "remove" - call strcmp, argv0, .builtin_remove - jraxz .handle_REMOVE - -.builtin_time = "time" - call strcmp, argv0, .builtin_time - jraxz .handle_TIME - -.builtin_vers = "vers" - call strcmp, argv0, .builtin_vers - jraxz .handle_VERS - - jmp .try_exec - -; -; call builtins -; - -# 1 "usr/cmd-dir.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - - - -.handle_DIR: - push rbp - mov rbp, rsp - - push r12, r13 - push r14, r15 - - nul r12 ; no. of files found - nul r13 ; no. of directories found - nul r14 ; total amount of bytes found - - call print, .dirmsg - -.first: - mov rax, Sys.FindFirst - mov ax0, .buf - mov ax1, 0x80 - trap 0 - - jmp .list - -.next: - mov rax, Sys.FindNext - mov ax0, .buf - mov ax1, 0x80 - trap 0 - -.list: - jraxz .end - - mov r15, rcx ; file size - inc r14, rcx - - ; directory? - bnz rdx, .is_dir - - ; found a file - inc r12 - - ; separate extension from file name - mov rcx, 0x80 - mov rsi, .buf - mov rdi, rsi - scasb rsi, '.' - - ; print file name - sub ax1, rsi, rdi - dec ax1 - call nprint, rdi - - ; calculate where to put extension - sub rdi, rsi, .buf - dec rdi - -.ext_pad: - ; print at least 11 non-space characters before extension - blte 11, rdi, .print_ext - prn ' ' - inc rdi - jmp .ext_pad - -.print_ext: - prn ' ' - ; here we print at least 4 characters excluding '.' - mov rcx, 4 - - bne b[rsi], '.', .print_ext.1 - inc rsi - -.print_ext.1: - bzr b[rsi], .print_ext.2 - - ; print and decrease rcx, unless it's already 0 - prn b[rsi] - inc rsi - jrcxz .print_ext.1 - - dec rcx - jmp .print_ext.1 - -.print_ext.2: - ; did we print at least 4 bytes? - jrcxz .print_bytes ; yes, carry on - -.pe2.l: - prn ' ' - loop .pe2.l - -.print_bytes: - ; print file size in bytes - prn ' ' - prn ' ' - prn ' ' - - shr rax, r15, 10 - and r15, 1023 - - push r15, rax - call printf, .bytesstr - inc rsp, 16 - -.prepare_next: - ; go find next entry - prn 10 - jmp .next - -.end: - shr rax, r14, 10 - shr rdx, rax, 10 - and rax, 1023 - and r14, 1023 - - push r14, rax, rdx - call printf, .endstr0 - inc rsp, 24 - - push r13, r12 - call printf, .endstr1 - inc rsp, 16 - - pop r15, r14 - pop r13, r12 - - leave - jmp .print_prompt - - ; special case: direcory -.is_dir: - inc r13 - - ; use printf instead of print - ; because it returns the # of - ; printed characters - call printf, .buf - - blte 11, rax, .dir_no_pad - sub rcx, 11, rax - dec rcx - -.dir.l: - prn ' ' - loop .dir.l - -.dir_no_pad: - call print, .dir_ext - - jmp .print_bytes - -.buf = [0x80] -.dir_ext = " " -.endstr0 = " total %dMB + %dKB + %dB\n" -.endstr1 = " found %d file(s), %d dir(s)\n" -.dirmsg = "Directory of C:\\\n\n" - -.bytesstr = "%d kilobytes + %d bytes" -; .bytesstr = "%dMB + %dKB + %dB" # too soon -# 228 "command.k" 2 -# 1 "usr/cmd-exec.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -.try_exec: - ; try without appending ".com" - mov rax, Sys.OpenFile - mov ax0, argv0 - trap 0 - - ; we good? - blte zero, rax, .do_exec - - ; nope, append ".com" and try again - sub rcx, argbuf.size, 5 - scasb ax0, zero ; find null-term - mov b[ax0+0], '.' ; ".com" - mov b[ax0+1], 'c' - mov b[ax0+2], 'o' - mov b[ax0+3], 'm' - nul b[ax0+4] - - ; try again - mov rax, Sys.OpenFile - mov ax0, argv0 - trap 0 - - ; still no good? - bltz rax, .exec_not_found - -.do_exec: - ; load file into memory - mov ax0, rax - mov ax1, 0x108000 ; + 32KB - mov ax2, 0x8000 - mov rax, Sys.ReadFile - trap 0 - - ; save load address - mov rcx, rax - - ; close file - mov rax, Sys.CloseFile - trap 0 - - ; read anything? - bltz rcx, .couldnt_read - jrcxz .empty_file - - ; all good, let's go - mov rax, Sys.ExecuteInFrame - mov ax0, 0x108000 ; + 32KB - mov ax1, 5 - trap 0 - - ; unreachable - jmp abort -# 229 "command.k" 2 -# 1 "usr/cmd-fsmisc.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -.handle_ERASE: - mov rax, Sys.RemoveFile - mov ax0, q[argv1pos] - bzr ax0, .need_params - trap 0 - - bltz rax, .couldnt_remove - - jmp .handle_MAKE ; re-create it back - -.handle_MAKE: - mov rax, Sys.CreateFile - mov ax0, q[argv1pos] - bzr ax0, .need_params - trap 0 - - bltz rax, .couldnt_open - - jmp .print_prompt - -.handle_PRINT: - mov rax, Sys.OpenFile - mov ax0, q[argv1pos] - bzr ax0, .need_params - trap 0 - - bltz rax, .file_not_found - - mov ax0, rax - mov ax1, 0x108000 ; + 32KB - mov ax2, 0x8000 - - mov rax, Sys.ReadFile - trap 0 - - mov rcx, rax - - mov rax, Sys.CloseFile - trap 0 - - bltz rcx, .couldnt_read - jrcxz .empty_file - - call nprint, 0x108000 ; + 32KB, rcx - - jmp .print_prompt - -.handle_REMOVE: - mov rax, Sys.RemoveFile - mov ax0, q[argv1pos] - bzr ax0, .need_params - trap 0 - - bltz rax, .couldnt_remove - - jmp .print_prompt -# 230 "command.k" 2 - -.handle_CLS: - prn 0x8BF00001 - jmp .print_prompt - -.handle_CRASH: - jmp abort - -.handle_DATE: - call GetTimeUTC - - mov rcx, b[rax+4] - inc rcx - - push b[rax+3], rcx, w[rax+6] - call printf, .datefmt - inc rsp, 40 - - jmp .print_prompt - -.datefmt = "%d/%d/%d\n" - -.handle_DUMP: - dump - jmp .print_prompt - -.handle_ECHO: - mov rax, q[argv1pos] - jraxz .echo.end - - call print, rax - -.echo.end: - prn 10 - jmp .print_prompt - -.handle_EXIT: - mov rax, Sys.Shutdown - trap 0 - jmp .print_prompt - -.handle_HALT: - mov rax, Sys.EnterHaltMode - trap 0 - jmp .print_prompt - -.handle_PROMPT: - mov ax0, prompt - mov ax1, q[argv1pos] - bzr ax1, .need_params - call strcpy - - jmp .print_prompt - -.handle_TIME: - call GetTimeUTC - - push b[rax], b[rax+1], b[rax+2] - call printf, .timefmt - inc rsp, 24 - - jmp .print_prompt - -.timefmt = "%d:%d:%d\n" - -.handle_VERS: - call print, cmd.versionstr - prn 10 - - jmp .print_prompt - -.handle_HELP: - call print, .helpmsg - call print, .helpmsg.cls - call print, .helpmsg.date - call print, .helpmsg.dir - call print, .helpmsg.dump - call print, .helpmsg.echo - call print, .helpmsg.erase - call print, .helpmsg.exit - call print, .helpmsg.help - call print, .helpmsg.halt - call print, .helpmsg.make - call print, .helpmsg.print - call print, .helpmsg.prompt - call print, .helpmsg.remove - call print, .helpmsg.time - call print, .helpmsg.ver - - jmp .print_prompt - -.helpmsg = "The following commands are built-in:\n" -.helpmsg.cls = " CLS Clear screen\n" -.helpmsg.date = " DATE Display current date\n" -.helpmsg.dir = " DIR Print contents of current directory\n" -.helpmsg.dump = " DUMP Toggles debug instruction dumping\n" -.helpmsg.echo = " ECHO Write arguments to standard output\n" -.helpmsg.erase = " ERASE Clear a file, making it blank\n" -.helpmsg.exit = " EXIT Initiate machine shutdown\n" -.helpmsg.help = " HELP Display these messages\n" -.helpmsg.halt = " HALT Put processor in halt mode\n" -.helpmsg.make = " MAKE Create an empty file\n" -.helpmsg.print = " PRINT Display contents of text file\n" -.helpmsg.prompt = " PROMPT Change the command line prompt\n" -.helpmsg.remove = " REMOVE Delete a file (permanently)\n" -.helpmsg.time = " TIME Display current time of day\n" -.helpmsg.ver = " VERS Display current COMMAND.COM version\n" - -.exec_not_found: - push argv0 - call printf, .enf_errmsg - inc rsp, 8 - - jmp .print_prompt - -.enf_errmsg = "%s: file not found\n" - -.file_not_found: - push q[argv1pos], argv0 - call printf, .fnf_errmsg - inc rsp, 16 - - jmp .print_prompt - -.fnf_errmsg = "%s: %s: file not found\n" - -.empty_file: - push q[argv1pos], argv0 - call printf, .ef_errmsg - inc rsp, 16 - - jmp .print_prompt - -.ef_errmsg = "%s: %s: file was empty\n" - -.couldnt_open: - push q[argv1pos], argv0 - call printf, .cno_errmsg - inc rsp, 16 - - jmp .print_prompt - -.cno_errmsg = "%s: %s: an error occured while opening file\n" - -.couldnt_remove: - push q[argv1pos], argv0 - call printf, .cne_errmsg - inc rsp, 16 - - jmp .print_prompt - -.cne_errmsg = "%s: %s: an error occured while removing file\n" - -.couldnt_read: - push q[argv1pos], argv0 - call printf, .cnr_errmsg - inc rsp, 16 - - jmp .print_prompt - -.cnr_errmsg = "%s: %s: an error occured while reading file\n" - -.need_params: - call print, argv0 - call print, .np_errmsg - - jmp .print_prompt - -.np_errmsg = ": need more parameters\n" diff --git a/vm/ob/doskrnl.ppc b/vm/ob/doskrnl.ppc deleted file mode 100644 index c737d80..0000000 --- a/vm/ob/doskrnl.ppc +++ /dev/null @@ -1,1629 +0,0 @@ -# 1 "doskrnl.k" -# 1 "" -# 1 "" -# 31 "" -# 1 "/usr/include/stdc-predef.h" 1 3 4 -# 32 "" 2 -# 1 "doskrnl.k" -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -__sysmain: - jmp start - -# 1 "crt/crt.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; Limits -; -# 31 "crt/crt.k" -; -; Magic numbers -; - - - - -; -; CRT librairies -; - -# 1 "./crt/sys.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; SHUTDOWN syscall -; -; End virtual machine -; -Sys.Shutdown := 0x00 - -; -; EXIT syscall -; -; Return to COMMAND.COM -; -Sys.Exit := 0x01 - -; -; EXEC syscall -; -; IN -; ax0 = new RIP to load -; ax1 = frame ID to switch to -; -; New frame ID must be higher than current -; frame ID, and cannot be below 5 -; -; New CR1 is set so that new RIP corresponds to 1MB -; -Sys.ExecuteInFrame := 0x02 - -; FIND syscalls -; -; Find file on disk -; -; IN -; ax0 = address of name buffer -; ax1 = size of name buffer -; -; OUT -; rax = # of bytes written in name buffer -; rdx = size of file -; -; -Sys.FindFirst := 0x20 -Sys.FindNext := 0x21 - -; -; OPEN syscall -; -; IN -; ax0 = name string -; -; OUT -; rax = handle of file, or <0 if couldn't open -; -Sys.OpenFile := 0x30 - -; -; CREATE syscall -; -; IN -; ax0 = name string -; -; OUT -; rax = 0 on success, or <0 if couldn't open -; -Sys.CreateFile := 0x31 - -; -; REMOVE syscall -; -; IN -; ax0 = name string -; -; OUT -; rax = 0 on success, or <0 if couldn't open -; -Sys.RemoveFile := 0x32 - -; -; CLOSE syscall -; -; IN -; ax0 = file handle -; -Sys.CloseFile := 0x35 - -; -; READ syscall -; -; IN -; ax0 = file handle -; ax1 = buffer address -; ax2 = buffer size -; -; OUT -; rax = number of bytes read, <0 on error -; -Sys.ReadFile := 0x38 - -; Halt mode -Sys.EnterHaltMode := 0x999 -# 43 "crt/crt.k" 2 -# 1 "./crt/str.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; int strnlen(char *, int) -; -strnlen: - mov rcx, ax1 - scasb ax0, zero - - sub rax, ax1, rcx - ret - -; -; int strlen(char *) -; -strlen: - mov rcx, 0x7AFFFFFF - mov rdx, rcx - scasb ax0, zero - - sub rax, rdx, rcx - ret - -; -; void strcpy(char *, const char *) -; -strcpy: -.l: - mov rcx, b[ax1] - mov b[ax0], rcx - - jrcxz .r - - inc ax0 - inc ax1 - - jmp .l - -.r: - ret - -; -; void strncpy(char *, const char *, int) -; -strncpy: - mov rcx, ax2 - jrcxz .r - -.l: - mov b[ax0], b[ax1] - - inc ax0 - inc ax1 - - loop .l - -.r: - ret - -; -; void strnzcpy(char *, const char *, int) -; -strnzcpy: - mov rcx, ax2 - jrcxz .r - -.l: - mov rax, b[ax1] - mov b[ax0], rax - - jraxz .r - - inc ax0 - inc ax1 - - loop .l - -.z: - nul b[ax0] - -.r: - ret - -; -; int strcmp(const char *str1, const char *str2) -; -; Returns: -; 0 if the contents of both strings are equal -; >0 if the first character that does not match has a greater value in str1 than in str2 -; <0 if the first character that does not match has a lower value in str1 than in str2 -; -strcmp: - nul rsi -.l: - movzx rax, b[ax0+rsi] - movzx rdx, b[ax1+rsi] - - bne rax, rdx, .r - - ; both zero? - add rcx, rax, rdx - jrcxz .r - - inc rsi - jmp .l - -.r: - sub rax, rdx - ret - -; -; int strncmp(const char *str1, const char *str2, int maxn) -; -strncmp: - mov rcx, ax2 - jrcxz .r - -.l: - movzx rax, b[ax0] - movzx rdx, b[ax1] - - bne rax, rdx, .r - - inc ax0 - inc ax1 - loop .l - -.r: - sub rax, rdx - ret - -; -; char *strchrnul(const char *str, int ch) -; -strchrnul: - mov rcx, 0x7AFFFFFF - scasb ax0, ax1 - - mov rax, ax0 - ret - -; -; char *strchr(const char *str, int ch) -; -strchr: - mov rcx, 0x7AFFFFFF - scasb ax0, ax1 - - bnz b[ax0], .r - nul rax - ret - -.r: - mov rax, ax0 - ret - -; -; void strrev(char *buf, const char *str) -; -; buf and src must NOT overlap -; -strrev: - bzr b[ax1], .z - - ; save str's location - mov rsi, ax1 - - ; go to str's end, just before - ; the null terminator - mov rcx, 0x7AFFFFFF - scasb ax1, zero - dec ax1 - -.l: - ; copy, going backward though str - ; and forward through buf - mov b[ax0], b[ax1] - - beq ax1, rsi, .r - - inc ax0 - dec ax1 - jmp .l - -.r: - nul b[ax0+1] - ret - -.z: - nul b[ax0] - ret - -; -; void strrev2(char *str) -; -; Inverses str -; -strrev2: - bzr b[ax0], .r - - mov ax1, ax0 - - ; go to str's end, just before - ; the null terminator - mov rcx, 0x7AFFFFFF - scasb ax1, zero - dec ax1 - - ; increase ax0 while decreasing ax1, performing exchanges -.l: - blteu ax1, ax0, .r - - xchg b[ax0], b[ax1] - - inc ax0 - dec ax1 - jmp .l - -.r: - ret -# 44 "crt/crt.k" 2 -# 1 "./crt/mem.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; void memcpy(void *, const void *, int) -; -memcpy: - mov rcx, ax2 - jrcxz .r - -.l: - sub rdx, ax2, rcx - mov b[ax0+rdx], b[ax1+rdx] - loop .l - -.r: - ret - -; -; void memzero(void *, int) -; -memzero: - mov rcx, ax1 - jrcxz .r - -.l: - nul b[ax0] - inc ax0 - loop .l - -.r: - ret -# 45 "crt/crt.k" 2 -# 1 "./crt/time.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; struct TIME -; { -; byte sec; +0 (0-59) -; byte min; +1 (0-59) -; byte hour; +2 (0-23) -; byte mday; +3 (0-31) -; byte month; +4 (0-11) -; byte; +5 (pad) -; word year; +6 (0-65536) -; word yday; +8 (0-365) -; word; +10 (pad) -; dword; +12 (pad) -; } 16 bytes -; - -; -; int DaysInYear(int year) -; -DaysInYear: - mov rax, 365 - - ; divisible by 4? - rem rcx, ax0, 4 - jrcxnz .end - - ; divisible by 100? - rem rcx, ax0, 100 - jrcxnz .leap - - ; divisible by 400? - rem rcx, ax0, 400 - jrcxnz .end - -.leap: - inc rax, 1 - -.end: - ret - -; -; TIME *GetTimeUTC(void) -; -GetTimeUTC: - ytime - - mov rdi, .buf - - ; seconds - rem rsi, rax, 60 - mov b[rdi], rsi - - ; minutes - div rsi, rax, 60 - rem rsi, 60 - mov b[rdi+1], rsi - - ; hours - div rsi, rax, 3600 - rem rsi, 24 - mov b[rdi+2], rsi - - ; month days - div rsi, rax, 3600*24 - mov b[rdi+3], rsi - - ; month - mov b[rdi+4], rbx - - ; years - mov w[rdi+6], rcx - - ; - ; ydays (TODO) - ; - - mov rax, .buf - ret - -.buf = [24] -# 46 "crt/crt.k" 2 - -# 1 "./crt/fmt/ltostr.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; void itoa(char *buf, int num, int base) -; -itoa: - mov ax3, 1 - jmp ltostr - -; -; void utoa(char *buf, int num, int base) -; -utoa: - nul ax3 - jmp ltostr - -; -; void ltostr(char *buf, int num, int base, bool signed) -; -ltostr: - mov rax, ax0 - nul rcx - - ; make sure base is in [2, 32] - bltu ax2, 2, .bad - bltu 36, ax2, .bad - - ; deal with zero - bzr ax1, .is_zero - - ; deal with base 10 signedness - - bzr ax3, .conv - bne ax2, 10, .conv ; base 10 - - shr rcx, ax1, 63 ; extract ax1 sign - jrcxz .conv - - neg ax1 ; NEG if negative - - ; main loop -.conv: - bzr ax1, .fini - - rem rdx, ax1, ax2 ; ax1 % base - - blt 9, rdx, .nondec ; rdx > 9 ? - - inc rdx, '0' - jmp .next - -.nondec: - inc rdx, 55 ; 'A' - 10 - -.next: - mov b[ax0], rdx - - inc ax0 - - div ax1, ax2 - jmp .conv - - ; add minus flag, null-terminate and reverse -.fini: - jrcxz .cxz - mov b[ax0], '-' - inc ax0 - -.cxz: - nul b[ax0] - - call strrev2, rax - ret - -; -; exceptional cases -; -.bad: - mov b[ax0], 0 - ret - -.is_zero: - mov b[ax0], 48 ; '0' - mov b[ax0+1], 0 - ret -# 48 "crt/crt.k" 2 -# 1 "./crt/fmt/strtol.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; int strtol(const char *str, int base) -; -; rax = integer extracted from str -; rdx = pointer to first invalid byte -; -strtol: - mov ax2, 1 - jmp strtoq - -; -; int strtoul(const char *str, int base) -; -; rax = integer extracted from str -; rdx = pointer to first invalid byte -; -strtoul: - nul ax2 - jmp strtoq - -; -; int strtoq(const char *str, int base, bool signed) -; -; guesses base when 'base'=0 -; -strtoq: - nul rax, rsi - mov rdx, ax0 - - ; make sure base is in [2, 32] - beq ax1, 1, .bad - bltu 36, ax1, .bad - - ; empty string? - bzr b[rdx], .done - -.skip_spc: - bne b[rdx], ' ', .no_spc - inc rdx - jmp .skip_spc - -.no_spc: - ; skip + - bne b[rdx], '+', .no_plus - inc rdx - -.no_plus: - ; unsigned? - bzr ax2, .unsigned - - ; parse '-' - bne b[rdx], '-', .unsigned - inc rdx - mov rsi, 1 - -.unsigned: - ; base 0 - bzr ax1, .base_0 - - ; base prefix? - bne b[rdx], '0', .main_loop - - inc rdx - movzx rcx, b[rdx] - - ; "0x"/"0b" prefix - jrcxz .done ; "0" - beq rcx, 'x', .parsed_0x - beq rcx, 'b', .parsed_0b - - ; may be octal, but we don't care - ; we accept "0110101010" (despite base=2) for instance - jmp .main_loop - -.parsed_0x: - ; are we in base 16? - ; if not, leave rax = 0 and *rdx = 'x' - bne ax1, 16, .done - ; else - inc rdx, 1 - jmp .main_loop - -.parsed_0b: - ; are we in base 2? - ; if not, leave rax = 0 and *rdx = 'b' - bne ax1, 2, .done - ; else - inc rdx - jmp .main_loop - -.base_0: - ; guess base - - beq b[rdx], '0', .b0_not10 - - ; must be base 10 - mov ax1, 10 - jmp .main_loop - -.b0_not10: - inc rdx - - bne b[rdx], 'x', .b0_not16 - inc rdx - mov ax1, 16 - jmp .main_loop - -.b0_not16: - bne b[rdx], 'b', .b0_not2 - inc rdx - mov ax1, 2 - jmp .main_loop - -.b0_not2: - ; take octal by default - mov ax1, 8 - -.main_loop: - movzx rcx, b[rdx] - inc rdx - - ; between 0 and 9? - bltu rcx, '0', .done - bltu '9', rcx, .not_digit10 - - ; yes - sub rcx, '0' - jmp .next - -.not_digit10: - bltu rcx, 'A', .done - bltu 'Z', rcx, .not_digitAZ - - sub rcx, 55 ; 'A' - 10 - jmp .next - -.not_digitAZ: - bltu rcx, 'a', .done - bltu 'z', rcx, .done - - sub rcx, 87 ; 'a' - 10 - jmp .next - -.next: - ; too large for base? - blteu ax1, rcx, .done - - mul rax, ax1 - inc rax, rcx - jmp .main_loop - -.done: - ; negative? - bzr rsi, .r - - ; yes - neg rax - -.r: - ret - -.bad: - ret -# 49 "crt/crt.k" 2 -# 1 "./crt/fmt/doprnt.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; typedef int (*PUTC)(int ch) -; int doprnt(PUTC putc, int n, const char *fmt, va_list ap) -; -doprnt: - push rbp - mov rbp, rsp - - push r12, r13, r14 - push r15, r16, r17 - - mov r12, ax2 ; fmt - mov r14, ax3 ; va_list - mov r15, ax1 ; n - mov r17, ax0 ; putc - nul r16 ; return value - -.main_loop: - ; find '%' or null-terminator - mov rcx, 0x7AFFFFFF - mov r13, r12 - scasb r13, '%' - - ; everything below r13 is a regular character; print it -.print_regular: - beq r12, r13, .check_modf - - call .doput, b[r12] - - inc r12, 1 - jmp .print_regular - -.check_modf: - ; did we find a '%' ? - ; if not, then we found fmt's null-terminator; we're done - bne b[r12], '%', .epilogue - - ; we did find a modifier / '%' - mov rax, b[r12+1] - inc r12, 2 - - beq rax, 's', .modf_s - beq rax, 'c', .modf_c - beq rax, 'p', .modf_p - beq rax, 'x', .modf_x - beq rax, 'd', .modf_d - beq rax, 'o', .modf_o - beq rax, 'b', .modf_b - beq rax, '%', .modf_percent - - ; unrecognized - jmp .bad_modifier - -.modf_s: - ; get string address - mov r13, q[r14] - inc r14, 8 - - bzr r13, .nullstring - -.print_string: - movzx ax0, b[r13] - bzr ax0, .main_loop - - inc r13 - call .doput - - jmp .print_string - -.modf_c: - call .doput, q[r14] - inc r14, 8 - - jmp .main_loop - -.modf_p: - call .doput, '0' - call .doput, 'x' - ; Fallthrough - -.modf_x: - mov ax2, 16 - jmp .print_number - -.modf_d: - mov ax2, 10 - jmp .print_number - -.modf_o: - mov ax2, 8 - jmp .print_number - -.modf_b: - mov ax2, 2 - jmp .print_number - -.print_number: - ; allocate itoa conversion buffer - sub rsp, 80 - mov r13, rsp - - ; assume modifier already set up ax2 - call itoa, rsp, q[r14] - inc r14, 8 - -.print_itoa_buf: - movzx ax0, b[r13] - - bzr ax0, .pib_end_loop - inc r13 - - call .doput - jmp .print_itoa_buf - -.pib_end_loop: - inc rsp, 80 - jmp .main_loop - -.modf_percent: - call .doput, '%' - jmp .main_loop - -.bad_modifier: - ; print "%?" to clearly indicate that something is wrong - call .doput, '%' - call .doput, '?' - - jmp .main_loop - -.nullstring: - ; %s was passed a NULL - call .doput, '(' - call .doput, 'n' - call .doput, 'u' - call .doput, 'l' - call .doput, 'l' - call .doput, ')' - - jmp .main_loop - -.epilogue: - mov rax, r16 - - pop r17, r16 - pop r15, r14 - pop r13, r12 - - leave - ret -; -; prints ax0 -; -.doput: - ; update print count - inc r16 - - ; if n==0, don't print - ; we follow the C convention that sprintf()-like functions - ; should return the number of characters that would have - ; been printed/written if 'n' were big enough - bzr r15, .r - - ; decrement n and print - dec r15 - call r17 - - ; did putc fail? - jraxz .r - - ; yes, so artificially set n=0 - nul r15 - -.r: - ret -# 50 "crt/crt.k" 2 -# 1 "./crt/fmt/printf.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; int putc(int ch) -; -putc: - prn ax0 - nul rax - ret - -; -; int printf(const char *fmt, ...) -; -printf: - mov ax2, ax0 - mov ax0, putc - mov ax1, 0x7AFFFFFF - add ax3, rsp, 8 - jmp doprnt - -; -; int nprintf(const char *fmt, int n, ...) -; -nprintf: - mov ax2, ax0 - mov ax0, putc - add ax3, rsp, 8 - jmp doprnt - -; -; Print a string -; Guaranteed to only affect rcx and ax0 -; -print: -.l: - movzx rax, b[ax0] - jraxz .r - - prn rax - inc ax0 - - jmp .l - -.r: - ret - -; -; Print exactly ax1 characters -; -nprint: - mov rcx, ax1 - jrcxz .r - -.l: - prn b[ax0] - inc ax0 - loop .l -.r: - ret -# 51 "crt/crt.k" 2 - -exit: - mov rax, Sys.Exit - trap 0 - -abort: - crash -# 8 "doskrnl.k" 2 - -; -; Special addresses -; - - - - - - -; The kernel guarantees that COMMAND.COM -; will always be loaded on a 16KB boundary -; This is guaranteed to be the case in all -; future versions as well - - - -; -; Entry point -; -start: - mov rsp, 0x104000 ; + 16KB - mov rbp, zero - - ;dump - - call main - - crash - -; -; Disk Operating System -; - -# 1 "sys/drv/cpudev.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -CPUDEV := 0 - -RFS.GetMaxIdx: - iocall CPUDEV, 16 - ret - -RFS.GetUsage: - iocall CPUDEV, 17 - ret - -RFS.GetCurIdx: - iocall CPUDEV, 18 - ret - -RFS.GetLeastAvail: - iocall CPUDEV, 19 - ret - -RFS.IsFrameActive: - iocall CPUDEV, 20 - ret - -RFS.ActivateFrame: - iocall CPUDEV, 21 - ret - -RFS.DeactivateFrame: - iocall CPUDEV, 22 - ret - -RFS.CopyFrame: - iocall CPUDEV, 23 - ret - -RFS.MoveFrame: - iocall CPUDEV, 24 - ret - -RFS.SwitchFrame: - iocall CPUDEV, 25 - ret - -RFS.LoadArgs: - iocall CPUDEV, 32 - ret - -RFS.LoadReg: - iocall CPUDEV, 33 - ret - -RFS.StoreReg: - iocall CPUDEV, 48 - ret - -IDT.AddHandler: - iocall CPUDEV, 64 - ret - -IDT.DelHandler: - iocall CPUDEV, 65 - ret - -IDT.QueryHandler: - iocall CPUDEV, 66 - -IDT.DoneHandling: - iocall CPUDEV, 67 - ret -# 43 "doskrnl.k" 2 -# 1 "sys/drv/memdev.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -MEMDEV := 1 - -MEM.GetMemOff: - iocall MEMDEV, 0 - ret - -MEM.GetMemSize: - iocall MEMDEV, 1 - ret -# 44 "doskrnl.k" 2 -# 1 "sys/drv/diskdev.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -DISKDEV := 4 - -DISK.FindFirst: -.slot := 16 - iocall DISKDEV, .slot - ret - -DISK.FindNext: -.slot := 17 - iocall DISKDEV, .slot - ret - -DISK.OpenFile: - iocall DISKDEV, 25 - ret - -DISK.CloseFile: - iocall DISKDEV, 26 - ret - -DISK.CreateFile: - iocall DISKDEV, 27 - ret - -DISK.RemoveFile: - iocall DISKDEV, 28 - ret - -DISK.ReadFile: - iocall DISKDEV, 32 - ret - -DISK.WriteFile: - iocall DISKDEV, 33 - ret -# 45 "doskrnl.k" 2 - -# 1 "sys/intr/excepts.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -DefaultExceptionHandler: - mov rsp, 0x105800 ; + 22KB - mov ax1, r12 - - bzr r12, DefaultTrapHandler.handle_Shutdown - bltu 11, r12, .unknown - - mov rsi, .err_ukn - lea ax0, b[rsi + r12 * 32] - call ScreenOfDeath - -.unknown: - call ScreenOfDeath, .err_ukn - crash - -.err_ukn = "Unknown exception number\0\0\0\0\0\0\0" -.err_udf = "Undefined behaviour exception\0\0" -.err_ill = "Illformed instruction exception" -.err_acc = "Invalid memory access exception" -.err_sys = "Supervisor-only instruct. used\0" -.err_dbf = "Double fault exception~~~~~~~~\0" -.err_imp = "Feat. not implemented exception" -.err_ali = "Misalignmed address exception\0\0" -.err_brk = "BREAK key (Ctrl+C) exception\0\0\0" -.err_ovf = "Overflow flag raised exception\0" -.err_div = "Division by zero exception\0\0\0\0\0" -# 47 "doskrnl.k" 2 -# 1 "sys/intr/common.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -ScreenOfDeath: - push r12 - mov r12, ax0 - - prn 10 - prn 0x8BF00001 - prn 0x8BF00002 - - push ax1 - call printf, .scr1 - pop - - bnz r14, .not_con - push .scr2_con - jmp .do_print - -.not_con: - ; rframes #2-#3-#4 belong to kernel - blt 4, r14, .not_krn - push .scr2_krn - jmp .do_print - -.not_krn: - push .scr2_usr - -.do_print: - push r14, r12 - call printf, .scr2 - inc rsp, 24 - - call dumprf, r14 - prn 10 - - call print, .scr3 - -.loop: - pause - pause - - scan rax - jraxz .loop - - beq rax, 0x0A, DefaultTrapHandler.handle_Exit - beq rax, 0x1B, DefaultTrapHandler.handle_Shutdown - - jmp .loop - - crash - -.scr1 = "-------- Unhandled EXCEPTION, TRAP/SYSCALL or INTERRUPT (code %d)\n" -.scr2 = "Description: %s\nFrame: %d (%s)\n\n" -.scr3 = "Press:\n ENTER to procede to COMMAND.COM\n ESCAPE to shutdown machine\n\n" - -.scr2_con = "dedicated command.com frame" -.scr2_usr = "userspace application frame" -.scr2_krn = "exception/interrupt handler" -# 48 "doskrnl.k" 2 -# 1 "sys/intr/trap0.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -TrapHandlers.prolog: - nul rbp - - ; rax = caller's cr1 - call RFS.LoadReg, r14, $cr1 - - ; we don't preserve the r12 we got - mov r12, rax - nul rdx - - jmp rcx - -TrapHandlers.epilog: - ; TRAP return values: RAX-RDX - - mov ax2, rax - call RFS.StoreReg, r14, $rax - - mov ax2, rdx - call RFS.StoreReg, r14, $rdx - - call IDT.DoneHandling, r13 - - iret - -; -; TRAP #0 handler -; -DefaultTrapHandler: - -.init: - mov rcx, .text - mov rsp, 0x104800 ; + 18KB - jmp TrapHandlers.prolog - -.text: - call RFS.LoadReg, r14, $rax - call RFS.LoadArgs, r14 - - ; will be optimized with a table - ; when we have a "finished" consistent API - jraxz .handle_Shutdown - beq rax, Sys.Exit, .handle_Exit - beq rax, Sys.ExecuteInFrame, .handle_EIF - beq rax, Sys.ReadFile, .handle_ReadFile - beq rax, Sys.OpenFile, .handle_OpenFile - beq rax, Sys.CloseFile, .handle_CloseFile - beq rax, Sys.CreateFile, .handle_CreateFile - beq rax, Sys.RemoveFile, .handle_RemoveFile - beq rax, Sys.FindNext, .handle_FindNext - beq rax, Sys.FindFirst, .handle_FindFirst - beq rax, Sys.EnterHaltMode, .handle_HaltMode - -.sod: - call ScreenOfDeath, .badsyscall, r13 - -.wrong: - call ScreenOfDeath, .badparams, r13 - -.fini.savecx: - mov ax2, rcx - call RFS.StoreReg, r14, $rcx - -.fini: - jmp TrapHandlers.epilog - -.badsyscall = "Invalid syscall number in RAX" -.badparams = "Invalid syscall parameters" - -;------------------------------------------------; -; Syscall implementations ; -;------------------------------------------------; - -; -; Pass control to COMMAND.COM in frame 0 -; -.handle_Exit: - ; deactivate current rframe - bzr r14, .hE_nz ; unless it's 0... - call RFS.DeactivateFrame, r14 - -.hE_nz: - ; open COMMAND.COM - call DISK.OpenFile, .cmdcom - - ; crash on failure - bltz rax, abort - - ; load at 0x108000 ; + 32KB - mov ax1, 0x108000 ; + 32KB - mov ax2, 0x80000 ; 512KB - call DISK.ReadFile, rax - - ; assume that COMMAND.COM being - ; less then 4KB means something - ; went wrong - blt rax, 0x1000, abort - - ; close the handle - call DISK.CloseFile, rax - - ; code address - mov ax2, 0x100000 - call RFS.StoreReg, zero, $rip - - ; usermode - mov ax2, 3 - call RFS.StoreReg, zero, $cr0 - - mov rcx, 0x108000 ; + 32KB - sub rcx, 0x100000 - - ; code offset - mov ax2, rcx - call RFS.StoreReg, zero, $cr1 - - ; return frame - nul r14 - - jmp .fini - -.cmdcom = "command.com" - -.handle_EIF: - blt ax1, 5, .wrong - - ; RIP can't be <1MB - mov rcx, 0x100000 - blt ax0, rcx, .wrong - - ; add old CR1 - add ax0, r12 - - ; real RIP can't be <1MB+32KB either - ; (kernel + cmdcom personal space) - add rdx, rcx, 0x8000 - blt ax0, rcx, .wrong - - ; save rframe and compute new CR1 - mov rbx, ax1 - sub rdi, ax0, rcx - - ; activate rframe - call RFS.ActivateFrame, rbx - - ; save new CR1 - mov ax2, rdi - call RFS.StoreReg, rbx, $cr1 - - ; interruptible user mode - mov ax2, 3 - call RFS.StoreReg, rbx, $cr0 - - ; set RIP = 1MB - mov ax2, rcx - call RFS.StoreReg, rbx, $rip - - ; change return frame - mov r14, rbx - - jmp .fini - -; -; Disk API -; -.handle_FindFirst: - inc ax0, r12 - call DISK.FindFirst - jmp .fini.savecx - -.handle_FindNext: - inc ax0, r12 - call DISK.FindNext - jmp .fini.savecx - -.handle_OpenFile: - inc ax0, r12 - call DISK.OpenFile - jmp .fini - -.handle_CreateFile: - inc ax0, r12 - call DISK.CreateFile - jmp .fini - -.handle_RemoveFile: - inc ax0, r12 - call DISK.RemoveFile - jmp .fini - -.handle_CloseFile: - call DISK.CloseFile - jmp .fini - -.handle_ReadFile: - inc ax1, r12 - call DISK.ReadFile - jmp .fini - -; -; Misc. -; -.handle_Shutdown: - call IDT.DelHandler, zero - stop - -.handle_HaltMode: - pause - pause - hlt - jmp .handle_HaltMode -# 49 "doskrnl.k" 2 - -# 1 "sys/dumprf.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -dumprf: - push rbp - mov rbp, rsp - - push r12, r13 - mov r12, ax0 - mov r13, rsp - - call RFS.LoadReg, r12, $cr1 - push rax - - call RFS.LoadReg, r12, $cr0 - push rax - - call RFS.LoadReg, r12, $rip - push rax - - push r12 - call printf, .dmp1 - - call RFS.LoadReg, r12, $srp - push rax - - call RFS.LoadReg, r12, $trp - push rax - - push zero # fixme - - call RFS.LoadReg, r12, $rbp - push rax - - call RFS.LoadReg, r12, $rsp - push rax - - call printf, .dmp2 - - call RFS.LoadReg, r12, $ax5 - push rax - - call RFS.LoadReg, r12, $ax4 - push rax - - call RFS.LoadReg, r12, $ax3 - push rax - - call RFS.LoadReg, r12, $ax2 - push rax - - call RFS.LoadReg, r12, $ax1 - push rax - - call RFS.LoadReg, r12, $ax0 - push rax - - call printf, .dmp3 - - call RFS.LoadReg, r12, $rdi - push rax - - call RFS.LoadReg, r12, $rsi - push rax - - call RFS.LoadReg, r12, $rdx - push rax - - call RFS.LoadReg, r12, $rcx - push rax - - call RFS.LoadReg, r12, $rbx - push rax - - call RFS.LoadReg, r12, $rax - push rax - - call printf, .dmp4 - - call RFS.LoadReg, r12, $r17 - push rax - - call RFS.LoadReg, r12, $r16 - push rax - - call RFS.LoadReg, r12, $r15 - push rax - - call RFS.LoadReg, r12, $r14 - push rax - - call RFS.LoadReg, r12, $r13 - push rax - - call RFS.LoadReg, r12, $r12 - push rax - - call printf, .dmp5 - - call RFS.LoadReg, r12, $r20 - push rax - - call RFS.LoadReg, r12, $r19 - push rax - - call RFS.LoadReg, r12, $r18 - push rax - - call printf, .dmp6 - - mov rsp, r13 - pop r13, r12 - - leave - ret - -.dmp1 = "Environ #1:\nfrm=0d%d rip=0x%x\ncr0=0x%x cr1=0x%x\n\n" -.dmp2 = "Environ #2:\nrsp=0x%x rbp=0x%x ind=0d%d\ngrp=0x%x trp=0x%x srp=0x%x\n\n" -.dmp3 = "Argument:\nax0=0x%x ax1=0x%x ax2=0x%x\nax3=0x%x ax4=0x%x ax5=0x%x\n\n" -.dmp4 = "Volatile:\nrax=0x%x rbx=0x%x rcx=0x%x\nrdx=0x%x rsi=0x%x rdi=0x%x\n\n" -.dmp5 = "Persistent:\nr12=0x%x r13=0x%x r14=0x%x\nr15=0x%x r16=0x%x r17=0x%x\n" -.dmp6 = "r18=0x%x r19=0x%x r20=0x%x\n" -# 51 "doskrnl.k" 2 -# 1 "sys/main.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -PrintBootMsg: - call print, .bootmsg - ret - -.bootmsg = "Starting DOS...\n\n" - -; -; Initialize TRAP handlers -; -InitSyscalls: - call RFS.ActivateFrame, 1 - - mov ax1, $rip - mov ax2, DefaultTrapHandler - call RFS.StoreReg - - mov ax0, 256 - mov ax1, 1 - call IDT.AddHandler - - ret - -InitExcepts: - call RFS.ActivateFrame, 2 - - mov ax1, $rip - mov ax2, DefaultExceptionHandler - call RFS.StoreReg - - call IDT.AddHandler, zero, 2 - -SwitchToCMD: - mov rax, Sys.Exit - trap 0 - -; -; Main function -; -main: - call PrintBootMsg - call InitSyscalls - call InitExcepts - call SwitchToCMD - ret -# 52 "doskrnl.k" 2 diff --git a/vm/ob/hello.ppc b/vm/ob/hello.ppc deleted file mode 100644 index eb98642..0000000 --- a/vm/ob/hello.ppc +++ /dev/null @@ -1,995 +0,0 @@ -# 1 "hello.k" -# 1 "" -# 1 "" -# 31 "" -# 1 "/usr/include/stdc-predef.h" 1 3 4 -# 32 "" 2 -# 1 "hello.k" -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -start: - jmp main - -# 1 "crt/crt.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; Limits -; -# 31 "crt/crt.k" -; -; Magic numbers -; - - - - -; -; CRT librairies -; - -# 1 "./crt/sys.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; SHUTDOWN syscall -; -; End virtual machine -; -Sys.Shutdown := 0x00 - -; -; EXIT syscall -; -; Return to COMMAND.COM -; -Sys.Exit := 0x01 - -; -; EXEC syscall -; -; IN -; ax0 = new RIP to load -; ax1 = frame ID to switch to -; -; New frame ID must be higher than current -; frame ID, and cannot be below 5 -; -; New CR1 is set so that new RIP corresponds to 1MB -; -Sys.ExecuteInFrame := 0x02 - -; FIND syscalls -; -; Find file on disk -; -; IN -; ax0 = address of name buffer -; ax1 = size of name buffer -; -; OUT -; rax = # of bytes written in name buffer -; rdx = size of file -; -; -Sys.FindFirst := 0x20 -Sys.FindNext := 0x21 - -; -; OPEN syscall -; -; IN -; ax0 = name string -; -; OUT -; rax = handle of file, or <0 if couldn't open -; -Sys.OpenFile := 0x30 - -; -; CREATE syscall -; -; IN -; ax0 = name string -; -; OUT -; rax = 0 on success, or <0 if couldn't open -; -Sys.CreateFile := 0x31 - -; -; REMOVE syscall -; -; IN -; ax0 = name string -; -; OUT -; rax = 0 on success, or <0 if couldn't open -; -Sys.RemoveFile := 0x32 - -; -; CLOSE syscall -; -; IN -; ax0 = file handle -; -Sys.CloseFile := 0x35 - -; -; READ syscall -; -; IN -; ax0 = file handle -; ax1 = buffer address -; ax2 = buffer size -; -; OUT -; rax = number of bytes read, <0 on error -; -Sys.ReadFile := 0x38 - -; Halt mode -Sys.EnterHaltMode := 0x999 -# 43 "crt/crt.k" 2 -# 1 "./crt/str.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; int strnlen(char *, int) -; -strnlen: - mov rcx, ax1 - scasb ax0, zero - - sub rax, ax1, rcx - ret - -; -; int strlen(char *) -; -strlen: - mov rcx, 0x7AFFFFFF - mov rdx, rcx - scasb ax0, zero - - sub rax, rdx, rcx - ret - -; -; void strcpy(char *, const char *) -; -strcpy: -.l: - mov rcx, b[ax1] - mov b[ax0], rcx - - jrcxz .r - - inc ax0 - inc ax1 - - jmp .l - -.r: - ret - -; -; void strncpy(char *, const char *, int) -; -strncpy: - mov rcx, ax2 - jrcxz .r - -.l: - mov b[ax0], b[ax1] - - inc ax0 - inc ax1 - - loop .l - -.r: - ret - -; -; void strnzcpy(char *, const char *, int) -; -strnzcpy: - mov rcx, ax2 - jrcxz .r - -.l: - mov rax, b[ax1] - mov b[ax0], rax - - jraxz .r - - inc ax0 - inc ax1 - - loop .l - -.z: - nul b[ax0] - -.r: - ret - -; -; int strcmp(const char *str1, const char *str2) -; -; Returns: -; 0 if the contents of both strings are equal -; >0 if the first character that does not match has a greater value in str1 than in str2 -; <0 if the first character that does not match has a lower value in str1 than in str2 -; -strcmp: - nul rsi -.l: - movzx rax, b[ax0+rsi] - movzx rdx, b[ax1+rsi] - - bne rax, rdx, .r - - ; both zero? - add rcx, rax, rdx - jrcxz .r - - inc rsi - jmp .l - -.r: - sub rax, rdx - ret - -; -; int strncmp(const char *str1, const char *str2, int maxn) -; -strncmp: - mov rcx, ax2 - jrcxz .r - -.l: - movzx rax, b[ax0] - movzx rdx, b[ax1] - - bne rax, rdx, .r - - inc ax0 - inc ax1 - loop .l - -.r: - sub rax, rdx - ret - -; -; char *strchrnul(const char *str, int ch) -; -strchrnul: - mov rcx, 0x7AFFFFFF - scasb ax0, ax1 - - mov rax, ax0 - ret - -; -; char *strchr(const char *str, int ch) -; -strchr: - mov rcx, 0x7AFFFFFF - scasb ax0, ax1 - - bnz b[ax0], .r - nul rax - ret - -.r: - mov rax, ax0 - ret - -; -; void strrev(char *buf, const char *str) -; -; buf and src must NOT overlap -; -strrev: - bzr b[ax1], .z - - ; save str's location - mov rsi, ax1 - - ; go to str's end, just before - ; the null terminator - mov rcx, 0x7AFFFFFF - scasb ax1, zero - dec ax1 - -.l: - ; copy, going backward though str - ; and forward through buf - mov b[ax0], b[ax1] - - beq ax1, rsi, .r - - inc ax0 - dec ax1 - jmp .l - -.r: - nul b[ax0+1] - ret - -.z: - nul b[ax0] - ret - -; -; void strrev2(char *str) -; -; Inverses str -; -strrev2: - bzr b[ax0], .r - - mov ax1, ax0 - - ; go to str's end, just before - ; the null terminator - mov rcx, 0x7AFFFFFF - scasb ax1, zero - dec ax1 - - ; increase ax0 while decreasing ax1, performing exchanges -.l: - blteu ax1, ax0, .r - - xchg b[ax0], b[ax1] - - inc ax0 - dec ax1 - jmp .l - -.r: - ret -# 44 "crt/crt.k" 2 -# 1 "./crt/mem.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; void memcpy(void *, const void *, int) -; -memcpy: - mov rcx, ax2 - jrcxz .r - -.l: - sub rdx, ax2, rcx - mov b[ax0+rdx], b[ax1+rdx] - loop .l - -.r: - ret - -; -; void memzero(void *, int) -; -memzero: - mov rcx, ax1 - jrcxz .r - -.l: - nul b[ax0] - inc ax0 - loop .l - -.r: - ret -# 45 "crt/crt.k" 2 -# 1 "./crt/time.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; struct TIME -; { -; byte sec; +0 (0-59) -; byte min; +1 (0-59) -; byte hour; +2 (0-23) -; byte mday; +3 (0-31) -; byte month; +4 (0-11) -; byte; +5 (pad) -; word year; +6 (0-65536) -; word yday; +8 (0-365) -; word; +10 (pad) -; dword; +12 (pad) -; } 16 bytes -; - -; -; int DaysInYear(int year) -; -DaysInYear: - mov rax, 365 - - ; divisible by 4? - rem rcx, ax0, 4 - jrcxnz .end - - ; divisible by 100? - rem rcx, ax0, 100 - jrcxnz .leap - - ; divisible by 400? - rem rcx, ax0, 400 - jrcxnz .end - -.leap: - inc rax, 1 - -.end: - ret - -; -; TIME *GetTimeUTC(void) -; -GetTimeUTC: - ytime - - mov rdi, .buf - - ; seconds - rem rsi, rax, 60 - mov b[rdi], rsi - - ; minutes - div rsi, rax, 60 - rem rsi, 60 - mov b[rdi+1], rsi - - ; hours - div rsi, rax, 3600 - rem rsi, 24 - mov b[rdi+2], rsi - - ; month days - div rsi, rax, 3600*24 - mov b[rdi+3], rsi - - ; month - mov b[rdi+4], rbx - - ; years - mov w[rdi+6], rcx - - ; - ; ydays (TODO) - ; - - mov rax, .buf - ret - -.buf = [24] -# 46 "crt/crt.k" 2 - -# 1 "./crt/fmt/ltostr.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; void itoa(char *buf, int num, int base) -; -itoa: - mov ax3, 1 - jmp ltostr - -; -; void utoa(char *buf, int num, int base) -; -utoa: - nul ax3 - jmp ltostr - -; -; void ltostr(char *buf, int num, int base, bool signed) -; -ltostr: - mov rax, ax0 - nul rcx - - ; make sure base is in [2, 32] - bltu ax2, 2, .bad - bltu 36, ax2, .bad - - ; deal with zero - bzr ax1, .is_zero - - ; deal with base 10 signedness - - bzr ax3, .conv - bne ax2, 10, .conv ; base 10 - - shr rcx, ax1, 63 ; extract ax1 sign - jrcxz .conv - - neg ax1 ; NEG if negative - - ; main loop -.conv: - bzr ax1, .fini - - rem rdx, ax1, ax2 ; ax1 % base - - blt 9, rdx, .nondec ; rdx > 9 ? - - inc rdx, '0' - jmp .next - -.nondec: - inc rdx, 55 ; 'A' - 10 - -.next: - mov b[ax0], rdx - - inc ax0 - - div ax1, ax2 - jmp .conv - - ; add minus flag, null-terminate and reverse -.fini: - jrcxz .cxz - mov b[ax0], '-' - inc ax0 - -.cxz: - nul b[ax0] - - call strrev2, rax - ret - -; -; exceptional cases -; -.bad: - mov b[ax0], 0 - ret - -.is_zero: - mov b[ax0], 48 ; '0' - mov b[ax0+1], 0 - ret -# 48 "crt/crt.k" 2 -# 1 "./crt/fmt/strtol.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; int strtol(const char *str, int base) -; -; rax = integer extracted from str -; rdx = pointer to first invalid byte -; -strtol: - mov ax2, 1 - jmp strtoq - -; -; int strtoul(const char *str, int base) -; -; rax = integer extracted from str -; rdx = pointer to first invalid byte -; -strtoul: - nul ax2 - jmp strtoq - -; -; int strtoq(const char *str, int base, bool signed) -; -; guesses base when 'base'=0 -; -strtoq: - nul rax, rsi - mov rdx, ax0 - - ; make sure base is in [2, 32] - beq ax1, 1, .bad - bltu 36, ax1, .bad - - ; empty string? - bzr b[rdx], .done - -.skip_spc: - bne b[rdx], ' ', .no_spc - inc rdx - jmp .skip_spc - -.no_spc: - ; skip + - bne b[rdx], '+', .no_plus - inc rdx - -.no_plus: - ; unsigned? - bzr ax2, .unsigned - - ; parse '-' - bne b[rdx], '-', .unsigned - inc rdx - mov rsi, 1 - -.unsigned: - ; base 0 - bzr ax1, .base_0 - - ; base prefix? - bne b[rdx], '0', .main_loop - - inc rdx - movzx rcx, b[rdx] - - ; "0x"/"0b" prefix - jrcxz .done ; "0" - beq rcx, 'x', .parsed_0x - beq rcx, 'b', .parsed_0b - - ; may be octal, but we don't care - ; we accept "0110101010" (despite base=2) for instance - jmp .main_loop - -.parsed_0x: - ; are we in base 16? - ; if not, leave rax = 0 and *rdx = 'x' - bne ax1, 16, .done - ; else - inc rdx, 1 - jmp .main_loop - -.parsed_0b: - ; are we in base 2? - ; if not, leave rax = 0 and *rdx = 'b' - bne ax1, 2, .done - ; else - inc rdx - jmp .main_loop - -.base_0: - ; guess base - - beq b[rdx], '0', .b0_not10 - - ; must be base 10 - mov ax1, 10 - jmp .main_loop - -.b0_not10: - inc rdx - - bne b[rdx], 'x', .b0_not16 - inc rdx - mov ax1, 16 - jmp .main_loop - -.b0_not16: - bne b[rdx], 'b', .b0_not2 - inc rdx - mov ax1, 2 - jmp .main_loop - -.b0_not2: - ; take octal by default - mov ax1, 8 - -.main_loop: - movzx rcx, b[rdx] - inc rdx - - ; between 0 and 9? - bltu rcx, '0', .done - bltu '9', rcx, .not_digit10 - - ; yes - sub rcx, '0' - jmp .next - -.not_digit10: - bltu rcx, 'A', .done - bltu 'Z', rcx, .not_digitAZ - - sub rcx, 55 ; 'A' - 10 - jmp .next - -.not_digitAZ: - bltu rcx, 'a', .done - bltu 'z', rcx, .done - - sub rcx, 87 ; 'a' - 10 - jmp .next - -.next: - ; too large for base? - blteu ax1, rcx, .done - - mul rax, ax1 - inc rax, rcx - jmp .main_loop - -.done: - ; negative? - bzr rsi, .r - - ; yes - neg rax - -.r: - ret - -.bad: - ret -# 49 "crt/crt.k" 2 -# 1 "./crt/fmt/doprnt.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; typedef int (*PUTC)(int ch) -; int doprnt(PUTC putc, int n, const char *fmt, va_list ap) -; -doprnt: - push rbp - mov rbp, rsp - - push r12, r13, r14 - push r15, r16, r17 - - mov r12, ax2 ; fmt - mov r14, ax3 ; va_list - mov r15, ax1 ; n - mov r17, ax0 ; putc - nul r16 ; return value - -.main_loop: - ; find '%' or null-terminator - mov rcx, 0x7AFFFFFF - mov r13, r12 - scasb r13, '%' - - ; everything below r13 is a regular character; print it -.print_regular: - beq r12, r13, .check_modf - - call .doput, b[r12] - - inc r12, 1 - jmp .print_regular - -.check_modf: - ; did we find a '%' ? - ; if not, then we found fmt's null-terminator; we're done - bne b[r12], '%', .epilogue - - ; we did find a modifier / '%' - mov rax, b[r12+1] - inc r12, 2 - - beq rax, 's', .modf_s - beq rax, 'c', .modf_c - beq rax, 'p', .modf_p - beq rax, 'x', .modf_x - beq rax, 'd', .modf_d - beq rax, 'o', .modf_o - beq rax, 'b', .modf_b - beq rax, '%', .modf_percent - - ; unrecognized - jmp .bad_modifier - -.modf_s: - ; get string address - mov r13, q[r14] - inc r14, 8 - - bzr r13, .nullstring - -.print_string: - movzx ax0, b[r13] - bzr ax0, .main_loop - - inc r13 - call .doput - - jmp .print_string - -.modf_c: - call .doput, q[r14] - inc r14, 8 - - jmp .main_loop - -.modf_p: - call .doput, '0' - call .doput, 'x' - ; Fallthrough - -.modf_x: - mov ax2, 16 - jmp .print_number - -.modf_d: - mov ax2, 10 - jmp .print_number - -.modf_o: - mov ax2, 8 - jmp .print_number - -.modf_b: - mov ax2, 2 - jmp .print_number - -.print_number: - ; allocate itoa conversion buffer - sub rsp, 80 - mov r13, rsp - - ; assume modifier already set up ax2 - call itoa, rsp, q[r14] - inc r14, 8 - -.print_itoa_buf: - movzx ax0, b[r13] - - bzr ax0, .pib_end_loop - inc r13 - - call .doput - jmp .print_itoa_buf - -.pib_end_loop: - inc rsp, 80 - jmp .main_loop - -.modf_percent: - call .doput, '%' - jmp .main_loop - -.bad_modifier: - ; print "%?" to clearly indicate that something is wrong - call .doput, '%' - call .doput, '?' - - jmp .main_loop - -.nullstring: - ; %s was passed a NULL - call .doput, '(' - call .doput, 'n' - call .doput, 'u' - call .doput, 'l' - call .doput, 'l' - call .doput, ')' - - jmp .main_loop - -.epilogue: - mov rax, r16 - - pop r17, r16 - pop r15, r14 - pop r13, r12 - - leave - ret -; -; prints ax0 -; -.doput: - ; update print count - inc r16 - - ; if n==0, don't print - ; we follow the C convention that sprintf()-like functions - ; should return the number of characters that would have - ; been printed/written if 'n' were big enough - bzr r15, .r - - ; decrement n and print - dec r15 - call r17 - - ; did putc fail? - jraxz .r - - ; yes, so artificially set n=0 - nul r15 - -.r: - ret -# 50 "crt/crt.k" 2 -# 1 "./crt/fmt/printf.k" 1 -; The OS/K Team licenses this file to you under the MIT license. -; See the LICENSE file in the project root for more information. - -; -; int putc(int ch) -; -putc: - prn ax0 - nul rax - ret - -; -; int printf(const char *fmt, ...) -; -printf: - mov ax2, ax0 - mov ax0, putc - mov ax1, 0x7AFFFFFF - add ax3, rsp, 8 - jmp doprnt - -; -; int nprintf(const char *fmt, int n, ...) -; -nprintf: - mov ax2, ax0 - mov ax0, putc - add ax3, rsp, 8 - jmp doprnt - -; -; Print a string -; Guaranteed to only affect rcx and ax0 -; -print: -.l: - movzx rax, b[ax0] - jraxz .r - - prn rax - inc ax0 - - jmp .l - -.r: - ret - -; -; Print exactly ax1 characters -; -nprint: - mov rcx, ax1 - jrcxz .r - -.l: - prn b[ax0] - inc ax0 - loop .l -.r: - ret -# 51 "crt/crt.k" 2 - -exit: - mov rax, Sys.Exit - trap 0 - -abort: - crash -# 8 "hello.k" 2 - -main: - mov rsp, 0x104000 - nul rbp - - call print, .hellow - - jmp exit - -.hellow = "Hello World!\n"