diff --git a/Compiler.exe b/Compiler.exe index 1586837..393ad75 100644 Binary files a/Compiler.exe and b/Compiler.exe differ diff --git a/compiler b/compiler index 8808960..fc19927 100755 Binary files a/compiler and b/compiler differ diff --git a/lib/KOSDRV/API.ob07 b/lib/KOSDRV/API.ob07 new file mode 100644 index 0000000..36606e9 --- /dev/null +++ b/lib/KOSDRV/API.ob07 @@ -0,0 +1,123 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018-2022, Anton Krotov + All rights reserved. +*) + +MODULE API; + +IMPORT SYSTEM; + +CONST + eol* = 0DX + 0AX; + BIT_DEPTH* = 32; + +VAR + action*, cmdline*, org*: INTEGER; + + +PROCEDURE [stdcall-] sysfunc3* (arg1, arg2, arg3: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 053H, (* push ebx *) + 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) + 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *) + 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *) + 0CDH, 040H, (* int 64 *) + 05BH, (* pop ebx *) + 0C9H, (* leave *) + 0C2H, 00CH, 000H (* ret 12 *) + ) + RETURN 0 +END sysfunc3; + + +PROCEDURE OutChar* (c: CHAR); +BEGIN + sysfunc3(63, 1, ORD(c)) +END OutChar; + + +PROCEDURE OutLn*; +BEGIN + OutChar(0DX); + OutChar(0AX) +END OutLn; + + +PROCEDURE OutStr (pchar: INTEGER); +VAR + c: CHAR; +BEGIN + IF pchar # 0 THEN + REPEAT + SYSTEM.GET(pchar, c); + IF c # 0X THEN + OutChar(c) + END; + INC(pchar) + UNTIL c = 0X + END +END OutStr; + + +PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); +BEGIN + IF lpCaption # 0 THEN + OutLn; + OutStr(lpCaption); + OutChar(":"); + OutLn + END; + OutStr(lpText); + IF lpCaption # 0 THEN + OutLn + END +END DebugMsg; + + +PROCEDURE _NEW* (size: INTEGER): INTEGER; + RETURN sysfunc3(68, 12, size) +END _NEW; + + +PROCEDURE _DISPOSE* (ptr: INTEGER): INTEGER; +BEGIN + sysfunc3(68, 13, ptr) + RETURN 0 +END _DISPOSE; + + +PROCEDURE init* (reserved, _org: INTEGER); +BEGIN + org := _org - 4096; + sysfunc3(68, 11, 0) +END init; + + +PROCEDURE exit* (code: INTEGER); +BEGIN + sysfunc3(-1, 0, 0) +END exit; + + +PROCEDURE exit_thread* (code: INTEGER); +BEGIN + sysfunc3(-1, 0, 0) +END exit_thread; + + +PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; +BEGIN + action := hinstDLL; + cmdline := fdwReason + RETURN hinstDLL +END dllentry; + + +PROCEDURE sofinit*; +END sofinit; + + +END API. \ No newline at end of file diff --git a/lib/KOSDRV/Debug.ob07 b/lib/KOSDRV/Debug.ob07 new file mode 100644 index 0000000..658fe39 --- /dev/null +++ b/lib/KOSDRV/Debug.ob07 @@ -0,0 +1,292 @@ +(* + Copyright 2016, 2018, 2022, 2023 Anton Krotov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE Debug; + +IMPORT API, sys := SYSTEM; + +CONST + + d = 1.0 - 5.0E-12; + +VAR + + Realp: PROCEDURE (x: REAL; width: INTEGER); + +PROCEDURE Char*(c: CHAR); +VAR res: INTEGER; +BEGIN + res := API.sysfunc3(63, 1, ORD(c)) +END Char; + +PROCEDURE String*(s: ARRAY OF CHAR); +VAR n, i: INTEGER; +BEGIN + n := LENGTH(s); + FOR i := 0 TO n - 1 DO + Char(s[i]) + END +END String; + +PROCEDURE WriteInt(x, n: INTEGER); +VAR i: INTEGER; a: ARRAY 16 OF CHAR; neg: BOOLEAN; +BEGIN + i := 0; + IF n < 1 THEN + n := 1 + END; + IF x < 0 THEN + x := -x; + DEC(n); + neg := TRUE + END; + REPEAT + a[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10; + INC(i) + UNTIL x = 0; + WHILE n > i DO + Char(" "); + DEC(n) + END; + IF neg THEN + Char("-") + END; + REPEAT + DEC(i); + Char(a[i]) + UNTIL i = 0 +END WriteInt; + +PROCEDURE IsNan(AValue: REAL): BOOLEAN; +VAR h, l: SET; +BEGIN + sys.GET(sys.ADR(AValue), l); + sys.GET(sys.ADR(AValue) + 4, h) + RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) +END IsNan; + +PROCEDURE IsInf(x: REAL): BOOLEAN; + RETURN ABS(x) = sys.INF() +END IsInf; + +PROCEDURE Int*(x, width: INTEGER); +VAR i: INTEGER; +BEGIN + IF x # 80000000H THEN + WriteInt(x, width) + ELSE + FOR i := 12 TO width DO + Char(20X) + END; + String("-2147483648") + END +END Int; + +PROCEDURE OutInf(x: REAL; width: INTEGER); +VAR s: ARRAY 5 OF CHAR; i: INTEGER; +BEGIN + IF IsNan(x) THEN + s := "Nan"; + INC(width) + ELSIF IsInf(x) & (x > 0.0) THEN + s := "+Inf" + ELSIF IsInf(x) & (x < 0.0) THEN + s := "-Inf" + END; + FOR i := 1 TO width - 4 DO + Char(" ") + END; + String(s) +END OutInf; + +PROCEDURE Ln*; +BEGIN + Char(0DX); + Char(0AX) +END Ln; + +PROCEDURE _FixReal(x: REAL; width, p: INTEGER); +VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; +BEGIN + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSIF p < 0 THEN + Realp(x, width) + ELSE + len := 0; + minus := FALSE; + IF x < 0.0 THEN + minus := TRUE; + INC(len); + x := ABS(x) + END; + e := 0; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + IF e >= 0 THEN + len := len + e + p + 1; + IF x > 9.0 + d THEN + INC(len) + END; + IF p > 0 THEN + INC(len) + END + ELSE + len := len + p + 2 + END; + FOR i := 1 TO width - len DO + Char(" ") + END; + IF minus THEN + Char("-") + END; + y := x; + WHILE (y < 1.0) & (y # 0.0) DO + y := y * 10.0; + DEC(e) + END; + IF e < 0 THEN + IF x - FLT(FLOOR(x)) > d THEN + Char("1"); + x := 0.0 + ELSE + Char("0"); + x := x * 10.0 + END + ELSE + WHILE e >= 0 DO + IF x - FLT(FLOOR(x)) > d THEN + IF x > 9.0 THEN + String("10") + ELSE + Char(CHR(FLOOR(x) + ORD("0") + 1)) + END; + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(e) + END + END; + IF p > 0 THEN + Char(".") + END; + WHILE p > 0 DO + IF x - FLT(FLOOR(x)) > d THEN + Char(CHR(FLOOR(x) + ORD("0") + 1)); + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(p) + END + END +END _FixReal; + +PROCEDURE Real*(x: REAL; width: INTEGER); +VAR e, n, i: INTEGER; minus: BOOLEAN; +BEGIN + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSE + e := 0; + n := 0; + IF width > 23 THEN + n := width - 23; + width := 23 + ELSIF width < 9 THEN + width := 9 + END; + width := width - 5; + IF x < 0.0 THEN + x := -x; + minus := TRUE + ELSE + minus := FALSE + END; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + WHILE (x < 1.0) & (x # 0.0) DO + x := x * 10.0; + DEC(e) + END; + IF x > 9.0 + d THEN + x := 1.0; + INC(e) + END; + FOR i := 1 TO n DO + Char(" ") + END; + IF minus THEN + x := -x + END; + Realp := Real; + _FixReal(x, width, width - 3); + Char("E"); + IF e >= 0 THEN + Char("+") + ELSE + Char("-"); + e := ABS(e) + END; + IF e < 100 THEN + Char("0") + END; + IF e < 10 THEN + Char("0") + END; + Int(e, 0) + END +END Real; + +PROCEDURE FixReal*(x: REAL; width, p: INTEGER); +BEGIN + Realp := Real; + _FixReal(x, width, p) +END FixReal; + +PROCEDURE Open*; +TYPE + + info_struct = RECORD + subfunc: INTEGER; + flags: INTEGER; + param: INTEGER; + rsrvd1: INTEGER; + rsrvd2: INTEGER; + fname: ARRAY 1024 OF CHAR + END; + +VAR info: info_struct; res: INTEGER; +BEGIN + info.subfunc := 7; + info.flags := 0; + info.param := sys.SADR(" "); + info.rsrvd1 := 0; + info.rsrvd2 := 0; + info.fname := "/sys/develop/board"; + res := API.sysfunc3(70, sys.ADR(info), 0) +END Open; + +END Debug. \ No newline at end of file diff --git a/lib/KOSDRV/RTL.ob07 b/lib/KOSDRV/RTL.ob07 new file mode 100644 index 0000000..22e0c63 --- /dev/null +++ b/lib/KOSDRV/RTL.ob07 @@ -0,0 +1,548 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018-2021, 2023, Anton Krotov + All rights reserved. +*) + +MODULE RTL; + +IMPORT SYSTEM, API; + + +CONST + + minint = ROR(1, 1); + + WORD = API.BIT_DEPTH DIV 8; + + +VAR + + name, types, tcount: INTEGER; + + +PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER); +BEGIN + SYSTEM.CODE( + 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) + 085H, 0C0H, (* test eax, eax *) + 07EH, 019H, (* jle L *) + 0FCH, (* cld *) + 057H, (* push edi *) + 056H, (* push esi *) + 08BH, 075H, 010H, (* mov esi, dword [ebp + 16] *) + 08BH, 07DH, 00CH, (* mov edi, dword [ebp + 12] *) + 089H, 0C1H, (* mov ecx, eax *) + 0C1H, 0E9H, 002H, (* shr ecx, 2 *) + 0F3H, 0A5H, (* rep movsd *) + 089H, 0C1H, (* mov ecx, eax *) + 083H, 0E1H, 003H, (* and ecx, 3 *) + 0F3H, 0A4H, (* rep movsb *) + 05EH, (* pop esi *) + 05FH (* pop edi *) + (* L: *) + ) +END _move; + + +PROCEDURE [stdcall] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + IF len_src > len_dst THEN + res := FALSE + ELSE + _move(len_src * base_size, dst, src); + res := TRUE + END + + RETURN res +END _arrcpy; + + +PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); +BEGIN + _move(MIN(len_dst, len_src) * chr_size, dst, src) +END _strcpy; + + +PROCEDURE [stdcall] _rot* (Len, Ptr: INTEGER); +BEGIN + SYSTEM.CODE( + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- Len *) + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- Ptr *) + 049H, (* dec ecx *) + 053H, (* push ebx *) + 08BH, 018H, (* mov ebx, dword [eax] *) + (* L: *) + 08BH, 050H, 004H, (* mov edx, dword [eax + 4] *) + 089H, 010H, (* mov dword [eax], edx *) + 083H, 0C0H, 004H, (* add eax, 4 *) + 049H, (* dec ecx *) + 075H, 0F5H, (* jnz L *) + 089H, 018H, (* mov dword [eax], ebx *) + 05BH, (* pop ebx *) + 05DH, (* pop ebp *) + 0C2H, 008H, 000H (* ret 8 *) + ) +END _rot; + + +PROCEDURE [stdcall] _set* (b, a: INTEGER); (* {a..b} -> eax *) +BEGIN + SYSTEM.CODE( + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- b *) + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- a *) + 039H, 0C8H, (* cmp eax, ecx *) + 07FH, 033H, (* jg L1 *) + 083H, 0F8H, 01FH, (* cmp eax, 31 *) + 07FH, 02EH, (* jg L1 *) + 085H, 0C9H, (* test ecx, ecx *) + 07CH, 02AH, (* jl L1 *) + 083H, 0F9H, 01FH, (* cmp ecx, 31 *) + 07EH, 005H, (* jle L3 *) + 0B9H, 01FH, 000H, 000H, 000H, (* mov ecx, 31 *) + (* L3: *) + 085H, 0C0H, (* test eax, eax *) + 07DH, 002H, (* jge L2 *) + 031H, 0C0H, (* xor eax, eax *) + (* L2: *) + 089H, 0CAH, (* mov edx, ecx *) + 029H, 0C2H, (* sub edx, eax *) + 0B8H, 000H, 000H, 000H, 080H, (* mov eax, 0x80000000 *) + 087H, 0CAH, (* xchg edx, ecx *) + 0D3H, 0F8H, (* sar eax, cl *) + 087H, 0CAH, (* xchg edx, ecx *) + 083H, 0E9H, 01FH, (* sub ecx, 31 *) + 0F7H, 0D9H, (* neg ecx *) + 0D3H, 0E8H, (* shr eax, cl *) + 05DH, (* pop ebp *) + 0C2H, 008H, 000H, (* ret 8 *) + (* L1: *) + 031H, 0C0H, (* xor eax, eax *) + 05DH, (* pop ebp *) + 0C2H, 008H, 000H (* ret 8 *) + ) +END _set; + + +PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *) +BEGIN + SYSTEM.CODE( + 031H, 0C0H, (* xor eax, eax *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *) + 083H, 0F9H, 01FH, (* cmp ecx, 31 *) + 077H, 003H, (* ja L *) + 00FH, 0ABH, 0C8H (* bts eax, ecx *) + (* L: *) + ) +END _set1; + + +PROCEDURE [stdcall] _divmod* (y, x: INTEGER); (* (x div y) -> eax; (x mod y) -> edx *) +BEGIN + SYSTEM.CODE( + 053H, (* push ebx *) + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- x *) + 031H, 0D2H, (* xor edx, edx *) + 085H, 0C0H, (* test eax, eax *) + 074H, 018H, (* je L2 *) + 07FH, 002H, (* jg L1 *) + 0F7H, 0D2H, (* not edx *) + (* L1: *) + 089H, 0C3H, (* mov ebx, eax *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- y *) + 0F7H, 0F9H, (* idiv ecx *) + 085H, 0D2H, (* test edx, edx *) + 074H, 009H, (* je L2 *) + 031H, 0CBH, (* xor ebx, ecx *) + 085H, 0DBH, (* test ebx, ebx *) + 07DH, 003H, (* jge L2 *) + 048H, (* dec eax *) + 001H, 0CAH, (* add edx, ecx *) + (* L2: *) + 05BH (* pop ebx *) + ) +END _divmod; + + +PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER); +BEGIN + ptr := API._NEW(size); + IF ptr # 0 THEN + SYSTEM.PUT(ptr, t); + INC(ptr, WORD) + END +END _new; + + +PROCEDURE [stdcall] _dispose* (VAR ptr: INTEGER); +BEGIN + IF ptr # 0 THEN + ptr := API._DISPOSE(ptr - WORD) + END +END _dispose; + + +PROCEDURE [stdcall] _length* (len, str: INTEGER); +BEGIN + SYSTEM.CODE( + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *) + 048H, (* dec eax *) + (* L1: *) + 040H, (* inc eax *) + 080H, 038H, 000H, (* cmp byte [eax], 0 *) + 074H, 003H, (* jz L2 *) + 0E2H, 0F8H, (* loop L1 *) + 040H, (* inc eax *) + (* L2: *) + 02BH, 045H, 00CH (* sub eax, dword [ebp + 0Ch] *) + ) +END _length; + + +PROCEDURE [stdcall] _lengthw* (len, str: INTEGER); +BEGIN + SYSTEM.CODE( + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *) + 048H, (* dec eax *) + 048H, (* dec eax *) + (* L1: *) + 040H, (* inc eax *) + 040H, (* inc eax *) + 066H, 083H, 038H, 000H, (* cmp word [eax], 0 *) + 074H, 004H, (* jz L2 *) + 0E2H, 0F6H, (* loop L1 *) + 040H, (* inc eax *) + 040H, (* inc eax *) + (* L2: *) + 02BH, 045H, 00CH, (* sub eax, dword [ebp + 0Ch] *) + 0D1H, 0E8H (* shr eax, 1 *) + ) +END _lengthw; + + +PROCEDURE [stdcall] strncmp (a, b, n: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 056H, (* push esi *) + 057H, (* push edi *) + 053H, (* push ebx *) + 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *) + 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *) + 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *) + 031H, 0C9H, (* xor ecx, ecx *) + 031H, 0D2H, (* xor edx, edx *) + 0B8H, + 000H, 000H, 000H, 080H, (* mov eax, minint *) + (* L1: *) + 085H, 0DBH, (* test ebx, ebx *) + 07EH, 017H, (* jle L3 *) + 08AH, 00EH, (* mov cl, byte[esi] *) + 08AH, 017H, (* mov dl, byte[edi] *) + 046H, (* inc esi *) + 047H, (* inc edi *) + 04BH, (* dec ebx *) + 039H, 0D1H, (* cmp ecx, edx *) + 074H, 006H, (* je L2 *) + 089H, 0C8H, (* mov eax, ecx *) + 029H, 0D0H, (* sub eax, edx *) + 0EBH, 006H, (* jmp L3 *) + (* L2: *) + 085H, 0C9H, (* test ecx, ecx *) + 075H, 0E7H, (* jne L1 *) + 031H, 0C0H, (* xor eax, eax *) + (* L3: *) + 05BH, (* pop ebx *) + 05FH, (* pop edi *) + 05EH, (* pop esi *) + 05DH, (* pop ebp *) + 0C2H, 00CH, 000H (* ret 12 *) + ) + RETURN 0 +END strncmp; + + +PROCEDURE [stdcall] strncmpw (a, b, n: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 056H, (* push esi *) + 057H, (* push edi *) + 053H, (* push ebx *) + 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *) + 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *) + 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *) + 031H, 0C9H, (* xor ecx, ecx *) + 031H, 0D2H, (* xor edx, edx *) + 0B8H, + 000H, 000H, 000H, 080H, (* mov eax, minint *) + (* L1: *) + 085H, 0DBH, (* test ebx, ebx *) + 07EH, 01BH, (* jle L3 *) + 066H, 08BH, 00EH, (* mov cx, word[esi] *) + 066H, 08BH, 017H, (* mov dx, word[edi] *) + 046H, (* inc esi *) + 046H, (* inc esi *) + 047H, (* inc edi *) + 047H, (* inc edi *) + 04BH, (* dec ebx *) + 039H, 0D1H, (* cmp ecx, edx *) + 074H, 006H, (* je L2 *) + 089H, 0C8H, (* mov eax, ecx *) + 029H, 0D0H, (* sub eax, edx *) + 0EBH, 006H, (* jmp L3 *) + (* L2: *) + 085H, 0C9H, (* test ecx, ecx *) + 075H, 0E3H, (* jne L1 *) + 031H, 0C0H, (* xor eax, eax *) + (* L3: *) + 05BH, (* pop ebx *) + 05FH, (* pop edi *) + 05EH, (* pop esi *) + 05DH, (* pop ebp *) + 0C2H, 00CH, 000H (* ret 12 *) + ) + RETURN 0 +END strncmpw; + + +PROCEDURE [stdcall] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: CHAR; + +BEGIN + res := strncmp(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmp; + + +PROCEDURE [stdcall] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: WCHAR; + +BEGIN + res := strncmpw(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2 * 2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1 * 2, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmpw; + + +PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); +VAR + c: CHAR; + i: INTEGER; + +BEGIN + i := 0; + REPEAT + SYSTEM.GET(pchar, c); + s[i] := c; + INC(pchar); + INC(i) + UNTIL c = 0X +END PCharToStr; + + +PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); +VAR + i, a: INTEGER; + +BEGIN + i := 0; + a := x; + REPEAT + INC(i); + a := a DIV 10 + UNTIL a = 0; + + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 +END IntToStr; + + +PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); +VAR + n1, n2: INTEGER; + +BEGIN + n1 := LENGTH(s1); + n2 := LENGTH(s2); + + ASSERT(n1 + n2 < LEN(s1)); + + SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); + s1[n1 + n2] := 0X +END append; + + +PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER); +VAR + s, temp: ARRAY 1024 OF CHAR; + +BEGIN + CASE err OF + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" + END; + + append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); + append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); + + API.DebugMsg(SYSTEM.ADR(s[0]), name); + + API.exit_thread(0) +END _error; + + +PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): BOOLEAN; +BEGIN + (* r IS t0 *) + WHILE (t1 # 0) & (t1 # t0) DO + SYSTEM.GET(types + t1 * WORD, t1) + END + + RETURN t1 = t0 +END _isrec; + + +PROCEDURE [stdcall] _is* (t0, p: INTEGER): BOOLEAN; +VAR + t1: INTEGER; + +BEGIN + (* p IS t0 *) + IF p # 0 THEN + SYSTEM.GET(p - WORD, t1); + WHILE (t1 # 0) & (t1 # t0) DO + SYSTEM.GET(types + t1 * WORD, t1) + END + ELSE + t1 := -1 + END + + RETURN t1 = t0 +END _is; + + +PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): BOOLEAN; +BEGIN + (* r:t1 IS t0 *) + WHILE (t1 # 0) & (t1 # t0) DO + SYSTEM.GET(types + t1 * WORD, t1) + END + + RETURN t1 = t0 +END _guardrec; + + +PROCEDURE [stdcall] _guard* (t0, p: INTEGER): BOOLEAN; +VAR + t1: INTEGER; + +BEGIN + (* p IS t0 *) + SYSTEM.GET(p, p); + IF p # 0 THEN + SYSTEM.GET(p - WORD, t1); + WHILE (t1 # t0) & (t1 # 0) DO + SYSTEM.GET(types + t1 * WORD, t1) + END + ELSE + t1 := t0 + END + + RETURN t1 = t0 +END _guard; + + +PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; + RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) +END _dllentry; + + +PROCEDURE [stdcall] _sofinit*; +BEGIN + API.sofinit +END _sofinit; + + +PROCEDURE [stdcall] _exit* (code: INTEGER); +BEGIN + API.exit(code) +END _exit; + + +PROCEDURE [stdcall] _init* (modname: INTEGER; _tcount, _types: INTEGER; code, param: INTEGER); +BEGIN + SYSTEM.CODE(09BH, 0DBH, 0E3H); (* finit *) + API.init(param, code); + tcount := _tcount; + types := _types; + name := modname +END _init; + + +END RTL. \ No newline at end of file diff --git a/lib/KOSKER/API.ob07 b/lib/KOSKER/API.ob07 new file mode 100644 index 0000000..e32d2e4 --- /dev/null +++ b/lib/KOSKER/API.ob07 @@ -0,0 +1,131 @@ +(* + BSD 2-Clause License + + Copyright (c) 2023, Anton Krotov + All rights reserved. +*) + +MODULE API; + +IMPORT SYSTEM; + +CONST + eol* = 0DX + 0AX; + BIT_DEPTH* = 32; + + HEAP_SIZE = 3*1024; + +VAR + org*: INTEGER; + + mem: ARRAY HEAP_SIZE OF BYTE; + heap: INTEGER; + + +PROCEDURE [stdcall-] sysfunc3* (arg1, arg2, arg3: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 053H, (* push ebx *) + 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) + 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *) + 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *) + 0CDH, 040H, (* int 64 *) + 05BH, (* pop ebx *) + 0C9H, (* leave *) + 0C2H, 00CH, 000H (* ret 12 *) + ) + RETURN 0 +END sysfunc3; + + +PROCEDURE OutChar* (c: CHAR); +BEGIN + sysfunc3(63, 1, ORD(c)) +END OutChar; + + +PROCEDURE OutLn*; +BEGIN + OutChar(0DX); + OutChar(0AX) +END OutLn; + + +PROCEDURE OutStr* (pchar: INTEGER); +VAR + c: CHAR; +BEGIN + IF pchar # 0 THEN + REPEAT + SYSTEM.GET(pchar, c); + IF c # 0X THEN + OutChar(c) + END; + INC(pchar) + UNTIL c = 0X + END +END OutStr; + + +PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); +BEGIN + IF lpCaption # 0 THEN + OutLn; + OutStr(lpCaption); + OutChar(":"); + OutLn + END; + OutStr(lpText); + IF lpCaption # 0 THEN + OutLn + END +END DebugMsg; + + +PROCEDURE _NEW* (size: INTEGER): INTEGER; +VAR + res: INTEGER; +BEGIN + IF heap + size <= SYSTEM.ADR(mem[0]) + HEAP_SIZE THEN + res := heap; + INC(heap, size) + ELSE + res := 0 + END + RETURN res +END _NEW; + + +PROCEDURE _DISPOSE* (ptr: INTEGER): INTEGER; + RETURN 0 +END _DISPOSE; + + +PROCEDURE init* (reserved, _org: INTEGER); +BEGIN + org := _org; + heap := SYSTEM.ADR(mem[0]) +END init; + + +PROCEDURE exit* (code: INTEGER); +BEGIN + sysfunc3(-1, 0, 0) +END exit; + + +PROCEDURE exit_thread* (code: INTEGER); +BEGIN + sysfunc3(-1, 0, 0) +END exit_thread; + + +PROCEDURE dllentry* (param1, param2, param3: INTEGER): INTEGER; + RETURN 0 +END dllentry; + + +PROCEDURE sofinit*; +END sofinit; + +END API. \ No newline at end of file diff --git a/lib/KOSKER/Debug.ob07 b/lib/KOSKER/Debug.ob07 new file mode 100644 index 0000000..658fe39 --- /dev/null +++ b/lib/KOSKER/Debug.ob07 @@ -0,0 +1,292 @@ +(* + Copyright 2016, 2018, 2022, 2023 Anton Krotov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE Debug; + +IMPORT API, sys := SYSTEM; + +CONST + + d = 1.0 - 5.0E-12; + +VAR + + Realp: PROCEDURE (x: REAL; width: INTEGER); + +PROCEDURE Char*(c: CHAR); +VAR res: INTEGER; +BEGIN + res := API.sysfunc3(63, 1, ORD(c)) +END Char; + +PROCEDURE String*(s: ARRAY OF CHAR); +VAR n, i: INTEGER; +BEGIN + n := LENGTH(s); + FOR i := 0 TO n - 1 DO + Char(s[i]) + END +END String; + +PROCEDURE WriteInt(x, n: INTEGER); +VAR i: INTEGER; a: ARRAY 16 OF CHAR; neg: BOOLEAN; +BEGIN + i := 0; + IF n < 1 THEN + n := 1 + END; + IF x < 0 THEN + x := -x; + DEC(n); + neg := TRUE + END; + REPEAT + a[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10; + INC(i) + UNTIL x = 0; + WHILE n > i DO + Char(" "); + DEC(n) + END; + IF neg THEN + Char("-") + END; + REPEAT + DEC(i); + Char(a[i]) + UNTIL i = 0 +END WriteInt; + +PROCEDURE IsNan(AValue: REAL): BOOLEAN; +VAR h, l: SET; +BEGIN + sys.GET(sys.ADR(AValue), l); + sys.GET(sys.ADR(AValue) + 4, h) + RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) +END IsNan; + +PROCEDURE IsInf(x: REAL): BOOLEAN; + RETURN ABS(x) = sys.INF() +END IsInf; + +PROCEDURE Int*(x, width: INTEGER); +VAR i: INTEGER; +BEGIN + IF x # 80000000H THEN + WriteInt(x, width) + ELSE + FOR i := 12 TO width DO + Char(20X) + END; + String("-2147483648") + END +END Int; + +PROCEDURE OutInf(x: REAL; width: INTEGER); +VAR s: ARRAY 5 OF CHAR; i: INTEGER; +BEGIN + IF IsNan(x) THEN + s := "Nan"; + INC(width) + ELSIF IsInf(x) & (x > 0.0) THEN + s := "+Inf" + ELSIF IsInf(x) & (x < 0.0) THEN + s := "-Inf" + END; + FOR i := 1 TO width - 4 DO + Char(" ") + END; + String(s) +END OutInf; + +PROCEDURE Ln*; +BEGIN + Char(0DX); + Char(0AX) +END Ln; + +PROCEDURE _FixReal(x: REAL; width, p: INTEGER); +VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; +BEGIN + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSIF p < 0 THEN + Realp(x, width) + ELSE + len := 0; + minus := FALSE; + IF x < 0.0 THEN + minus := TRUE; + INC(len); + x := ABS(x) + END; + e := 0; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + IF e >= 0 THEN + len := len + e + p + 1; + IF x > 9.0 + d THEN + INC(len) + END; + IF p > 0 THEN + INC(len) + END + ELSE + len := len + p + 2 + END; + FOR i := 1 TO width - len DO + Char(" ") + END; + IF minus THEN + Char("-") + END; + y := x; + WHILE (y < 1.0) & (y # 0.0) DO + y := y * 10.0; + DEC(e) + END; + IF e < 0 THEN + IF x - FLT(FLOOR(x)) > d THEN + Char("1"); + x := 0.0 + ELSE + Char("0"); + x := x * 10.0 + END + ELSE + WHILE e >= 0 DO + IF x - FLT(FLOOR(x)) > d THEN + IF x > 9.0 THEN + String("10") + ELSE + Char(CHR(FLOOR(x) + ORD("0") + 1)) + END; + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(e) + END + END; + IF p > 0 THEN + Char(".") + END; + WHILE p > 0 DO + IF x - FLT(FLOOR(x)) > d THEN + Char(CHR(FLOOR(x) + ORD("0") + 1)); + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(p) + END + END +END _FixReal; + +PROCEDURE Real*(x: REAL; width: INTEGER); +VAR e, n, i: INTEGER; minus: BOOLEAN; +BEGIN + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSE + e := 0; + n := 0; + IF width > 23 THEN + n := width - 23; + width := 23 + ELSIF width < 9 THEN + width := 9 + END; + width := width - 5; + IF x < 0.0 THEN + x := -x; + minus := TRUE + ELSE + minus := FALSE + END; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + WHILE (x < 1.0) & (x # 0.0) DO + x := x * 10.0; + DEC(e) + END; + IF x > 9.0 + d THEN + x := 1.0; + INC(e) + END; + FOR i := 1 TO n DO + Char(" ") + END; + IF minus THEN + x := -x + END; + Realp := Real; + _FixReal(x, width, width - 3); + Char("E"); + IF e >= 0 THEN + Char("+") + ELSE + Char("-"); + e := ABS(e) + END; + IF e < 100 THEN + Char("0") + END; + IF e < 10 THEN + Char("0") + END; + Int(e, 0) + END +END Real; + +PROCEDURE FixReal*(x: REAL; width, p: INTEGER); +BEGIN + Realp := Real; + _FixReal(x, width, p) +END FixReal; + +PROCEDURE Open*; +TYPE + + info_struct = RECORD + subfunc: INTEGER; + flags: INTEGER; + param: INTEGER; + rsrvd1: INTEGER; + rsrvd2: INTEGER; + fname: ARRAY 1024 OF CHAR + END; + +VAR info: info_struct; res: INTEGER; +BEGIN + info.subfunc := 7; + info.flags := 0; + info.param := sys.SADR(" "); + info.rsrvd1 := 0; + info.rsrvd2 := 0; + info.fname := "/sys/develop/board"; + res := API.sysfunc3(70, sys.ADR(info), 0) +END Open; + +END Debug. \ No newline at end of file diff --git a/lib/KOSKER/RTL.ob07 b/lib/KOSKER/RTL.ob07 new file mode 100644 index 0000000..22e0c63 --- /dev/null +++ b/lib/KOSKER/RTL.ob07 @@ -0,0 +1,548 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018-2021, 2023, Anton Krotov + All rights reserved. +*) + +MODULE RTL; + +IMPORT SYSTEM, API; + + +CONST + + minint = ROR(1, 1); + + WORD = API.BIT_DEPTH DIV 8; + + +VAR + + name, types, tcount: INTEGER; + + +PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER); +BEGIN + SYSTEM.CODE( + 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) + 085H, 0C0H, (* test eax, eax *) + 07EH, 019H, (* jle L *) + 0FCH, (* cld *) + 057H, (* push edi *) + 056H, (* push esi *) + 08BH, 075H, 010H, (* mov esi, dword [ebp + 16] *) + 08BH, 07DH, 00CH, (* mov edi, dword [ebp + 12] *) + 089H, 0C1H, (* mov ecx, eax *) + 0C1H, 0E9H, 002H, (* shr ecx, 2 *) + 0F3H, 0A5H, (* rep movsd *) + 089H, 0C1H, (* mov ecx, eax *) + 083H, 0E1H, 003H, (* and ecx, 3 *) + 0F3H, 0A4H, (* rep movsb *) + 05EH, (* pop esi *) + 05FH (* pop edi *) + (* L: *) + ) +END _move; + + +PROCEDURE [stdcall] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + IF len_src > len_dst THEN + res := FALSE + ELSE + _move(len_src * base_size, dst, src); + res := TRUE + END + + RETURN res +END _arrcpy; + + +PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); +BEGIN + _move(MIN(len_dst, len_src) * chr_size, dst, src) +END _strcpy; + + +PROCEDURE [stdcall] _rot* (Len, Ptr: INTEGER); +BEGIN + SYSTEM.CODE( + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- Len *) + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- Ptr *) + 049H, (* dec ecx *) + 053H, (* push ebx *) + 08BH, 018H, (* mov ebx, dword [eax] *) + (* L: *) + 08BH, 050H, 004H, (* mov edx, dword [eax + 4] *) + 089H, 010H, (* mov dword [eax], edx *) + 083H, 0C0H, 004H, (* add eax, 4 *) + 049H, (* dec ecx *) + 075H, 0F5H, (* jnz L *) + 089H, 018H, (* mov dword [eax], ebx *) + 05BH, (* pop ebx *) + 05DH, (* pop ebp *) + 0C2H, 008H, 000H (* ret 8 *) + ) +END _rot; + + +PROCEDURE [stdcall] _set* (b, a: INTEGER); (* {a..b} -> eax *) +BEGIN + SYSTEM.CODE( + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- b *) + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- a *) + 039H, 0C8H, (* cmp eax, ecx *) + 07FH, 033H, (* jg L1 *) + 083H, 0F8H, 01FH, (* cmp eax, 31 *) + 07FH, 02EH, (* jg L1 *) + 085H, 0C9H, (* test ecx, ecx *) + 07CH, 02AH, (* jl L1 *) + 083H, 0F9H, 01FH, (* cmp ecx, 31 *) + 07EH, 005H, (* jle L3 *) + 0B9H, 01FH, 000H, 000H, 000H, (* mov ecx, 31 *) + (* L3: *) + 085H, 0C0H, (* test eax, eax *) + 07DH, 002H, (* jge L2 *) + 031H, 0C0H, (* xor eax, eax *) + (* L2: *) + 089H, 0CAH, (* mov edx, ecx *) + 029H, 0C2H, (* sub edx, eax *) + 0B8H, 000H, 000H, 000H, 080H, (* mov eax, 0x80000000 *) + 087H, 0CAH, (* xchg edx, ecx *) + 0D3H, 0F8H, (* sar eax, cl *) + 087H, 0CAH, (* xchg edx, ecx *) + 083H, 0E9H, 01FH, (* sub ecx, 31 *) + 0F7H, 0D9H, (* neg ecx *) + 0D3H, 0E8H, (* shr eax, cl *) + 05DH, (* pop ebp *) + 0C2H, 008H, 000H, (* ret 8 *) + (* L1: *) + 031H, 0C0H, (* xor eax, eax *) + 05DH, (* pop ebp *) + 0C2H, 008H, 000H (* ret 8 *) + ) +END _set; + + +PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *) +BEGIN + SYSTEM.CODE( + 031H, 0C0H, (* xor eax, eax *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *) + 083H, 0F9H, 01FH, (* cmp ecx, 31 *) + 077H, 003H, (* ja L *) + 00FH, 0ABH, 0C8H (* bts eax, ecx *) + (* L: *) + ) +END _set1; + + +PROCEDURE [stdcall] _divmod* (y, x: INTEGER); (* (x div y) -> eax; (x mod y) -> edx *) +BEGIN + SYSTEM.CODE( + 053H, (* push ebx *) + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- x *) + 031H, 0D2H, (* xor edx, edx *) + 085H, 0C0H, (* test eax, eax *) + 074H, 018H, (* je L2 *) + 07FH, 002H, (* jg L1 *) + 0F7H, 0D2H, (* not edx *) + (* L1: *) + 089H, 0C3H, (* mov ebx, eax *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- y *) + 0F7H, 0F9H, (* idiv ecx *) + 085H, 0D2H, (* test edx, edx *) + 074H, 009H, (* je L2 *) + 031H, 0CBH, (* xor ebx, ecx *) + 085H, 0DBH, (* test ebx, ebx *) + 07DH, 003H, (* jge L2 *) + 048H, (* dec eax *) + 001H, 0CAH, (* add edx, ecx *) + (* L2: *) + 05BH (* pop ebx *) + ) +END _divmod; + + +PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER); +BEGIN + ptr := API._NEW(size); + IF ptr # 0 THEN + SYSTEM.PUT(ptr, t); + INC(ptr, WORD) + END +END _new; + + +PROCEDURE [stdcall] _dispose* (VAR ptr: INTEGER); +BEGIN + IF ptr # 0 THEN + ptr := API._DISPOSE(ptr - WORD) + END +END _dispose; + + +PROCEDURE [stdcall] _length* (len, str: INTEGER); +BEGIN + SYSTEM.CODE( + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *) + 048H, (* dec eax *) + (* L1: *) + 040H, (* inc eax *) + 080H, 038H, 000H, (* cmp byte [eax], 0 *) + 074H, 003H, (* jz L2 *) + 0E2H, 0F8H, (* loop L1 *) + 040H, (* inc eax *) + (* L2: *) + 02BH, 045H, 00CH (* sub eax, dword [ebp + 0Ch] *) + ) +END _length; + + +PROCEDURE [stdcall] _lengthw* (len, str: INTEGER); +BEGIN + SYSTEM.CODE( + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *) + 048H, (* dec eax *) + 048H, (* dec eax *) + (* L1: *) + 040H, (* inc eax *) + 040H, (* inc eax *) + 066H, 083H, 038H, 000H, (* cmp word [eax], 0 *) + 074H, 004H, (* jz L2 *) + 0E2H, 0F6H, (* loop L1 *) + 040H, (* inc eax *) + 040H, (* inc eax *) + (* L2: *) + 02BH, 045H, 00CH, (* sub eax, dword [ebp + 0Ch] *) + 0D1H, 0E8H (* shr eax, 1 *) + ) +END _lengthw; + + +PROCEDURE [stdcall] strncmp (a, b, n: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 056H, (* push esi *) + 057H, (* push edi *) + 053H, (* push ebx *) + 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *) + 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *) + 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *) + 031H, 0C9H, (* xor ecx, ecx *) + 031H, 0D2H, (* xor edx, edx *) + 0B8H, + 000H, 000H, 000H, 080H, (* mov eax, minint *) + (* L1: *) + 085H, 0DBH, (* test ebx, ebx *) + 07EH, 017H, (* jle L3 *) + 08AH, 00EH, (* mov cl, byte[esi] *) + 08AH, 017H, (* mov dl, byte[edi] *) + 046H, (* inc esi *) + 047H, (* inc edi *) + 04BH, (* dec ebx *) + 039H, 0D1H, (* cmp ecx, edx *) + 074H, 006H, (* je L2 *) + 089H, 0C8H, (* mov eax, ecx *) + 029H, 0D0H, (* sub eax, edx *) + 0EBH, 006H, (* jmp L3 *) + (* L2: *) + 085H, 0C9H, (* test ecx, ecx *) + 075H, 0E7H, (* jne L1 *) + 031H, 0C0H, (* xor eax, eax *) + (* L3: *) + 05BH, (* pop ebx *) + 05FH, (* pop edi *) + 05EH, (* pop esi *) + 05DH, (* pop ebp *) + 0C2H, 00CH, 000H (* ret 12 *) + ) + RETURN 0 +END strncmp; + + +PROCEDURE [stdcall] strncmpw (a, b, n: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 056H, (* push esi *) + 057H, (* push edi *) + 053H, (* push ebx *) + 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *) + 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *) + 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *) + 031H, 0C9H, (* xor ecx, ecx *) + 031H, 0D2H, (* xor edx, edx *) + 0B8H, + 000H, 000H, 000H, 080H, (* mov eax, minint *) + (* L1: *) + 085H, 0DBH, (* test ebx, ebx *) + 07EH, 01BH, (* jle L3 *) + 066H, 08BH, 00EH, (* mov cx, word[esi] *) + 066H, 08BH, 017H, (* mov dx, word[edi] *) + 046H, (* inc esi *) + 046H, (* inc esi *) + 047H, (* inc edi *) + 047H, (* inc edi *) + 04BH, (* dec ebx *) + 039H, 0D1H, (* cmp ecx, edx *) + 074H, 006H, (* je L2 *) + 089H, 0C8H, (* mov eax, ecx *) + 029H, 0D0H, (* sub eax, edx *) + 0EBH, 006H, (* jmp L3 *) + (* L2: *) + 085H, 0C9H, (* test ecx, ecx *) + 075H, 0E3H, (* jne L1 *) + 031H, 0C0H, (* xor eax, eax *) + (* L3: *) + 05BH, (* pop ebx *) + 05FH, (* pop edi *) + 05EH, (* pop esi *) + 05DH, (* pop ebp *) + 0C2H, 00CH, 000H (* ret 12 *) + ) + RETURN 0 +END strncmpw; + + +PROCEDURE [stdcall] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: CHAR; + +BEGIN + res := strncmp(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmp; + + +PROCEDURE [stdcall] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: WCHAR; + +BEGIN + res := strncmpw(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2 * 2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1 * 2, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmpw; + + +PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); +VAR + c: CHAR; + i: INTEGER; + +BEGIN + i := 0; + REPEAT + SYSTEM.GET(pchar, c); + s[i] := c; + INC(pchar); + INC(i) + UNTIL c = 0X +END PCharToStr; + + +PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); +VAR + i, a: INTEGER; + +BEGIN + i := 0; + a := x; + REPEAT + INC(i); + a := a DIV 10 + UNTIL a = 0; + + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 +END IntToStr; + + +PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); +VAR + n1, n2: INTEGER; + +BEGIN + n1 := LENGTH(s1); + n2 := LENGTH(s2); + + ASSERT(n1 + n2 < LEN(s1)); + + SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); + s1[n1 + n2] := 0X +END append; + + +PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER); +VAR + s, temp: ARRAY 1024 OF CHAR; + +BEGIN + CASE err OF + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" + END; + + append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); + append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); + + API.DebugMsg(SYSTEM.ADR(s[0]), name); + + API.exit_thread(0) +END _error; + + +PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): BOOLEAN; +BEGIN + (* r IS t0 *) + WHILE (t1 # 0) & (t1 # t0) DO + SYSTEM.GET(types + t1 * WORD, t1) + END + + RETURN t1 = t0 +END _isrec; + + +PROCEDURE [stdcall] _is* (t0, p: INTEGER): BOOLEAN; +VAR + t1: INTEGER; + +BEGIN + (* p IS t0 *) + IF p # 0 THEN + SYSTEM.GET(p - WORD, t1); + WHILE (t1 # 0) & (t1 # t0) DO + SYSTEM.GET(types + t1 * WORD, t1) + END + ELSE + t1 := -1 + END + + RETURN t1 = t0 +END _is; + + +PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): BOOLEAN; +BEGIN + (* r:t1 IS t0 *) + WHILE (t1 # 0) & (t1 # t0) DO + SYSTEM.GET(types + t1 * WORD, t1) + END + + RETURN t1 = t0 +END _guardrec; + + +PROCEDURE [stdcall] _guard* (t0, p: INTEGER): BOOLEAN; +VAR + t1: INTEGER; + +BEGIN + (* p IS t0 *) + SYSTEM.GET(p, p); + IF p # 0 THEN + SYSTEM.GET(p - WORD, t1); + WHILE (t1 # t0) & (t1 # 0) DO + SYSTEM.GET(types + t1 * WORD, t1) + END + ELSE + t1 := t0 + END + + RETURN t1 = t0 +END _guard; + + +PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; + RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) +END _dllentry; + + +PROCEDURE [stdcall] _sofinit*; +BEGIN + API.sofinit +END _sofinit; + + +PROCEDURE [stdcall] _exit* (code: INTEGER); +BEGIN + API.exit(code) +END _exit; + + +PROCEDURE [stdcall] _init* (modname: INTEGER; _tcount, _types: INTEGER; code, param: INTEGER); +BEGIN + SYSTEM.CODE(09BH, 0DBH, 0E3H); (* finit *) + API.init(param, code); + tcount := _tcount; + types := _types; + name := modname +END _init; + + +END RTL. \ No newline at end of file diff --git a/source/KOS.ob07 b/source/KOS.ob07 index 979a8cf..ec4f3b1 100644 --- a/source/KOS.ob07 +++ b/source/KOS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2020, 2023, Anton Krotov All rights reserved. *) @@ -77,14 +77,11 @@ BEGIN END Import; -PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR); - +PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; kernel: BOOLEAN); CONST - PARAM_SIZE = 2048; FileAlignment = 16; - VAR header: HEADER; @@ -100,7 +97,7 @@ VAR ImportTable: CHL.INTLIST; ILen, libcount, isize: INTEGER; - icount, dcount, ccount: INTEGER; + icount, dcount, ccount, glob32_size: INTEGER; code: CHL.BYTELIST; @@ -111,7 +108,11 @@ BEGIN dcount := CHL.Length(program.data); ccount := CHL.Length(program.code); - text := base + HEADER_SIZE; + text := base; + IF ~kernel THEN + INC(text, HEADER_SIZE) + END; + data := WR.align(text + ccount, FileAlignment); idata := WR.align(data + dcount, FileAlignment); @@ -175,18 +176,19 @@ BEGIN WR.Create(FileName); - FOR i := 0 TO 7 DO - WR.WriteByte(ORD(header.menuet01[i])) + IF ~kernel THEN + FOR i := 0 TO 7 DO + WR.WriteByte(ORD(header.menuet01[i])) + END; + WR.Write32LE(header.ver); + WR.Write32LE(header.start); + WR.Write32LE(header.size); + WR.Write32LE(header.mem); + WR.Write32LE(header.sp); + WR.Write32LE(header.param); + WR.Write32LE(header.path) END; - WR.Write32LE(header.ver); - WR.Write32LE(header.start); - WR.Write32LE(header.size); - WR.Write32LE(header.mem); - WR.Write32LE(header.sp); - WR.Write32LE(header.param); - WR.Write32LE(header.path); - CHL.WriteToFile(code); WR.Padding(FileAlignment); @@ -196,8 +198,15 @@ BEGIN FOR i := 0 TO ILen - 1 DO WR.Write32LE(CHL.GetInt(ImportTable, i)) END; - CHL.WriteToFile(program._import); + WR.Padding(FileAlignment); + + IF kernel THEN + glob32_size := program.bss DIV 4 + ORD(program.bss MOD 4 # 0); + FOR i := 1 TO glob32_size DO + WR.Write32LE(0) + END + END; WR.Close END write; diff --git a/source/TARGETS.ob07 b/source/TARGETS.ob07 index fb52518..e008a4f 100644 --- a/source/TARGETS.ob07 +++ b/source/TARGETS.ob07 @@ -28,6 +28,8 @@ CONST STM32CM3* = 13; RVM32I* = 14; RVM64I* = 15; + KolibriOSKer* = 16; + KolibriOSDrv* = 17; cpuX86* = 0; cpuAMD64* = 1; cpuMSP430* = 2; cpuTHUMB* = 3; cpuRVM32I* = 4; cpuRVM64I* = 5; @@ -57,7 +59,7 @@ TYPE VAR - Targets*: ARRAY 16 OF TARGET; + Targets*: ARRAY 18 OF TARGET; CPUs: ARRAY 6 OF RECORD @@ -106,10 +108,10 @@ BEGIN LibDir := Targets[i].LibDir; FileExt := Targets[i].FileExt; - Import := OS IN {osWIN32, osWIN64, osKOS}; + Import := (OS IN {osWIN32, osWIN64, osKOS}) & (target # KolibriOSKer); Dispose := ~(target IN noDISPOSE); RTL := ~(target IN noRTL); - Dll := target IN {Linux32SO, Linux64SO, Win32DLL, Win64DLL, KolibriOSDLL}; + Dll := target IN {Linux32SO, Linux64SO, Win32DLL, Win64DLL, KolibriOSDLL, KolibriOSDrv}; WinLin := OS IN {osWIN32, osLINUX32, osWIN64, osLINUX64}; WordSize := BitDepth DIV 8; AdrSize := WordSize @@ -151,4 +153,6 @@ BEGIN Enter( STM32CM3, cpuTHUMB, 4, osNONE, "stm32cm3", "STM32CM3", ".hex"); Enter( RVM32I, cpuRVM32I, 4, osNONE, "rvm32i", libRVM32I, ".bin"); Enter( RVM64I, cpuRVM64I, 8, osNONE, "rvm64i", libRVM64I, ".bin"); + Enter( KolibriOSKer, cpuX86, 8, osKOS, "kosker", "KOSKER", ".bin"); + Enter( KolibriOSDrv, cpuX86, 8, osKOS, "kosdrv", "KOSDRV", ".dll"); END TARGETS. \ No newline at end of file diff --git a/source/UTILS.ob07 b/source/UTILS.ob07 index 7ab8954..e6201ec 100644 --- a/source/UTILS.ob07 +++ b/source/UTILS.ob07 @@ -23,8 +23,8 @@ CONST max32* = 2147483647; vMajor* = 1; - vMinor* = 65; - Date* = "04-feb-2023"; + vMinor* = 66; + Date* = "10-feb-2023"; FILE_EXT* = ".ob07"; RTL_NAME* = "RTL"; diff --git a/source/X86.ob07 b/source/X86.ob07 index 982943f..40a5c32 100644 --- a/source/X86.ob07 +++ b/source/X86.ob07 @@ -774,7 +774,7 @@ BEGIN END LoadFltConst; -PROCEDURE translate (pic: BOOLEAN; stroffs: INTEGER); +PROCEDURE translate (pic: BOOLEAN; stroffs, target: INTEGER); VAR cmd, next: COMMAND; @@ -1887,19 +1887,28 @@ BEGIN |IL.opISREC: PushAll(2); - pushc(param2 * tcount); + IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN + param2 := param2*tcount + END; + pushc(param2); CallRTL(pic, IL._isrec); GetRegA |IL.opIS: PushAll(1); - pushc(param2 * tcount); + IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN + param2 := param2*tcount + END; + pushc(param2); CallRTL(pic, IL._is); GetRegA |IL.opTYPEGR: PushAll(1); - pushc(param2 * tcount); + IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN + param2 := param2*tcount + END; + pushc(param2); CallRTL(pic, IL._guardrec); GetRegA @@ -1907,7 +1916,10 @@ BEGIN UnOp(reg1); PushAll(0); push(reg1); - pushc(param2 * tcount); + IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN + param2 := param2*tcount + END; + pushc(param2); CallRTL(pic, IL._guard); GetRegA @@ -1915,14 +1927,20 @@ BEGIN UnOp(reg1); PushAll(0); pushm(reg1, -4); - pushc(param2 * tcount); + IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN + param2 := param2*tcount + END; + pushc(param2); CallRTL(pic, IL._guardrec); GetRegA |IL.opCASET: push(ecx); push(ecx); - pushc(param2 * tcount); + IF ~(target IN {TARGETS.KolibriOSDrv, TARGETS.KolibriOSKer}) THEN + param2 := param2*tcount + END; + pushc(param2); CallRTL(pic, IL._guardrec); pop(ecx); test(eax); @@ -2286,8 +2304,12 @@ BEGIN mainLocVarSize := 0; LocVarSize := 0; - IF target = TARGETS.Win32DLL THEN - pushm(ebp, 16); + IF target IN {TARGETS.Win32DLL, TARGETS.KolibriOSDrv} THEN + IF target = TARGETS.Win32DLL THEN + pushm(ebp, 16) + ELSE + pushc(0) + END; pushm(ebp, 12); pushm(ebp, 8); CallRTL(pic, IL._dllentry); @@ -2390,10 +2412,20 @@ BEGIN movrc(eax, 1); OutByte(0C9H); (* leave *) OutByte3(0C2H, 0CH, 0) (* ret 12 *) + ELSIF target = TARGETS.KolibriOSDrv THEN + OutByte(0C9H); (* leave *) + ret; + SetLabel(dllret); + movrc(eax, 0); + OutByte(0C9H); (* leave *) + ret ELSIF target = TARGETS.KolibriOSDLL THEN movrc(eax, 1); OutByte(0C9H); (* leave *) ret + ELSIF target = TARGETS.KolibriOSKer THEN + OutByte(0C9H); (* leave *) + ret; ELSIF target = TARGETS.Linux32SO THEN OutByte(0C9H); (* leave *) ret; @@ -2474,6 +2506,10 @@ BEGIN opt.pic := FALSE END; + IF target IN {TARGETS.KolibriOSKer, TARGETS.KolibriOSDrv} THEN + opt.pic := TRUE + END; + IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32} THEN opt.pic := TRUE END; @@ -2481,14 +2517,16 @@ BEGIN REG.Init(R, push, pop, mov, xchg, {eax, ecx, edx}); dllinit := prolog(opt.pic, target, opt.stack, dllret); - translate(opt.pic, tcount * 4); + translate(opt.pic, tcount * 4, target); epilog(opt.pic, outname, target, opt.stack, opt.version, dllinit, dllret, sofinit); BIN.fixup(program); IF TARGETS.OS = TARGETS.osWIN32 THEN PE32.write(program, outname, target = TARGETS.Win32C, target = TARGETS.Win32DLL, FALSE, opt.PE32FileAlignment) - ELSIF target = TARGETS.KolibriOS THEN - KOS.write(program, outname) + ELSIF target = TARGETS.KolibriOSDrv THEN + PE32.write(program, outname, FALSE, TRUE, FALSE, 512) + ELSIF target IN {TARGETS.KolibriOS, TARGETS.KolibriOSKer} THEN + KOS.write(program, outname, target = TARGETS.KolibriOSKer) ELSIF target = TARGETS.KolibriOSDLL THEN MSCOFF.write(program, outname, opt.version) ELSIF TARGETS.OS = TARGETS.osLINUX32 THEN