From 4f527e21aa1b22aca71b9690c965684527ea0777 Mon Sep 17 00:00:00 2001 From: julianb0 Date: Thu, 13 Jun 2019 22:20:35 +0200 Subject: [PATCH] stuff --- Makefile | 6 ++ as/k-as.py | 2 +- ka/dos.k | 23 +++++- ka/fmt/itoa.k | 15 +--- ka/main.k | 51 +++++++----- ka/str/strcmp.k | 34 ++------ ka/str/strcpy.k | 42 +++------- ka/str/strlen.k | 41 ++++------ vm/in/INSTRS | 19 +++++ vm/in/arith.c | 3 +- vm/in/string.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++ vm/pc/decd.c | 10 +-- vm/pc/dump.c | 10 ++- 13 files changed, 327 insertions(+), 130 deletions(-) diff --git a/Makefile b/Makefile index 5f8204e..2546594 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,12 @@ DOSK = $(shell find ka -name '*.k') vm/a.out: $(DOSK) @cd ka && ../as/k-as.py dos.k 0x100000 ../vm/a.out +.PHONY: clean + +clean: + @cd vm && make clean + @rm -f vm/a.out vm/k.exe vm/stdout.txt as/instrs.lst + test: kas vm/a.out @vm/k.exe vm/a.out > vm/stdout.txt @rm -f vm/a.out diff --git a/as/k-as.py b/as/k-as.py index df844f4..e9307fc 100755 --- a/as/k-as.py +++ b/as/k-as.py @@ -203,7 +203,7 @@ def parse(): def parse_preproc(line): global pdata - tok = line.split(' ', 2) + tok = line.split(None, 2) # preprocessor if len(tok) > 1 and tok[1] == ':=': diff --git a/ka/dos.k b/ka/dos.k index 2672518..3c976ac 100644 --- a/ka/dos.k +++ b/ka/dos.k @@ -16,10 +16,29 @@ _start: jmp .1 ; -; Essential definitions +; Some definitions ; + +CHAR_MIN := 0x80 +SHRT_MIN := 0x8000 +INT_MIN := 0x80000000 +LONG_MIN := 0x8000000000000000 + +XCHAR_MIN := 0xFFFFFFFFFFFFFF80 +XSHRT_MIN := 0xFFFFFFFFFFFF8000 +XINT_MIN := 0xFFFFFFFF80000000 + CHAR_MAX := 0x7F -INT_MAX := 0x7FFF +SHRT_MAX := 0x7FFF +INT_MAX := 0x7FFFFFFF +LONG_MAX := 0x7FFFFFFFFFFFFFFF + +BYTE_MAX := 0xFF +WORD_MAX := 0xFFFF +LWORD_MAX := 0xFFFFFFFF +QWORD_MAX := 0xFFFFFFFFFFFFFFFF + +STRLEN_MAX := 0xFFFFFFFF ; ; Include librairies diff --git a/ka/fmt/itoa.k b/ka/fmt/itoa.k index 530edd7..ad9605d 100644 --- a/ka/fmt/itoa.k +++ b/ka/fmt/itoa.k @@ -30,14 +30,10 @@ _itoa: cmp ax2, 10 ; base 10 jmp.nz .conv - cmp ax1, -9223372036854775808 ; LONG_MIN - jmp.z .min - sgn rdx, ax1 ; extract ax1 sign cmp rdx, -1 ; negative? - not.z ax1 ; -x = ~x+1 - inc.z ax1 ; need "neg" inst... + neg.z ax1 ; main loop .conv: @@ -50,7 +46,7 @@ _itoa: cmp rsx, 9 ; rsx > 9 ? jmp.a .nondec - add rsx, 48 ; '0' + add rsx, 48 ; '0' jmp .next .nondec: @@ -90,13 +86,6 @@ _itoa: mov b[ax0+1], 0 ret -.min: - mov ax1, .min10 - call strcpy - ret - -.min10 = "-9223372036854775808" - ; ; wrappers ; diff --git a/ka/main.k b/ka/main.k index 120d35c..028db5f 100644 --- a/ka/main.k +++ b/ka/main.k @@ -5,6 +5,10 @@ ; Main function ; main: + call itoa_test + ret + +stosb_test: cld mov rcx, 11 mov rax, 33 @@ -44,7 +48,7 @@ movzx_test: itoa_test: mov ax0, .buf - mov ax1, -9223372036854775807 + mov ax1, LONG_MIN mov ax2, 10 call itoa @@ -60,10 +64,6 @@ itoa_test: mov ax0, rax call print - mov rsi, 0x10 - mov rdi, 8 - lea rbi, b[rdi + rsi * 2 + 1] - ret .buf = [32] @@ -84,42 +84,55 @@ devtest: .buf = [32] -strtest: - enter - +str_test: mov ax0, .msg call print - mov ax0, .buf + mov ax0, .buf1 mov ax1, .msg - mov ax2, 5 + call strcpy + + prn 10 + mov ax0, .buf1 + call print + + mov ax0, .buf2 + mov ax1, .msg + mov ax2, 8 call strnzcpy prn 10 - mov ax0, .buf - mov ax1, 10 + mov ax0, .buf2 + mov ax1, 12 call print_n - mov ax0, .buf + mov ax0, .msg + mov ax1, .buf1 + call strcmp + mov rbx, rax + + mov ax0, .buf2 mov ax1, .msg call strcmp + mov rsx, rax + + mov ax0, .msg + call strlen - leave ret -.msg = "HelloWorld :)" -.buf = [32] +.msg = "Hello World :)" + +.buf1 = [32] +.buf2 = "!!!!!!!!!!!!!" ; ; Exit function ; exit: - enter - mov ax0, .msg call print - leave ret .msg = "Goodbye World :(\n" diff --git a/ka/str/strcmp.k b/ka/str/strcmp.k index 142feec..cfb9e03 100644 --- a/ka/str/strcmp.k +++ b/ka/str/strcmp.k @@ -9,44 +9,24 @@ ; 1 if the first character that does not match has a greater value in str1 than in str2 ; -1 if the first character that does not match has a lower value in str1 than in str2 ; - strcmp: - cmp b[ax0], b[ax1] - jmp.nz .1 - - test b[ax0], b[ax0] - jmp.z .1 - - inc ax0 - inc ax1 - jmp strcmp - -.1: - mov rax, b[ax0] - sub rax, b[ax1] - sgn rax, rax - ret + mov ax2, STRLEN_MAX + jmp strncmp ; ; int strncmp(const char *str1, const char *str2, int maxn) ; strncmp: mov rcx, ax2 + mov.cxz rax, 0 + ret.cxz -.0: - cmp b[ax0], b[ax1] - jmp.nz .1 + cld + rep.e cmpzsb ax0, ax1 - test b[ax0], b[ax0] - jmp.z .1 - - inc ax0 - inc ax1 - loop .0 - -.1: mov rax, b[ax0] sub rax, b[ax1] sgn rax, rax + ret diff --git a/ka/str/strcpy.k b/ka/str/strcpy.k index 02f9817..27f2fab 100644 --- a/ka/str/strcpy.k +++ b/ka/str/strcpy.k @@ -5,34 +5,19 @@ ; void strcpy(char *, const char *) ; strcpy: - mov b[ax0], b[ax1] - - test b[ax1], b[ax1] - ret.z - - inc ax0 - inc ax1 - jmp strcpy + mov ax2, STRLEN_MAX + jmp strncpy ; ; void strncpy(char *, const char *, int) ; strncpy: mov rcx, ax2 - j.cxz .2 - dec rcx + ret.cxz -.1: - mov b[ax0], b[ax1] + cld + rep.nz movsb ax0, ax1 - test b[ax1], b[ax1] - ret.z - - inc ax0 - inc ax1 - loop .1 - -.2: ret ; @@ -40,20 +25,15 @@ strncpy: ; strnzcpy: mov rcx, ax2 - j.cxz .2 + ret.cxz + dec rcx + jmp.cxz .1 + + cld + rep.nz movsb ax0, ax1 .1: - mov b[ax0], b[ax1] - - test b[ax1], b[ax1] - ret.z - - inc ax0 - inc ax1 - loop .1 - -.2: mov b[ax0], 0 ret diff --git a/ka/str/strlen.k b/ka/str/strlen.k index 21c4c2a..2b99274 100644 --- a/ka/str/strlen.k +++ b/ka/str/strlen.k @@ -1,37 +1,22 @@ ; 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 strlen(char *) -; -strlen: - xor rax, rax - -.1: - test b[ax0], b[ax0] - ret.z - - inc rax - inc ax0 - jmp .1 - ; ; int strnlen(char *, int) ; strnlen: - xor rax, rax - + cld mov rcx, ax1 - j.cxz .2 - dec rcx - -.1: - test b[ax0], b[ax0] - ret.z - - inc rax - inc ax0 - loop .1 - -.2: + rep.nz scasb ax0, 0 + + mov rax, ax1 + sub rax, rcx ret + +; +; int strlen(char *) +; +strlen: + mov ax1, STRLEN_MAX + jmp strnlen + diff --git a/vm/in/INSTRS b/vm/in/INSTRS index 0c8aa73..7b89a0b 100644 --- a/vm/in/INSTRS +++ b/vm/in/INSTRS @@ -408,6 +408,9 @@ stosb r rim # %str = %str - sizeof(x) # FI # +# Preserves CF, OF and SF +# Sets ZF according to the loaded value +# # When no parameters are given, %dest = RAX and %str = RSI # When one parameter is given, %dest = $1 and %str = RSI # When two parameters are given, %dest = $1 and %str = $2 @@ -460,6 +463,19 @@ cmpsb cmpsb r cmpsb r r +# +# Safe compare bytes in strings (CMPZSx) +# +# Behaves precisely like CMPSx, except in the following case: +# - If both [%str1] and [%str2] are zero, clears ZF (indicating NOT EQUAL) +# +# This prevents 'rep.e cmpsb' from looping infinitely when both strings +# have the exact same content; this allows for short strcmp's +# +cmpzsb +cmpzsb r +cmpzsb r r + # # Move value from string to string (MOVSx) # @@ -472,6 +488,9 @@ cmpsb r r # %str2 = %str2 - sizeof(x) # FI # +# Preserves CF, OF and SF +# Sets ZF according to the moved value +# # When no parameters are given, %str1 = RDI and %str2 = RSI # When one parameter is given, %str1 = RDI and %str2 = $1 # When two parameters are given, %str1 = $1 and %str2 = $2 diff --git a/vm/in/arith.c b/vm/in/arith.c index 99e05c5..05338a6 100644 --- a/vm/in/arith.c +++ b/vm/in/arith.c @@ -7,7 +7,8 @@ IMPL_START_2(sgn) { - v1 = (long)v2 < 0 ? (ulong)-1L : 1; + v1 = (v2 == 0 ? 0 : + ((long)v2 < 0 ? (ulong)-1L : 1)); } IMPL_OUT; diff --git a/vm/in/string.c b/vm/in/string.c index 363105f..233e519 100644 --- a/vm/in/string.c +++ b/vm/in/string.c @@ -85,6 +85,10 @@ void lods_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) } R(reg1) = readmem(ctx, R(reg2), len); + + flg = (R(reg1) == 0 ? flg|ZF : flg&~ZF); + + STR_MOVE(reg2, len); } IMPL_START_0(lodsb) @@ -113,22 +117,219 @@ IMPL_END; //----------------------------------------------------------------------------// +void scas_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) +{ + ulong reg, val; + + if (p2) { + DECV(v2, p2); + reg = p1->reg; + val = v2; + } + + else if (p1) { + DECV(v1, p1); + reg = RDI; + val = v1; + } + + else { + reg = RDI; + val = rax; + } + + ulong x = readmem(ctx, R(reg), len); + COMPARE(x, val); + + STR_MOVE(reg, len); +} + IMPL_START_0(scasb) { + scas_impl(ctx, p1, p2, 1); +} +IMPL_END; + +IMPL_START_0(scasw) +{ + scas_impl(ctx, p1, p2, 2); +} +IMPL_END; + +IMPL_START_0(scasl) +{ + scas_impl(ctx, p1, p2, 4); +} +IMPL_END; + +IMPL_START_0(scasq) +{ + scas_impl(ctx, p1, p2, 8); } IMPL_END; //----------------------------------------------------------------------------// +void cmps_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) +{ + ulong reg1, reg2; + + if (p2) { + reg1 = p1->reg; + reg2 = p2->reg; + } + + else if (p1) { + reg1 = RDI; + reg2 = p1->reg; + } + + else { + reg1 = RDI; + reg2 = RSI; + } + + ulong x1 = readmem(ctx, R(reg1), len); + ulong x2 = readmem(ctx, R(reg2), len); + + COMPARE(x1, x2); + + STR_MOVE(reg1, len); + STR_MOVE(reg2, len); +} + IMPL_START_0(cmpsb) { + cmps_impl(ctx, p1, p2, 1); +} +IMPL_END; + +IMPL_START_0(cmpsw) +{ + cmps_impl(ctx, p1, p2, 2); +} +IMPL_END; + +IMPL_START_0(cmpsl) +{ + cmps_impl(ctx, p1, p2, 4); +} +IMPL_END; + +IMPL_START_0(cmpsq) +{ + cmps_impl(ctx, p1, p2, 8); } IMPL_END; //----------------------------------------------------------------------------// +void cmpzs_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) +{ + ulong reg1, reg2; + + if (p2) { + reg1 = p1->reg; + reg2 = p2->reg; + } + + else if (p1) { + reg1 = RDI; + reg2 = p1->reg; + } + + else { + reg1 = RDI; + reg2 = RSI; + } + + ulong x1 = readmem(ctx, R(reg1), len); + ulong x2 = readmem(ctx, R(reg2), len); + + COMPARE(x1, x2); + + if (!x1 && !x2) + flg &= ~ZF; + + STR_MOVE(reg1, len); + STR_MOVE(reg2, len); +} + +IMPL_START_0(cmpzsb) +{ + cmpzs_impl(ctx, p1, p2, 1); +} +IMPL_END; + +IMPL_START_0(cmzpsw) +{ + cmpzs_impl(ctx, p1, p2, 2); +} +IMPL_END; + +IMPL_START_0(cmpzsl) +{ + cmpzs_impl(ctx, p1, p2, 4); +} +IMPL_END; + +IMPL_START_0(cmpzsq) +{ + cmpzs_impl(ctx, p1, p2, 8); +} +IMPL_END; + +//----------------------------------------------------------------------------// + +void movs_impl(ctx_t *ctx, acc_t *p1, acc_t *p2, uint len) +{ + ulong reg1, reg2; + + if (p2) { + reg1 = p1->reg; + reg2 = p2->reg; + } + + else if (p1) { + reg1 = RDI; + reg2 = p1->reg; + } + + else { + reg1 = RDI; + reg2 = RSI; + } + + ulong x = readmem(ctx, R(reg2), len); + writemem(ctx, x, R(reg1), len); + + flg = (x == 0 ? flg|ZF : flg&~ZF); + + STR_MOVE(reg1, len); + STR_MOVE(reg2, len); +} + IMPL_START_0(movsb) { + movs_impl(ctx, p1, p2, 1); +} +IMPL_END; + +IMPL_START_0(movsw) +{ + movs_impl(ctx, p1, p2, 2); +} +IMPL_END; + +IMPL_START_0(movsl) +{ + movs_impl(ctx, p1, p2, 4); +} +IMPL_END; + +IMPL_START_0(movsq) +{ + movs_impl(ctx, p1, p2, 8); } IMPL_END; diff --git a/vm/pc/decd.c b/vm/pc/decd.c index c918693..65f9a98 100644 --- a/vm/pc/decd.c +++ b/vm/pc/decd.c @@ -7,7 +7,7 @@ // Imperatively read the "DECD" file before reading this code // -static void check_param_type(ctx_t *ctx, uint prm, uchar fmt) +static void check_param_type(ctx_t *ctx, instr_t *in, uint prm, uchar fmt) { bool ok; @@ -22,8 +22,8 @@ static void check_param_type(ctx_t *ctx, uint prm, uchar fmt) if (!ok) _except(ctx, E_ILL, - "FT1 or FT2 not matching INSTR's expected parameter types: " - "fmt=0x%x prm=0x%x", fmt, prm); + "FT1 or FT2 not matching %s's expected parameter types: " + "fmt=0x%x prm=0x%x", in->full, fmt, prm); } void decode(ctx_t *ctx) @@ -102,7 +102,7 @@ skip_w2: return; } - check_param_type(ctx, in->prm1, f1); + check_param_type(ctx, in, in->prm1, f1); extract_param(ctx, &p1, f1); // @@ -121,7 +121,7 @@ skip_w2: return; } - check_param_type(ctx, in->prm2, f2); + check_param_type(ctx, in, in->prm2, f2); extract_param(ctx, &p2, f2); exec_instr(ctx, in, &p1, &p2, lock, rep, cond, pc); diff --git a/vm/pc/dump.c b/vm/pc/dump.c index ddd75dc..03e1f54 100644 --- a/vm/pc/dump.c +++ b/vm/pc/dump.c @@ -76,10 +76,10 @@ void dump_instr(ctx_t *ctx, log("0x%lX: ", pc); if (lock) - log("lock "); + log("lock"); if (rep) - log("rep "); + log(" rep"); if (cond) { @@ -95,8 +95,12 @@ void dump_instr(ctx_t *ctx, log("%s", cond_suffixes[cond]); } + + if (!rep) + log("\t\t"); - log("\t"); + else + log("\t"); log("%s\t", in->name);