diff --git a/as/k-as.py b/as/k-as.py index 03fa119..3489c7c 100755 --- a/as/k-as.py +++ b/as/k-as.py @@ -248,7 +248,15 @@ def parse_preproc(line): print("Invalid format: {}".format(line)) leave() sys.exit(1) - pdefs[tok[0]] = tok[2] + + s = tok[0] + if s in pdefs: + s = pdefs[s] + + if s[0] == '.': + s = plastlabel + s + + pdefs[s] = tok[2] return # .data @@ -275,6 +283,13 @@ def parse_preproc(line): assert(tok[2][-1] == ']') s = tok[2][1:-1].strip() + + if s[0] == '.': + s = plastlabel + s + + if s in pdefs: + s = pdefs[s] + if not is_number(s): print("Invalid bss format: {}".format(line)) leave() @@ -285,7 +300,6 @@ def parse_preproc(line): written = b_data.write(bytearray(i)) assert(written == i) - pdefs[label + "_len"] = s pdata += written # string data @@ -482,14 +496,20 @@ def parse_instr(line): if len(fts) != 0: fts += ' ' + if len(word) == 0: + print("Wrong syntax in line: '{}'".format(line)) + leave() + sys.exit(-1) + + # local labels + if word[0] == '.': + word = plastlabel + word + # preprocessor if word in pdefs: word = pdefs[word] # Fall through - if len(word) == 0: - continue - # arithmetic expressions word = arith_eval(word) diff --git a/ka/command.k b/ka/command.k index 66d55db..0e864ca 100644 --- a/ka/command.k +++ b/ka/command.k @@ -1,13 +1,23 @@ ; 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: - call CMD.builtins.dir - stop - +__cmdstart: + jmp start include "crt/crt.k" -include "usr/cmd/dir.k" -include "sys/drv/diskdev.k" +start: + mov rsp, 0x140000 + xor rbp, rbp + + cls + call main + + mov rax, Sys.HLT + trap 0 + + crash + +include "usr/cmd/main.k" +include "usr/cmd/dir.k" diff --git a/ka/crt/sys.k b/ka/crt/sys.k index 0e6b322..53e6db8 100644 --- a/ka/crt/sys.k +++ b/ka/crt/sys.k @@ -17,6 +17,13 @@ Sys.FindFirst := 0x20 Sys.FindNext := 0x21 +; +; EXIT syscall +; +; Return to COMMAND.COM +; +Sys.Exit := 0x00 + ; Halt mode Sys.HLT := 0x99 diff --git a/ka/doskrnl.k b/ka/doskrnl.k index 17e40ac..4067430 100644 --- a/ka/doskrnl.k +++ b/ka/doskrnl.k @@ -7,18 +7,28 @@ __sysmain: include "crt/crt.k" +; +; Special addresses +; +DOSKRNL_CODE := 0x100000 ; 1MB (code) +DOSKRNL_STACK := 0x120000 ; + 128KB +TRAP0_STACK := 0x124000 ; + 16KB +INTR0_STACK := 0x128000 ; + 16KB +EXCT0_STACK := 0x12B000 ; + 16KB + +CMDCOM_LOADP := 0x140000 ; 1MB + 256KB +CMDCOM_MAXSZ := 0x80000 ; 512KB + ; ; Entry point ; start: - mov rsp, 0x200000 + mov rsp, DOSKRNL_STACK xor rbp, rbp call main - call CMD.builtins.dir - - mov rax, Sys.HLT + mov rax, Sys.Exit trap 0 crash @@ -37,4 +47,3 @@ include "sys/intr/trap0.k" include "sys/tests.k" include "sys/main.k" -include "usr/cmd/dir.k" diff --git a/ka/sys/drv/cpudev.k b/ka/sys/drv/cpudev.k index c3b6d53..c278c66 100644 --- a/ka/sys/drv/cpudev.k +++ b/ka/sys/drv/cpudev.k @@ -48,7 +48,8 @@ RFS.LoadArgs: ret RFS.LoadReg: - iocall CPUDEV, 33 +.slot := 33 + iocall CPUDEV, .slot ret RFS.StoreReg: diff --git a/ka/sys/drv/diskdev.k b/ka/sys/drv/diskdev.k index f806354..c6c6fb1 100644 --- a/ka/sys/drv/diskdev.k +++ b/ka/sys/drv/diskdev.k @@ -4,10 +4,32 @@ DISKDEV := 4 DISK.FindFirst: - iocall DISKDEV, 16 +.slot := 16 + iocall DISKDEV, .slot ret DISK.FindNext: - iocall DISKDEV, 17 +.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.ReadFile: + iocall DISKDEV, 32 + ret + +DISK.WriteFile: + iocall DISKDEV, 33 ret diff --git a/ka/sys/intr/common.k b/ka/sys/intr/common.k index 1827d51..93d5773 100644 --- a/ka/sys/intr/common.k +++ b/ka/sys/intr/common.k @@ -2,12 +2,20 @@ ; See the LICENSE file in the project root for more information. TrapHandlers.prolog: - sub rsp, rbp, 24 mov q[rbp-8], r11 mov q[rbp-16], r12 mov q[rbp-24], r13 + sub rsp, rbp, 24 xor rdx, rdx + ; nx0 = caller's cr2 + push cr2 + mov ax0, r12 + mov ax1, $cr2 + iocall CPUDEV, RFS.LoadReg.slot + mov nx0, cr2 + pop cr2 + jmp rcx ; go back TrapHandlers.epilog: diff --git a/ka/sys/intr/trap0.k b/ka/sys/intr/trap0.k index 58db099..9d36cb6 100644 --- a/ka/sys/intr/trap0.k +++ b/ka/sys/intr/trap0.k @@ -1,8 +1,6 @@ ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. -TRAP0_STACK := 0x300000 - trap0_handler: .init: @@ -17,27 +15,100 @@ trap0_handler: call RFS.LoadArgs b.z rax, Sys.HLT, .handle_HLT + b.z rax, Sys.Exit, .handle_Exit b.z rax, Sys.FindNext, .handle_FindNext b.z rax, Sys.FindFirst, .handle_FindFirst .fini: jmp TrapHandlers.epilog -; -; Syscall implementations -; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Syscall implementations ;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Pass control to COMMAND.COM in frame 0 +; +.handle_Exit: + + ; Open COMMAND.COM + mov ax0, .cmdcom + call DISK.OpenFile + + ; Crash on failure + cmp rax, 0 + crash.l + + ; Load at CMDCOM_LOADP + mov ax0, rax + mov ax1, CMDCOM_LOADP + mov ax2, CMDCOM_MAXSZ + call DISK.ReadFile + + ; Assume that COMMAND.COM being + ; less then 4KB means something + ; went wrong + cmp rax, 0x1000 + crash.b + + ; Close the handle + mov ax0, rax + call DISK.CloseFile + + ; Code address + xor ax0, ax0 + mov ax1, $rip + mov ax2, 0x100000 + call RFS.StoreReg + + ; No flags set + mov ax1, $flg + xor ax2, ax2 + call RFS.StoreReg + + ; Usermode + mov ax1, $cr0 + mov ax2, 3 + call RFS.StoreReg + + mov rcx, CMDCOM_LOADP + sub rcx, 0x100000 + + ; Code offset + mov ax1, $cr1 + mov ax2, rcx + call RFS.StoreReg + + ; Data offset + mov ax1, $cr2 + mov ax2, rcx + call RFS.StoreReg + + ; Return frame + mov q[rbp-16], 0 + + jmp .fini + +.cmdcom = "command.com" + +; +; Disk API +; .handle_FindFirst: + add ax0, nx0 call DISK.FindFirst jmp .fini .handle_FindNext: + add ax0, nx0 call DISK.FindNext jmp .fini +; +; Misc. +; .handle_HLT: hlt - .HLT.loop: xpause diff --git a/ka/sys/tests.k b/ka/sys/tests.k index 4309208..ce85f98 100644 --- a/ka/sys/tests.k +++ b/ka/sys/tests.k @@ -1,6 +1,31 @@ ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. +file_test: +.bufsize := 256 + + mov ax0, .fn + call DISK.OpenFile + push rax + + mov ax0, rax + mov ax1, .buf + mov ax2, .bufsize + call DISK.ReadFile + + mov rcx, .bufsize + mov rdx, .buf + prns.rep.nz rdx + + pop rax + call DISK.CloseFile + + hlt + ret + +.fn = "doskrnl.sym" +.buf = [.bufsize] + movsx_test: mov rcx, 0x1188FF movsxb rx8, rcx diff --git a/ka/usr/cmd/dir.k b/ka/usr/cmd/dir.k index 9e0931a..ec0cb57 100644 --- a/ka/usr/cmd/dir.k +++ b/ka/usr/cmd/dir.k @@ -1,6 +1,9 @@ +; The OS/K Team licenses this file to you under the MIT license. +; See the LICENSE file in the project root for more information. + NAME_MAX := 256 -CMD.builtins.dir: +builtins.dir: push nx0 xor nx0, nx0 # no. of files found diff --git a/ka/usr/cmd/main.k b/ka/usr/cmd/main.k new file mode 100644 index 0000000..6a0e2b9 --- /dev/null +++ b/ka/usr/cmd/main.k @@ -0,0 +1,8 @@ +; The OS/K Team licenses this file to you under the MIT license. +; See the LICENSE file in the project root for more information. + +main: + call builtins.dir + + ret + diff --git a/vm/Makefile b/vm/Makefile index 4394e93..b248ba2 100644 --- a/vm/Makefile +++ b/vm/Makefile @@ -6,7 +6,7 @@ verbose ?= yes OBJDIR = ob -FLAGS=-O2 -g -Wall -fno-builtin-log -I. +FLAGS=-O2 -Wall -fno-builtin-log -I. dv_src = $(shell ls dv/*.c) in_src = $(shell ls in/*.c) diff --git a/vm/dv/DISKDEV b/vm/dv/DISKDEV index 3cdd1d0..df3b886 100644 --- a/vm/dv/DISKDEV +++ b/vm/dv/DISKDEV @@ -18,11 +18,11 @@ Disk device function slots: - rax = number of bytes written (0 = no files found) - rdx = number of bytes in file - 18-25 - - - - (reserved) (reserved) + 18-21 - - - - (reserved) (reserved) - 26 p i - - open - - open file whose name is stored in #ax1-sized buffer #ax0 + 25 p i - - open + - open file whose name is stored in string *ax0 - rax = -1 if couldn't open file, rax = file handle otherwise - 27 i - - - close closes file with handle #ax0 + 26 i - - - close closes file with handle #ax0 diff --git a/vm/dv/diskdev.c b/vm/dv/diskdev.c index b4b46cc..ae3a0e8 100644 --- a/vm/dv/diskdev.c +++ b/vm/dv/diskdev.c @@ -4,8 +4,11 @@ #include #include #include +#include +#include #define MAXOPEN 4096 +#define MAXRW 0x800000 // 8MB typedef struct disk_t disk_t; typedef struct dirent dirent_t; @@ -15,8 +18,8 @@ struct disk_t // disk directory DIR *dir; - // open files - int *table[MAXOPEN]; + // opened files + int table[MAXOPEN]; uint opened; }; @@ -48,7 +51,7 @@ long diskdev_findnext(ctx_t *ctx, dev_t *dev) break; } - rax = copystr(ctx, ax0, ax1, ent->d_name); + rax = writestr(ctx, ax0, ax1, ent->d_name); snprintf(name, NAME_MAX+4, "fs/%s", ent->d_name); @@ -75,6 +78,82 @@ long diskdev_findfirst(ctx_t *ctx, dev_t *dev) //----------------------------------------------------------------------------// +long diskdev_open(ctx_t *ctx, dev_t *dev) +{ + GETDISK(); + + int fd, tmp; + char buf[NAME_MAX+4] = { 'f', 's', '/', 0 }; + + readstr(ctx, ax0, NAME_MAX, buf+3); + + for (fd = 0; fd < MAXOPEN; fd++) + if (disk->table[fd] == 0) + break; + + if (fd == MAXOPEN) + return -1; + + tmp = open(buf, O_RDWR); + + if (tmp < 0) + return -1; + + disk->table[fd] = tmp; + rax = fd; + + return 0; +} + +long diskdev_close(ctx_t *ctx, dev_t *dev) +{ + GETDISK(); + + if (ax0 >= MAXOPEN) + return -1; + + if (disk->table[ax0] <= 0) + return -1; + + close(disk->table[ax0]); + + return 0; +} + +//----------------------------------------------------------------------------// + +long diskdev_read(ctx_t *ctx, dev_t *dev) +{ + GETDISK(); + + if (ax0 >= MAXOPEN || disk->table[ax0] <= 0 || ax2 >= MAXRW) + return -1; + + int ret; + char *buf = malloc(MAXRW); + + if (buf == NULL) + return -1; + + ret = read(disk->table[ax0], buf, ax2); + + if (ret < 0) + { + free(buf); + return -1; + } + + rax = ret; + + // Xxx dedicated function & faster copy + for (; ret; ret--, ax1++, buf++) + writemem(ctx, *buf, ax1, 1); + + return 0; +} + +//----------------------------------------------------------------------------// + long diskdev_poweron(ctx_t *ctx, dev_t *dev) { disk_t *disk = calloc(1, sizeof(disk_t)); @@ -92,6 +171,11 @@ long diskdev_poweron(ctx_t *ctx, dev_t *dev) dev->fslots[16] = diskdev_findfirst; dev->fslots[17] = diskdev_findnext; + dev->fslots[25] = diskdev_open; + dev->fslots[26] = diskdev_close; + + dev->fslots[32] = diskdev_read; + dev->state = DEVGOOD; return 0; @@ -100,12 +184,19 @@ long diskdev_poweron(ctx_t *ctx, dev_t *dev) long diskdev_poweroff(ctx_t *ctx, dev_t *dev) { GETDISK(); - - if (disk && disk->dir) - closedir(disk->dir); + int fd; if (disk) + { + if (disk->dir) + closedir(disk->dir); + + for (fd = 0; fd < MAXOPEN; fd++) + if (disk->table[fd] > 0) + close(disk->table[fd]); + free(disk); + } dev->data = NULL; dev->state = DEVPWOF; diff --git a/vm/in/MISC b/vm/in/MISC index ca81c36..0f9034b 100644 --- a/vm/in/MISC +++ b/vm/in/MISC @@ -53,21 +53,25 @@ cpuid #---------------------------------------------------------------------------# # -# Clear base volatile registers (CLR) +# Clear all GPR registers except RBP/RSP # -# RAX = RBX = RCX = RDX = 0 -# RSX = RBI = RDI = RSI = 0 +cls + +# +# Clear base registers except RBP/RSP (CLR) # clr # # Clear argument registers (CLA) # -# AX0 = AX1 = AX2 = AX3 = 0 -# AX4 = AX5 = AX6 = AX7 = 0 -# cla +# +# Clear nonvolatile registers (CLN) +# +cln + #---------------------------------------------------------------------------# # Byte-wise / bit-wise manipulation instructions # #---------------------------------------------------------------------------# diff --git a/vm/in/debug.c b/vm/in/debug.c index f833124..8b02163 100644 --- a/vm/in/debug.c +++ b/vm/in/debug.c @@ -3,12 +3,15 @@ #include +extern void do_hlt(ctx_t *ctx); + IMPL_START_0(break) { trace("\nExecuting BREAK INSTR\n"); dumpregs(ctx); - getchar(); + do_hlt(ctx); + trace("Resuming execution\n"); } IMPL_END; diff --git a/vm/in/misc.c b/vm/in/misc.c index 94d56b1..6103c96 100644 --- a/vm/in/misc.c +++ b/vm/in/misc.c @@ -54,16 +54,29 @@ IMPL_OUT; //----------------------------------------------------------------------------// +IMPL_START_0(cls) +{ + rax = rbx = rcx = rdx = rdi = rsi = 0; + for (int i = RX8; i <= N15; i++) R(i) = 0; +} +IMPL_END; + IMPL_START_0(clr) { rax = rbx = rcx = rdx = rdi = rsi = 0; + for (int i = RX8; i <= R15; i++) R(i) = 0; } IMPL_END; IMPL_START_0(cla) { - for (int i = AX0; i < AX8; i++) - R(i) = 0; + for (int i = AX0; i <= A15; i++) R(i) = 0; +} +IMPL_END; + +IMPL_START_0(cln) +{ + for (int i = NX0; i <= N15; i++) R(i) = 0; } IMPL_END; diff --git a/vm/in/super.c b/vm/in/super.c index ad3875c..aee8f1d 100644 --- a/vm/in/super.c +++ b/vm/in/super.c @@ -20,9 +20,8 @@ IMPL_START_0(crash) } IMPL_END; -IMPL_START_0(hlt) +void do_hlt(ctx_t *ctx) { - CHK_SUPERV(); SDL_Event evt; while (1) @@ -41,6 +40,13 @@ IMPL_START_0(hlt) } } } + +IMPL_START_0(hlt) +{ + CHK_SUPERV(); + + do_hlt(ctx); +} IMPL_END; // @@ -79,19 +85,19 @@ IMPL_START_2(devctl) switch (v2) { case 0: - copystr(ctx, ax0, DEVLEN, dev->type); + writestr(ctx, ax0, DEVLEN, dev->type); break; case 1: - copystr(ctx, ax0, DEVLEN, dev->name); + writestr(ctx, ax0, DEVLEN, dev->name); break; case 2: - copystr(ctx, ax0, DEVLEN, dev->modl); + writestr(ctx, ax0, DEVLEN, dev->modl); break; case 3: - copystr(ctx, ax0, DEVLEN, dev->vend); + writestr(ctx, ax0, DEVLEN, dev->vend); break; case 4: diff --git a/vm/pc/mem.c b/vm/pc/mem.c index 1b4156f..dee164c 100644 --- a/vm/pc/mem.c +++ b/vm/pc/mem.c @@ -5,7 +5,23 @@ //----------------------------------------------------------------------------// -ulong copystr(ctx_t *ctx, ulong addr, ulong maxn, char *str) +ulong readstr(ctx_t *ctx, ulong addr, ulong maxn, char *buf) +{ + ulong orig_maxn = maxn; + + for (; maxn > 0; buf++, addr++, maxn--) { + *buf = readmemzx(ctx, addr, 1) & 0xFF; + + if (*buf == 0) + break; + } + + *buf = 0; + + return orig_maxn - maxn; +} + +ulong writestr(ctx_t *ctx, ulong addr, ulong maxn, char *str) { ulong orig_maxn = maxn; @@ -113,8 +129,7 @@ static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr) } #define GETREAL() \ - addr += cr2; \ - ulong real = addr2real(addr) + ulong real = addr2real(addr + cr2) //----------------------------------------------------------------------------// diff --git a/vm/pc/mem.h b/vm/pc/mem.h index 8aa56f2..a158e8b 100644 --- a/vm/pc/mem.h +++ b/vm/pc/mem.h @@ -10,13 +10,16 @@ static inline char getmempref(ushort len) #define MEMOFF (1 * 1024 * 1024) #define MEMSIZE (16 * 1024 * 1024) // 16MB +#define MAXADDR 0x8000000000000 // 2^48 - 1 + #define addr2real(p) (((p) - MEMOFF) / 2) #define real2addr(p) (((p) + MEMOFF) / 2) // Address of boot firmware stack #define FWSTACK (MEMOFF * 2) // 2MB -ulong copystr(ctx_t *ctx, ulong addr, ulong maxn, char *str); +ulong readstr(ctx_t *ctx, ulong addr, ulong maxn, char *buf); +ulong writestr(ctx_t *ctx, ulong addr, ulong maxn, char *str); ulong readmem(ctx_t *c, ulong addr, uint len); void writemem(ctx_t *, ulong val, ulong addr, uint len); diff --git a/vm/pc/regs.c b/vm/pc/regs.c index 12f09c4..8697613 100644 --- a/vm/pc/regs.c +++ b/vm/pc/regs.c @@ -8,7 +8,7 @@ reg_t arch_r[] = { "inv", RES }, { "flg", GPR }, { "rip", GPR }, { "rpc", GPR }, { "px0", RES }, { "px1", RES }, { "fc1", RES }, { "fc2", RES }, { "sa0", SYS }, { "sa1", SYS }, { "sa2", SYS }, { "sa3", SYS }, - { "cr0", CTL }, { "cr1", CTL }, { "cr2", CTL }, { "cr3", CTL }, + { "cr0", SYS }, { "cr1", SYS }, { "cr2", SYS }, { "cr3", SYS }, { "rax", GPR }, { "rbx", GPR }, { "rcx", GPR }, { "rdx", GPR }, { "rsi", GPR }, { "rdi", GPR }, { "rbp", GPR }, { "rsp", GPR },