From bdb36e2864c141aaa6dc3ba9ce989a8740c43c3e Mon Sep 17 00:00:00 2001 From: julianb0 Date: Sun, 23 Jun 2019 20:56:04 +0200 Subject: [PATCH] strtol! --- ka/crt/chr/ctype.k | 9 ++ ka/crt/fmt/format.k | 3 +- ka/crt/fmt/{itoa.k => ltostr.k} | 19 +++- ka/crt/fmt/strtol.k | 170 ++++++++++++++++++++++++++++++++ ka/dos.k | 4 + ka/sys/main.k | 1 - ka/sys/tests.k | 30 +++++- vm/in/LOGIC | 6 ++ vm/in/inout.c | 8 +- vm/in/logic.c | 46 +++++++++ vm/pc/mem.c | 5 - vm/pc/mem.h | 6 ++ 12 files changed, 288 insertions(+), 19 deletions(-) create mode 100644 ka/crt/chr/ctype.k rename ka/crt/fmt/{itoa.k => ltostr.k} (83%) create mode 100644 ka/crt/fmt/strtol.k diff --git a/ka/crt/chr/ctype.k b/ka/crt/chr/ctype.k new file mode 100644 index 0000000..6e34e41 --- /dev/null +++ b/ka/crt/chr/ctype.k @@ -0,0 +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. + +; +; bool isdigit(int c) +; +isdigit: + ret + diff --git a/ka/crt/fmt/format.k b/ka/crt/fmt/format.k index 0c485eb..a79e79e 100644 --- a/ka/crt/fmt/format.k +++ b/ka/crt/fmt/format.k @@ -1,7 +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. -include "crt/fmt/itoa.k" +include "crt/fmt/ltostr.k" +include "crt/fmt/strtol.k" include "crt/fmt/doprnt.k" include "crt/fmt/printf.k" diff --git a/ka/crt/fmt/itoa.k b/ka/crt/fmt/ltostr.k similarity index 83% rename from ka/crt/fmt/itoa.k rename to ka/crt/fmt/ltostr.k index fa88810..cfce069 100644 --- a/ka/crt/fmt/itoa.k +++ b/ka/crt/fmt/ltostr.k @@ -5,14 +5,25 @@ ; void itoa(char *buf, int num, int base) ; itoa: + mov ax3, 1 + jmp ltostr + +; +; void utoa(char *buf, int num, int base) +; + sub ax3, ax3 + jmp ltostr + +; +; void ltostr(char *buf, int num, int base, bool signed) +; +ltostr: mov rax, ax0 xor lx0, lx0 ; make sure base is in [2, 32] - cmp ax2, 2 j.b .bad - cmp ax2, 36 j.a .bad @@ -22,7 +33,8 @@ itoa: ; deal with base 10 signedness - cmp ax2, 10 ; base 10 + test ax3, ax3 + cmp.nz ax2, 10 ; base 10 j.nz .conv sgn lx0, ax1 ; extract ax1 sign @@ -70,7 +82,6 @@ itoa: ; ; exceptional cases ; - .bad: mov q[errno], EINVAL mov b[ax0], 0 diff --git a/ka/crt/fmt/strtol.k b/ka/crt/fmt/strtol.k new file mode 100644 index 0000000..0395587 --- /dev/null +++ b/ka/crt/fmt/strtol.k @@ -0,0 +1,170 @@ +; 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: + sub ax2, ax2 + jmp strtoq + +; +; int strtoq(const char *str, int base, bool signed) +; +; guesses base when 'base'=0 +; +strtoq: + xor rax, rax + mov rdx, ax0 + + ; make sure base is in [2, 32] + cmp ax1, 1 + j.z .bad + cmp ax1, 36 + j.a .bad + + ; empty string? + cmp b[rdx], 0 + jmp.z .done + +.skip_spc: + cmp b[rdx], ' ' + inc.z rdx + jmp.z .skip_spc + + ; skip + + cmp b[rdx], '+' + inc.z rdx + + ; signed? + test ax2, ax2 + sub.z lx1, lx1 + jmp.z .unsigned + + ; parse '-' + cmp b[rdx], '-' + inc.z rdx + mov.z lx1, 1 + sub.nz lx1, lx1 + +.unsigned: + ; base 0 + test ax1, ax1 + jmp.z .base_0 + + ; base prefix? + cmp b[rdx], '0' + jmp.nz .main_loop + + inc rdx + + ; string is "0" + cmp b[rdx], 0 + jmp.z .done + + ; "0x" prefix + cmp b[rdx], 'x' + jmp.z .parsed_0x + + ; "0b" prefix + cmp b[rdx], 'b' + jmp.z .parsed_0b + + ; may be octal, but we don't care + ; we accept "0110101010" (binary) for instance + jmp .main_loop + +.parsed_0x: + ; are we in base 16? + ; if not, leave rax = 0 and *rdx = 'x' + cmp ax1, 16 + jmp.nz .done + ; else + inc rdx + jmp .main_loop + +.parsed_0b: + ; are we in base 2? + ; if not, leave rax = 0 and *rdx = 'b' + cmp ax1, 2 + jmp.nz .done + ; else + inc rdx + jmp .main_loop + +.base_0: + ; guess base + + cmp b[rdx], '0' + mov.nz ax1, 10 + jmp.nz .main_loop + inc rdx + + cmp b[rdx], 'x' + inc.z rdx + mov.z ax1, 16 + jmp.z .main_loop + + cmp b[rdx], 'b' + inc.z rdx + mov.z ax1, 2 + jmp.z .main_loop + + mov ax1, 8 + +.main_loop: + mov lx0, b[rdx] + inc rdx + + cmp lx0, '0' + jmp.b .done + cmp.ae lx0, '9' + sub.be lx0, '0' + jmp.be .next + + cmp lx0, 'A' + cmp.ae lx0, 'Z' + sub.be lx0, 55 ; 'A' - 10 + jmp.be .next + + cmp lx0, 'a' + jmp.b .next + cmp.ae lx0, 'z' + sub.be lx0, 87 ; 'a' - 10 + jmp.be .next + +.next: + ; too large for base? + cmp lx0, ax1 + jmp.ae .done + + mul rax, ax1 + add rax, lx0 + jmp .main_loop + +.done: + ; negative? + test lx1, lx1 + ret.z + + ; yes + neg rax + ret + +.bad: + mov q[errno], EINVAL + ret + diff --git a/ka/dos.k b/ka/dos.k index 2973b85..7c93b51 100644 --- a/ka/dos.k +++ b/ka/dos.k @@ -10,6 +10,10 @@ start: call main + call strtol_test + + stop + ; Wait for and print input indefinitely .1: scan rax diff --git a/ka/sys/main.k b/ka/sys/main.k index 7b56274..5d3cfe8 100644 --- a/ka/sys/main.k +++ b/ka/sys/main.k @@ -13,6 +13,5 @@ PrintBootMsg: ; main: call PrintBootMsg - ret diff --git a/ka/sys/tests.k b/ka/sys/tests.k index 06bcbcd..dd5b4f4 100644 --- a/ka/sys/tests.k +++ b/ka/sys/tests.k @@ -1,6 +1,34 @@ ; The OS/K Team licenses this file to you under the MIT license. ; See the LICENSE file in the project root for more information. +strtol_test: + mov ax0, .s1 + mov ax1, 10 + call strtol + mov nx0, rax + + mov ax0, .s2 + mov ax1, 16 + call strtol + mov nx1, rax + + mov ax0, .s3 + mov ax1, 0 + call strtol + mov nx2, rax + + mov ax0, .s4 + mov ax1, 10 + call strtol + mov nx3, rax + + ret + +.s1 = "+065536" +.s2 = "0xABCD" +.s3 = "0b100000" +.s4 = "-1" + speed_test: utime lx0 @@ -12,7 +40,7 @@ speed_test: mov rax, lx1 sub rax, lx0 - stop + ret putc_scroll_test: mov rdx, 25 diff --git a/vm/in/LOGIC b/vm/in/LOGIC index 88fed45..eb6b270 100644 --- a/vm/in/LOGIC +++ b/vm/in/LOGIC @@ -58,8 +58,14 @@ xor rm rim xorf rm rim # To document + shl rm rim shr rm rim shlf rm rim shrf rm rim +sal rm rim +sar rm rim +salf rm rim +sarf rm rim + diff --git a/vm/in/inout.c b/vm/in/inout.c index 6f94f19..5bde55c 100644 --- a/vm/in/inout.c +++ b/vm/in/inout.c @@ -4,8 +4,6 @@ #include #include -//----------------------------------------------------------------------------// - IMPL_START_1(prn) { if (p1->mlen > 1) { @@ -13,9 +11,7 @@ IMPL_START_1(prn) } console_putc(ctx, (char)v1); } -IMPL_END; - -//----------------------------------------------------------------------------// +IMPL_END IMPL_START_1(scan) { @@ -23,5 +19,3 @@ IMPL_START_1(scan) } IMPL_OUT; -//----------------------------------------------------------------------------// - diff --git a/vm/in/logic.c b/vm/in/logic.c index 6d9eead..542db29 100644 --- a/vm/in/logic.c +++ b/vm/in/logic.c @@ -91,3 +91,49 @@ IMPL_OUT_ZSF; //-------------------------------------------------------------------------- +IMPL_START_2(sal) +{ + long w1 = v1; + long w2 = v2; + + w1 <<= w2; + + v1 = (ulong) w1; +} +IMPL_OUT; + +IMPL_START_2(salf) +{ + long w1 = v1; + long w2 = v2; + + w1 <<= w2; + + v1 = (ulong) w1; +} +IMPL_OUT_ZSF; + +IMPL_START_2(sar) +{ + long w1 = v1; + long w2 = v2; + + w1 >>= w2; + + v1 = (ulong) w1; +} +IMPL_OUT; + +IMPL_START_2(sarf) +{ + long w1 = v1; + long w2 = v2; + + w1 >>= w2; + + v1 = (ulong) w1; +} +IMPL_OUT_ZSF; + +//-------------------------------------------------------------------------- + diff --git a/vm/pc/mem.c b/vm/pc/mem.c index 93a0bff..3ecf3c6 100644 --- a/vm/pc/mem.c +++ b/vm/pc/mem.c @@ -101,11 +101,6 @@ static void writemem64(ctx_t *ctx, ulong val, ulong real, ulong addr) addr += cr2; \ ulong real = addr2real(addr) -#define SIGN_EXTEND(val, mask) \ - (val & ((mask + 1) >> 1) \ - ? (val | ~mask) \ - : val) - //----------------------------------------------------------------------------// ulong readmem(ctx_t *ctx, ulong addr, uint len) diff --git a/vm/pc/mem.h b/vm/pc/mem.h index 9cda0e1..ebaa28d 100644 --- a/vm/pc/mem.h +++ b/vm/pc/mem.h @@ -21,3 +21,9 @@ void writemem(ctx_t *, ulong val, ulong addr, uint len); ulong readmemzx(ctx_t *c, ulong addr, uint len); void writememzx(ctx_t *, ulong val, ulong addr, uint len); + +#define SIGN_EXTEND(val, mask) \ + (val & ((mask + 1) >> 1) \ + ? (val | ~mask) \ + : val) +