From b6a5171cd908819275f07b162bfc00fb0d14c2e3 Mon Sep 17 00:00:00 2001 From: Max Logaev Date: Wed, 28 Jan 2026 13:36:40 +0300 Subject: [PATCH] oberon07: Source code removed Signed-off-by: Max Logaev --- programs/develop/oberon07/Compiler.kex | Bin 272509 -> 0 bytes programs/develop/oberon07/LICENSE | 25 - programs/develop/oberon07/doc/CC.txt | 61 - programs/develop/oberon07/doc/KOSLib.txt | 566 --- .../doc/Oberon07.Report_2016_05_03.pdf | Bin 70214 -> 0 bytes programs/develop/oberon07/doc/x86.txt | 423 -- .../develop/oberon07/lib/KolibriOS/API.ob07 | 290 -- .../develop/oberon07/lib/KolibriOS/Args.ob07 | 100 - .../oberon07/lib/KolibriOS/ColorDlg.ob07 | 105 - .../oberon07/lib/KolibriOS/Console.ob07 | 94 - .../oberon07/lib/KolibriOS/ConsoleLib.ob07 | 103 - .../oberon07/lib/KolibriOS/DateTime.ob07 | 141 - .../develop/oberon07/lib/KolibriOS/Debug.ob07 | 292 -- .../develop/oberon07/lib/KolibriOS/File.ob07 | 330 -- .../develop/oberon07/lib/KolibriOS/HOST.ob07 | 553 --- .../develop/oberon07/lib/KolibriOS/In.ob07 | 282 -- .../oberon07/lib/KolibriOS/KOSAPI.ob07 | 436 --- .../develop/oberon07/lib/KolibriOS/Math.ob07 | 449 --- .../oberon07/lib/KolibriOS/NetDevices.ob07 | 107 - .../oberon07/lib/KolibriOS/OpenDlg.ob07 | 158 - .../develop/oberon07/lib/KolibriOS/Out.ob07 | 267 -- .../develop/oberon07/lib/KolibriOS/RTL.ob07 | 543 --- .../oberon07/lib/KolibriOS/RasterWorks.ob07 | 124 - .../develop/oberon07/lib/KolibriOS/Read.ob07 | 46 - .../oberon07/lib/KolibriOS/UnixTime.ob07 | 64 - .../oberon07/lib/KolibriOS/Vector.ob07 | 121 - .../develop/oberon07/lib/KolibriOS/Write.ob07 | 46 - .../oberon07/lib/KolibriOS/kfonts.ob07 | 492 --- .../oberon07/lib/KolibriOS/libimg.ob07 | 435 --- programs/develop/oberon07/lib/Math/CMath.ob07 | 462 --- .../develop/oberon07/lib/Math/MathBits.ob07 | 33 - .../develop/oberon07/lib/Math/MathRound.ob07 | 99 - .../develop/oberon07/lib/Math/MathStat.ob07 | 238 -- programs/develop/oberon07/lib/Math/Rand.ob07 | 81 - .../develop/oberon07/lib/Math/RandExt.ob07 | 298 -- .../develop/oberon07/samples/BUILD_ALL.SH | 5 - .../develop/oberon07/samples/Dialogs.ob07 | 159 - programs/develop/oberon07/samples/HW.ob07 | 78 - programs/develop/oberon07/samples/HW_con.ob07 | 59 - programs/develop/oberon07/source/AMD64.ob07 | 2424 ------------ programs/develop/oberon07/source/ARITH.ob07 | 797 ---- .../develop/oberon07/source/AVLTREES.ob07 | 197 - programs/develop/oberon07/source/BIN.ob07 | 384 -- .../develop/oberon07/source/CHUNKLISTS.ob07 | 255 -- .../develop/oberon07/source/COLLECTIONS.ob07 | 59 - programs/develop/oberon07/source/CONSOLE.ob07 | 78 - .../develop/oberon07/source/Compiler.ob07 | 352 -- programs/develop/oberon07/source/ELF.ob07 | 592 --- programs/develop/oberon07/source/ERRORS.ob07 | 222 -- programs/develop/oberon07/source/FILES.ob07 | 200 - programs/develop/oberon07/source/HEX.ob07 | 117 - programs/develop/oberon07/source/IL.ob07 | 1201 ------ programs/develop/oberon07/source/KOS.ob07 | 206 - programs/develop/oberon07/source/LISTS.ob07 | 199 - programs/develop/oberon07/source/MSCOFF.ob07 | 309 -- programs/develop/oberon07/source/MSP430.ob07 | 1771 --------- .../develop/oberon07/source/MSP430RTL.ob07 | 671 ---- programs/develop/oberon07/source/PARS.ob07 | 1397 ------- programs/develop/oberon07/source/PATHS.ob07 | 151 - programs/develop/oberon07/source/PE32.ob07 | 695 ---- programs/develop/oberon07/source/PROG.ob07 | 1283 ------ programs/develop/oberon07/source/REG.ob07 | 286 -- programs/develop/oberon07/source/RVMxI.ob07 | 1415 ------- programs/develop/oberon07/source/SCAN.ob07 | 783 ---- .../develop/oberon07/source/STATEMENTS.ob07 | 3444 ----------------- programs/develop/oberon07/source/STRINGS.ob07 | 342 -- programs/develop/oberon07/source/TARGETS.ob07 | 154 - programs/develop/oberon07/source/TEXTDRV.ob07 | 210 - programs/develop/oberon07/source/THUMB.ob07 | 2459 ------------ programs/develop/oberon07/source/UTILS.ob07 | 217 -- programs/develop/oberon07/source/WRITER.ob07 | 104 - programs/develop/oberon07/source/X86.ob07 | 2507 ------------ 72 files changed, 33646 deletions(-) delete mode 100644 programs/develop/oberon07/Compiler.kex delete mode 100644 programs/develop/oberon07/LICENSE delete mode 100644 programs/develop/oberon07/doc/CC.txt delete mode 100644 programs/develop/oberon07/doc/KOSLib.txt delete mode 100644 programs/develop/oberon07/doc/Oberon07.Report_2016_05_03.pdf delete mode 100644 programs/develop/oberon07/doc/x86.txt delete mode 100644 programs/develop/oberon07/lib/KolibriOS/API.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/Args.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/ColorDlg.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/Console.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/ConsoleLib.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/DateTime.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/Debug.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/File.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/HOST.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/In.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/KOSAPI.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/Math.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/NetDevices.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/OpenDlg.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/Out.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/RTL.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/RasterWorks.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/Read.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/UnixTime.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/Vector.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/Write.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/kfonts.ob07 delete mode 100644 programs/develop/oberon07/lib/KolibriOS/libimg.ob07 delete mode 100644 programs/develop/oberon07/lib/Math/CMath.ob07 delete mode 100644 programs/develop/oberon07/lib/Math/MathBits.ob07 delete mode 100644 programs/develop/oberon07/lib/Math/MathRound.ob07 delete mode 100644 programs/develop/oberon07/lib/Math/MathStat.ob07 delete mode 100644 programs/develop/oberon07/lib/Math/Rand.ob07 delete mode 100644 programs/develop/oberon07/lib/Math/RandExt.ob07 delete mode 100644 programs/develop/oberon07/samples/BUILD_ALL.SH delete mode 100644 programs/develop/oberon07/samples/Dialogs.ob07 delete mode 100644 programs/develop/oberon07/samples/HW.ob07 delete mode 100644 programs/develop/oberon07/samples/HW_con.ob07 delete mode 100644 programs/develop/oberon07/source/AMD64.ob07 delete mode 100644 programs/develop/oberon07/source/ARITH.ob07 delete mode 100644 programs/develop/oberon07/source/AVLTREES.ob07 delete mode 100644 programs/develop/oberon07/source/BIN.ob07 delete mode 100644 programs/develop/oberon07/source/CHUNKLISTS.ob07 delete mode 100644 programs/develop/oberon07/source/COLLECTIONS.ob07 delete mode 100644 programs/develop/oberon07/source/CONSOLE.ob07 delete mode 100644 programs/develop/oberon07/source/Compiler.ob07 delete mode 100644 programs/develop/oberon07/source/ELF.ob07 delete mode 100644 programs/develop/oberon07/source/ERRORS.ob07 delete mode 100644 programs/develop/oberon07/source/FILES.ob07 delete mode 100644 programs/develop/oberon07/source/HEX.ob07 delete mode 100644 programs/develop/oberon07/source/IL.ob07 delete mode 100644 programs/develop/oberon07/source/KOS.ob07 delete mode 100644 programs/develop/oberon07/source/LISTS.ob07 delete mode 100644 programs/develop/oberon07/source/MSCOFF.ob07 delete mode 100644 programs/develop/oberon07/source/MSP430.ob07 delete mode 100644 programs/develop/oberon07/source/MSP430RTL.ob07 delete mode 100644 programs/develop/oberon07/source/PARS.ob07 delete mode 100644 programs/develop/oberon07/source/PATHS.ob07 delete mode 100644 programs/develop/oberon07/source/PE32.ob07 delete mode 100644 programs/develop/oberon07/source/PROG.ob07 delete mode 100644 programs/develop/oberon07/source/REG.ob07 delete mode 100644 programs/develop/oberon07/source/RVMxI.ob07 delete mode 100644 programs/develop/oberon07/source/SCAN.ob07 delete mode 100644 programs/develop/oberon07/source/STATEMENTS.ob07 delete mode 100644 programs/develop/oberon07/source/STRINGS.ob07 delete mode 100644 programs/develop/oberon07/source/TARGETS.ob07 delete mode 100644 programs/develop/oberon07/source/TEXTDRV.ob07 delete mode 100644 programs/develop/oberon07/source/THUMB.ob07 delete mode 100644 programs/develop/oberon07/source/UTILS.ob07 delete mode 100644 programs/develop/oberon07/source/WRITER.ob07 delete mode 100644 programs/develop/oberon07/source/X86.ob07 diff --git a/programs/develop/oberon07/Compiler.kex b/programs/develop/oberon07/Compiler.kex deleted file mode 100644 index 5598014e71e9e7c7b9f57167e9d37d987b547476..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 272509 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

f(2m_HJsL8miYir9?{N;JP$u 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 diff --git a/programs/develop/oberon07/LICENSE b/programs/develop/oberon07/LICENSE deleted file mode 100644 index 3abe18a44..000000000 --- a/programs/develop/oberon07/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -BSD 2-Clause License - -Copyright (c) 2018-2023, Anton Krotov -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/programs/develop/oberon07/doc/CC.txt b/programs/develop/oberon07/doc/CC.txt deleted file mode 100644 index 278b0616b..000000000 --- a/programs/develop/oberon07/doc/CC.txt +++ /dev/null @@ -1,61 +0,0 @@ -Условная компиляция - -синтаксис: - - $IF "(" ident {"|" ident} ")" - <...> - {$ELSIF "(" ident {"|" ident} ")"} - <...> - [$ELSE] - <...> - $END - - где ident: - - одно из возможных значений параметра в командной строке - - пользовательский идентификатор, переданный с ключом -def при компиляции - - один из возможных предопределенных идентификаторов: - - WINDOWS - приложение Windows - LINUX - приложение Linux - KOLIBRIOS - приложение KolibriOS - CPU_X86 - приложение для процессора x86 (32-бит) - CPU_X8664 - приложение для процессора x86_64 - - -примеры: - - $IF (win64con | win64gui | win64dll) - OS := "WIN64"; - $ELSIF (win32con | win32gui | win32dll) - OS := "WIN32"; - $ELSIF (linux64exe | linux64so) - OS := "LINUX64"; - $ELSIF (linux32exe | linux32so) - OS := "LINUX32"; - $ELSE - OS := "UNKNOWN"; - $END - - - $IF (debug) (* -def debug *) - print("debug"); - $END - - - $IF (WINDOWS) - $IF (CPU_X86) - (*windows 32*) - - $ELSIF (CPU_X8664) - (*windows 64*) - - $END - $ELSIF (LINUX) - $IF (CPU_X86) - (*linux 32*) - - $ELSIF (CPU_X8664) - (*linux 64*) - - $END - $END \ No newline at end of file diff --git a/programs/develop/oberon07/doc/KOSLib.txt b/programs/develop/oberon07/doc/KOSLib.txt deleted file mode 100644 index 01364faf9..000000000 --- a/programs/develop/oberon07/doc/KOSLib.txt +++ /dev/null @@ -1,566 +0,0 @@ -============================================================================== - - Библиотека (KolibriOS) - ------------------------------------------------------------------------------- -MODULE Out - консольный вывод - - PROCEDURE Open - формально открывает консольный вывод - - PROCEDURE Int(x, width: INTEGER) - вывод целого числа x; - width - количество знакомест, используемых для вывода - - PROCEDURE Real(x: REAL; width: INTEGER) - вывод вещественного числа x в плавающем формате; - width - количество знакомест, используемых для вывода - - PROCEDURE Char(x: CHAR) - вывод символа x - - PROCEDURE FixReal(x: REAL; width, p: INTEGER) - вывод вещественного числа x в фиксированном формате; - width - количество знакомест, используемых для вывода; - p - количество знаков после десятичной точки - - PROCEDURE Ln - переход на следующую строку - - PROCEDURE String(s: ARRAY OF CHAR) - вывод строки s - ------------------------------------------------------------------------------- -MODULE In - консольный ввод - - VAR Done: BOOLEAN - принимает значение TRUE в случае успешного выполнения - операции ввода, иначе FALSE - - PROCEDURE Open - формально открывает консольный ввод, - также присваивает переменной Done значение TRUE - - PROCEDURE Int(VAR x: INTEGER) - ввод числа типа INTEGER - - PROCEDURE Char(VAR x: CHAR) - ввод символа - - PROCEDURE Real(VAR x: REAL) - ввод числа типа REAL - - PROCEDURE String(VAR s: ARRAY OF CHAR) - ввод строки - - PROCEDURE Ln - ожидание нажатия ENTER - ------------------------------------------------------------------------------- -MODULE Console - дополнительные процедуры консольного вывода - - CONST - - Следующие константы определяют цвет консольного вывода - - Black = 0 Blue = 1 Green = 2 - Cyan = 3 Red = 4 Magenta = 5 - Brown = 6 LightGray = 7 DarkGray = 8 - LightBlue = 9 LightGreen = 10 LightCyan = 11 - LightRed = 12 LightMagenta = 13 Yellow = 14 - White = 15 - - PROCEDURE Cls - очистка окна консоли - - PROCEDURE SetColor(FColor, BColor: INTEGER) - установка цвета консольного вывода: FColor - цвет текста, - BColor - цвет фона, возможные значения - вышеперечисленные - константы - - PROCEDURE SetCursor(x, y: INTEGER) - установка курсора консоли в позицию (x, y) - - PROCEDURE GetCursor(VAR x, y: INTEGER) - записывает в параметры текущие координаты курсора консоли - - PROCEDURE GetCursorX(): INTEGER - возвращает текущую x-координату курсора консоли - - PROCEDURE GetCursorY(): INTEGER - возвращает текущую y-координату курсора консоли - ------------------------------------------------------------------------------- -MODULE ConsoleLib - обертка библиотеки console.obj - ------------------------------------------------------------------------------- -MODULE Math - математические функции - - CONST - - pi = 3.141592653589793E+00 - e = 2.718281828459045E+00 - - - PROCEDURE IsNan(x: REAL): BOOLEAN - возвращает TRUE, если x - не число - - PROCEDURE IsInf(x: REAL): BOOLEAN - возвращает TRUE, если x - бесконечность - - PROCEDURE sqrt(x: REAL): REAL - квадратный корень x - - PROCEDURE exp(x: REAL): REAL - экспонента x - - PROCEDURE ln(x: REAL): REAL - натуральный логарифм x - - PROCEDURE sin(x: REAL): REAL - синус x - - PROCEDURE cos(x: REAL): REAL - косинус x - - PROCEDURE tan(x: REAL): REAL - тангенс x - - PROCEDURE arcsin(x: REAL): REAL - арксинус x - - PROCEDURE arccos(x: REAL): REAL - арккосинус x - - PROCEDURE arctan(x: REAL): REAL - арктангенс x - - PROCEDURE arctan2(y, x: REAL): REAL - арктангенс y/x - - PROCEDURE power(base, exponent: REAL): REAL - возведение числа base в степень exponent - - PROCEDURE log(base, x: REAL): REAL - логарифм x по основанию base - - PROCEDURE sinh(x: REAL): REAL - гиперболический синус x - - PROCEDURE cosh(x: REAL): REAL - гиперболический косинус x - - PROCEDURE tanh(x: REAL): REAL - гиперболический тангенс x - - PROCEDURE arsinh(x: REAL): REAL - обратный гиперболический синус x - - PROCEDURE arcosh(x: REAL): REAL - обратный гиперболический косинус x - - PROCEDURE artanh(x: REAL): REAL - обратный гиперболический тангенс x - - PROCEDURE round(x: REAL): REAL - округление x до ближайшего целого - - PROCEDURE frac(x: REAL): REAL; - дробная часть числа x - - PROCEDURE floor(x: REAL): REAL - наибольшее целое число (представление как REAL), - не больше x: floor(1.2) = 1.0 - - PROCEDURE ceil(x: REAL): REAL - наименьшее целое число (представление как REAL), - не меньше x: ceil(1.2) = 2.0 - - PROCEDURE sgn(x: REAL): INTEGER - если x > 0 возвращает 1 - если x < 0 возвращает -1 - если x = 0 возвращает 0 - - PROCEDURE fact(n: INTEGER): REAL - факториал n - ------------------------------------------------------------------------------- -MODULE Debug - вывод на доску отладки - Интерфейс как модуль Out - - PROCEDURE Open - открывает доску отладки - ------------------------------------------------------------------------------- -MODULE File - работа с файловой системой - - TYPE - - FNAME = ARRAY 520 OF CHAR - - FS = POINTER TO rFS - - rFS = RECORD (* информационная структура файла *) - subfunc, pos, hpos, bytes, buffer: INTEGER; - name: FNAME - END - - FD = POINTER TO rFD - - rFD = RECORD (* структура блока данных входа каталога *) - attr: INTEGER; - ntyp: CHAR; - reserved: ARRAY 3 OF CHAR; - time_create, date_create, - time_access, date_access, - time_modif, date_modif, - size, hsize: INTEGER; - name: FNAME - END - - CONST - - SEEK_BEG = 0 - SEEK_CUR = 1 - SEEK_END = 2 - - PROCEDURE Load(FName: ARRAY OF CHAR; VAR size: INTEGER): INTEGER; - Загружает в память файл с именем FName, записывает в параметр - size размер файла, возвращает адрес загруженного файла - или 0 (ошибка). При необходимости, распаковывает - файл (kunpack). - - PROCEDURE GetFileInfo(FName: ARRAY OF CHAR; VAR Info: rFD): BOOLEAN - Записывает структуру блока данных входа каталога для файла - или папки с именем FName в параметр Info. - При ошибке возвращает FALSE. - - PROCEDURE Exists(FName: ARRAY OF CHAR): BOOLEAN - возвращает TRUE, если файл с именем FName существует - - PROCEDURE Close(VAR F: FS) - освобождает память, выделенную для информационной структуры - файла F и присваивает F значение NIL - - PROCEDURE Open(FName: ARRAY OF CHAR): FS - возвращает указатель на информационную структуру файла с - именем FName, при ошибке возвращает NIL - - PROCEDURE Delete(FName: ARRAY OF CHAR): BOOLEAN - удаляет файл с именем FName, при ошибке возвращает FALSE - - PROCEDURE Seek(F: FS; Offset, Origin: INTEGER): INTEGER - устанавливает позицию чтения-записи файла F на Offset, - относительно Origin = (SEEK_BEG - начало файла, - SEEK_CUR - текущая позиция, SEEK_END - конец файла), - возвращает позицию относительно начала файла, например: - Seek(F, 0, SEEK_END) - устанавливает позицию на конец файла и возвращает длину - файла; при ошибке возвращает -1 - - PROCEDURE Read(F: FS; Buffer, Count: INTEGER): INTEGER - Читает данные из файла в память. F - указатель на - информационную структуру файла, Buffer - адрес области - памяти, Count - количество байт, которое требуется прочитать - из файла; возвращает количество байт, которое было прочитано - и соответствующим образом изменяет позицию чтения/записи в - информационной структуре F. - - PROCEDURE Write(F: FS; Buffer, Count: INTEGER): INTEGER - Записывает данные из памяти в файл. F - указатель на - информационную структуру файла, Buffer - адрес области - памяти, Count - количество байт, которое требуется записать - в файл; возвращает количество байт, которое было записано и - соответствующим образом изменяет позицию чтения/записи в - информационной структуре F. - - PROCEDURE Create(FName: ARRAY OF CHAR): FS - создает новый файл с именем FName (полное имя), возвращает - указатель на информационную структуру файла, - при ошибке возвращает NIL - - PROCEDURE CreateDir(DirName: ARRAY OF CHAR): BOOLEAN - создает папку с именем DirName, все промежуточные папки - должны существовать, при ошибке возвращает FALSE - - PROCEDURE DeleteDir(DirName: ARRAY OF CHAR): BOOLEAN - удаляет пустую папку с именем DirName, - при ошибке возвращает FALSE - - PROCEDURE DirExists(DirName: ARRAY OF CHAR): BOOLEAN - возвращает TRUE, если папка с именем DirName существует - ------------------------------------------------------------------------------- -MODULE Read - чтение основных типов данных из файла F - - Процедуры возвращают TRUE в случае успешной операции чтения и - соответствующим образом изменяют позицию чтения/записи в - информационной структуре F - - PROCEDURE Char(F: File.FS; VAR x: CHAR): BOOLEAN - - PROCEDURE Int(F: File.FS; VAR x: INTEGER): BOOLEAN - - PROCEDURE Real(F: File.FS; VAR x: REAL): BOOLEAN - - PROCEDURE Boolean(F: File.FS; VAR x: BOOLEAN): BOOLEAN - - PROCEDURE Set(F: File.FS; VAR x: SET): BOOLEAN - - PROCEDURE WChar(F: File.FS; VAR x: WCHAR): BOOLEAN - ------------------------------------------------------------------------------- -MODULE Write - запись основных типов данных в файл F - - Процедуры возвращают TRUE в случае успешной операции записи и - соответствующим образом изменяют позицию чтения/записи в - информационной структуре F - - PROCEDURE Char(F: File.FS; x: CHAR): BOOLEAN - - PROCEDURE Int(F: File.FS; x: INTEGER): BOOLEAN - - PROCEDURE Real(F: File.FS; x: REAL): BOOLEAN - - PROCEDURE Boolean(F: File.FS; x: BOOLEAN): BOOLEAN - - PROCEDURE Set(F: File.FS; x: SET): BOOLEAN - - PROCEDURE WChar(F: File.FS; x: WCHAR): BOOLEAN - ------------------------------------------------------------------------------- -MODULE DateTime - дата, время - - CONST ERR = -7.0E5 - - PROCEDURE Now(VAR Year, Month, Day, Hour, Min, Sec: INTEGER) - записывает в параметры компоненты текущей системной даты и - времени - - PROCEDURE Encode(Year, Month, Day, Hour, Min, Sec: INTEGER): REAL - возвращает дату, полученную из компонентов - Year, Month, Day, Hour, Min, Sec; - при ошибке возвращает константу ERR = -7.0E5 - - PROCEDURE Decode(Date: REAL; VAR Year, Month, Day, - Hour, Min, Sec: INTEGER): BOOLEAN - извлекает компоненты - Year, Month, Day, Hour, Min, Sec из даты Date; - при ошибке возвращает FALSE - ------------------------------------------------------------------------------- -MODULE Args - параметры программы - - VAR argc: INTEGER - количество параметров программы, включая имя - исполняемого файла - - PROCEDURE GetArg(n: INTEGER; VAR s: ARRAY OF CHAR) - записывает в строку s n-й параметр программы, - нумерация параметров от 0 до argc - 1, - нулевой параметр -- имя исполняемого файла - ------------------------------------------------------------------------------- -MODULE KOSAPI - - PROCEDURE sysfunc1(arg1: INTEGER): INTEGER - PROCEDURE sysfunc2(arg1, arg2: INTEGER): INTEGER - ... - PROCEDURE sysfunc7(arg1, arg2, ..., arg7: INTEGER): INTEGER - Обертки для функций API ядра KolibriOS. - arg1 .. arg7 соответствуют регистрам - eax, ebx, ecx, edx, esi, edi, ebp; - возвращают значение регистра eax после системного вызова. - - PROCEDURE sysfunc22(arg1, arg2: INTEGER; VAR res2: INTEGER): INTEGER - Обертка для функций API ядра KolibriOS. - arg1 - регистр eax, arg2 - регистр ebx, - res2 - значение регистра ebx после системного вызова; - возвращает значение регистра eax после системного вызова. - - PROCEDURE malloc(size: INTEGER): INTEGER - Выделяет блок памяти. - size - размер блока в байтах, - возвращает адрес выделенного блока - - PROCEDURE free(ptr: INTEGER): INTEGER - Освобождает ранее выделенный блок памяти с адресом ptr, - возвращает 0 - - PROCEDURE realloc(ptr, size: INTEGER): INTEGER - Перераспределяет блок памяти, - ptr - адрес ранее выделенного блока, - size - новый размер, - возвращает указатель на перераспределенный блок, - 0 при ошибке - - PROCEDURE GetCommandLine(): INTEGER - Возвращает адрес строки параметров - - PROCEDURE GetName(): INTEGER - Возвращает адрес строки с именем программы - - PROCEDURE LoadLib(name: ARRAY OF CHAR): INTEGER - Загружает DLL с полным именем name. Возвращает адрес таблицы - экспорта. При ошибке возвращает 0. - - PROCEDURE GetProcAdr(name: ARRAY OF CHAR; lib: INTEGER): INTEGER - name - имя процедуры - lib - адрес таблицы экспорта DLL - Возвращает адрес процедуры. При ошибке возвращает 0. - ------------------------------------------------------------------------------- -MODULE ColorDlg - работа с диалогом "Color Dialog" - - TYPE - - Dialog = POINTER TO RECORD (* структура диалога *) - status: INTEGER (* состояние диалога: - 0 - пользователь нажал Cancel - 1 - пользователь нажал OK - 2 - диалог открыт *) - - color: INTEGER (* выбранный цвет *) - END - - PROCEDURE Create(draw_window: DRAW_WINDOW): Dialog - создать диалог - draw_window - процедура перерисовки основного окна - (TYPE DRAW_WINDOW = PROCEDURE); - процедура возвращает указатель на структуру диалога - - PROCEDURE Show(cd: Dialog) - показать диалог - cd - указатель на структуру диалога, который был создан ранее - процедурой Create - - PROCEDURE Destroy(VAR cd: Dialog) - уничтожить диалог - cd - указатель на структуру диалога - ------------------------------------------------------------------------------- -MODULE OpenDlg - работа с диалогом "Open Dialog" - - TYPE - - Dialog = POINTER TO RECORD (* структура диалога *) - status: INTEGER (* состояние диалога: - 0 - пользователь нажал Cancel - 1 - пользователь нажал OK - 2 - диалог открыт *) - - FileName: ARRAY 4096 OF CHAR (* имя выбранного файла *) - FilePath: ARRAY 4096 OF CHAR (* полное имя выбранного - файла *) - END - - PROCEDURE Create(draw_window: DRAW_WINDOW; type: INTEGER; def_path, - filter: ARRAY OF CHAR): Dialog - создать диалог - draw_window - процедура перерисовки основного окна - (TYPE DRAW_WINDOW = PROCEDURE) - type - тип диалога - 0 - открыть - 1 - сохранить - 2 - выбрать папку - def_path - путь по умолчанию, папка def_path будет открыта - при первом запуске диалога - filter - в строке записано перечисление расширений файлов, - которые будут показаны в диалоговом окне, расширения - разделяются символом "|", например: "ASM|TXT|INI" - процедура возвращает указатель на структуру диалога - - PROCEDURE Show(od: Dialog; Width, Height: INTEGER) - показать диалог - od - указатель на структуру диалога, который был создан ранее - процедурой Create - Width и Height - ширина и высота диалогового окна - - PROCEDURE Destroy(VAR od: Dialog) - уничтожить диалог - od - указатель на структуру диалога - ------------------------------------------------------------------------------- -MODULE kfonts - работа с kf-шрифтами - - CONST - - bold = 1 - italic = 2 - underline = 4 - strike_through = 8 - smoothing = 16 - bpp32 = 32 - - TYPE - - TFont = POINTER TO TFont_desc (* указатель на шрифт *) - - PROCEDURE LoadFont(file_name: ARRAY OF CHAR): TFont - загрузить шрифт из файла - file_name имя kf-файла - рез-т: указатель на шрифт/NIL (ошибка) - - PROCEDURE SetSize(Font: TFont; font_size: INTEGER): BOOLEAN - установить размер шрифта - Font указатель на шрифт - font_size размер шрифта - рез-т: TRUE/FALSE (ошибка) - - PROCEDURE Enabled(Font: TFont; font_size: INTEGER): BOOLEAN - проверить, есть ли шрифт, заданного размера - Font указатель на шрифт - font_size размер шрифта - рез-т: TRUE/FALSE (шрифта нет) - - PROCEDURE Destroy(VAR Font: TFont) - выгрузить шрифт, освободить динамическую память - Font указатель на шрифт - Присваивает переменной Font значение NIL - - PROCEDURE TextHeight(Font: TFont): INTEGER - получить высоту строки текста - Font указатель на шрифт - рез-т: высота строки текста в пикселях - - PROCEDURE TextWidth(Font: TFont; - str, length, params: INTEGER): INTEGER - получить ширину строки текста - Font указатель на шрифт - str адрес строки текста в кодировке Win-1251 - length количество символов в строке или -1, если строка - завершается нулем - params параметры-флаги см. ниже - рез-т: ширина строки текста в пикселях - - PROCEDURE TextOut(Font: TFont; - canvas, x, y, str, length, color, params: INTEGER) - вывести текст в буфер - для вывода буфера в окно, использовать ф.65 или - ф.7 (если буфер 24-битный) - Font указатель на шрифт - canvas адрес графического буфера - структура буфера: - Xsize dd - Ysize dd - picture rb Xsize * Ysize * 4 (32 бита) - или Xsize * Ysize * 3 (24 бита) - x, y координаты текста относительно левого верхнего - угла буфера - str адрес строки текста в кодировке Win-1251 - length количество символов в строке или -1, если строка - завершается нулем - color цвет текста 0x00RRGGBB - params параметры-флаги: - 1 жирный - 2 курсив - 4 подчеркнутый - 8 перечеркнутый - 16 применить сглаживание - 32 вывод в 32-битный буфер - возможно использование флагов в любых сочетаниях ------------------------------------------------------------------------------- -MODULE RasterWorks - обертка библиотеки Rasterworks.obj ------------------------------------------------------------------------------- -MODULE libimg - обертка библиотеки libimg.obj ------------------------------------------------------------------------------- \ No newline at end of file diff --git a/programs/develop/oberon07/doc/Oberon07.Report_2016_05_03.pdf b/programs/develop/oberon07/doc/Oberon07.Report_2016_05_03.pdf deleted file mode 100644 index 2bcb834137ac7b95c4031fc5239d6dc67dd09140..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70214 zcmce-1z23mmMDz7yVJNsOe9*Dfk$i5E<)%pAy6>l)3#7f3M@<{Cgb_@896Dv$FI2M|kY)oPY1f$@4cp*m>CgMl(AP z??1qEb~LuK0XZTgJZVSmNgDueE*51+kn6MD*|}I$?d_cb&wK+^S!C?Y?EzfCUu6kB z0TYlJ8wUrkxj7rB35d(wm;+?YVGJ||nVE8%@v?H53kd*$CO{J&Gj3iG4+zB0VayBS z0vVf`v$L_W^0I<>&4mn}6pP^GZ0zX#OMyUS1S%>?r5DHu|D@(8%|5B)4;zvP*;zPS z0@$7iePLze402?7VPotJk^q_7n}ME8h@FF%MGe5l%OND>ZfCh9IdCWu4kv)pUO6i+TmW)ujTzh4XjjksNHQQWpVt4)X+*~AZcNo zR0+nJjUfTz@Ma}oF=+A!mSCr%d0CZ+A*yUJ2*4tDXAx}wYxzNdfuG1RA=)Jo8Xg;P z5jtfEasnDk2&p-O;WH6QKd+715?LHD78DEv*)_22F~V#ETcx8YBF}01@_GZJia4Yc z90Cap-pAlGGQyKb{UM+~eCwy4e>tkMu?5Hp!1-iQPl{LfZ~(E08#^1@*junXx5yit zfNY+cIes=PfSirZo>~FVHVIJu?WBbK7)FK=lIkBc=m-S zRI2vQPr3vESrkBKR>orX?t0Jm#>L78;O1pBU=eq;clcYSD#*#+#nJSMUap_O|ABz# z=U)W8cp~7*#MRZ=09=1?rOp9(_S9zv)w!PR{f{CKfa?!Fo*cp6R1M^;$MQ6zv8aRG zoefwd-JPY>o@smnCZ)y-;QlECp{LKEGt^J;zmWbE+%sktNxLWOw6e2c(Xz4=wR5ui z>sid$3G}mvx|J=+NfG3xYHw?7r>v%+{$$;bPR`<%#*P4XHWqo~Kgt|jENU($&d(}Q zcXR>$g+c=4Wa?<;;B4>sG>QIXMa#;}+0sdmjq~~OKl?tlK0D!`7Vs>O|32-aj#kDt z|0%_+oWOri@^g$(eUi>ElDT=F{F~<~P;de`e;VPF4Ls@UY1RO+Kh4ZPFCJb1ClAN3 zeouAJ{hzPr{{J`EU;Uq8Ji~duo`v*`=lSA(nmM1ZpU+?g{+oF@KEb<#;l+Kj3mb!TJT``IqCTtpR^i4E$YwZvT@Lwr9*w7w1#^^Zgm` zpKX8MpQZA%{m*eveV=K2uKV+1XMd8|(;WVM|C8fCO@s9*2>ukofA#x>>>usrSr-38 zdtnl@w=w(AjfRc&-y6-ZxbzQ3^Pf}xOXPow>fhb}8O~1yKMC^B`=2K9-0K(I=P8Qy zr&69o{x418m&rUE!mrXlV|b?L8Nxr_pVj$X_uF88VdHr+{6Fjeyg$YCpJV?V^9=nD z9{*8W&-2>DEtN|0&n!=l@)9zs5du`CAKr z!u#!t&pP{8`g$JsUpw!gu>Pdx7nc8y!~Sx+|Bk!^UwnaXy7HCUzh{iHpUiCPZ<-7nls2&6Trjv6y_bI zK~@%)Pgx%)7mM~EWgv^Flj(Dq=HX>!c}DzPW@2OIV)WR4a1ADR1W3jJpepB4=N>nw8rlm32Z>;JX>I9a)W>5mo2!v^5x z<@pLR@DuVfjTY= zk`1bq4wryoCHd-;4(ONR)Tf)Yf5WkUEdCD9d0}Qr^j^U&xLOGB^lTK#tA56si$4M) z#qXN&y^K5h2l@3bq@H(IkH(q%6DyQ#r`ART!;mSmehS7}AX418O@J@Kb)sciNoZMH&zS|LGdafCG;ZcDZh9b9UpLS%U$v*Mu&cqHc>|? zt;etRjnPFedM)-m>_9>NHhKOxNZr|4=jyPZJs-)jecr9{nD;|z&I=6W3 zv;%tlxf?q0@nC$4wJS-#HsY0rddKIqgXUBWnbebU;lU_n><16l7j-XGaJ?zH;y-?$Ldng2O5oZfD}OrAF0b zv_EmVISJm=yIeAEK(#-L;^mT$`muD)Q2$f`JWTU->`0CVTQ~|r6)<5vX?AoUm(Ar) zD#*)uqFt0DZvBH-k=qVT1f76j^DXpOR~Hot+*ltQ95gx{G`Z7UIznN8HP7)ZdiO%Y z4!CQ*(8@!l3gC$m(oS#0aS9qXrsD)&Li%+Y9+2GYYpVM??7R3*V!^haG+Ipy+N6=z%9}x)<8G1uQ$Npdv{)B7}Z#mUWVG7!==sd2tF~>Gd20*5l(bQ z3mAqd4G96dev-8u0ft-1honAQ5mCW;<}4F^QQiZ|Cnm$@-|T}qp>MupSLLvJcLr1E z+2Qcw28X9NfoV2mc?o35YfZDf!&u0Te$B0xFXH#(&>pQ{`_T)Q0opU%CD4%dB@qNi z3b=*RWX4VUjuB6`T=5&cUYBWYEmIoaeo#99fXw#W!|S5_bYgVE6dF8V2)1u8`8HPj zty+AUmiLB_70(Muk?jOoA8t~lkak~2a7c$kK49Q=Aih^eF)hkrbh_v8_c?cR7qVs; zR$CFsCV)@yeHgD_XV~*Q^_M)dQr3G5ZkYj>4E1_znwXgG)x6VW+yaF$02I=4~2>L$n8YT*pb=NKhF2i=ImpAf98EqIzRu_&RWEyQ(%cBXq%3uyYPG zHQ|jv_DRSgN)7Y?h~6{Ozz4?%=*gEAsyx6USX+w!C{m*Gwfb8y0iJ}1kJfj4s7UEl z#v zQ=YRdb0w3qF!~HiyXy>TV8XOZy8fyI}$L2)7(N zC1iD@V1gaok6~|PJ*`{$GRt~%Q&kaeLuN{MuaM@>1-{_q$(=G#@4eJD;Li%HHia{Y zN5K|U@Nwd98zBJCGh5$h2*|r2R%2j1!s(n$Zn*$Qr+Ba7Km`-2iN&jHwTvR#jF}I^ zfnp*>iu8__Q!qp7P;8FygwMZ&LVE(;ihavOp_`pu9)g^n{fkn2?Rn2jTXG!h2Qa;0 zblzw~^x14wjCca-mLs4f&cvS2N-u>R0q9ee922h0*n9q`um z2vZC^EhAg}YWwU`Aq1y8nf~+YXuK#HbiRApv0%}d-7guMWT_VC$_!k37R3#83r~4@ z_CxGg6Z!`ICr3!;#YucHiJAEWQcLjC_WWGdK6CoZO7%1**(eP)y5jH!Rub(K6SBv# z!P8GwK$V^xkvr_t7%~FaGV#VKj#2j*>R_%Q3RrI1z6vsm zrQ})4HtqT)mD0N`2#G*}M+#p35dTIN5pC6qcF;~p-!2{^@TNse+LGz_9TdwH~rmo-@p%m_d zzJ#6$G@J+Da47RZYqAH>Z{uSLj(4toS-3!k$JZ(hHB0TCV*?rVz@K$vzbQ7*#;$ZF z>ybwgj@^7LcI=Gk3-^7vLzqIurt)dW3{QdSK!X+K7)_i5(1qz)1l_3L00WY!na>wL zk;y7L*%egLQItBd0FoYOuraP%sVAM}dr0icdpdU-V23-e>ns%`Y4hHnRTA$X0jVH! z@d$Vo5D~YK7+BvH@$~S#No}NxYTlT{9~2nL4ZH~e0d?IH{Y{kK>DlDI){f)RRo=J{ zbEhg)9HDdGT4X!1pooGr}gE1o9=NPb%lj_MV9^9I<)Mahr}&2&TTa z;PQz(_bC}zHWc=^-8H;r|TFwUX5bkv=5p)&{lyy z`{MZ;0*v|d_UYSLnk^O7#yoFu+41>Z_gJa}6rMD`9@t~OF{ZM@#c`+yV7+_OR*30` zhQ?$R;>Z-4v?UwpCiOWB^h;7Y#M-XxHA5 zr{Ef2zqmj`kaGVZ>~#k}MCojri1h&=6y4iM-}~u~cuM@9tD~25;~2%(cv}|!3j~tJ zyBrUALaluyGCC$rN)ZYZ%m=f^stzXUgDCJyHiog8RQTaUM56bqA7}8g^=P=j4BQ~4 z=6cS8f^ucICKAY4|F%xn}yJWmvBa!LCDbece zMy^*)rFa@nL#&zNZ2hnpCr1FinG8WpFn0OX$pA5 z-Z>L-8xmpBx!V@0H54^3g4TSjb#0jkRhe9S>X9fc!nLBDoKP zjwZn3aPO$7tV|Vq^7>UNN9Ncg0yutYmrw*P1k%ie1~HytF(_qAmP376JrZAI16I$M zeRNS>vsJKz7bWa-JKnwT<)xG&Fj;=u;Iu+)(9&}%2#e;uF;rnAQ=tNKceUIcwH{lFY7hpX3L zgxi7}7ub)EyiRPjg>O6yV3sV1P#PzuR)z?srbsRHS0e5b`B109yJT;*lKunG>lUO0 ze!l#2EZRhO6oJxl9fjnRS!_XMN(*7$OJt5Y%}aQ%9kfrC?ScS{duuek)<` zLqh@&f$X%iM{RSji8C7q*^l1pj=eVVhpw78G!0W21HL(J0P280eHxF-m^aafIZwx& zUi{kgS=}svbrIq{V&Dkuj5lq?qXPW`7~DTIHq$?$t=|JR-XCGdC~X3vmx+%G5puo z6({$0RYUl@j;?JFF53pS-3Aa|1=2EWI^7kAeP$T;t99WhmfD_0Pf2mj$ zFQ#hw-S%kd=#s;rFE)64{aUZ_LU}Hyl3w<(=sU3Rgc{6+z&boWB-=6>JPbfRd8}p*8*OyA}HjJb) z!V}b=d)M4IeB?_ZmuZne>#yqbfN-Z0+P>@IUXRT0sfKU&3DEo!|2H}t z@FfYPja$6EE|uNKuu2I)pz|vhpV%Ge(PTsJ^Px9qvR^9vIu$jq*S`+E4ZSdn@@u7( z|AajQ#;3^DKIo6k!)GZ~r(!5Fmm?CDk)NR62%~Rp`JE-Q?+^pZG~RZLZ{2FmWJIsxFm+3;Dbo%SKPKKoV=1I+VXU&*I#R#C9KN*%@kWGBvw~wz>U2Yt zYF^UtTOMVN<#p?aSlI;uD3mfn{}^e0&2ezmT0|h8TCV}e46A9JM}ve5W1xz4m|?GX zjCm3K*Opz{^fG-i)W#f~B?6sreYr)5)6agb7b&J=o?pTVA;!4M&xO9OH zJ*%i=o8DukJ>Z8kc(3M_dr{oPyKO@F5Xt>GJeI1{*S%5h$M>u4o;&YG`wS?K*p>n; zN@SN+r<;Tw5IRwb?YnJ>OxZp6WpF)D*AaH`^&BMH0`fl&2xxNT|3?>&^{>4Fa(=`TO zk(^r6o&g@vTe3YqIW;XQRwc?$+)j{p_b9Ev`TDJzSA(~2qX~mr6O0?jkSAEX04@Fm zVXaDiULRV+=W25bak1m$IkS^qyfK0x>@H6_7;eqDRB=$FYuDqutu z_WoOaR{AWA)yxvJNG|Cy8YD+8kIa$P`|*^3_tA{u#rlcF9B|t$7&!w`+w9I-S-Lf^XJ`spJynCw!?Are$7;v#5vncGMk7f;4JM;Z86JK$EQsO+$uJni)ZBqDy~lY$1hFx-{wXH6SawsC(_2@Bf=@y0Bu$PNP&Iy zLQ`!CGwpy0-EyWj<5Z9s#w}~@V>{SsA}hiDSC4RU$lYX;&lZEE$rGw%8751$W*JGdeVGmY*JxaO66{#O(lwai+WX4?m}xnrH;Lqxw+}gpnG)C{W_=vMVNRMwm^Aq z$%U-zLIU;6fT2N+6Y0S*rv5>yHL*<(mOocdmi}24Fh#DB!~}Y5P2R07#de*X#cFzc z9fy^iyDb}s)fdR3r;=zpOC$Vn*+7F{D8IaKSf>Cc$LKv8ZauR54kY`2D3#`OuRJI_ zkAUAwucsI0tZ_4Krn7n4b^u@r?VR(u_X4A)sgVf5T%CG6D?@Nw!YX~4S+#1muJ%6X z5KYf%%e2&aiW0q{0Ums4*F~tA7k&!=dO67M^CowPZ6D(XSh?-1mua5PCjNG{*=A{l zTUCYpjk;W=ZCbK#A-pyzx(E{#Z6|(!m1U93XkTB4@}w)Gu7K+l!BWE4_H2AGQp#s< zy#yo83Amm<+`8Trs`G#qiUgyiAcoGqvnS|I{eHi9-E#_0rbsZ}64)n$5tBK$sYm2k zDMv$E;cy)iBWNsWyes4-Rri8U^5Hsxs*hDaU125S_~QTza^7PN;y(B7i5ibu%1`e;MgIEZfsukoR5MkeKB==KxAAPt@CL;bJCaRKpy9_Ub zPsJ8iv6NE@nxe<5n=Fps-4h*?1m|XK(qg#0$O%xJR0)rNZR*q6PRm5|4eCJYKB`fDN(@ zJZkHdj<2)v8}W13N&)L`rY7lP+olBhWN=OVLfPlzGB{lavr_}rl}XC_0)uDVQ*Wvz z3Bu#m=WT9QQw45TJGv>SBTDEcC7Z@j=icB4Bw$ams)k0n>`%m!qE}r|y2ev;;ZFf8 zZypTaVvW(+Y4#qRt{pBHFXLoZ1zv&Frj6#70hK#g`99&NulznZsxO4XQ)RM$TZqJ;}=-yl)M~Bn8OiGuI4$H>y6cN(tB3le8qY*%tZ4eOOV+HzRdg|nh z&4x-xV~_hv;_-SDNzg}SaGZHz1U@h;#=yHHh*fR$>I&^&N@{#8yW4NAs$819gy{UF zIafK2)w3M6TbdYs;m?LzCAW32^KE`xlxtg$@AHzI;KTCX?A={mWn0;!Q{81}{r6Vu{b<*H%J=iL&8-s#1;v>c7Mj5Z z=jh)ZYtvAyy%{gOG}5G0dNi3~*l{yA0(Clj!!iux@c3bO_GVNpC@BC_x^*EdS$saZ zTn4#^k`i^hm$6%KvN0`;1>Td7{0_3KjQ7`Eq~)$ zGxw@Tdf!4+n04Xrd^OpX^Weau&&Z+U8cHL!yfx3>eZ3ooJDo_&T#WAs+73&ER*^{g=ZPhIvcpu z$9^s>4%*J2k|j?Yx~V&+&1(q#xLHwY`o4?%ebH>pfrfmcWcRkDApS$(u2D(z^nMXJ zti+6NU8Oe@y^m5+M}hSEaTNY44aNSFwt*;qf;Mv17b1@KZT{B@qhk$gn~c2jxD<&W zNrr}0aFKh)V20x!NI=L*IrG~r*4N|by0(Oi*+x6H*4Bb%OdX}9tt0a~Ie1&NaD%8y zRU`GD-}?v@UkZ2>lEeZHIzU0{d1%(&JB#CEEoE|f*d#FLrajdMF!8cV>f}FYKV{a6 zN*^tl57n=5V$*vbA*6{UHM5#gI4hiR8UXL?bO=J-((9Nzks0m2)Xn>LkG5UAF}kSV z5!z#}RI_z$Wf^+A&&Olj;SA~FBdIwwVA8I71y3zMCONjffbL|y>BT4DCJQHRX~pTN zOB*b0{UTBu1xd+`k-L!oZPgt54*HFqu;8%{9MI`s3$aHs|6P;nO%#b23!7NkX4M8@;iIkiC$mrd(fYf&w zkVgAT7C_+l3c#w@A>gik@K~(9Bxn&v13N41Y+XSKc0ad<`x=OL&F! ziD5{7!3sbkmKL|>_llvK3j(+#rSY1{@4cL z&gnO#MId2%hl0ssPn2miKbFH$Fc;^|-q9i|c%C%6Vgj+Q(M7}pg-buyErd}D@%DI# z@F#be3fK;U&zVP*9H^Z1ZSQBgJJKLNQc>`S=D+94Q=EkLU(%$$%W>FtbE{anCl|dPpLH)>0lZnQ<|?HB$HU~SwWjV)qe#q zvm#)rh@uu`#!G;Z0(L!@JRkVo-+D0Jhc@?4Fyu#{(2Dw%NLqU_tw$dk=@-p)kuL&z zlMbo+P~b%_-xbV7u7#YJ(Ow}z9HRDs$tDC??a{b&aTS{GT$d!X7uXpmd&Dm~#}Sea zZslg3#PqLI$ekIPLqT0}_mM`mJ$|S`t7x#w3@Vb!Pagm+;br+`fte)`g3L|S;)WR#7J2RHD@KwT+Wo)Acy?lIt-)GMJc{FT`pV9c z)Nq@mLZQdzDyB8&p4uwT@V|(HH;;Ky7CWp&E+E|zG%0hfhsU4ITX}%rClLso7Dd(C z=8)6L zTFH?Bp=8{ZZFnFg)r?dmFJSfW z@ok(V+)|fI%yK|eBvrat&g(4^h`bmHs=UevRl!qFyPJqlb<)zvXgJ-cdD+K(iiyY( z#G5>?X1?_5$wOw8cTW{|1j}_$grHVRlkHi&01Q*CkcYSWfE$O{1m-}!ugMT`7kvpY z!|IK|Gk*9{k&aw8bxtJ=e8f2`LHEWjSW$}U!`Zi}kf2TEZc`4%RkK%&Rsv}aQ~Ax@ z(@cmJh#V(kZRm% z)_Ukk6{g%0sOQ39uUcsH8ui`FjjxD-qKk#F(vI({AZ0HY^I)!6w0NU#Tdam&h3*R5 znm;61&`JEb%lPimQ>wA+RaFtk)Rt()@u z@Mc~?fJcG=G>&V{ZO!{7b(R_3D%V1>m63H1)fc(0UA-i%^;>R)+vjModo39NEDqf& z8NE(ZeWNXd`V|vT{}(#Na_l*I)%0e8_BmYFoDsuFLoT!2rTFjIzjNkFMBEKQ&{#x zX-T6Z4S*(b{17H6Hc5c1iDT;toF=Iy)A!^EW3pm`VO5Cte!DV!D8}H35kTx}zC8M- zTxdurmAx6$6ns162IpO$?iDp!pR-K%1a5VK2L-I`MK@OSM><22D2%a)VQv0db~_3y zVZ1tZYnl7^S1*{h5^)Nql1Wa_91D)#9)MTXEvRCJ)O1tU38%dcUM~_q+J<|1a^fH% zI;XPGKdKQ-F(rOM$KhKkm;+lVwEv>D`lk3x+2ZkQC8wknjAg6)H5nS2w|jK%uw`(B zE2s<)Jf~|}zEG_gZ7Q>A_Li1X)iQv>N{5tMc7jpm!)sV{D9%ToQyk{#crBErOI}$F zqE+&!IJV1)LbX$}S-o{D!mM3GLFD9chEIu*#EAJ+zL7DQ>}@E6F^69QHFJ2&G8D;e zB4OYQ#_%H~5vaZ2$K9zo(VIriPj-AE-)a_zSB?qfLHNY zR#wN>;ku*C?8w(ky<6vnyQaNRnW!uI&N{JXhS{OpJGByp)X~nMasFc(yQPY@dxQ@> zW2DTRv1*&g98K$oyst*i&>ZH)=~Z$iOXe;u;qgq`fb+rTIhbwh7T~*V61P3K|$ehBzgAx5HYf*W4LX z?^ec$wiJJa_o*a!TIJ=>x>89ue~HE_4e|%^z?DL-oRy+_hjq3iy1XwMzasy>5l~}{ zWzC{^FVRz(WZoN7gwA#C-OlP>8H$OpIod#9T;@Pg@LH-jJR{9hbmdE1BL8IXSaW|$ zM7iBk|J3NFZbPN0&8T3T+cEvs!8!M!_#3|AxD3MF9-fHqR<3g^w0!Qj#ot{{6%7=r zlin4#7cNBa?+Yi{?aMEdY9oK8?;}w?gt_Tm8-0rgf&r(SwzGg^dtL0=@uA|IuF_O~ z3>9t%^eCceyay4%aG$&Eo3p{%?LO{Ve*+m>i{2t@g@sMl7%$TL=|$qeLT#-XY|y7E zxZ17Me9C4u$8MXvD`x# zKU!7+XYS6Hq)cr%DhmWJ$n1w2_7_$514pY%VjHXJ<}-8^>f<&^|oq`ylel@&pN@I@zQpziCG7)`MZBc85(8RZc7jYVgH-6=o z>2l0l{Ze=9D;nR|!a-c1qIyj2Z)c zm{>HN{QB2$uz=3ibKpK3d7t`hDO`1RG(Hkiw1g=~qKx0Cv8)Jes5q!67QF2_w%tk+ z$6PlL<;!MqyigVzI8IDGwO~%e6Br{*Bh<3JEnk!1-Sy=AZik8qGr&Jr8*CfR#)|PR zjTV!F)XrWwn#I2GP1P4=mJX9yn&!TSrIKeZSM|5kgi{!&M@_r#Yo~jUAo3gR`+2SH-=E3-@9UcCn+1v9s(yyDa7wZ z8o81kczqPec(pkwh#4+(7xCohBGR`OCvv4yOu3&eK_%N4o?T#pZTP~U5H4DvGUw`o z78pZ=@dNIVy3J=7YCeBn1rJZp9Q5d*mQteCILa88v?mTO&E0kHCO(BW?*mO`U67H4 zFk+-)@gHT)x5*NV5@jGc#On+tVN=`33#)OOiR5~vmPQ<+Od)fwvuMZ#Dp|^+^Y9O& z?s4TcF}`~lq`BatL6eN%3xEUhkw{{%OCT1HfRO}xGoBhemc~TLE zni8?gUun%miIk{|)hi^cT`jej@pii+_-jLoXa(7yViMA)$vYz-#Wc(5C9&x#wQa3wM->>TrR6ZySX0-1j2fe{Fzm0@A_6kLI%qz2I z)}MCWAWiGltYrFDe3km>Z9HmJEXiu5Lp>_#&+aLiz;RGtE8SQg8L5TfuyNMhGJ!jI zCg757*E+H2vn~RiFE|MEVrn;%Aj_(5I0CIuVPU#fK)f46e9NyyM@^u?IgpMDIZgb7 z;gn$A{&5fS9wHQQgk*JVn#QxuwIgz%pMmSWwd?2}yk?>3Ep< z1%C_+8;a|N@O*7>e)mJ9oz`iI3%C8Y&|_?Q$NeYZwYOO0=xib`hxKh3MwKrBqJ}3Q z#PTJG2@R%xZD`YWh{nS406$x^0&()e=%g;{G)A zwXty*B~9;1f07ZB824^u4u|&PbMVLo;|v$D;qL?^@8~H@^lq^8M$SEI}n{AoU z`wBuzzfDJffZ2Pwe7wGA)f``vU%`4;t?GkYANSqUoPW@@c`GP_R*fjoFd-m?r_sq1 z%Vytu`J_LyG}GfKX$UlN`1Sn?U>==R@WH~6=;HucIo`^0AOT-OU?G=z+)bF^CWgIf zPeDsBx=uD_nu%hP-s_N1s?svEj-zxrELeO)ASxm*vmy`A>Ai#n`IT>FIQb8lHar zF04FMI?)`h=8({1N!wBa_UzUNEl&i%6BkK!XC)u<0c z@7WO3S$d50N*uR)v^aZnUfY!!VGx!NfFFpXk$oq|4@z~%KE1CU(b^L8F6BF(MkhH$ zURbV+Wt&-uB8M&uw;t`3IW5<|mWLqN6X9qP7S?&V`zRljk1US~zAwMQ^YRMQH-0~N zbR`2dQETiY3(=q*>TJRYG&}+NHr@dkn-$;V#Uhnd(}hsG7JgluDU>f&u9CCb!ieBk z`F1RM4CftsZ=3y~+pjwMh5oJ^C6HJ8SIKVc)0ShDDm<%!4m+cn5EpnSf(%#};b}Zy z*f`ly;>CPQzy#V0E70bHNdegep2XiOUH8KDSn3#(47KfVpvz{;Z11EENz`F|#Ay$j zZ>Y6RnMXJ4$RT}?Wxp?+M&#qC>}FXMjJVdtopRM+w!TX)tGjQ$Zw8Jv~4C0SVT(Ko$J2 z@@m%SV`;y37XC`CpH4|XpRfD>=S8ZglZa2if2Ycot_TJJRG$_kaj2rP{2VzP3;A9oEl6u%#&z2WsKhNiOZ>XqbM{|VoUw-a>E6a z46P!zV5_8j1jA{vUwLyk#quNJQ10F7>{gG`5U7(<&yLxw)8rbKlnZyJicvw*?(6q8 za&x2AAC7_VGMRb8-~R|KN3;!`wz(NFQc0<(GfAW1nnac|s z-}qW^sd&ik6UN7v&*F4~H{i{gu+T0%{ZZxtD3^J{trGO+{^34Zzk zw79DM9Am(l9*(a(LC&fb?ra@G+%{j|BjJo(*TcCnk&qlz^}&$|A`TcsJ|-TCq*`Lq zCSO3Sk&o79Y)VAaUT3^xOv^qj1BwmJg4}0u2{Dj*(wbAF(5a8ST>EA<5>8P%(Rf+3 z#9P|J@ys#&p=})czcva-4kDz;ZD<@0- zJye{j8q^{B2pa-7lyL%qXzF3aH!d=vxUNgt5E40R@EQx7Mrb4nk_1AeLHom4D&ovK z!Z|0q9dXCw1jNi;pQDCtv4+a*ozB)F)UcY5a+KJbB0DET3elBfO*wwHJ92^a%_m?{ zNOlJ5v3M*>LGZUMn(Sd3n#@GlYnnrPNY%_@V>yjEbx=#tqf9oSV1Y2(i68nE*IX+d zNe+@`hyDf4xyXtAQ#{Hm;50)UTc*Zl zHcC!`B@8Yo#61B9sBc8kF_?C~?Yc%NVQrjC2u*)3IEGohL@t5Re6-j4!Y&Pw*xlP~ z%$+h43hh>HTwixa$mdyjvu%UE@z=409|_*Qt!=*F z`aV;NMjCotNPTpYr1iniCF7fq>nYAm{XOPq=JMqRYrwHCAQ2?qTL?SqDZBe7Q zWnnPF?HyWAGt^N_%fpF%K8EW9``vXtYW+JQ%rl8kqN!%vr8Eq!?GUjmy~Mm#_hz9o z$={WIDxiYsV&Qn;EyJRy!LPqa*1sFGV-dc;4I+XNiO?#MnRYHVl1)G_ddY1YcnOI> z3f^OdvSmRdwuhLooAM?3X;Y*P+dyM+R+$@E21V~YcNmL915O?f?IO^pk3l6cRjt^T zV!VxJAa!gVv8J_9Iv~M7@u7pF%L%i;b#?*%iiCJ?3w-mg(cSfS{ar?qO zpw-KPAw81cw`wmd(;gsp+%1tVgD=0iL#CTm4npPcgp837fJs_PlJ1XE^>MFFbn*$3 z=x!)ru(4Vhff%cVnsg$XUPpI2Iw1FOYb6I-YlBvFW7AQB=rLp0-}I!K?yX z(5>L*Eim8%kYnWmjLneC%W-rrZswlA*o-3G-WesGt8XZm5WzeWycwL^HXeT4>Snwr zYs2A6LA7pXh}WK)_SsuRAItY97-jnvVa{G0_o7V3eto)qpEKjxu*Jz8*GR0bsT&sgj>K6E2b43=eR#4fXCR@M#y3ftexW;ZW3LSQ;#JA zsu2YXFISEyJ&7o3O5K6W0eJ+MD39U5ZXLU9gDO=+Z0ai zKr&JbYCUKr5U_N3@Z=%r7)%c2-;+JDj}=HivxkaVO%TevnezGk^_O(1b!$sK?!402 z_?>lNis{NK7vw;`qGNVR_R)xqd(C_yH|co9z!1&Fr|fcYd!}@%KIfn!KW5BR+2zk^ zXT@UNsf+O2Q+|`KYtJrhi;~P zf$F2Xr*f%+5Y7y(U^bjX`euUFTS}1?kuDMY>wF(RdX$PL>Kfjjp}?qVd{)-M0%WUF zu$nKmQ*wZiGUs+`QJpuT9*4TOEn!$S77fcTR85^s?2qOAkJ491u|c3fN5FWmq=YW(e#4`F-dAr1o4N91_Jv@&2K$)T3{KHB1q z_r)|L)PbA>={-h?aGWGvQ8UA6$dn=9{YJaAdX&r7Fb|OyMC$Th3GCKmlwU#$ZL(lH z*rABiWTZhQw))(>kU|uBzwDWNYKM=PQ?Wr#!@m0+rOP~j6weFaUFA+Q(6``rk_TO6 zvcTSH!$viJWbzEcjz*l}$h-=e&sd*Gs+9rf3&})`I6{lI|GxOf;e5WVBe}iIQ~?;g ziNPLSI4)4_|JeV9ZNPfG!q0rB7yU=7HxEY7NRuPvV`X*;gMa{FQFxSipIs0*^6jn!#I6_0C89N!0CPv{yUk}V}_Jse$A@Qsl8+`_Q>szrfQO>YYGMa#?!(k~lzSm6RLm7#KE>E^@vT2p`@(jyaDZx!$3u#!G z^Cx)n>)Jv$O0(+j&Aw1y+cKdap8GM1*?hU89YP#;6PX#=mBA)sBK-ynCVh=ryGM3H zP-3P7Z&7w<#m~0CWw6`RIY+U1>Lx;-ES(8iDJ_JxAG~hqsU8o6L4XRFuA#wWfyt9$ zePQ=jWm}Pz*JgWR7>?WaTdFJjM2SwNBZCW&2 z*F_;Q!ldv;0FZbwi4 z=Pm5Ryv>!Xw3G`-dG$#|*6t>De*QB-{Qz=j-t}vd#EkZ4Cll!eSHXmeH5Zi4#JhSj|_(;r_eEmSWm8N?w`RFh?7?J49&^vB$ zmy!wEd&*6w(A!pXk8A&8+(GsdJxWZhUeti-<$;}pPs%r$8Bsyrv|vM@HBa(NctBpc zpX~CT7AU5mC5JXkt0A-_txTpuxnSw86AM={sjNrq%$c~%(Jc~?EvT@_mW(lLw`t|f z>MX`eiaulEQ9stywrAk22jqSYE@-uA(tdFsGYOKerX(YArC};ifxSO`4BiET-l{b@ zg4rlS`NGsPGbR{|LWbRhW24guGsDGFd`kAW;c}7F7NIY--oS2hOw7Ay&dz#>rKCll zG#pqxg{XPGL`hN*&KTUg#V5IttakE$XnUt1OZX*UyUVt1ciFaW+qPZRW!tuG+qSJP z+f`rh_d93aJ#lu#j+vObTr1Yi|6)aC{_@EuNk9rB3_LF6%&*$|8H6atHWQ+Z)+$Gwn+B;~|6Osoo1nH&r$pANp{lM6w%c6Sj=>hk6& z@X1~E(l!QUfKUS06H2y%FoIAV)33a{Tz~3UN>0Lcvc*UNJ>iv`ElStR)urbi9K=kX zQSbwsI#BrJw=GLlycgmC$dv-p zjfbsdPy-EMDz(!(ForjCQ5<9GAtp$h&m8lf2yitbf+c`Tyb)zL$rf-WBGDBmCImt96C0^&{3f&6|Fy z?e)lj?0`HBaqMN@EWitrk6dA^LS$=UvNs0o6mBxf3c}WA@CJW_%K$h-j=~?d zy(^75bDLY8eRf_?Xq4gf4F56@_yiy0P=q;5BLYn`OkU4-*D%DJrDR}VEZF5 z`acQ7e^0wc|2N+Gf97sXbd2=>CK@PIwT#&qM)|zbrC*gbB9LZ->(+W0SY9iH4QO43 zBoEid$`!Im@fV^bHohjj^u6|mrU*~m#|+vdVJ5!b9BDhre!Uv;CBI$lem(y^Nn~3^HpdlGQPK;33#1J)T@l6UZd*j>G$E&;T*01{s*)l;FCr+-i(}99CK@1L3 zy*|farMCs@550-&gr-4MC84Mfgt5<~^9%21RlGd*AYr&syhT)T@(n*c`h&kslYlI4 z=S3C#7ehc+GUZa(;`Zg|=VgyxAm2;e^B$PJuj_lm4R5uNKunSnOO!0=KwqxJ+AbPh z=&->m*F}`@ejr@ijnB=V_IXwsqfvC_P$2WcCXnQCX==B+MJNh(XOHJ|UrgcMRbTOK zcgU2{McCB6CU21P?UilIvv2or`*2S)F->eZO=1dAnn6$(AX>{tboY^RPb#mLvv*w; zSKjTdhP9=fQC)JTRfc);1UAinQ%%<%FJJ1>UpS!yt2d&x6Xg_;K6v3c+9HaD0JzDs zzf6$(%u5SX#O$9P%)*x&J!T2L+XM*qo@L)WCWK^H6P`PRLW!-9M$#&6HyikP(ZI?RydOKca z5?%_MS%b|C?J@+gnY*X%ntD`!(uwjD?lym#QaiVMWVal*>Jm&5*ygx38;HeG!sP{g zembwueLJe*IRK?Ln$%)w@zZd`I@=3{e-CN@4dQw-Bk!WVZDpku-a6ArwCa9v^{XzWr z0q$&t7Ny3SU??~xY$-x=getv=j=sRuh)ZFr0z{&Mtl4ZfDZqP{7|9SAlh%=U5c0ga z?F4MIpG{RU017k=MtzcR@>avHkRW123d|0U2f2XE1|WgW98V`8l-jEH+HJ-n=J15e zVmxydz?9uYzbI4)z%G_0HfS=LgWHXSx|qNFQm^O@@$J)jfKR-6#Mt3Tn^^~_8pNMc zV^b4DyF4?ErbM?_*Xc5sKW`3EFOGl~;>38ZgXuEeEcG2uN2k%xjqX9o-e2)pX7b5B zU9gNWRgUb6k$VS=m4(>Dn`-v(54|GAlG)6tmBeRi{#`&+J@o=2e>{u&V=f;-y3Tl) zMS4s&hi$<>QYleOZ?CsC->?Dy(khjvO$&-2Sd7Y&@}OD`+zwvMaDYp?3)Jx`vQciN^?A~OAy zrbV>tjDp(l_-ug0{0>oH0Jca`!!WJ%BlG3cRU2bb0KxI*M;ldNec25IRV)0@Wc@HZ z|84RXC9Pid7_fCe17CbQ`b?-d8rMqs8s8(3c_lh0p|B{ja2%)r?r04mLY6)Ig}&KX zZ*rRu`kBZP*?ol%A1dq*cM&70Ep2`*`W9B{r*^*Y3iBRHA|#wNgg`S#h0_)|S3ELA zNMt1QQVPJnoNhRWMfO_n=S*jK3PICrqEYQuMKV9efK_!I9C(|VXHcLxoP<6m6nyXB zsC-Ak#rMj&-6I>1-dFIx zRH~G<_x5UCz@taK^^?hhYgY?!W1EnMvq^dgyyBMVufm(e2h}Na+U5x{f0Z@n5?n2{ zH%H~96yM{LhbJ;+LQ;qkb%s#)^KcawY={D7r~C-wO#$MgC7P^L%_)BDRXcH14kF^o zQ$H0e+O@v53)sjH)XkolYS?9V?K~p@6r3bB`6)`?ReXIx?h-ydBdYwlm#e6`+c z+0-{;{>^p*6&<185yJmQUBp)7f?Qm^u_K$IrQNtGMU91&4uy?@!CaW&$wF%ULlKbi z^x<hs5M@(697Ei|RJuo*d~4e^n^ zRuHh`=*o)gqBbJI-Y-_8hwsXz6-)&f_WA^kHJza~fSt|6Sqqk<&l`=c{WuNuqrHlug_6sMG7q=hd{W>f84n30A_~9r zPAIaIU^nC|XFyDTk6D3M&QV@2*|;B-`~#P89f$(10vlNvH^DJVSa?*xrj-7aj*#tY z<;Wt}R$32D@QTlVJr7QLb0N!3h|oXNWlO@EiXdE!bpRZL#J#5cWgVG*)k&Mc_>s}N z*_to;(Yaj~Dhhf)Fi*H!nqmApmXaQ)Y;onrn5ZAgQ&hZ_JaY-v(je85i=Od!-P9EW&`l&?G?~Txa9u; zTz+LU>@*yKoD)m>HAnIW(^OE82&cqn=oC+Rh7J5-51EvW`tXbxCagi$K=5VV7b3V* z+L)pQK2t)J%*Kz}H?Riaf%WUxK6+l+=^iGW(>hR6;8#Ploo1vTZ-EMlDV_AZk&n+? z`#U$vBiLw4G<%7~M7piVZ5CRF_VEjOPbeXXz{&if=F~J4B|2+&eF^eB*nPq%hUOk#S*chEs6FERb@24h4;L8Ro88yEnA_Z2MXXqtb$f;cvlc8fanQ@}uCTLU4;% zfL-9xRgouA&0XvQ9HdyjE*)_XU$a+ZoGNAqd19FH!{y%F%%Na4#0*1}b846x;5CX~cK6xa-ONZ%wN(^+*1* zh1CTm2CYm`QZqFqdCkwTZtJBX^U?N}3bUkRJ>r5Ru{HWJl35vys zC-M;84avFyRDilsGJ8L_0-aPxBI_ztItqxW>v9k(cppZNtTGwHCev^rpQ?-qUv(-} zJRv}$rwgzch@PA$Au^KsD}`lFc{S6PR`P4o5e$UfYjN!CU{Pq%rwVZu?#dS)g`|`_ zj0Sg@6&&i!0rnKibSwflC8P2o<4SE-ABDTNXCI+Z*;f>Ya^Uv`T%ipRsm*^!6^G?Y?#zDEtu1Eu&hM58}a0{p@G!; zj^I8Pe=K;YFQWfK7XW5$sW`IYP^5!T^sY<51uq4QocB|?Ljy;Dp-B>Pr8|dgk6ZyL zZgPuv(?<-c5x_lZv6iv6l<*NL=spv1;D;GS0pOH`cBmeT(VV&MtEYZYQ&fdMTW=eZ z1du0jf3Z<^C5t!~?%2-+aD27KGx&`473_21oS61dyieWpjx!t2xDLcWFy$y>x$;K0TJG&Qr zIju53*02A$6+>Re%e%Rkl6gA<8_>pXU)4q=>+=HzFd&XhCtE)D`5`>Vc>KxpTGuf% zXfc8J5R1`NERaj)lAp8TtgG2${fX^&H}kRc^^4`sgaW6Hha0e0UZ(LPjoAE2@u6=$ zsg6nY3JjG_=}a^2&j1Dz6>>9&K>K_trPu7l$bGa{gJ)S9U%Km{dCKjqQPY14SY+$W}gBJ=gda0_}bxS+b(kHDyo z1-n8k0$tj6UB3e30g&FEXwV`CA;?ITb&8-St>9Nxl+#eDdn;i7_CWViAYB}LX3~eZ zv zvSgo(#23jotU_j=3Jqe!@!TZv1Z?29!3-mt4axkCi08Zq@ojE=xR(dSOgSNu>smj7 z6Ur zX9d5=(&WpBY^ni0?0IbL(PXxqB@@foBMSs=EQ>iKa-+w*v50z$?KtlS1wfgtDWFXa6o*B=#Z5O*7QXO(&v z=ut{O`aEN?e3xKiJma8umpS3#M*P<<3}&)cPkGErUvHNWOA&^6NgY40d|!QkIBju{ z|H~BQ?|sX^Q;@%y;Qy@@qs5P3k6gJghQI(MoG*gGgT)Q zSVOoDO%VBy{Ky-Txetv?nsii|FL;y9S;xe>uDUlXbrhJ=h31C{8qo`ALC;(XXIN$& zCq$CH&Mrn0+s6hJ`<(*M>+vPnTdNBhv9P}<=O@`~Y0|AUAL%CB%8-TPv2C}_@6J5O z^*Y@ktnyiY#@&F#LfGD^Q!N_N>Jq|}jZhGSp9)w|Rq>;&=upU8BTpc2$6Z{Zn8TzG z3hblPhDJ~Jq3i?&nr8PNAkQiHuS=vg4KCXE31CAMsb+XU)*phdhqaPl^H>i42n!rh zb4KBZ>|m#>PO?Mxh#wdWpFBa?amew(RIc&4cQMFQwNO0k{=>z=kxzlK2t%|_3?Fhv zu@y7{AONfo3OE!wmAXcZ;RBzZU*?+osuvdn4Wo4C{(_>o!Dml`I8UMX?{e??=bz1+ z6TNC_p|!$w9>aAWGCXwSr+{%cZQyN?{lD@}ZLO3*!(C>~_e!YW6uyga7%~yn>=bgUS{IQ8z zmgI%weExRm?T)d^|Ea`jPFBW7;X}zoHiE6EF*fh#1u-xvm_b{(N>BYv)H*idm843& z88d7axXHEIf2#jbz~$x*T1omIo)HRb*sl~n{nh%*Z+OV}A;PxyE$Mfc@UHMGj?I!j zL*tqDeEz9}NGW|Za7P4Vd88qpz9YdUC~+$5YS=bPl=p!O;W|o;y#8;pLltb|KynB4 z+i~Ey(oCOefG8RE&u1z*37ZPAUjj`w_aax=gQHx%+@MlXc{2$ zmDV8*Q{%rItt~|a2um;uka`NnNG2nO1aOysF*^y_nDN~z3zGuN02$FHVeAv43;>qw z6Qyl7zGCxSwu7q~vH_ZJqNPa}!74&2I<)go`bF4nD?(`%6R=TLUd_*$A^%> zmdt_z>>QgSqXA<`rWr?hvu%HO%R2d0xv&9`B4TAl5^)uPBPHrjJ!h_aMqAIhMPT`vw=f+`u4@i*y*y!%oOB@rrvFs$0;92TQMBI2Rw?ssR&SmJS|-e5Dglb7 zN41uWSjwtMY)N3>I2#dGFtnORXGi&TySf(Owne{o$8Cj#&>dU88s9D`z{>v?e5hx( zNQ4Bj`=Sbom}}#LcOe-iO18yEeG~dal$850*i@LI;bm|FKKL* z&xVQ@J!kUA2sXejXPT8k%!^tQt+lqn8TUE^yU-?K#wKcGUcfPbZE|!#mc(rLS|a!e zb7yV2C@rv2GD2Q*`c>99gN=#5#&Qd&p#WJ*P`3NEi{XH^AOpt@1 zd3ysh=bZT|lA*OQXEGDZXnMlw$aJY%Z*X~u!57^yMHtOa6zaiCJE4LeF1mYbAik@ zBbx;u2U5!d9s zDa#0ELtD`&F49sE8W-eJ@$ zI2)(aek{cASa(AqQZ8^K3lXBUzPRIO=#dLNls%lV$&6}^B2i*&U-$cNvM6D<8Eo+ zPC#Le37#rB3VA4B#p)dkalm`K+5zaQ<1$xeRq8PF7VhuBSaaugmTVb}E2^ajKKxXg zV-EE(6B*xqa?i9sndTOEWfFVVD|9(UR=h{4{?%>8vG^$G9YDqBUCuJpb*yITUAdGx z3;jL@hi=TW>1%ec0nSFbR_}&`lHNGwA;aGHiaDg?#WnTG6YCFis7gTMr~aeWvw47> zlCdaR$4W|Kp4-iye@J%#YE>QgUdYFxzd1A;oj7R4y<>+p)M{z|@SDRVpXgAyPnHe| z2V@*dYyr;!Nrw~;Goy7wF#*7HMKsyVDxL}2Xp@=#J{X# z|6U^dk2;p&ukqObQXR|i51ja)rg?vT{_oPg{{toMUyuFIpf4Q*+rKGkGyjNFutX96 zAx=Tmn@b?!TyV?@vg&ndRHue^CqU?ci^mf&lEe#b#L zsh%h+S5)Tx@+ungcD(a(xjV2z1*bM~CF6kS`Pw6!P)-hG3RlVwU3(iudw$`~Sje#@ zQ*djbZOt4`8#kbTALE8lOnR-$Etxx|M;4Otukk7gtl1}5iko&sc%>xeW+(t!5UU`5 zRE#60oCx$2+VjLC(+f~>PaH8CX|l>*ZplarnJFxtDmR;uCh44M@XgMg+Lf8qdBJdx zBXK&YV7mE)$IID_yAMGH;ZU*1SJ*6?zW1&vfk!3LkZKCg*Lp54de};&5wx~O+K+A7R9;YfeFwAR-6}pk56PcPmYBh1t#ifIZ-s_ z;1)MFK2X8OlE147N}UjFJNQ0jVjM0Jwib_vu2)-o{kwjD$I~;Lazs*JQvbRv6myT{ z&Z&PGgpYg{!lH0s6g9tz$__oNJ8d?t1t}aDqwvV3!vpbBq*0Qnd~1D?gn=mD@rQr~ zM6?MZ&&RZs0b%vD2~u*jZF5Gw!8vG57UUC~ ztgfJkrY*WQSb_S@R<(;oQWE(5)X%dwmWlv^p-+GOMxszr#NbN)eAX>@(RDutnY)!N zw0!dj$g5(9xlm4}4cC}_Ap@2E%E@)5s@2V~;|`(&z80VItOtY@o-0;ZT?BF>BoXLY zlrxW&#{K13LYl_=h_$sDQyo%TGN4(asZ#!`0-~v@ykqon&?&Y#PTLNF5;y=A?H)&t zUer_6Zrqh7W{%$|Iul^Ez~g{U1SX=ZWIl~4Zh>#rH{h=zrnCoNe65-pofJo{d52(g zlih~sH!eE(3T;|dlLE-1twxmKbGo85aK-X!U zj<9=Mgo;89ddKSF$k9a^GPMOm2@>KulY4{Bt<@W|>YxVb!H>L^8=aE31iuSGiBBr> zMUI`F8Slw}E)zD1U>5_)xVXiDo9cxu|-giX%bxm20|`lCxtV%b{1c zT8hk5xKz<4vc;Ak5-+HZsYPIzf`?w56}RuHd+W;5=8&;Fr)~KvWpVtxh$>*jlJ)~K zW98)O;#)dYvpIE&}K?G&Yk#&o3dni1XYzvlkT z1Pk&c_J88|b1H02mEKsWBFNP-xf&azT9h(2))=C4OGH|_KdDu=q>8OM{rGA<5*Ush z#J~tdxuE`0Ifdgvw_evrQ0>j5uHtkzpb+*j{GP$Q7jzpL;$tVhoYXemfE+@w>71jb zvo7BZHT>o0EhJd%3k}gr4l9-oCQx=&Iq<+ws3ecAPy%jDSNrVSp^diw< zpJ)W2PPpTnp9YLbOThLBl=-s*alC{4T#GD(`VqPR zqa{R}`RQKO@)F7xffYCA+Nf*TBQ5$?tkTm%>|u7Aok*#cFud%AIV04I(CLLUC>hj& zS3Yz2dZq%6H z0r_LjEY=y|UY7f?+RG5B~f&{BS09uu)su)h!tqM?PI zd*Mmr5eg=m{FLlAxH>kXduj+@koR1;q?LVi2p^m9c2eOfVk_Uw;Ij!?B8*maEY+~? zV_^(jb09kX;hKvs3;}UWkLChj!L6xUbAJ#n`0Z(ESO(Rl7e6&GJE0B@7q(yDWFM5# z0=~OfHo4*_5eeQmaKoa>%vFMMK@Ns|=_y^Dr{-Z?uAs5YA-0KsrPVv zDe+qE0y@4UuFX|prbFSy>O6v~JZ%j!hv+%cH3%|gAM9w$pJ&eOT3NePg9rocaPZ62M|9EtXj=lZfDZUG`}D(Vedx z?-J9@aoT;^}x%}bXIsRdDDVbxh{QoHvD?Cl*3kXoMCX~ zisv(TdKnugk;c?Hyh2T-&U%Fm!hF{Zp| zEmX7nvRSRLjVi@nfIqL`H?@l5Z$+ez5xvy+=AS2$>+Xh&k>r}tw0O z1*=zDa&>x*7xYqSk2Xi~e#lHuL6Tf^tE!pEM(dmSXdMVxUP(oBx1rpal&~+dp{xOa zZb;NNIQv=KS_^8e={4=M-qv_9w!oq72E*wAb8+>Yb3$D4AV;-flJ(gxlUt`m6%cb~ zj#nS~CLfJ!IoC2m2#k_A)R@(9VPa{B9lE80T3}wU z6hUN^bx`iOYVFau<4Xu0+xs0*!R6YO)J$`{VIPQDUrPTNxM4)D%p3=_LulVjwE=hX z1j7muKIx^p^8Ok9#G%RSAN7oo(~HllxAs|c+9D%~)6!_Ba_sA^+F>z3hrIQULYe?n zMd1?*f4Z6{Sz-9KW6-f2>|(75iSz7HtnRMRS&JQc*E;s%WAEPh<2L`fG2`14M*Vpx zX2M|l_ldYr#L|^9h*tU2+%Sjs9<~Exs~iy6)ft4Gc`O*upEId9Dob zDshCE^5g;s_R;d6gO;2wx{}+Wv;c_va<(x0_WaaoXNZ%|7FhA;ev^boWE~? z#?@ zWW(lY>wW9-5W9yl!+OxboqtGkE zUq8$$&Y9b}{P(4AH}LOr-nZws(@PJWa=t3sm;kxgmw^?^m5QYCeYKM^4cizm=b&$A zal97MY>mpEJ%_Z)2TJ*K-3#%=v!onyjwsU+Ie1Nw?x!l)Zi#)d5&rCo)fI@dTL%w) z3^ER>0->TZog;m*{A9PjXP{>OclYdA0@Llc_0l~b(?!C^bxG#k<;_b}x1Dp;3AvH% zy^QV})H0dQY%!ZJ_W%lTgci&#~^L63HWhlq1tDqbhVHX5$it$pqid@sK&g@Eg&UvT{u~dsjK&^cIJfG?%7nu#1W9q=^SD;btd5k#pMNb)vLt|YT zX(ZEo)sVVq9XWNdNZ$>MUum_fG9$sF1p02q3lxe^-`^x z`wB={w%tUxh4a;)HG_6k>pqDR`OGlauR?rO80^S+@915Lr3!-0z~9(8 zW~e!447|0imG8;5u!Xch0BC%M8HmyGqr>xWD|?$8=skD5)nbO?Wa9I0O_z=HB(_yK^LIK;PD^` zfpM)59;TcFM}sA@X-X9UB&7*wK z%G0L2N8=JUSOn>3s<{I)$Uw+_vB>&#Q?+t!B95TQ826aCp_}S8V}EA*065wti>Cj8 z&5nab5YvjqP23K#tYYBd(v>?!y3SHVIwMAlG`_W9Fdz5SqbgLm-cH~`?&fv;^*T=f zFbPKkU>lO6RJ2`Ti&PR~AKwXF%jt2lB75#w>Qw+39DyE{Z#s0o@^oZX&ybMPlMt5c zQHS!XNAdKw@fra5JaOi${KBWeAU?i!Ct06wQ`4Wex2%jz<@1h!TXCvJGD69z!teKe zdSXbX?#4qO_*lnQ(H$S_cx{6~;A(sI3iZ^5JCl5{=3llLK3>Kj*Z7B(LQkWAzHpPu zD)S%|C)CT2>75_BRDTTCf$H3?psA^Xhaam*P$dKflBEQinI|Ci>RpEubUV(=Fn<(X zNj4Ew&QVx;U;O05ao&oFza%FKLMVcp+Y^iv+=Fmdpo05p@Qa22uItR^LW@`$jD+G4 zSfj=!9KiW~SNn4i{V)cSh&77-8S84-Ntk=80muK1)soDFd;@d~9G_awHmJNJn-g*I z8mfGJ@x6n6G%7&d0I9<<%Bf?w)t;!Ut2#D+Uk_jD^Q)gj_Fz~J<{e-YPVmnKJV>bU zhVF;NI&1NDwX)Mr7G*Hq_UQ*Er)s`ZEGg+wa*iA04Qqb$? z1LqN*SDYOx*=3`2ZP*)mFSbe3=^vZlbmOqO@QlbRsE~_+3=r0o_iEIlpL`a2^8GJ6 z_ZecDp=NFjjctSCGV|KhKVJ7b;Y14vnt>y#8qu5m`bBYK$-2OMJLn&|Wsh)h5^xzIq)maD&zW=8?7m(1jd_q<6r!^>s&?DLya;F8Vw5!pw{aTuBAPF-nmC!Ggvz_NzSWj_ zIS`OF**_wQxZjyYlOSChiQ1pABNtk`WlZMf9%TiV2l)XNuzmoI>SP~fjw38lqanB^ z&3baq?9Hp+#LAMT3V{_R+EE;7NnAW+!_j(N5eya!-r_itzkz@EK195+t0aklb%5H0?=R*MUCop{rCJD#Cs!u&K_pF?1upU&IK#Km z^czzY#kvtPqg{~x(x!kcE-V8fod*=>)yRbcl3vDk)vWV_t2Z@Aw#2pekD;Up)goiB zL|i66S`;JDPv3D?fcy+-&d7d3p$LCuX3pWH5Yd!|!z*g0sxnXKtW=&+mQMvmEg%A4 zvf(jN()wA2-(8SpDwVDT=4?n2p)ejrMyuxd^T8ZJAmg|IfLLn89#vrN5oJ~_kf54; zC!U>+CIO6EZ;(^fW#p)Ht#}x2@#Fp%T*o#~@Q9VJdo!g?&1)=ZP4Ur$X8Q9>c}jR} zT1ClN&5#t^ZMF8&OMdBlvTFL^J%|&>EK|xP>%c1}%f^7!7NrmiBtzkV%yQN%A5p0X zEsP+-``C*P{fW!(i^9Y}fCJ3p<@_(hW#iM38rjQYS(bj$inDu1^)cWi0;I)?_Y|~g zvgHt7={k06P%FDeAnF0)N%HvmNrG&f@{Bax5&0WGk0F=1m!4`&=m=UiShdIjG_sb4ohpZRZGSm zf2?VO?S2o{H;~;(-cTm0)f90nUYvtyqNfzmv zC0^R1vg8pXFM1Xj`XKo(RlA5I5cKU2tH=45)3#qtgRee9O{gGJnHm6 zj3>3-5|=6l(p*%gP_1W_@6V2a*#QUqUj|15i_(HVY{9cbiD4bU-)?Ug&`Q*Awj~op?|+%-Wb+^)|02wuhVOY%T&&U6 zJW(x7LQR{b;0~;gvCwCZkerCzn2ay?a-c*gDGlw$bwiQvy`}{p2`3uJR-)aN?GS&Z68}K)3^j~iS{wF3Rf0IW40sYYbJLo4< zRnu{U1@#}df=}~+T&REj=*viOB6VJ5;mjr`vaE5zH4AHQD-sqh#Pp2+c+Q5xmru+z zcVUR;Lu7lt_XeBs;a=G<=6-W`d9Y$(6o^=RjAJ4E<$IHGL^&a3Q8kW4-@yqv1oJU< z{IXL*L=mv|t;ZhCm^5VYwB8k_kQ7wc+tU1uiL6$FuavjIUx6;GrZ0$+fQk~VA8t_y zdwYluEjB=mAf8{piJr(_tQ{OF&k;kd;Y6^b712!9epjvK!e1O|CG3eeC^6xnqs<$B z)m%u1KnAShY496)3gAdaYa;hUn~TKqW|%=I|hks(z&tnbHKXtNLDy)uJQn^mK_tc=21u zg+*ikU<^8|%+b5O?C#0{aMvd4)T#av1h;sjICRS*>+JeHj&LGW-yVasdp&IbG88k( z!#fe=4ZC>Iui1SXdfMOVveYk{EAmO`A+! zm*VS**Y6I}?^`lc0Ouhw(_b@ps>G6#Zo;x-@(vNth^mzhq=pe<=5U6^TQ%pH0~mQ=hC!J=3>|**Y$el3f~530t5ySxbeU}gFQ}s6sFJ&(V{O6Z zt&z{Dxv$mu@O*HhMelrXI6MJSk`dE^F|&~W_ZKRrJ$*TOdBeWpT|Tp(eKG*IQ=rEurx(PDLm z5gC<5QDV&=W{h!Fm8K>&JxPd)2?NZf*YP9ATa7T3*FLC25fNkpz%S5Bt_~a_4JL(yNpH0Wzy$ zrQTXM+2eiduwbvBZqk)LrwN2(5`7otAB)@=mwtZvb`_4Q$(U8k%^0G8ZxYW=kzXQW z=NlF?yD|LXDZ1s}(qE2GvL~~XFSIbRx3Q8vk0?@EH&dwJ>$yImH6)RVO1((!zN8;W zB=m?|n_l+r8Tvan?n0t~cssC~*k#sP10KDpn~@I@2}X|KU=e%CXddCuF8D5+F$A4Z ziAzcV;tYc0NWhQJA%{H;Knzg1xm#dwVG~LDyz9bQ8#5S~=q|l;KX83e850L>nlrSw z#$6Ch$R`%6+`>hoggDj*6#00K)dT9r55K+U-9n_4A4VVocLoqVbhiMYjVME9>Xf&V zO%|N-Tq9gK>xcX-3(K$(=}xcJK#BOc0lRkWNG8-^y-N%+UWal1`Fiw_r8FQ?5iA8G zt5jPQvPf+nu57|55NiNdyj$~z3y7;zZS%W%$4Qnn+gcIrfIIq3zadq+t+=IFRIzO8 z#LJ&=cZ9+w%=+v#0QVGH5kCB}6wmU<=YY%TlaKvhAaxp3ec6T@?Qv!WpWWaNKsTfY z)=BA%mg&CVsb7vSt?tf^BowHjB^Mp{A6iuP@{<+}0Rmx!Oj+rwS~VRHIqX5w)Lo9G z+bmdt^ize`>~i(0VCk`NG32m_8=QfLVZvjKwWCj3He0A_Cbr& zmdCSfuF84G-{utKrjy1LIz)xJ{B9ir(cn!YgkS;=-EFrc1R!3xr}Y_D?jBHPiH^#h z->Gl~@ini(4XL9@Rcr?NZFpk3Bb#^ld~{b-=^+$eQRgwoR<<4JU}{k>SXiRL4xqpm zA5oLylB;q~M^G_=^6Qyj0qvh6TeOoN)rAMRiS3*i5U1rU^Sl^uGY?983%)u(a!(=W zh=7sKU$7{)@vkvHQFTm%IRfo72a-xnw=ryTXBPUE1u1w2q~gZpbNez6;&Qnalh4O< zKg!=oFNMr=0MsF#FevNf##yBTNx1#!IimG!&eoI<5bWs{EQrlM`zSI$PZzBsMq3HX zvuNk~gj#J7bb*r@t${+u5Fu!Jt0UU`^?`x9`8i5AC$Cg*o?#W&ow=8;uf;y;E(Q9Y z%)42IQmbt9?xpo&@u%4s!4a}&txxzfd$IYGp7FnqRbpPSE|nt14Os=B3cV2C{E%fI z*%i4LDP06&BIh#E^i*Du;P8A%{mvCu4Ogqc>N=>yM9~(0)qrr{y->;cA{_g*@q!*e zXKmSIN*KAZa2!&0y1C$Mc^~pH*+;#LU!e)Z9hqyzG2&zDh0nuTT!~otXF790muG?m zhLUnjzTH3g3>|>aWzlXDX;6uAN7g&+h4ERU&+dblH@(mm3B2GCuhz}H) z@f2#NsvuJRPkL{pCyd~^8q#Gy`QzXArHJJ#LM}6KC->bVt6LkDEtpNWGK%5^qWf9B zggv){VWnBNmSDE!4}CE`2=Lv_?)^j_8O)^uB z=f2hR#F5{+-!N&UD6TAp*LIdj+utOmyt73O-<>(36uPgy6=%TJT_xAWHNy6UAK0P0 zcOMY&zayL?B@)dWGlTa@v~kEv0OH3vFH*#0&i0xz?rF9dH?3;ah~%^g)v2!^+A%n~ z>^`^pOA=Ix-=SLsrk}RnNb#+hGP;iwnMVpKjHlvOGC8JB64ny2yXkZKlfT zzg{gUuVe?`Pn0J1d@yWf&3O15Cb*@kzXol*o=>{1{bUBa+5zuSIDlEUVXT_DQ=q5M zrq~M%eCal^a9X+F^KMV*`0TXbv2mg9A3524TGYy3bM}4C*0}$;0&3~^Uo?|aDulv( zw^W+QkoTLEJOt7vqrb3!fDNz2{L7;CZ&3R`idM$I$eVvrwEq9tx`M5fzLPON9j&yn zk-5Hrt()dQe$VnpgvZLxpiL|2U~BjPe5qjUXzT1?XzYm3@Rw`*pNiJMxuXAi(aOW~ z-`mXp>xKV0yJlkjcSn#4RnKiUL{Pu3OVFMChv1vkrlD)ZadOwlwP^uMYLlo@U3_Qf z#q=rTs>RruQQtA&J3VO_iJk2iToBXQAhOS!q<*}B2v9%Ox>Q`ry=)UAaTjWb4?=AdmgArp&rW<+A-r&2l}l- zg!Ye)<(2@;4iZN9|0?_?k8DgXLK#Fxmdl4)R3^4SN832eN!Cb3Vk}VPpmeJ8^-`yy ziBMR7IX-O@z@#+4tSu=C$KvOC$d#H(m$Y;zZgm-WSzc}NTTY8cSbXPPFJFKtN2mc= z`)1(+&y)kOj{VO}QoQ=kfpH*!SL3!FBAzaJYCV~GyrGB3ikiB~AAnl}exT;%QKs7E zK?PJ#g0cnb%LOg8WW0JylWtC*U?>v0ZJ3paS87HW>`tsHYz4+i#Xjy4(_&e!M7|Gm zI)l0_;ijt1D>vm2t;5V+B^M_I>4IZh<6I^xhpMK48OT#07Y6T<+^HY)FUfzx)d4D*biUb&$|yLdOJD?Z(b(lvACqGt6S?+hMBBbi-|sMbN+4eOyPcOoS-RVx zR`~sq9^LK&s*(%CM3HM`ZLu2G>!GN7;wo3xr<5$u><*y`fh4jswy9Mq#?&)`x9hWx zjENSWOvFNe7Er{fquLIoQlf-tL_;Up;pf)be41Q{LbT8LY5G!O+i!%03f3;yyV)OH zwVqB6p@_ih3%V0i1MAJS=w=lHv~zw3f@&O^S4>Wv}Q%3B3fOyvz%r;3`w}2V#G_=xxwFr z)igT*-5)4B{W%z*mq?YWwQnRD!Cuk(f(aaS6sd!1q}r{`6Ib6YLNGK+7FJ^-odWWZ zl<>~mY;!l=2;V`>@z|FTI01W1C(u;{nOL0#!=a0Im;xPZ9l0;kRe1$Pn{yr|XL2NC zj0zESP(#cDP>0oVI0NjE&cYdj^bRcoD8W8s+w|rRo4$#H_1EAHt$9wsd%$5z{Q1th z$D1Sd(d3KSvD>-U>M_1N6ZKUAi#bJB#T}j+*K)}fb*$9q7#ojZa+B2aL5(;5# z?ZHHjHYu|{;Hr$kq2-V0SHEyjmg&ozXVEokLuW1gKY!r~?_l#GXkh4L2Fm?^yuDM9 zr0uq@UFfoH+qP}nwq0GeZ5v&-ZQEV8ZSS7n+-rX;cFg$aj`hb{CmHePNoF2o#5JDh z8u!fzM9|%hoB3#2ZH~=CI)Dw z2Uf?Xlp7K{ytM`-Wqe+V`w+SF%mW~>5yzbI*VYv3N3rnQFavFaEg=XGHSFvSnD!Po z$ebS;yi-TAJ_8L6Z@I1!847}}c|RK(Qk#jZUGtn&36*k4I%S}R*>V7i)9OdcE-$pEd--=9iJNRD@iv(65im4TN~jO;fz5AJw@Q? z?b30$?$z&21GKF?i<1R@Lof1-&UtF5cJTDgyRp6tD^5DSxbqv-G;Zi;9 z;ux?)K*56sp9hH#Sapq=Vf3E$NZxoILS)kgrt7%5n~LP+yE7coT4!VuySEPIi1Btt z;(4#&C3AJ}4AILub>GG7E}mfC%C%cBeR!Jdx(31cMRWgBF7$Ds1NOQpz$5Sh$f*+? zL@F7hupjF_^MQNa^=7n%RpDrkt0MaR05Fx$@jxt}&MX7V!*SMecbiqNKU2Kpi&NUI zB4pC$}y0V@it`| zDN*9bYX)aLekM*#H8Hv-3E=sxNM8b%wM%1hPz2UgyNoxQ`(Eijud$w`PO22)fsGj+ zJ<0iS19mX=NKl6Q^d2^QJE#b`-9+=|Tuk&KY@h`cWCal+8vs*ag{0pZQfmx0J*l4G z;9jT=Q)r|?v*dxT)lmQR$|341D|3pFpd03Z3U;st+^(%DgMw}?JZh~GD9AIDuTcV6 zfjbUGP6}}{s^*awJ?~;nYkP7G8N!ZC43;7ljbI{$(`Xg}4%#B)Y<28|@q~!V!U80V zIPtLt8-F)=u23tpKM#DTH{Dy*utKE(M2iyj-YJ{2Whi)ZRZpK;5A=xRKmi>{*Tz(rx~}Xp!pJG>37vQ|=frP7T#wgT|mNp&qm> ze0dZrO;-pBJ#qxYP`TiPOW;yCeXxptK$_L5G{??tZjdP*63>v+ji2C&#hN>|1C=z1 z7cSJIX`Cm4LuG+E_O!x11l4TXTd=6=!vvHkt4bXq(?*+8ZfGlbbnk@DD!9>H{p?i* zjbWbUKaQnd&UxAPj>mV|)HKhJAS9{3YS$f;_HR#C_0Br|k)&iWlOG~25+yo(5V!om zLdMN52->`mu^Ts*21pxaYq`q4q8~VFequ8sONe`u^i`bKpUWe!WGKBIEC$OBn^3d| zmf}kSM;#K$L_Ny^5arEeEvm2jR8w|@kTI^p&4B=rBA=Dpjgl0T-S8A%N*(#@ris>{8eb&d)5H+P#ZFA;K&Br4( zna+pLHrRC*WIh<)GOdf^Sw?7xF_m{=N-Ob9B68$-&e)Z>cbY;Fs#RA?d$UMLays5q zP@s&!$L!M%*(wnsH>%-Ou5D}JWySHS&Xi$!1AKm`QJ%FL@4RB+VKtQpKdWQ0TyL@Y z26`uDN|}arWuGRq610***R*<)hZ7^TYXOg=w0RI{O4?tvOxjI^;hAPGo(js+yT zV4GfFxEm2KQ7Rsq(kBml&zmH{gQ_J#%)|qdc}e3%m{={k9s_FcadF zcGHNGn?6{=+Ebw@ES4U^yJj!kJSZ09I+Z;tTHVg5Dm68QPO9Ic5gCOE_R`rXoTseX z1z_#b4dvDt&APw=rnM+6lH4ZSrs(*Z!8m1(QABTi9E`Sv0t1{F?d~WscH0PyUCU_v zMT8)ZXN_f*N>%*W29Cq9ld=*EJ|khVrAp6N1eZtPxRU_*USp?unqde?+3C9#s0KN{ z6o&B$1C#`!LH@GiqUycpoxVNY-E4@y>rgXcb2e^Nr_#HU{%YENd7U>16A5Y{uXB0% zc?ee~g0tho@260ltc`n#A>XyQ(F)g$rf4u=qOAMKR1B_5s-Jxd;UB~@LQv5RY}Ntl z_&!I(G=t;-?8L)X;a_Uuy!~ENGN1-4_tF^xZ;4q=+McmVT|O{eH?QqsW7Xp&b0DL? zS!!}9w8GO=n}lj|uyTsYXH}in$zI|~%y6s*&tkb$GuCCh`zsvXcF;ufaB%o~yAdy0 zEQ{7y&EM}f#{33qn-*NQ9IOvYF`jo=LaatbBe_&a!NpEYA_TG%DLKuT54O5(m}M9o zmNQtGXZ9cLJl0PxvC)aRr<&`wzrR)S-Yqat5WC1fB_y_^4aRk%x1{Og461xo4r)6r z&3xlhQXBM)LkTkve)`VlmY2kT9_894p*YT7|B_&vgyYB!-oPXbEcq>_X7x?mx{b`(d5p1Wokxwfm_D-4UBmzB*%63C=gP@+s-< zD`x`yB&t~iB`G%58E+2c`u(}bXmU7RK(LnEzxyjr(7<1u=p3%XcXPA+nrasNz`RZx zKD&-x_$?4vJqL}0Oc8YjiC%Oh#BHLcXVRi$L;frd~*N*hoxdOt=maRMz>?Mr^P{p zcwIK$nr_8_tg)AgL*VAEyPzRhK#pcOXa_|5D~bP%Yzp%hrCAma<%CiUM`p4-P_I2Qy9z+T($PV-HU5QR0arwLJAmJy6sbCdJm2*>2y@S>|Bk1ycWhZ(CQ5KbQ-@&NmX7z(<_O5 zL%MSc#Z0oRPDAG&6t#ghVy@EBQ*dBh?;pf~0IA3Ln{9tCPfk-sZkc2+0L5iOFH_VM z$NWSiOHx{+48+{q%v(E4e=<(7o^FLZUr!FNxCFeaD^%9mvg)_;#l6n<1Bf)A5bhjU9@}RYL6Bh!I1$(-0R{2ZS z=**5P2tWPuAnjFPaXLKofiES)QsxBNLdCoN6|mwDj$cPv{)m4(`9Ng&15v^=y(4Oi zb$j@6uzZgg<+Ny)m8n)4YPrSI^MZ8}9-@h$LY7A!+h=d>YuXcdX`swJAF|(gs{^=~RFB13}T&jh*YaZW}3Il`be4DI^ z;mtycF0Qfoc2x!RGrCQVkIcxhr=o03R5z{?8jKgHE=6yYVBz^I3bIYO6#;GJl;Yh* zDFF<5mnC<%sVNB$ZH^EeIl*7Kd^TmsXZrmTidVwx$`I=EQWlgNf-RZ@^Aa?$;Usk9nV29&Iu~AY4CYS&66Qb|MmTi> zS&$hCI_LTXxs z`Yj?B;bWXooTFv3V;MeJAlV`!!y-Bh`FO|kwkbnMbLt@L&g+Vu#t&eYT%Y&p5F6~q z0dU@42oEr%;%RRnUR(afI&{XVJ}gi-;76#CQXrmf-ghJcZZCu&0)1|OQC080*+uN$ zLyfse{E#_6IzD7v1{~eO&NV|rid~{sHAasNys@!{8D3<2A;TVicwfw3JC>aCt?S&J zE8kx=3vdzvetxU!LHspeyzs&nxLln4gdzv?AkqtwW^Zo+4OVKa8EXs(R;o-)0AjHV ziX0n=>_r+>yp=+hH_pUrHyFS=FC~DG2&{RLsE9!=ire;jMTH_j|Fxh3M=6G7`oXWG{1(BB(D*% zAYnW{ca2SLHGWDoM?f5UDRxD+U09*s>^nTaSlrNw_~{SM0(MGIAv z8TgJR+hT?xYmt}Rt``_2Y!xflcO|czbvEINmmfYn(p$fBY7v3y{bD>dWHfvfg+)UJ+ewoK#-D^vJu5i&po0n~y@VDqeW@|=EGH?4@J4ie zw@WK7{lj5H2Pzg>8BLb4;)j5UAQ_a4YEho3!S7=*ET!K;!CM{;I*wy~2~ms91af9Y zym48YKePf9H8KvDDQ?Jz{BvgvN6A$hfAOm--UcRd2=}!m5Qy4Y?k4Dd*tHV#GhbEw zFqozVpJ!j<>gM8f#!s;oL`MctKalmC94Ki5kGy7UwofqYE)&<`Hmy){ZGhMX-jc5_ zDz<7WA}c~H;9vU6w!laXEw8%>gIRVx7?phqEEF&dA6YN_d2^%MdBsY91KM_YS`RJUesn|X+ms3Cy#l*DQRB_3hs1A^$ zj5ZDO#DPWF7$V=EGhIx`5(|=Su_Ex1*wY&`PBUHi6QNXk8>wK|reHmjrjjp)u5LS2 zySsQk&S#c13G~hj>XY3#?t8f3W>9bUpZt(!PjuX{gqLUHlcIl$Rkbfg0#pZ<8Iglj z{f|9V!T3a+36b-UMJtCMx#%x;Tpq?)Ji4eCjqY`%+dJXDAFH9d@^LG zhhY!K;*narKe%xsEm(Va^i)>vo(X)@Ie`yL6s_e3Uk|N647j^oWrOcsp49F@+xwZ< zPWjPYIg{oHvi$KV@b*dw(L}?T_~VF$vm-!ws9yba)HxB%@In`=U-C%09r_w*JF$G( zdx-n&B;@gf-NtFPrBblRLRY3tFur87BHEX~Zf`#fsjCkOMtZrBdkFa@yNmUS6{&Hv zMqv({h`tELkwC6@hjIoU;I}Di!?W0D5haX9F2b7F#sh0BI=@J2;vNgNJN;9_k%SJN z4}xr|B`n0dcWL4S(YD=hX9<|N(FG9FOji-bA)$Q__hUjy(AVJDfLGjz^hTDOZx6-U zt(UhhDuzkuPTCurAb{fTWRW{T8OF;AWl)1-LipY%&zF<0N%JYFjrdnbF9Uc?YNj}2idnvL;&*Fx2a=E>3E!bz3%MYo~E0rHi^Oa?#{~A+o@Pn!9r*Q zOe@D@*?j4n{bhq59o?#w*z;%Y*1>~jjWNdPgeP)cPlq{R#l&iVTZH_^P>3b1<-z$X20FW=v`uEnl#onMIWrvkOW}SQ^!AffI$In zjo4h0j0jqsOCeJ47@xU|)`?Q~URMrGD7~G`KXh!nO$^_$4yV@pymQN2cL6s+cN#$S zsh+(Pu2CkWRJS6w$r|eVdw$|jD*%2 zW)`Fx^w+N2r1W4!ftL<&F@QJU6#WgnGrbxgRvRC5B9gFzBxc>W&cssq=I)cJcv04D zTvLH1{Ixl9CT)j|>U7zSRb4v-;34Z#=?-O6aqu|ftde#p!YfA_LZvsVQYToR8?Rr_ za`1#%dNfQ8(^FL_C>L%RPo`eNFErM~=3z2IBtE+7k%U|)>@o?d)<}b0g)fU#QY_6R z4W%7GOdc#@DyJf)HxhyLs_O}lL0f7kC#IRU-)wjK;I2iWHA-yAkntgrFW6DrGTZD) zJxO`)M@9~vD!9P}!XPSywsjK`u&OL+#xE$Sj-(WL_yisCnIQQIrRuto&PSqFB3>hW z?Oy33$nlSJgf*trT1fVE!rI(3&|b6HHqa3!F3`b;Ve9s2)|Lmc5dW+WQLl(nYnP#f zr6+?r?PzEFZjSkOFg=ake3~}>x?=$ahVk0Vsz_SZ5+$X4HoV z|A2dth(>0ZV}Ef7qDLJNs;hFNlzJ2~!8!tcv?=i2Q2J%(aHz2Qel!4$+pt?ig>c6{ zHvimK2)!@rn7B*wrJ5+UPXrrx78@>X3+-*6@!ffCKgR*$XDa6KJO2-wyZ6wu)~l$R zw#YgXfMiNq(8R~q!#ejV6D@a2kUSQXshkI!kzCm{Sx(ttAIaidBv~7gy6PhoF9SOF zEmXFdyphaKO1*^5yea8+i=R{6h7fk5Ag%heGKWY4z+KULkf8zUN9QP7?k)RSi?hje z6G&vq-(X4L;Gfud<>W5k)Hns0=jz=(Y0|9=O63Tc8xlVeGh;&0HuA~i*q4dfAPn7g zD%o7XoRItA5(hKTx@$Czk%N4g2wt&g0EWt3s=Q5GYy4v*mC%KL3&A=eFR&+Un^sWP zllF}lRA1(_m)N7LRqH!|LDSvthj~tM2aOXz|B}0 zvgvmG1w1(wPr?$8r8_n$+2@_lWyA`jwU(Ca?Rl|$1p zo5YHaX>z=pP((;Y;lOa%p8iK}O@FN$NdzNQRnu&5nGYb(lf3sI^-c_R^lxZA9;Lzw zv}2cp79IEHXL7fLwV*e@|2DqXAN@>pH_H7`Yxk|{t!;_Fu#$5#e-jf_%a*e9jH-8< zF!wS&0*6{B2Y-qn?F&S61znaUGBYcM@w026iUql9sq+mLVW(AxQv$jO1_|Ra#Y6rq z>ms(5yAXUiU!_k;fK$VUJ_)Pv4p{cd>xfe)b=1Zk%kdqF4P=0{0g}p! z66|J9uK>X#eru1L0A}?`Z_DOh{W&Zo)7xyR*_zh7$BP1q*k&( zZu?naTA`NHKJvYm_2uPToXqr&Qj^H;)Sy1KwU$ip!bGRqh#8$ifL{;9z0$z=LQ{ei zAHmILN>P3MlOlZ1N0^K({`$=)t&G^AfgAi}8p1buPVM82tY{w1o8!}~5YG<#P`ZC~ zW|P0>y#7qOu)Va&fsiePHF0ppkZo?rQDY`@`qxMg#qs&YjB(U;NxVAI^A)i$;qJvk z>FMKz=yp9k-y`?N!_(Q>z{5pCb&OK06k3bR0#3!9?B}`b^_9L`OX@Xk?BQLk8Qk~BJrLXcx#5?Ljfw(|a&eaMz%*u$+x!Q)oZI|- zcB699r`M~4oMy@o+g7sZ>pP+qsXgr5H@FzQ)26az5YLRI22Bl`Q(pEdnLTPAd)C@n zJt>6}D>FFJO&dxwS8txsAMS-z=aQed14}5VyIANu0G4mV4y1s=&t=RLA{Crj+NfT& zZEPRbmmo!nZD6DaTfhBBu_vCR0WlB4x+*=%S6j5yoZ&Xv;p!d8*C4pkf>;wO^#iE# z@U!AAwxh=;!hH(8tc8OH$icnxj(4=Q@$T8!Z$)K*&Rgnktl??B}7ZALyhABVi7xk&uAT(WnJ{)Uy_h@i<7>eaf#5YMr#bD z1!-eg4%A@#DQA`k@|LCGr(d>LyRVNHDz)yVhxkdum)`nEtOKKT*%#&GL1Suew_1+Y zk-4{6C%@V#@e1ZbZv|L6bp`oA=7CtsZSBlhq13X1iw`#r(K+~uzy7R7;am(pYO%L4CVJDOvzQh3b3$0j<% zK?H8}`(@T%tu4}OZrrd*4HzfwCd;3z{5*q$%dePW`W-r;F`+~FgB3x1pgd$&oQ*0) zgLDuE=%<(gp(w;{RW}JjBm3(g_>XV{1iukOnf_bBg z_H4-1;`g^=gsvx+bcLUnI%jf~%=h&gSyp>^8eL)OQlQ z(n~(BaNUO@^q+6ft9T4F)sl|fBQ-vkb(3Kh%z~IY6Qtnt5sRr1b<*@xjTnK zHcObQDuJZ3*8+l0%t|Oo#(k{V(FwRKT-u7#Dh%Bmm6A81mMpc+26R$1_fYw{HgH}w z((>Wl3m1o$I&%4>*IM#*;c0NQaVZ`Ty_!Tl@AIuYYR+)%VR|6qW|a`i`Q~JL;zuX| zi|h+Qxz#Ld_-+fckKYU#Z}$Pvg9clsgLc@xeSOM!8A9@=$mCnfRtXUL!C$+-%1ctO zl_|#C#TMf&p7VS}6;2Wl=sf6yZ6Opqvmj2;LOSz75Pf`ZZ_hkRB){Z8_fK9%yT22= zc4P8-IT+nJwlItvgo5&y4~(_pjVX{rb451k#K`Po4nEKG$302-nt!C4y;dIxQTZ_^ z`jF1byJ`rc&bKR7S*QQ}sfOtzvI)@c6df3FB|VFCV)E@Tzwiv!W>XUd zz--EJM~NfKr3@~~=N6Kj_=c2&TdqDt4B-3bBl($g^%!(JM^8XV4g_S!;#!|xQE^F_VYJL! zO^_P8RjOji1E;7#zY4wu9AR~Oy*ElRFYo)>(ou7=tCCBBTe0q%Pi)JCpQiDg8oS=PeK<_Tf~0o~1!G3CRf0&le1yazuBQ&+zmr zzBNz7YA+F%icn1`*l`&!Nl7^Z6|U7@-lj3wTxTv(w#Zd&c~tDm?!FEme-1hFiK=35 z<__kRYM5J|WXr~Q2eM~U;dA0X4=iq?EK<{?w*rhp0$Pd5P`^uS5phO`<2gW*Z!9>s zd#Eqr&wJhJF?HDYdn*@tRi|a`4C1{OtvMtT`)%hz;oT<(1UjyLc722 z5qN?2guA4@smq!6_XWeFC~`b>Ko#%s96@78cqJZw9F4w*WY^K0ePB=lV~rYB(krq? z=T29%oxmFwTwca?N&jiHdR6LCP-#VyDH&$j%MhF)W|`nBPK;S~gRQ4bqaOdn zQVEyJllQYS_@kA48dIH&Y*8`jE$>foEGGwGcyyCj@ZGT;u$j9s4gA5&aK+rrdZv*l z%r6Js{N>yA(1;Y^Pt4W2uUa)FfPH4)Vdaw}KsyPqQ|vOQ;`xhXiY8AcAx&Eg*8#-@ zqwBL}<_DCwfHP-qjX~zIuj;Qwyov0dES-uOGRu(kd>1~Wbe(}8;7A#_*&M)^n_IWB zD{6c)+X^|PZ^!3loUOZ$(K&oszjD8vU1{_-**je%yCEKP#`h3Jb=$4{297C_P!MDS z&GJ~0M2}yhI%Z%(I<-@$gO1oVSlBYq`0y%Tfr~WYZ&1HSbU=w}~NISxV6}AL)*nDeHqXK!#JeteO2*e`)s zxKAa{PkE;~LK07#epJyi4hrJ)IeW9KVM=X@40hd(t)-=bONeo{E5j2-V@9zC6NXP< zb<^Jgh|(vD)RlZJn^k8DLb5YsL51~1M2#!VG!F~85*W|{*2@S~_D=<+s#aNzf0}4+ z;k!D?b^~7H{J=hPOW|-H_WUD+#ljNsp+?m8(n8XGcdY7wW7RGYsGoSEU(LnOFA^Bl z6q*LaUDM^fX}m@K7nID6a)QhA)3E_-%W^i!vh{!#Q}jS7i}Vxk08Oo0|xdUhLEl#lx+0+7WVxy2X z9rnPIUWmm>9)AYHo4K73ERQtVr^A=qL-cIhE_j8jv*TF8-j(nC2!6mB`<}w2DSve8 zsm~rmB%wavUh0jylX7s7?CJ$pf|@9-{YAKcwxE$A>j&OMJ}}qU++WN5Ejlv>I7=rj zuQ}QD)6@YMSRrq}zY?F0VdX^mR)rsAs@i92#NcF(p~o`hNHi9xNM65i78Hu|qK(ms#NRe?dpYUOuOx-ut){3FmmR;k%;}ibUTa?0 zt(Axv`h@~@R-kbC%h${oj2=w=ZagqiEsDgsTngo|Ryqti_OINycUR>`M(@M=D#$(|E4jO`LAT$zsJ(PYav-`pd7a%_t1_r86H)Y2Qo$oFhd;W3+oP$0Z8q_KSh`Z(^@ zX5O8;*(AL2Y^G1BaswQ?FP(~tc~7nIO}NC zh!{MX*wX)6lrfUK{oSC>JTf2t#c(dNj2Ultz9q3C-n?GU7>xf+;T|j38CvMpT+8hT zq1|QS+J)3n#(Y^dYH6ik0?Zbs#Gq6SIsalVR)>>Z#F{kR7z=x$Y6|NWKN@1oX;z{` zVxx*Lk{`6lzp7PN1gB|sWVFTD{>}!XWb94)2CPMI4NF+G4ikJhP)I+|%3?(BDkrm? zDn$)+KokcycSQ*t$x>tm^>kYAO<5O_X*yx|VnJZdTV7cLcCOQ00_9_u$k^x>3AFPqgl4qdRVc1*mxbN5JrHQz$)(8p!`Z$>JB&Ri(QMtYholvrQH5WE-i~W<# zWhoFL*%7fBq(n=KKPi~FXp`5`R6gN(9q5h_7oB{Os%&-^ES#=j)yaE3*7&joOdVsQ zjY%p$$SsC!o2h%|O?rgjY0dZ(xuqL&bwkdOV5uL$DdKoeUpw4-h_}Ku?gakr*F`NS zN*6trket;Z5I*@p(6luTBHQ8^N|0tL=$6%l zcXLo)#{cK(JfI5ITPVF-o%avjyu$>?5eACkBzEdJ<6@D-QAESH^DiZe~~6psAD;G)Rl3WpUS9p->cpX|~<3=rLC4+RE5l@{i&x?tL}_SB@<8QJuwQgwn7 zz;Jn1Mk)EHsG3w14!rraJ#g5Ogxb}FVX6x77!We6@GU&$9966c`ZgkXxGk*egT2kJ zD7<{@1lvUsy6ELnMksEaUzonH!=2X{isM7kfwOPdL4Jq?cIoLLsY%2kegtRj_l5aQ z*Xnd(CAnmW1qlHK2wa4Lt5!P5XMhrhPe$dX6r$H__4vuUD*)eJ1r9SuIiB8KDiuCV z>$KfaHSI~0MTO89?~1DbEhm?2SjV+heLIi}7)6Slb*1h$qdNZ`DfLg_%NR+gg1qO_ z{#7Riq%8#|Jqg4^a*X0h`sH@q5)^l}Kw}h7{FomDdJMfyVTLQtrZV$0Uji zZ+l%2SG36ZSB+Z+ehZ8ZyyD-@jL=j)3h@%fX&&lmhQ?VK&)#b<9=EYO9$joa^`cVW zWFpl;3TBg;PVF^1&A4#`)86sm@Dx6o3Zc#p&2(^zX@aMPAg_uPr)CyD@_K8_y98SJmrni?L4`e{y8mzD zS_pZTfl4vovovLs#5eoznU3JBh5`O!_dUQ+RwV&QFjALOlrUy|(zN{6x4>1W zp8yimGi%=;HOnY{H<4a0e0rl7s*4ws3%HwI@M8D8;$Y-^6|s2Rn_VA%dL$6#ktF87 zF`ru*GU?W?(QdH$4+5=WVv$02jU;ZBI&3bY47fEz?4}%8KQK65m?^MNg|H_Bwejsi z;X7*62CV{mfTTH5Yk*k`@r4(0v`D)6_5H$g0B*ESpbW{M*!tKkHmUU8Jx5RsKVA(2 z6bZ4Q9uimAe*of`TYvE9xo_3 zZ-WW~XcEdd+7?F41o&>qwaXmfnD?JgirK%$1>tONcaSFL3|H>~WB2FkW_h}e!FvwV zr3r@1ob;sheGuM8aDNqfof%8SArQSe6f%6qUXa&T_8Ve zT0%Y1-1p4W*@Kt8>Xx&7*Fm=gspzF{62HmbBBb0ISinfcoh-u+9 zcS}sroren%u@&kWnFTCQ?4tX`=)R6=L;eQhJbu0SZX0#<)Fpl!_MO|nnP<2fkO}jQ zdriR~IwS4P-VOr!f!p7y5H&`#ykqhDDv*}9SlAW&0KVOU#x=78e7fC%{#;Q46Z$$i zDjJcAfPUbaSpz2hL_O3uJ8O8PLf-76Q!(?X$ph!X8&R$*m_nemq|YpX1Uchh2y zHlFY`a@;bom`JS6=3eeDdkb(&ENE(nfg3dMtP{88V3-iZp#1)`4bToCU5-&^aY)eO z-IIkISV^8Vv7ntHovKL?al+LrhVJq@wJ~7 z%ijH=oZfw$gsVU* zF9&P=zhMD>-U_+?OG5s8U*!K>6*^9r-w$%UR~?a2LA z881&p!tI?gsoB1CNxa51ABP>1)vfSbGaYLuRJSdXnMetrFaiEo9K`c{ARlP; z0nOB6+MpNwAZ+nEG+8p$J0jlC*qmp^FSY5O{cXRo)9pQp(4LrUd|lDSNzX}N_0&eBJGkU zstTB@7zH&%Mnemblu9Wc!6(Zyr)Ar_d&BN$>*+p|3$?v7`tPTtDm5vxALo<^Oev%~ z9B2!OY2f!8(;*D0C{Eu!3Lm!S#o4>EfuIT5R*`VkOK&b`G4+y#y3~QsgDIVMy1FSDf77bY3;Tgdk` zfP%4}VlSla)sQe9ytR~C8@M))KU5f+Ae}V5|!O0((?QJlg)Y>SQ0>v5kP1 z(m%YwdMV5a1?lzZL(I`oZQ&Dlz={s!>YF^=x%`?i!MWY)teBg06Sl{YAYi)%1IESa z@2ri8R+W2T&0c$OxuDHh;$OI&x{uJ$_Q1q z@G?pLa%UKzy&@P;_HykiYAF{_r#Gs>FCS{jB&Y$e+U#vC%j&%`&}LY1Zu+ThH8I(i zhT!`BpT4NOeTNRYfBLwHn60o{exO;SHia3Tm#?muUXvWi#NGxD z<;R=Gbt3?zOvqTK1T&vharNp>v4aorAleC?GI3i7s%#CV$)Sw13H}=5Uq}&9peG}Q z?eq(2vftgY+vmM$a`b_cSynz<0DDMBRQ;-AzE1%ex$EPlu~}1VJ(TTeE8P;8tZ+Mi z?izz+*g5R%=FLp~+ktyCboV zN=wU&Ygp>{rK}5czMpC}tx#b=e?|n$JQPlkQz*L%T7#h}R$zgGTaABkuQyX6WP|#a zJ*)P;NV<$)^DeGERXD7vo@)GPp-pxbX6!p4Jf)hS9ypI!L<+tI;>7udD)^h;w$&md z0wyNAMaX1W19Oll%w$O*kRBo<$$g_hS*3^mQ4^UZgDl%FxLZLJ)L-U7K6kM1VjPvy z*iX~vZ6J&`q=g$YLaln1yzF%=lH#OLZQBc@-p>gmX zK*7rT*{#BvwLe6x-u^Di;3gQ&Tcs^z6Fn$2iLw=QO>2(4>*X7u3fU9qUt-kXQt;mx z_0QNG<)8K@bn*sf|9EjUv3160`RDup|KfC*{|cD=PX~>E3pxK^81-Lfr@wWZ|IJPe zOsuT`)_l=$`YjIcbFAikYSGvv?Tpuv47NTRt~4l*PxfbrkDUItKDZCGt)8Oacl#=5 z&fmYvT035pNfA%a*ZbyZb2T{B=9uxibIb`&d$h+z8xH$pKr3PVAC0cYm;zs`4m*I~ z$4u>B*Wk7HJq~LyNa;aw&yz8D6N3=`u7S&}l;BZ7Vw|F2HG*%1e!cMoR`D_WgGHjP z4Bl%n+^2aQ3dD(v_u|H>y8Sd>Wx77s(t|2>O&$IZLG>Ng(nGD(l8?VsNqV)o;Q`dp z_MsQ~F#p?HWCP6sUUfDlG_Q^PU?g+ZHlb z=Jmz`DX$%S-X;&O$43pN%=++S;{_%Qb@(dbUk7%RjcYq+%_R6 zz`7F8-jiha4kpa^H*H3P@T%z^_GAyq`HHR5s1|$7+AC}**7@hw(y&D?0n_H_z5G(A zJqp{TXe8ac*NZHke<_I0pS=Kh`S>cC(OdaYuYCPkj3Qts9~%4&XJq6&wg}Ow2WXM{ zIKsA~iDDS^8=awu;M~BXnu=#6mR_lxz2#s~Q#O*!Tq3A;HrWPtmfFYizUka!-eu!p zb+|~PGz`hBC`VbL*$G@f38o=3%Rg_!SqP&*L6)f4z;MqBN{d@G?aJ0^Fuh9%3V566 zRL8KhLdbuo2we6s2yL8Mm|QD<>1<&bA`yJ$e98dhCVmTGB@lsLihg&p#Dps?wo(x* z3=qP*$7IJL17qC~Qu|K1_8Am(?s#~Z5_YGwiPb{It3 z+)@R!DtR`&%(^l=DUZ@8k4^-KN#$cHi0G)OPW3S#Juz!(ku`upotQr_Xc5E4LWpN& z1SA_3QDJCdpUQFvmWjLwdqmw@V^j=U6>EJiqS?TVm2e>K?33#l|IyyPWeNvvL(Vw4w|NBV!6l(Y>>JmI}@TKMc2u z!l1F!eev7eMa<*cedmEMQB83$UACm3@uD$V{KJ=}DsfR8D*~Jh>hP$zvdo4F+i*;) zhkQB6qGB^3E}D)1tGzFQrs{hemLi1A^KfMz@4dL!JP#Q%WX#NUFK*_0uQ^I&p2tE& zNXQUH5+XwgAqfdd#*mQtJ@}3Kz3>0~ukTy$THjj#yB2Go=RDJX_Otid&pyxDJ5;7U z29@bKxRO^~t0Qj})5k|wzhmS=*J}DvB6Z_NXA-!YJ@stR4KTZ)XwiEC{QHRTU1h$& znEk9}@F3$QhaF|H7!%SIo71iEM5dYj1@gT*V~^B8p)?hlHuJWJN<0b}g9Q33CVpq` zd4)PJL{~sk!|Y)L?FCCyr{=~lUzYT`$!0M|*f5NnN;<=omThyXQ9+9BZWpk-6s?$e zYzP!4930MJ{mqZnH|x-zKeR;xZ9!9eIqX;V%$n$z#F^%b-UB-+SA|R>x0?^p)-QI#G%{R-pO&e1l*RL(( zt#Dt${o}Lem#jp%6#Spw{D6;#ZYT%}g+N8+<*_&n%FdOHL?d#{l-S77l&Qhb?1t)7 zp4k|K7mAmIDXbOs;m$;-a#|dyC?0uTY7SAYO57ZdB8iN;_s)Rc@?p`VB3rfSt{<0J zWzFdYXlkP3Mmr?m)fp|A5a7OrT<#mXgPqB`Bjz|Rvsu4+u(@-v^Ks|k`aXRVJ{~Dv z!40yu){=-<(Q3lUi8GRT7cLhIaN)-H7T`aE20N!?FfN~Z21K!Sn$kbt||l4GGr{H7}dfVMQvxnZ+#X$F}TQjRnJUDQ`rE(#G=AS(nTGF#ehNB)Tgz99AMK z-)3clL3vVe@9_59{T!9`mJSEA+*TSP6;O#|EOzyyAv4sdYeHo5vxWvh@q+u72oy<) zt8_2Wehz*?9Tb>GNKI^9-G+qS#@>sn{=$soGBOvc#?i2iM3ZZ2-qH*eiqp6-n4Eh_ z#5DgQ?J7djfSy8%siBTg9+%)e?Idf-6cyhFY}yc+*xv`4Q+Rc-M>hO^QvpjyU$GSZ z_L-@zw~Qoru+MtctCv*IH+9F$%wJmTz1RF|yyVB)-i+^aH)#6%c+rl8K+ZE#r=7I~ z{_9R#`&ZLf6VNs-QuJ({WgILaLiz(c+w6VLg>|E9(Gt5LC z$mdNO=ZBHnVcM=h71J#fp=%jmc6(Zq^)Bx}y+;}B7hEp;J}dpx#@wZjEYr7H`qp#T zFN*ISfFlpdSF(6!QkZ8>P&@}2tD9h%&C2QrZV=2Cy{i*0)T z7es1yr;_`+rJyURtt#B;nX&1%z7c!N&`oZx zpWk4Uxcg^3Gw1wGE0IrCz$kcE@-B0>d4I94>!@IyGkvx2xWv*{cK_43;x;Oq3q38q zSB*~#+7G;R=U%wamg4ey?AlOz{f3>@WSv5`cFaH{z3lS)v9zZEY;U%mcbiIsKP;G;*-Tfg#x zH;c|9`;7I=hVnYQi?8xS2kb@JwyRlK*jN|YN9s1_bK1D~``om;8;3&OF<@6=bbPkq z8dB|^c*nxr<+n@GWD>wTwouzuma)mljAWZk@U~`1eBPqK+F00Axzd{McRI01x9e>T zT261uv$iuiX~MJvPP6?K<(#HVj;x*|W#Tk4dpw698ykxDGru3)pA0AIM9J|>5wdf~ zHm#=fzmCYYn@pTcH1s&Tuy-IyjK*jC5?&|s}bo+ha1@7Vnk5!}|9+){(wTPl42 z@@pZ&OyD4r8&YHZo%!8NUxeU;_3OmTJmXi(=PxuGM@|IwRGw#JtIA0GB)#7nr+7`r zX{J=p!g2d+sau`-%IVFKcvj>1nsY(Vx7Kd^4V5TZ6c+Y8tres__o63>K98e@(>ufy zm6F+H<2(A5xt8nu=_Si=(8iZmo%7rC`NdUG{yUX%Q!*lxjL+9~JfmXY_UqhT5|kc@ zkEn5xW=I&>w*6qWQ85)@ec9srcp5z2xqsY>ONbp?)-oC^-Nd~4r6WYbB5j84L(U85 zkdaLprJm9pdK%+F$F&-rYa^~}a{>VeDcr^ObEc5c|~xz1xGfzj>=b z%)*R2xTTEos8s)99I*qrBq=n6?EzVairEAO+IXM-aNCey@vSm(}X7> zirds3lHvWOoUQuyJvRw6Zu-&Oyqu8dO33OeG-c>F!k8ZyR;@;gmLuLFpDeH`wC;Cd zVtpg7I+)?qubP3Dq=FJpaAwe)PSEnG)@W$69dwE%O*Vb8?uvJHmTx~3&h)0jL-WK#-WZ7#HEs)`1WRD|~4GmJ=i#aF~ueq&C6;F6AFd1!Gv zYocNY>MDV1p4KC->G}NE`l)OZN*tytUIO;bz50B_KiUNf*t0csg3(%cEOk0)JIJLp zO!A8;T^)#(3$|s}jM?Z~6I*SJy?Q6^<$>62t7$3qTgcgb@2SR3CK#>6I6K2460_ zaf6Yj!bX%IFdro;oW=f`(R?t$8s}}@nOScnWjY959fF>S4|5S5*sb;Ux zv9Nf-_{FDXR^z4U1!C`pXv_L*eRO8=iJfd`ZkB}CJYTTLq}8quq|qwq3n$TB!FggvSO*-kDw`U0tHG(hgKs6mN*iYFJ-EQtVXwYptGXJz6V!gB4Sz|Q_u;#DneA-(Xuhp6))Tbs_jz$JJ zM^Vr+(zx)ew%UvAuFX-^iEOR-2;7A};7qrD(xTUhjo-+BI0nnCJlbPjS|%nW44jw9VN z&~6{Rkwce8#TxgM>=3ChW80Zz33I!s_s{OMH%gI`r_AD#mHpT@9!dwpZ7FmmhCJNsZmg%GgO$(AKSS*dHT`fm$l7!qw{CE zxm3i@gplMZ-tgFs4gQ%#Jij{Pf*Ax-`MA=}2T z0aYPEvSKryLC;DbcMNY_j{HdUV5OpNESgytB~;Vf<(G0DH6DKs9@OAA7?~3lSNVSb zYgFEHtBo_-`zQZkz4Tn_`{E@|T|d$~i~_Ik!hCPoB5R|;c1y+O*B_{N*)vgunK4>g z_r^*QHCyWMt{eXRkP#4<(m;=(tHSm7G=c-}KHlsahN25D<_Ly=^Bbz;z7Ks~>o6w$ zB5gw^Q5*jOZQWa}NKVi-KIZ|IOc|zfx%Z~Ld^VX+kZ@g>Kid$yFlrRnyg7?xPuHX)K+~*smh&}Js zTQ7CxYW9^<%S`f1A8S?}^WyI`Cohr^1skO4l- zAWvnJBP{fUPs`=eCA#=tot>Z$JrDE-JzG_@&oUIaHi(O0uWnall$;Okp4oV4cIvf{ zdsJJ242g>v2LDpcNBN(Z%G_-p2i2R-;HBI2URkc(+8$8v9TG-)j^wG=3Uaag;x#1X zgy{@?vw6zi{BU2fZ7r1QVd!^*Ss%Y5gb}1sWtL(~n2A?Z=VJO`aX`-Zu9s0h;g!De z4l+#)iuF4i4dtu!>}w@2Rjah>QH9|ljn@KvY?N$C1e@^b6oqlX2N%Tkll8u2%C^LN z6yxptvXTT}C&?w1`Sc+d9)cp&DhPO*35U;DNpV(EjZNmpv5|%oL&A#`@xv%i?Q{rx z5J+UT5N2^OBUS@AHX1=yE5xT5h1%cwG_gsZy&lYNOVi^-tTVe!KV>>`gO>Y@!G!qO z=#|J&Wj7d}tr1klC7f3}shBc(9Y0c|0QANtT0+{BsA7uL|Kkq<(Oa zqKddmD<$Yw<&{aE`+*HtR)67wKaBSTu!{!Nn}I}*Bfc?7C7%?kP6Ozi9!zDPv$G*vCDrPQYI`C(8qvh^&v9siv|iY>&6=O*LSs(N|YL>yIc(NL3l3UbR>cEzFR5@T<%G>h%g8t+AC79Qldr+eAMz8kozGnr#=Uh=@Xs42ERtGC1vwE=ZgjRHkJKr zT%>^kcj_$HLiL=}#JQqylA^_&9j<6n4%!t)v^|UA0AXF|d_PapODk@N+2Chqep-&X zUROW&iSzy3rN_5#B@}en5EApAsz{G@I6I8*G+`f+|kk9j_6y3b5Bg`NEx^IfVm zxjqk7L4}!{?=g6rLrTakr5bPhD*vTr#YD`#$etNpYQw8aB?ax8w8L85F7V9z_ro8l zEV5-h9DK{Uw8Fgej&AIgSJ*+-^AW2qct7u||P)#r7R zUsFiyK<2LxJ+3q?oYVeP*YC5xvvnYsF87>xRc=h7#=||9sC-InQe-RnJE=(x-#&hz zuG0BuyA`C?60M<|5{J?epfF`<}P0ba@LtQFU2QMT7uh&ME0b~JeO zH1K(PmpMLdq;Ztw{i1oBg%+nVkNeJYUO!}4r1Sz`8``XL(aoREsYwhI?;Iz-Dt>W; z{9je$Q$N`E41^Gns){tSFr^76L`21Bhl#gc+ z$mm3S;}Kk%(KPP{sde!mZ<*0Twg02m(c4c_gvngIKW^h28q{TIJ{l(N@%U=#i$o!b%QZ%W1#iCP zYSqeP8aF)aZorzL>wS;e8hZ1x3yUK%iI!jrtxf-a&DQ~AA)c{+#)H6#eb@C7&*i=j zw=Ui$vj$z0A*PXZznRsFFv14a6uch(p<(+DJwN97uV)(JuDKc>KW&NH;gkzk+a`UU z{XApSF$W35ml0#JO5%@^no)G$cy*iNYuYW8cB`A4RF#VvalCVFQu)*tf&R^D=xCF4- z_L+&aHoGg?w_Gv2F7&<1^dst&*3~aU;S$^IB7NzhJ=fUQWhmJ>m?$aFsKsy~BCI0Z zIl^w~`ciwIvJaHaHe9`+D&@XSmXf*AM6L0tpS41}CRf+H$s0%mE-Go=wb0>)MAVPs zNIFxQ*pd$fJD(#Zws%>bCGns1kM;#uek{c5M?P^^u?T<2wmrRfdl_zoP*6xdP$s|d z5lxau{+(S5w0~-ctyNkVwA~s&(LBtWboOba%<8_|4bz|eXA;8ttb?6WgF-i_gM~ZR zwnr1=Iqs_FD8;Pb3uKOa!0yaSr4SaVky-gEaB6viaO;$%`nJfn0{_QwvS~xk^7siC zyY2x=6Hpff+?7u-r$Dj!PENmkEEuwJuqaAf(|k(a+qYSduI79VY@!0QI*r8Ee__mN{-4pjza=El)=y26*= z6c=|E=aUE&eR;O4^RY$Z`ZJeF)ihs0#(K30;ZL(axhNt8Cf>7-g2HZj^#H6_PGRI}qQA%uOQ(PZPzcW4U^bzq0HOW}j95{#8VpM4XP(?rB2k3Il4B(>(6> zsuHSyo2V*`Lw3Y5r1SHOr`FDTW{%fapgQ$^{%lt8-g!Y;+?185)(&<^ml!VU4Q&hbqe|1H!J-Zxa>cK z-GR+D)MUA_F?9?#ZrZ{m#>uepdd<(T>aJlPu$JZjWw_D266=O9Pd5Y3z>Bc|pq&@GGtr#9L zm?`$q-01yA;-6$Xv_a5lb#Sn!cYRm1WiHhx#T_hHaHBkBolkg`>bn?$wfcU$6Tw5G zg76iGVBU(zZaUvnLy4d0d@0wL>3oT|0tl?bbZ&b6c!ir+yl^M4eBf;)4eM=bSuYx6 zamf1Ek3nqY{ba-NxgWVmYBHWUo`$A}cYM@24a4I+-%!?lhO|BL_I~PHiFVH0R|%hO zq)WMzec7OtBE>w*+$b$$YG!Ko>+}Ow%R8AVIiHzt=5$ds>%Z1-O6W`=T-@Y2jV1_7 zRb**SIOVV-IxRMR%9GeA6+c8Q!SoC=q(k+dFVB@*`1)LDi)_w!U`|Ez8aO4%kD*9N zUn<^V2{Wk8K-{~{n-Dha*kMZ?N=RC#pGJ9Qkg|yLtj5_>>-ncY>f;a5o)Ir+h=^wB zyunq0BE&u73}FwUrf@#J^bpyB(!d{`Iake|FU{)YPTm)&c4pAv!a2>mXK#2{-ZbQ- z4#Dd?AXgl+FbS$4(#U=o%(30+lH(hcSjU{hnY7{Z}~>M*4Dktq{_&H9^^%3`y!j8pi4E{lVwoHfN{T za#ML-kYL?j*38@BARPVv;em{W_4e27Yxr9|FUfD)exGJ|Us0)6JGDs6MAkEk!@)*d zRTJ*WE;=_CJm6OxCD}?0cb;PX*0wsQ1RVEjAHIn0>A1hY+u2dk`ZMI50X~7%S#n+u zFqo$ygFwk-ie2&>rPBKbsp^mx7*n*1le$ytRU;oduFdN~kIRzx;6gpFkC;D3)(1}9 zGIguls$j-Gy>h->J&HijcSnb`vM80J5uX%qwCt+;KN{!H?f8!}Vh*!Zz-n&x?ntzo zBUlp&WX7Oze!?1HWjieD=%%`=lCH9@prM~D!rev32yEzuz#Zn&9Fjx8swk{I$_;7f zhC4*YTELDz>$3tIxf{Eo0j?;}QF9plnIdz9ar}jxsRa~n0TY+B0`L!69?AQcf>ktC z4-pS3M8Uv?p&u59a@BNmaF>+@>tT>63{Vxm->bq8Hb6O|fp@Had`d`n1d1Q1fQN?* z%Jnb@2m&PH9P&D>1qSVbbH{*S$7d6$nu4GZ2ymYas2!j!*%AC$?LTz=lkA9#I@$## z3KBowf9H^`^6^1j!lI%O;AJmV?2skQ>IhfY&K0Qd3Dc^(*g0ZB;$TCdJ|@5kUn+JU z8Yr}*6QC$q>Cn!&BM!eA9S0H?g-U@nads|fdnGqVm%~HB4#le5xuRYC_>NnQ{|ICV zyko}MJArlGF|KwlMR#FFrvqRe9?EdItS9C7@nI0gk;Ok*$ z?~KBM5P(Cw$?+~fZ{!7`k#fAIFdc}FhYHFGt>KSB8T#uQ+50=&OCfm`<+zN z*w@ZO*a7W=Lt(HWz}e+4s2E&Qzn~ybMk4Dg?d$5{3djcey1KYwrG4dik7%TU@*x<^ z3pzrI5}P~FEmmbB?(6$;1DTc2|F=K zVR11DNntxNgo7~B4j~SKp%C^cN#yVHJpQ8R-vk0T0EuFNC4iE&KE@sCWskzh@haJ4 z+!1y-kSZ|1pj}*07!X_p0^&1817n5{mY-K%7JR7BU-bLkIDY~CU#SeV>p$BFxN&SG z5Kxj<0a8qGC{^H3j#m@{g$qMq!cd42L`oV4krsstLPVt@5Woz-qq<{^fL4~{)i*pE z7hxhu7Z;ET;5>&WhKY!Zh#n*B0M88vzkkK|f5i+sI{&jFTwM|+JjNY4<{_pd{97Tq`kDm;iwHbv>ou^LfhNnfJOiVjtICHaMS*4!1;II=)yV$uo%JKRNBT)`^ zUM@IZc^x$1^H_HW9LUrig9HhK^bjbFyBkD8!~o^tj=_l_-R)1vJmPsM^EWyF)F+N$ zz=&~ZWAGm%5^x3jU-?rGTZr$qdSK0zn?AhA0Cu_6g2StbIf4*d(dFX&kt7e!Z`u# zjwf*Ze+H_)7?cAU$>Cw&!2dsfAUF&r1_K@5Ir>RJrGUWo@CS1H112U4gs&%H;)g-( z-(XOPC>#i7Pr$^afQb483=(O;0(&_9B3D96;ul&; zz}rsplN3E%Ncfw6Vo)*BlXez^iXSevoWO%goUDf!&}_fpi33WXq!ow5f1#Ct9xhe< zU513H#4r3Ler имя результирующего файла; по умолчанию, - совпадает с именем главного модуля, но с другим расширением - (соответствует типу исполняемого файла) - -stk размер стэка в мегабайтах (по умолчанию 2 Мб, - допустимо от 1 до 32 Мб) - -tab размер табуляции (используется для вычисления координат в - исходном коде), по умолчанию - 4 - -nochk <"ptibcwra"> отключить проверки при выполнении (см. ниже) - -lower разрешить ключевые слова и встроенные идентификаторы в - нижнем регистре (по умолчанию) - -upper только верхний регистр для ключевых слов и встроенных - идентификаторов - -def <имя> задать символ условной компиляции - -ver версия программы (только для kosdll) - -uses вывести список импортированных модулей - - параметр -nochk задается в виде строки из символов: - "p" - указатели - "t" - типы - "i" - индексы - "b" - неявное приведение INTEGER к BYTE - "c" - диапазон аргумента функции CHR - "w" - диапазон аргумента функции WCHR - "r" - эквивалентно "bcw" - "a" - все проверки - - Порядок символов может быть любым. Наличие в строке того или иного - символа отключает соответствующую проверку. - - Например: -nochk it - отключить проверку индексов и охрану типа. - -nochk a - отключить все отключаемые проверки. - - Например: - - Compiler.exe "C:\example.ob07" win32con -out "C:\example.exe" -stk 1 - Compiler.exe "C:\example.ob07" win32dll -out "C:\example.dll" - Compiler.exe "C:\example.ob07" win32gui -out "C:\example.exe" -stk 4 - Compiler.exe "C:\example.ob07" win32con -out "C:\example.exe" -nochk pti - Compiler.kex "/tmp0/1/example.ob07" kosexe -out "/tmp0/1/example.kex" -stk 4 - Compiler.kex "/tmp0/1/example.ob07" kosdll -out "/tmp0/1/mydll.obj" -ver 2.7 - Compiler.exe "C:\example.ob07" linux32exe -out "C:\example" -stk 1 -nochk a - - В случае успешной компиляции, компилятор передает код завершения 0, иначе 1. -При работе компилятора в KolibriOS, код завершения не передается. - ------------------------------------------------------------------------------- - Отличия от оригинала - -1. Расширен псевдомодуль SYSTEM -2. В идентификаторах допускается символ "_" -3. Добавлены системные флаги -4. Усовершенствован оператор CASE (добавлены константные выражения в - метках вариантов и необязательная ветка ELSE) -5. Расширен набор стандартных процедур -6. Семантика охраны/проверки типа уточнена для нулевого указателя -7. Добавлены однострочные комментарии (начинаются с пары символов "//") -8. Разрешено наследование от типа-указателя -9. Добавлен синтаксис для импорта процедур из внешних библиотек -10. "Строки" можно заключать также в одиночные кавычки: 'строка' -11. Добавлен тип WCHAR -12. Добавлена операция конкатенации строковых и символьных констант -13. Возможен импорт модулей с указанием пути и имени файла -14. Добавлен специальный синтаксис для условной компиляции (см. CC.txt) -15. Имя процедуры в конце объявления (после END) необязательно -16. Разрешено использовать нижний регистр для ключевых слов - ------------------------------------------------------------------------------- - Особенности реализации - -1. Основные типы - - Тип Диапазон значений Размер, байт - - INTEGER -2147483648 .. 2147483647 4 - REAL 4.94E-324 .. 1.70E+308 8 - CHAR символ ASCII (0X .. 0FFX) 1 - BOOLEAN FALSE, TRUE 1 - SET множество из целых чисел {0 .. 31} 4 - BYTE 0 .. 255 1 - WCHAR символ юникода (0X .. 0FFFFX) 2 - -2. Максимальная длина идентификаторов - 255 символов -3. Максимальная длина строковых констант - 511 символов (UTF-8) -4. Максимальная размерность открытых массивов - 5 -5. Процедура NEW заполняет нулями выделенный блок памяти -6. Глобальные и локальные переменные инициализируются нулями -7. В отличие от многих Oberon-реализаций, сборщик мусора и динамическая - модульность отсутствуют -8. Тип BYTE в выражениях всегда приводится к INTEGER -9. Контроль переполнения значений выражений не производится -10. Ошибки времени выполнения: - - 1 ASSERT(x), при x = FALSE - 2 разыменование нулевого указателя - 3 целочисленное деление на неположительное число - 4 вызов процедуры через процедурную переменную с нулевым значением - 5 ошибка охраны типа - 6 нарушение границ массива - 7 непредусмотренное значение выражения в операторе CASE - 8 ошибка копирования массивов v := x, если LEN(v) < LEN(x) - 9 CHR(x), если (x < 0) OR (x > 255) -10 WCHR(x), если (x < 0) OR (x > 65535) -11 неявное приведение x:INTEGER к v:BYTE, если (x < 0) OR (x > 255) - ------------------------------------------------------------------------------- - Псевдомодуль SYSTEM - - Псевдомодуль SYSTEM содержит низкоуровневые и небезопасные процедуры, -ошибки при использовании процедур псевдомодуля SYSTEM могут привести к -повреждению данных времени выполнения и аварийному завершению программы. - - PROCEDURE ADR(v: любой тип): INTEGER - v - переменная или процедура; - возвращает адрес v - - PROCEDURE SADR(x: строковая константа (CHAR UTF-8)): INTEGER - возвращает адрес x - - PROCEDURE WSADR(x: строковая константа (WCHAR)): INTEGER - возвращает адрес x - - PROCEDURE VAL(v: любой тип; T): T - v - переменная; - интерпретирует v, как переменную типа T - - PROCEDURE SIZE(T): INTEGER - возвращает размер типа T - - PROCEDURE TYPEID(T): INTEGER - T - тип-запись или тип-указатель, - возвращает номер типа в таблице типов-записей - - PROCEDURE INF(): REAL - возвращает специальное вещественное значение "бесконечность" - - PROCEDURE MOVE(Source, Dest, n: INTEGER) - Копирует n байт памяти из Source в Dest, - области Source и Dest не могут перекрываться - - PROCEDURE GET(a: INTEGER; - VAR v: любой основной тип, PROCEDURE, POINTER) - v := Память[a] - - PROCEDURE GET8(a: INTEGER; - VAR x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) - Эквивалентно - SYSTEM.MOVE(a, SYSTEM.ADR(x), 1) - - PROCEDURE GET16(a: INTEGER; - VAR x: INTEGER, SET, WCHAR, SYSTEM.CARD32) - Эквивалентно - SYSTEM.MOVE(a, SYSTEM.ADR(x), 2) - - PROCEDURE GET32(a: INTEGER; VAR x: INTEGER, SET, SYSTEM.CARD32) - Эквивалентно - SYSTEM.MOVE(a, SYSTEM.ADR(x), 4) - - PROCEDURE PUT(a: INTEGER; x: любой основной тип, PROCEDURE, POINTER) - Память[a] := x; - Если x: BYTE или x: WCHAR, то значение x будет расширено - до 32 бит, для записи байтов использовать SYSTEM.PUT8, - для WCHAR -- SYSTEM.PUT16 - - PROCEDURE PUT8(a: INTEGER; - x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) - Память[a] := младшие 8 бит (x) - - PROCEDURE PUT16(a: INTEGER; - x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) - Память[a] := младшие 16 бит (x) - - PROCEDURE PUT32(a: INTEGER; - x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) - Память[a] := младшие 32 бит (x) - - PROCEDURE COPY(VAR Source: любой тип; VAR Dest: любой тип; n: INTEGER) - Копирует n байт памяти из Source в Dest. - Эквивалентно - SYSTEM.MOVE(SYSTEM.ADR(Source), SYSTEM.ADR(Dest), n) - - PROCEDURE CODE(byte1, byte2,... : INTEGER) - Вставка машинного кода, - byte1, byte2 ... - константы в диапазоне 0..255, - например: - SYSTEM.CODE(08BH, 045H, 008H) (* mov eax, dword [ebp + 08h] *) - - Также, в модуле SYSTEM определен тип CARD32 (4 байта). Для типа CARD32 не -допускаются никакие явные операции, за исключением присваивания. - - Функции псевдомодуля SYSTEM нельзя использовать в константных выражениях. - ------------------------------------------------------------------------------- - Системные флаги - - При объявлении процедурных типов и глобальных процедур, после ключевого -слова PROCEDURE может быть указан флаг соглашения о вызове: [stdcall], -[cdecl], [fastcall], [ccall], [windows], [linux], [oberon]. Например: - - PROCEDURE [ccall] MyProc (x, y, z: INTEGER): INTEGER; - - Если указан флаг [ccall], то принимается соглашение cdecl, но перед -вызовом указатель стэка будет выравнен по границе 16 байт. - Флаг [windows] - синоним для [stdcall], [linux] - синоним для [ccall]. - Знак "-" после имени флага ([stdcall-], [linux-], ...) означает, что -результат процедуры можно игнорировать (не допускается для типа REAL). - Если флаг не указан или указан флаг [oberon], то принимается внутреннее -соглашение о вызове. - - При объявлении типов-записей, после ключевого слова RECORD может быть -указан флаг [noalign]. Флаг [noalign] означает отсутствие выравнивания полей -записи. Записи с системным флагом не могут иметь базовый тип и не могут быть -базовыми типами для других записей. - Для использования системных флагов, требуется импортировать SYSTEM. - ------------------------------------------------------------------------------- - Оператор CASE - - Синтаксис оператора CASE: - - CaseStatement = - CASE Expression OF Case {"|" Case} - [ELSE StatementSequence] END. - Case = [CaseLabelList ":" StatementSequence]. - CaseLabelList = CaseLabels {"," CaseLabels}. - CaseLabels = ConstExpression [".." ConstExpression]. - - Например: - - CASE x OF - |-1: DoSomething1 - | 1: DoSomething2 - | 0: DoSomething3 - ELSE - DoSomething4 - END - - В метках вариантов можно использовать константные выражения, ветка ELSE -необязательна. Если значение x не соответствует ни одному варианту и ELSE -отсутствует, то программа прерывается с ошибкой времени выполнения. - ------------------------------------------------------------------------------- - Тип WCHAR - - Тип WCHAR добавлен в язык для удобной поддежки юникода. Для типов WCHAR и -ARRAY OF WCHAR допускаются все те же операции, как для типов CHAR и -ARRAY OF CHAR, за исключением встроенной процедуры CHR, которая возвращает -только тип CHAR. Для получения значения типа WCHAR, следует использовать -процедуру WCHR вместо CHR. Для правильной работы с типом, необходимо сохранять -исходный код в кодировке UTF-8 с BOM. - ------------------------------------------------------------------------------- - Конкатенация строковых и символьных констант - - Допускается конкатенация ("+") константных строк и символов типа CHAR: - - str = CHR(39) + "string" + CHR(39); (* str = "'string'" *) - - newline = 0DX + 0AX; - ------------------------------------------------------------------------------- - Проверка и охрана типа нулевого указателя - - Оригинальное сообщение о языке не определяет поведение программы при -выполнении охраны p(T) и проверки типа p IS T при p = NIL. Во многих -Oberon-реализациях выполнение такой операции приводит к ошибке времени -выполнения. В данной реализации охрана типа нулевого указателя не приводит к -ошибке, а проверка типа дает результат FALSE. В ряде случаев это позволяет -значительно сократить частоту применения охраны типа. - ------------------------------------------------------------------------------- - Дополнительные стандартные процедуры - - DISPOSE (VAR v: любой_указатель) - Освобождает память, выделенную процедурой NEW для - динамической переменной v^, и присваивает переменной v - значение NIL. - - COPY (x: ARRAY OF CHAR/WCHAR; VAR v: ARRAY OF CHAR/WCHAR); - v := x; - Если LEN(v) < LEN(x), то строка x будет скопирована - не полностью - - LSR (x, n: INTEGER): INTEGER - Логический сдвиг x на n бит вправо. - - MIN (a, b: INTEGER): INTEGER - Минимум из двух значений. - - MAX (a, b: INTEGER): INTEGER - Максимум из двух значений. - - BITS (x: INTEGER): SET - Интерпретирует x как значение типа SET. - Выполняется на этапе компиляции. - - LENGTH (s: ARRAY OF CHAR/WCHAR): INTEGER - Длина 0X-завершенной строки s, без учета символа 0X. - Если символ 0X отсутствует, функция возвращает длину - массива s. s не может быть константой. - - WCHR (n: INTEGER): WCHAR - Преобразование типа, аналогично CHR(n: INTEGER): CHAR - ------------------------------------------------------------------------------- - Импорт модулей с указанием пути и имени файла - -Примеры: - - IMPORT Math IN "./lib/math.ob07"; (* относительно текущего модуля *) - - IMPORT M1 IN "C:\lib\math.ob07"; (* абсолютный путь *) - ------------------------------------------------------------------------------- - Импортированные процедуры - - Синтаксис импорта: - - PROCEDURE [callconv, library, function] proc_name (FormalParam): Type; - - - callconv -- соглашение о вызове - - library -- имя файла динамической библиотеки (строковая константа) - - function -- имя импортируемой процедуры (строковая константа), если - указана пустая строка, то имя процедуры = proc_name - - например: - - PROCEDURE [windows, "kernel32.dll", ""] ExitProcess (code: INTEGER); - - PROCEDURE [stdcall, "Console.obj", "con_exit"] exit (bCloseWindow: BOOLEAN); - - В конце объявления может быть добавлено (необязательно) "END proc_name;" - - Объявления импортированных процедур должны располагаться в глобальной - области видимости модуля после объявления переменных, вместе с объявлением - "обычных" процедур, от которых импортированные отличаются только отсутствием - тела процедуры. В остальном, к таким процедурам применимы те же правила: - их можно вызвать, присвоить процедурной переменной или получить адрес. - - Так как импортированная процедура всегда имеет явное указание соглашения о - вызове, то совместимый процедурный тип тоже должен быть объявлен с указанием - соглашения о вызове: - - VAR - ExitProcess: PROCEDURE [windows] (code: INTEGER); - con_exit: PROCEDURE [stdcall] (bCloseWindow: BOOLEAN); - - В KolibriOS импортировать процедуры можно только из библиотек, размещенных - в /sys/lib. Импортировать и вызывать функции инициализации библиотек - (lib_init, START) при этом не нужно. - - Для Linux, импортированные процедуры не реализованы. - ------------------------------------------------------------------------------- - Скрытые параметры процедур - - Некоторые процедуры могут иметь скрытые параметры, они отсутствуют в списке -формальных параметров, но учитываются компилятором при трансляции вызовов. -Это возможно в следующих случаях: - -1. Процедура имеет формальный параметр открытый массив: - PROCEDURE Proc (x: ARRAY OF ARRAY OF REAL); - Вызов транслируется так: - Proc(LEN(x), LEN(x[0]), SYSTEM.ADR(x)) -2. Процедура имеет формальный параметр-переменную типа RECORD: - PROCEDURE Proc (VAR x: Rec); - Вызов транслируется так: - Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) - - Скрытые параметры необходимо учитывать при связи с внешними приложениями. - ------------------------------------------------------------------------------- - Модуль RTL - - Все программы неявно используют модуль RTL. Компилятор транслирует -некоторые операции (проверка и охрана типа, сравнение строк, сообщения об -ошибках времени выполнения и др.) как вызовы процедур этого модуля. Не -следует вызывать эти процедуры явно. - Сообщения об ошибках времени выполнения выводятся в диалоговых окнах -(Windows), в терминал (Linux), на доску отладки (KolibriOS). - ------------------------------------------------------------------------------- - Модуль API - - Существуют несколько реализаций модуля API (для различных ОС). - Как и модуль RTL, модуль API не предназначен для прямого использования. -Он обеспечивает связь RTL с ОС. - ------------------------------------------------------------------------------- - Генерация исполняемых файлов DLL - - Разрешается экспортировать только процедуры. Для этого, процедура должна -находиться в главном модуле программы, и ее имя должно быть отмечено символом -экспорта ("*"). Нельзя экспортировать процедуры, которые импортированы из -других dll-библиотек. - - KolibriOS DLL всегда экспортируют идентификаторы "version" (версия -программы) и "lib_init" - адрес процедуры инициализации DLL: - - PROCEDURE [stdcall] lib_init (): INTEGER - -Эта процедура должна быть вызвана перед использованием DLL. -Процедура всегда возвращает 1. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/API.ob07 b/programs/develop/oberon07/lib/KolibriOS/API.ob07 deleted file mode 100644 index 4151eb236..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/API.ob07 +++ /dev/null @@ -1,290 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018, 2020-2022, Anton Krotov - All rights reserved. -*) - -MODULE API; - -IMPORT SYSTEM, K := KOSAPI; - - -CONST - - eol* = 0DX + 0AX; - BIT_DEPTH* = 32; - - MAX_SIZE = 16 * 400H; - HEAP_SIZE = 1 * 100000H; - - _new = 1; - _dispose = 2; - - SizeOfHeader = 36; - - -TYPE - - CRITICAL_SECTION = ARRAY 2 OF INTEGER; - - -VAR - - heap, endheap: INTEGER; - pockets: ARRAY MAX_SIZE DIV 32 + 1 OF INTEGER; - - CriticalSection: CRITICAL_SECTION; - - multi: BOOLEAN; - - base*: INTEGER; - - -PROCEDURE [stdcall] zeromem* (dwords: INTEGER; adr: INTEGER); -BEGIN - SYSTEM.CODE( - 0FCH, (* cld *) - 031H, 0C0H, (* xor eax, eax *) - 057H, (* push edi *) - 08BH, 07DH, 00CH, (* mov edi, dword [ebp + 12] *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) - 0F3H, 0ABH, (* rep stosd *) - 05FH (* pop edi *) - ) -END zeromem; - - -PROCEDURE mem_commit* (adr, size: INTEGER); -VAR - tmp: INTEGER; -BEGIN - FOR tmp := adr TO adr + size - 1 BY 4096 DO - SYSTEM.PUT(tmp, 0) - END -END mem_commit; - - -PROCEDURE switch_task; -BEGIN - K.sysfunc2(68, 1) -END switch_task; - - -PROCEDURE futex_create (ptr: INTEGER): INTEGER; - RETURN K.sysfunc3(77, 0, ptr) -END futex_create; - - -PROCEDURE futex_wait (futex, value, timeout: INTEGER); -BEGIN - K.sysfunc5(77, 2, futex, value, timeout) -END futex_wait; - - -PROCEDURE futex_wake (futex, number: INTEGER); -BEGIN - K.sysfunc4(77, 3, futex, number) -END futex_wake; - - -PROCEDURE EnterCriticalSection* (VAR CriticalSection: CRITICAL_SECTION); -BEGIN - switch_task; - futex_wait(CriticalSection[0], 1, 10000); - CriticalSection[1] := 1 -END EnterCriticalSection; - - -PROCEDURE LeaveCriticalSection* (VAR CriticalSection: CRITICAL_SECTION); -BEGIN - CriticalSection[1] := 0; - futex_wake(CriticalSection[0], 1) -END LeaveCriticalSection; - - -PROCEDURE InitializeCriticalSection* (VAR CriticalSection: CRITICAL_SECTION); -BEGIN - CriticalSection[0] := futex_create(SYSTEM.ADR(CriticalSection[1])); - CriticalSection[1] := 0 -END InitializeCriticalSection; - - -PROCEDURE __NEW (size: INTEGER): INTEGER; -VAR - res, idx, temp: INTEGER; -BEGIN - IF size <= MAX_SIZE THEN - idx := ASR(size, 5); - res := pockets[idx]; - IF res # 0 THEN - SYSTEM.GET(res, pockets[idx]); - SYSTEM.PUT(res, size); - INC(res, 4) - ELSE - temp := 0; - IF heap + size >= endheap THEN - IF K.sysfunc2(18, 16) > ASR(HEAP_SIZE, 10) THEN - temp := K.sysfunc3(68, 12, HEAP_SIZE) - ELSE - temp := 0 - END; - IF temp # 0 THEN - mem_commit(temp, HEAP_SIZE); - heap := temp; - endheap := heap + HEAP_SIZE - ELSE - temp := -1 - END - END; - IF (heap # 0) & (temp # -1) THEN - SYSTEM.PUT(heap, size); - res := heap + 4; - heap := heap + size - ELSE - res := 0 - END - END - ELSE - IF K.sysfunc2(18, 16) > ASR(size, 10) THEN - res := K.sysfunc3(68, 12, size); - IF res # 0 THEN - mem_commit(res, size); - SYSTEM.PUT(res, size); - INC(res, 4) - END - ELSE - res := 0 - END - END; - IF (res # 0) & (size <= MAX_SIZE) THEN - zeromem(ASR(size, 2) - 1, res) - END - RETURN res -END __NEW; - - -PROCEDURE __DISPOSE (ptr: INTEGER): INTEGER; -VAR - size, idx: INTEGER; -BEGIN - DEC(ptr, 4); - SYSTEM.GET(ptr, size); - IF size <= MAX_SIZE THEN - idx := ASR(size, 5); - SYSTEM.PUT(ptr, pockets[idx]); - pockets[idx] := ptr - ELSE - size := K.sysfunc3(68, 13, ptr) - END - RETURN 0 -END __DISPOSE; - - -PROCEDURE NEW_DISPOSE (func, arg: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF multi THEN - EnterCriticalSection(CriticalSection) - END; - - IF func = _new THEN - res := __NEW(arg) - ELSIF func = _dispose THEN - res := __DISPOSE(arg) - END; - - IF multi THEN - LeaveCriticalSection(CriticalSection) - END - - RETURN res -END NEW_DISPOSE; - - -PROCEDURE _NEW* (size: INTEGER): INTEGER; - RETURN NEW_DISPOSE(_new, size) -END _NEW; - - -PROCEDURE _DISPOSE* (ptr: INTEGER): INTEGER; - RETURN NEW_DISPOSE(_dispose, ptr) -END _DISPOSE; - - -PROCEDURE exit* (p1: INTEGER); -BEGIN - K.sysfunc1(-1) -END exit; - - -PROCEDURE exit_thread* (p1: INTEGER); -BEGIN - K.sysfunc1(-1) -END exit_thread; - - -PROCEDURE OutStr (pchar: INTEGER); -VAR - c: CHAR; -BEGIN - IF pchar # 0 THEN - REPEAT - SYSTEM.GET(pchar, c); - IF c # 0X THEN - K.OutChar(c) - END; - INC(pchar) - UNTIL c = 0X - END -END OutStr; - - -PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); -BEGIN - IF lpCaption # 0 THEN - K.OutLn; - OutStr(lpCaption); - K.OutChar(":"); - K.OutLn - END; - OutStr(lpText); - IF lpCaption # 0 THEN - K.OutLn - END -END DebugMsg; - - -PROCEDURE init* (import_, code: INTEGER); -BEGIN - multi := FALSE; - base := code - SizeOfHeader; - K.sysfunc2(68, 11); - InitializeCriticalSection(CriticalSection); - K._init(import_) -END init; - - -PROCEDURE SetMultiThr* (value: BOOLEAN); -BEGIN - multi := value -END SetMultiThr; - - -PROCEDURE GetTickCount* (): INTEGER; - RETURN K.sysfunc2(26, 9) * 10 -END GetTickCount; - - -PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; - RETURN 0 -END dllentry; - - -PROCEDURE sofinit*; -END sofinit; - - -END API. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/Args.ob07 b/programs/develop/oberon07/lib/KolibriOS/Args.ob07 deleted file mode 100644 index 889059d0a..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/Args.ob07 +++ /dev/null @@ -1,100 +0,0 @@ -(* - Copyright 2016, 2018 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 Args; - -IMPORT sys := SYSTEM, KOSAPI; - -CONST - - MAX_PARAM = 1024; - -VAR - - Params: ARRAY MAX_PARAM, 2 OF INTEGER; - argc*: INTEGER; - -PROCEDURE GetChar(adr: INTEGER): CHAR; -VAR res: CHAR; -BEGIN - sys.GET(adr, res) - RETURN res -END GetChar; - -PROCEDURE ParamParse; -VAR p, count, name: INTEGER; c: CHAR; cond: INTEGER; - - PROCEDURE ChangeCond(A, B, C: INTEGER; c: CHAR; VAR cond: INTEGER); - BEGIN - IF (c <= 20X) & (c # 0X) THEN - cond := A - ELSIF c = 22X THEN - cond := B - ELSIF c = 0X THEN - cond := 6 - ELSE - cond := C - END - END ChangeCond; - -BEGIN - p := KOSAPI.GetCommandLine(); - name := KOSAPI.GetName(); - Params[0, 0] := name; - WHILE GetChar(name) # 0X DO - INC(name) - END; - Params[0, 1] := name - 1; - cond := 0; - count := 1; - WHILE (argc < MAX_PARAM) & (cond # 6) DO - c := GetChar(p); - CASE cond OF - |0: ChangeCond(0, 4, 1, c, cond); IF cond = 1 THEN Params[count, 0] := p END - |1: ChangeCond(0, 3, 1, c, cond); IF cond IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END - |3: ChangeCond(3, 1, 3, c, cond); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END - |4: ChangeCond(5, 0, 5, c, cond); IF cond = 5 THEN Params[count, 0] := p END - |5: ChangeCond(5, 1, 5, c, cond); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END - ELSE - END; - INC(p) - END; - argc := count -END ParamParse; - -PROCEDURE GetArg*(n: INTEGER; VAR s: ARRAY OF CHAR); -VAR i, j, len: INTEGER; c: CHAR; -BEGIN - j := 0; - IF n < argc THEN - len := LEN(s) - 1; - i := Params[n, 0]; - WHILE (j < len) & (i <= Params[n, 1]) DO - c := GetChar(i); - IF c # 22X THEN - s[j] := c; - INC(j) - END; - INC(i); - END; - END; - s[j] := 0X -END GetArg; - -BEGIN - ParamParse -END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/ColorDlg.ob07 b/programs/develop/oberon07/lib/KolibriOS/ColorDlg.ob07 deleted file mode 100644 index 23c74e383..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/ColorDlg.ob07 +++ /dev/null @@ -1,105 +0,0 @@ -(* - Copyright 2016, 2018, 2020, 2022 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 ColorDlg; - -IMPORT sys := SYSTEM, KOSAPI; - -TYPE - - DRAW_WINDOW = PROCEDURE; - - TDialog = RECORD - _type, - procinfo, - com_area_name, - com_area, - start_path: INTEGER; - draw_window: DRAW_WINDOW; - status*, - X, Y, - color_type, - color*: INTEGER; - - procinf: ARRAY 1024 OF CHAR; - s_com_area_name: ARRAY 32 OF CHAR - END; - - Dialog* = POINTER TO TDialog; - -VAR - - Dialog_start, Dialog_init: PROCEDURE [stdcall] (cd: Dialog); - -PROCEDURE Show*(cd: Dialog); -BEGIN - IF cd # NIL THEN - cd.X := 0; - cd.Y := 0; - Dialog_start(cd) - END -END Show; - -PROCEDURE Create*(draw_window: DRAW_WINDOW): Dialog; -VAR res: Dialog; -BEGIN - NEW(res); - IF res # NIL THEN - res.s_com_area_name := "FFFFFFFF_color_dlg"; - res.com_area := 0; - res._type := 0; - res.color_type := 0; - res.procinfo := sys.ADR(res.procinf[0]); - res.com_area_name := sys.ADR(res.s_com_area_name[0]); - res.start_path := sys.SADR("/sys/colrdial"); - res.draw_window := draw_window; - res.status := 0; - res.X := 0; - res.Y := 0; - res.color := 0; - Dialog_init(res) - END - RETURN res -END Create; - -PROCEDURE Destroy*(VAR cd: Dialog); -BEGIN - IF cd # NIL THEN - DISPOSE(cd) - END -END Destroy; - -PROCEDURE Load; -VAR Lib: INTEGER; - - PROCEDURE GetProc(Lib, v: INTEGER; name: ARRAY OF CHAR); - VAR a: INTEGER; - BEGIN - a := KOSAPI.GetProcAdr(name, Lib); - ASSERT(a # 0); - sys.PUT(v, a) - END GetProc; - -BEGIN - Lib := KOSAPI.LoadLib("/sys/Lib/Proc_lib.obj"); - GetProc(Lib, sys.ADR(Dialog_init), "ColorDialog_init"); - GetProc(Lib, sys.ADR(Dialog_start), "ColorDialog_start"); -END Load; - -BEGIN - Load -END ColorDlg. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/Console.ob07 b/programs/develop/oberon07/lib/KolibriOS/Console.ob07 deleted file mode 100644 index 7d80c4fb0..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/Console.ob07 +++ /dev/null @@ -1,94 +0,0 @@ -(* - Copyright 2016, 2018 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 Console; - -IMPORT ConsoleLib, In, Out; - - -CONST - - Black* = 0; Blue* = 1; Green* = 2; Cyan* = 3; - Red* = 4; Magenta* = 5; Brown* = 6; LightGray* = 7; - DarkGray* = 8; LightBlue* = 9; LightGreen* = 10; LightCyan* = 11; - LightRed* = 12; LightMagenta* = 13; Yellow* = 14; White* = 15; - - -PROCEDURE SetCursor* (X, Y: INTEGER); -BEGIN - ConsoleLib.set_cursor_pos(X, Y) -END SetCursor; - - -PROCEDURE GetCursor* (VAR X, Y: INTEGER); -BEGIN - ConsoleLib.get_cursor_pos(X, Y) -END GetCursor; - - -PROCEDURE Cls*; -BEGIN - ConsoleLib.cls -END Cls; - - -PROCEDURE SetColor* (FColor, BColor: INTEGER); -VAR - res: INTEGER; - -BEGIN - IF (FColor IN {0..15}) & (BColor IN {0..15}) THEN - res := ConsoleLib.set_flags(LSL(BColor, 4) + FColor) - END -END SetColor; - - -PROCEDURE GetCursorX* (): INTEGER; -VAR - x, y: INTEGER; - -BEGIN - ConsoleLib.get_cursor_pos(x, y) - RETURN x -END GetCursorX; - - -PROCEDURE GetCursorY* (): INTEGER; -VAR - x, y: INTEGER; - -BEGIN - ConsoleLib.get_cursor_pos(x, y) - RETURN y -END GetCursorY; - - -PROCEDURE open*; -BEGIN - ConsoleLib.open(-1, -1, -1, -1, ""); - In.Open; - Out.Open -END open; - - -PROCEDURE exit* (bCloseWindow: BOOLEAN); -BEGIN - ConsoleLib.exit(bCloseWindow) -END exit; - - -END Console. diff --git a/programs/develop/oberon07/lib/KolibriOS/ConsoleLib.ob07 b/programs/develop/oberon07/lib/KolibriOS/ConsoleLib.ob07 deleted file mode 100644 index b1b1f2ac2..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/ConsoleLib.ob07 +++ /dev/null @@ -1,103 +0,0 @@ -(* - Copyright 2016, 2018, 2022 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 ConsoleLib; - -IMPORT sys := SYSTEM, KOSAPI; - -CONST - - COLOR_BLUE* = 001H; - COLOR_GREEN* = 002H; - COLOR_RED* = 004H; - COLOR_BRIGHT* = 008H; - BGR_BLUE* = 010H; - BGR_GREEN* = 020H; - BGR_RED* = 040H; - BGR_BRIGHT* = 080H; - IGNORE_SPECIALS* = 100H; - WINDOW_CLOSED* = 200H; - -TYPE - - gets2_callback* = PROCEDURE [stdcall] (keycode: INTEGER; pstr: INTEGER; VAR n, pos: INTEGER); - -VAR - - version* : INTEGER; - init* : PROCEDURE [stdcall] (wnd_width, wnd_height, scr_width, scr_height, title: INTEGER); - exit* : PROCEDURE [stdcall] (bCloseWindow: BOOLEAN); - write_asciiz* : PROCEDURE [stdcall] (string: INTEGER); - write_string* : PROCEDURE [stdcall] (string, length: INTEGER); - get_flags* : PROCEDURE [stdcall] (): INTEGER; - set_flags* : PROCEDURE [stdcall] (new_flags: INTEGER): INTEGER; - get_font_height* : PROCEDURE [stdcall] (): INTEGER; - get_cursor_height* : PROCEDURE [stdcall] (): INTEGER; - set_cursor_height* : PROCEDURE [stdcall] (new_height: INTEGER): INTEGER; - getch* : PROCEDURE [stdcall] (): INTEGER; - getch2* : PROCEDURE [stdcall] (): INTEGER; - kbhit* : PROCEDURE [stdcall] (): INTEGER; - gets* : PROCEDURE [stdcall] (str, n: INTEGER): INTEGER; - gets2* : PROCEDURE [stdcall] (callback: gets2_callback; str, n: INTEGER): INTEGER; - cls* : PROCEDURE [stdcall] (); - get_cursor_pos* : PROCEDURE [stdcall] (VAR x, y: INTEGER); - set_cursor_pos* : PROCEDURE [stdcall] (x, y: INTEGER); - set_title* : PROCEDURE [stdcall] (title: INTEGER); - -PROCEDURE open*(wnd_width, wnd_height, scr_width, scr_height: INTEGER; title: ARRAY OF CHAR); -BEGIN - init(wnd_width, wnd_height, scr_width, scr_height, sys.ADR(title[0])) -END open; - -PROCEDURE main; -VAR Lib: INTEGER; - - PROCEDURE GetProc(Lib, v: INTEGER; name: ARRAY OF CHAR); - VAR a: INTEGER; - BEGIN - a := KOSAPI.GetProcAdr(name, Lib); - ASSERT(a # 0); - sys.PUT(v, a) - END GetProc; - -BEGIN - Lib := KOSAPI.LoadLib("/sys/lib/Console.obj"); - ASSERT(Lib # 0); - GetProc(Lib, sys.ADR(version), "version"); - GetProc(Lib, sys.ADR(init), "con_init"); - GetProc(Lib, sys.ADR(exit), "con_exit"); - GetProc(Lib, sys.ADR(write_asciiz), "con_write_asciiz"); - GetProc(Lib, sys.ADR(write_string), "con_write_string"); - GetProc(Lib, sys.ADR(get_flags), "con_get_flags"); - GetProc(Lib, sys.ADR(set_flags), "con_set_flags"); - GetProc(Lib, sys.ADR(get_font_height), "con_get_font_height"); - GetProc(Lib, sys.ADR(get_cursor_height), "con_get_cursor_height"); - GetProc(Lib, sys.ADR(set_cursor_height), "con_set_cursor_height"); - GetProc(Lib, sys.ADR(getch), "con_getch"); - GetProc(Lib, sys.ADR(getch2), "con_getch2"); - GetProc(Lib, sys.ADR(kbhit), "con_kbhit"); - GetProc(Lib, sys.ADR(gets), "con_gets"); - GetProc(Lib, sys.ADR(gets2), "con_gets2"); - GetProc(Lib, sys.ADR(cls), "con_cls"); - GetProc(Lib, sys.ADR(get_cursor_pos), "con_get_cursor_pos"); - GetProc(Lib, sys.ADR(set_cursor_pos), "con_set_cursor_pos"); - GetProc(Lib, sys.ADR(set_title), "con_set_title"); -END main; - -BEGIN - main -END ConsoleLib. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/DateTime.ob07 b/programs/develop/oberon07/lib/KolibriOS/DateTime.ob07 deleted file mode 100644 index 12291065f..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/DateTime.ob07 +++ /dev/null @@ -1,141 +0,0 @@ -(* - Copyright 2016, 2018 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 DateTime; - -IMPORT KOSAPI; - -CONST ERR* = -7.0E5; - -PROCEDURE Encode*(Year, Month, Day, Hour, Min, Sec: INTEGER): REAL; -VAR d, i: INTEGER; M: ARRAY 14 OF CHAR; Res: REAL; -BEGIN - Res := ERR; - IF (Year >= 1) & (Year <= 9999) & (Month >= 1) & (Month <= 12) & - (Day >= 1) & (Day <= 31) & (Hour >= 0) & (Hour <= 23) & - (Min >= 0) & (Min <= 59) & (Sec >= 0) & (Sec <= 59) THEN - M := "_303232332323"; - IF (Year MOD 4 = 0) & (Year MOD 100 # 0) OR (Year MOD 400 = 0) THEN - M[2] := "1" - END; - IF Day <= ORD(M[Month]) - ORD("0") + 28 THEN - DEC(Year); - d := Year * 365 + (Year DIV 4) - (Year DIV 100) + (Year DIV 400) + Day - 693594; - FOR i := 1 TO Month - 1 DO - d := d + ORD(M[i]) - ORD("0") + 28 - END; - Res := FLT(d) + FLT(Hour * 3600000 + Min * 60000 + Sec * 1000) / 86400000.0 - END - END - RETURN Res -END Encode; - -PROCEDURE Decode*(Date: REAL; VAR Year, Month, Day, Hour, Min, Sec: INTEGER): BOOLEAN; -VAR Res, flag: BOOLEAN; d, t, i: INTEGER; M: ARRAY 14 OF CHAR; - - PROCEDURE MonthDay(n: INTEGER; VAR d, Month: INTEGER; M: ARRAY OF CHAR): BOOLEAN; - VAR Res: BOOLEAN; - BEGIN - Res := FALSE; - IF d > ORD(M[n]) - ORD("0") + 28 THEN - d := d - ORD(M[n]) + ORD("0") - 28; - INC(Month); - Res := TRUE - END - RETURN Res - END MonthDay; - -BEGIN - IF (Date >= -693593.0) & (Date < 2958466.0) THEN - d := FLOOR(Date); - t := FLOOR((Date - FLT(d)) * 86400000.0); - d := d + 693593; - Year := 1; - Month := 1; - WHILE d > 0 DO - d := d - 365 - ORD((Year MOD 4 = 0) & (Year MOD 100 # 0) OR (Year MOD 400 = 0)); - INC(Year) - END; - IF d < 0 THEN - DEC(Year); - d := d + 365 + ORD((Year MOD 4 = 0) & (Year MOD 100 # 0) OR (Year MOD 400 = 0)) - END; - INC(d); - M := "_303232332323"; - IF (Year MOD 4 = 0) & (Year MOD 100 # 0) OR (Year MOD 400 = 0) THEN - M[2] := "1" - END; - i := 1; - flag := TRUE; - WHILE flag & (i <= 12) DO - flag := MonthDay(i, d, Month, M); - INC(i) - END; - Day := d; - Hour := t DIV 3600000; - t := t MOD 3600000; - Min := t DIV 60000; - t := t MOD 60000; - Sec := t DIV 1000; - Res := TRUE - ELSE - Res := FALSE - END - RETURN Res -END Decode; - -PROCEDURE Now*(VAR Year, Month, Day, Hour, Min, Sec, Msec: INTEGER); -VAR date, time: INTEGER; -BEGIN - date := KOSAPI.sysfunc1(29); - time := KOSAPI.sysfunc1(3); - - Year := date MOD 16; - date := date DIV 16; - Year := (date MOD 16) * 10 + Year; - date := date DIV 16; - - Month := date MOD 16; - date := date DIV 16; - Month := (date MOD 16) * 10 + Month; - date := date DIV 16; - - Day := date MOD 16; - date := date DIV 16; - Day := (date MOD 16) * 10 + Day; - date := date DIV 16; - - Hour := time MOD 16; - time := time DIV 16; - Hour := (time MOD 16) * 10 + Hour; - time := time DIV 16; - - Min := time MOD 16; - time := time DIV 16; - Min := (time MOD 16) * 10 + Min; - time := time DIV 16; - - Sec := time MOD 16; - time := time DIV 16; - Sec := (time MOD 16) * 10 + Sec; - time := time DIV 16; - - Year := Year + 2000; - Msec := 0 -END Now; - -END DateTime. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/Debug.ob07 b/programs/develop/oberon07/lib/KolibriOS/Debug.ob07 deleted file mode 100644 index c7f98638e..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/Debug.ob07 +++ /dev/null @@ -1,292 +0,0 @@ -(* - Copyright 2016, 2018, 2022 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 KOSAPI, 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 := KOSAPI.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 := KOSAPI.sysfunc2(70, sys.ADR(info)) -END Open; - -END Debug. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/File.ob07 b/programs/develop/oberon07/lib/KolibriOS/File.ob07 deleted file mode 100644 index dc99a0c68..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/File.ob07 +++ /dev/null @@ -1,330 +0,0 @@ -(* - Copyright 2016, 2018, 2021 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 File; - -IMPORT sys := SYSTEM, KOSAPI; - - -CONST - - SEEK_BEG* = 0; SEEK_CUR* = 1; SEEK_END* = 2; - - -TYPE - - FNAME* = ARRAY 520 OF CHAR; - - FS* = POINTER TO rFS; - - rFS* = RECORD - subfunc*, pos*, hpos*, bytes*, buffer*: INTEGER; - name*: FNAME - END; - - FD* = POINTER TO rFD; - - rFD* = RECORD - attr*: INTEGER; - ntyp*: CHAR; - reserved: ARRAY 3 OF CHAR; - time_create*, date_create*, - time_access*, date_access*, - time_modif*, date_modif*, - size*, hsize*: INTEGER; - name*: FNAME - END; - - -PROCEDURE [stdcall] f_68_27 (file_name: INTEGER; VAR size: INTEGER): INTEGER; -BEGIN - sys.CODE( - 053H, (* push ebx *) - 06AH, 044H, (* push 68 *) - 058H, (* pop eax *) - 06AH, 01BH, (* push 27 *) - 05BH, (* pop ebx *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) - 0CDH, 040H, (* int 64 *) - 08BH, 04DH, 00CH, (* mov ecx, dword [ebp + 12] *) - 089H, 011H, (* mov dword [ecx], edx *) - 05BH, (* pop ebx *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 8 *) - ) - RETURN 0 -END f_68_27; - - -PROCEDURE Load* (FName: ARRAY OF CHAR; VAR size: INTEGER): INTEGER; - RETURN f_68_27(sys.ADR(FName[0]), size) -END Load; - - -PROCEDURE GetFileInfo* (FName: ARRAY OF CHAR; VAR Info: rFD): BOOLEAN; -VAR - res2: INTEGER; fs: rFS; - -BEGIN - fs.subfunc := 5; - fs.pos := 0; - fs.hpos := 0; - fs.bytes := 0; - fs.buffer := sys.ADR(Info); - COPY(FName, fs.name) - - RETURN KOSAPI.sysfunc22(70, sys.ADR(fs), res2) = 0 -END GetFileInfo; - - -PROCEDURE FileSize* (FName: ARRAY OF CHAR): INTEGER; -VAR - Info: rFD; - res: INTEGER; -BEGIN - IF GetFileInfo(FName, Info) THEN - res := Info.size - ELSE - res := -1 - END - RETURN res -END FileSize; - - -PROCEDURE Exists* (FName: ARRAY OF CHAR): BOOLEAN; -VAR - fd: rFD; -BEGIN - RETURN GetFileInfo(FName, fd) & ~(4 IN BITS(fd.attr)) -END Exists; - - -PROCEDURE Close* (VAR F: FS); -BEGIN - IF F # NIL THEN - DISPOSE(F) - END -END Close; - - -PROCEDURE Open* (FName: ARRAY OF CHAR): FS; -VAR - F: FS; - -BEGIN - - IF Exists(FName) THEN - NEW(F); - IF F # NIL THEN - F.subfunc := 0; - F.pos := 0; - F.hpos := 0; - F.bytes := 0; - F.buffer := 0; - COPY(FName, F.name) - END - ELSE - F := NIL - END - - RETURN F -END Open; - - -PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; -VAR - F: FS; - res, res2: INTEGER; - -BEGIN - - IF Exists(FName) THEN - NEW(F); - IF F # NIL THEN - F.subfunc := 8; - F.pos := 0; - F.hpos := 0; - F.bytes := 0; - F.buffer := 0; - COPY(FName, F.name); - res := KOSAPI.sysfunc22(70, sys.ADR(F^), res2); - DISPOSE(F) - ELSE - res := -1 - END - ELSE - res := -1 - END - - RETURN res = 0 -END Delete; - - -PROCEDURE Seek* (F: FS; Offset, Origin: INTEGER): INTEGER; -VAR - res: INTEGER; - fd: rFD; - -BEGIN - - IF (F # NIL) & GetFileInfo(F.name, fd) & (BITS(fd.attr) * {4} = {}) THEN - CASE Origin OF - |SEEK_BEG: F.pos := Offset - |SEEK_CUR: F.pos := F.pos + Offset - |SEEK_END: F.pos := fd.size + Offset - ELSE - END; - res := F.pos - ELSE - res := -1 - END - - RETURN res -END Seek; - - -PROCEDURE Read* (F: FS; Buffer, Count: INTEGER): INTEGER; -VAR - res, res2: INTEGER; - -BEGIN - - IF F # NIL THEN - F.subfunc := 0; - F.bytes := Count; - F.buffer := Buffer; - res := KOSAPI.sysfunc22(70, sys.ADR(F^), res2); - IF res2 > 0 THEN - F.pos := F.pos + res2 - END - ELSE - res2 := 0 - END - - RETURN res2 -END Read; - - -PROCEDURE Write* (F: FS; Buffer, Count: INTEGER): INTEGER; -VAR - res, res2: INTEGER; - -BEGIN - - IF F # NIL THEN - F.subfunc := 3; - F.bytes := Count; - F.buffer := Buffer; - res := KOSAPI.sysfunc22(70, sys.ADR(F^), res2); - IF res2 > 0 THEN - F.pos := F.pos + res2 - END - ELSE - res2 := 0 - END - - RETURN res2 -END Write; - - -PROCEDURE Create* (FName: ARRAY OF CHAR): FS; -VAR - F: FS; - res2: INTEGER; - -BEGIN - NEW(F); - - IF F # NIL THEN - F.subfunc := 2; - F.pos := 0; - F.hpos := 0; - F.bytes := 0; - F.buffer := 0; - COPY(FName, F.name); - IF KOSAPI.sysfunc22(70, sys.ADR(F^), res2) # 0 THEN - DISPOSE(F) - END - END - - RETURN F -END Create; - - -PROCEDURE DirExists* (FName: ARRAY OF CHAR): BOOLEAN; -VAR - fd: rFD; -BEGIN - RETURN GetFileInfo(FName, fd) & (4 IN BITS(fd.attr)) -END DirExists; - - -PROCEDURE CreateDir* (DirName: ARRAY OF CHAR): BOOLEAN; -VAR - F: FS; - res, res2: INTEGER; - -BEGIN - NEW(F); - - IF F # NIL THEN - F.subfunc := 9; - F.pos := 0; - F.hpos := 0; - F.bytes := 0; - F.buffer := 0; - COPY(DirName, F.name); - res := KOSAPI.sysfunc22(70, sys.ADR(F^), res2); - DISPOSE(F) - ELSE - res := -1 - END - - RETURN res = 0 -END CreateDir; - - -PROCEDURE DeleteDir* (DirName: ARRAY OF CHAR): BOOLEAN; -VAR - F: FS; - res, res2: INTEGER; - -BEGIN - - IF DirExists(DirName) THEN - NEW(F); - IF F # NIL THEN - F.subfunc := 8; - F.pos := 0; - F.hpos := 0; - F.bytes := 0; - F.buffer := 0; - COPY(DirName, F.name); - res := KOSAPI.sysfunc22(70, sys.ADR(F^), res2); - DISPOSE(F) - ELSE - res := -1 - END - ELSE - res := -1 - END - - RETURN res = 0 -END DeleteDir; - - -END File. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/HOST.ob07 b/programs/develop/oberon07/lib/KolibriOS/HOST.ob07 deleted file mode 100644 index fcc0463ca..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/HOST.ob07 +++ /dev/null @@ -1,553 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2022, Anton Krotov - All rights reserved. -*) - -MODULE HOST; - -IMPORT SYSTEM, K := KOSAPI, API; - - -CONST - - slash* = "/"; - eol* = 0DX + 0AX; - - bit_depth* = API.BIT_DEPTH; - maxint* = ROR(-2, 1); - minint* = ROR(1, 1); - - MAX_PARAM = 1024; - - -TYPE - - DAYS = ARRAY 12, 31, 2 OF INTEGER; - - FNAME = ARRAY 520 OF CHAR; - - FS = POINTER TO rFS; - - rFS = RECORD - subfunc, pos, hpos, bytes, buffer: INTEGER; - name: FNAME - END; - - FD = POINTER TO rFD; - - rFD = RECORD - attr: INTEGER; - ntyp: CHAR; - reserved: ARRAY 3 OF CHAR; - time_create, date_create, - time_access, date_access, - time_modif, date_modif, - size, hsize: INTEGER; - name: FNAME - END; - - -VAR - - - Console: BOOLEAN; - - days: DAYS; - - Params: ARRAY MAX_PARAM, 2 OF INTEGER; - argc*: INTEGER; - - maxreal*, inf*: REAL; - - -PROCEDURE [stdcall, "Console.obj", "con_init"] con_init (wnd_width, wnd_height, scr_width, scr_height, title: INTEGER); - -PROCEDURE [stdcall, "Console.obj", "con_exit"] con_exit (bCloseWindow: BOOLEAN); - -PROCEDURE [stdcall, "Console.obj", "con_write_string"] con_write_string (string, length: INTEGER); - - -PROCEDURE ExitProcess* (p1: INTEGER); -BEGIN - IF Console THEN - con_exit(FALSE) - END; - K.sysfunc1(-1) -END ExitProcess; - - -PROCEDURE OutChar* (c: CHAR); -BEGIN - IF Console THEN - con_write_string(SYSTEM.ADR(c), 1) - ELSE - K.sysfunc3(63, 1, ORD(c)) - END -END OutChar; - - -PROCEDURE GetFileInfo (FName: ARRAY OF CHAR; VAR Info: rFD): BOOLEAN; -VAR - res2: INTEGER; - fs: rFS; - -BEGIN - fs.subfunc := 5; - fs.pos := 0; - fs.hpos := 0; - fs.bytes := 0; - fs.buffer := SYSTEM.ADR(Info); - COPY(FName, fs.name) - RETURN K.sysfunc22(70, SYSTEM.ADR(fs), res2) = 0 -END GetFileInfo; - - -PROCEDURE Exists (FName: ARRAY OF CHAR): BOOLEAN; -VAR - fd: rFD; - -BEGIN - RETURN GetFileInfo(FName, fd) & ~(4 IN BITS(fd.attr)) -END Exists; - - -PROCEDURE Close (VAR F: FS); -BEGIN - IF F # NIL THEN - DISPOSE(F) - END -END Close; - - -PROCEDURE Open (FName: ARRAY OF CHAR): FS; -VAR - F: FS; - -BEGIN - IF Exists(FName) THEN - NEW(F); - IF F # NIL THEN - F.subfunc := 0; - F.pos := 0; - F.hpos := 0; - F.bytes := 0; - F.buffer := 0; - COPY(FName, F.name) - END - ELSE - F := NIL - END - - RETURN F -END Open; - - -PROCEDURE Read (F: FS; Buffer, Count: INTEGER): INTEGER; -VAR - res, res2: INTEGER; - -BEGIN - IF F # NIL THEN - F.subfunc := 0; - F.bytes := Count; - F.buffer := Buffer; - res := K.sysfunc22(70, SYSTEM.ADR(F^), res2); - IF res2 > 0 THEN - F.pos := F.pos + res2 - END - ELSE - res2 := 0 - END - - RETURN res2 -END Read; - - -PROCEDURE Write (F: FS; Buffer, Count: INTEGER): INTEGER; -VAR - res, res2: INTEGER; - -BEGIN - IF F # NIL THEN - F.subfunc := 3; - F.bytes := Count; - F.buffer := Buffer; - res := K.sysfunc22(70, SYSTEM.ADR(F^), res2); - IF res2 > 0 THEN - F.pos := F.pos + res2 - END - ELSE - res2 := 0 - END - - RETURN res2 -END Write; - - -PROCEDURE Create (FName: ARRAY OF CHAR): FS; -VAR - F: FS; - res2: INTEGER; - -BEGIN - NEW(F); - IF F # NIL THEN - F.subfunc := 2; - F.pos := 0; - F.hpos := 0; - F.bytes := 0; - F.buffer := 0; - COPY(FName, F.name); - IF K.sysfunc22(70, SYSTEM.ADR(F^), res2) # 0 THEN - DISPOSE(F) - END - END - - RETURN F -END Create; - - -PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; -VAR - n: INTEGER; - fs: FS; - -BEGIN - SYSTEM.GET(SYSTEM.ADR(F), fs); - n := Read(fs, SYSTEM.ADR(Buffer[0]), bytes); - IF n = 0 THEN - n := -1 - END - - RETURN n -END FileRead; - - -PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; -VAR - n: INTEGER; - fs: FS; - -BEGIN - SYSTEM.GET(SYSTEM.ADR(F), fs); - n := Write(fs, SYSTEM.ADR(Buffer[0]), bytes); - IF n = 0 THEN - n := -1 - END - - RETURN n -END FileWrite; - - -PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; -VAR - fs: FS; - res: INTEGER; - -BEGIN - fs := Create(FName); - SYSTEM.GET(SYSTEM.ADR(fs), res) - RETURN res -END FileCreate; - - -PROCEDURE FileClose* (F: INTEGER); -VAR - fs: FS; - -BEGIN - SYSTEM.GET(SYSTEM.ADR(F), fs); - Close(fs) -END FileClose; - - -PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; -VAR - fs: FS; - res: INTEGER; - -BEGIN - fs := Open(FName); - SYSTEM.GET(SYSTEM.ADR(fs), res) - RETURN res -END FileOpen; - - -PROCEDURE chmod* (FName: ARRAY OF CHAR); -END chmod; - - -PROCEDURE GetTickCount* (): INTEGER; - RETURN K.sysfunc2(26, 9) -END GetTickCount; - - -PROCEDURE AppAdr (): INTEGER; -VAR - buf: ARRAY 1024 OF CHAR; - a: INTEGER; - -BEGIN - a := K.sysfunc3(9, SYSTEM.ADR(buf), -1); - SYSTEM.GET(SYSTEM.ADR(buf) + 22, a) - RETURN a -END AppAdr; - - -PROCEDURE GetCommandLine (): INTEGER; -VAR - param: INTEGER; - -BEGIN - SYSTEM.GET(28 + AppAdr(), param) - RETURN param -END GetCommandLine; - - -PROCEDURE GetName (): INTEGER; -VAR - name: INTEGER; - -BEGIN - SYSTEM.GET(32 + AppAdr(), name) - RETURN name -END GetName; - - -PROCEDURE GetChar (adr: INTEGER): CHAR; -VAR - res: CHAR; - -BEGIN - SYSTEM.GET(adr, res) - RETURN res -END GetChar; - - -PROCEDURE ParamParse; -VAR - p, count, name, cond: INTEGER; - c: CHAR; - - - PROCEDURE ChangeCond (A, B, C: INTEGER; c: CHAR; VAR cond: INTEGER); - BEGIN - IF (c <= 20X) & (c # 0X) THEN - cond := A - ELSIF c = 22X THEN - cond := B - ELSIF c = 0X THEN - cond := 6 - ELSE - cond := C - END - END ChangeCond; - - -BEGIN - p := GetCommandLine(); - name := GetName(); - Params[0, 0] := name; - WHILE GetChar(name) # 0X DO - INC(name) - END; - Params[0, 1] := name - 1; - cond := 0; - count := 1; - WHILE (argc < MAX_PARAM) & (cond # 6) DO - c := GetChar(p); - CASE cond OF - |0: ChangeCond(0, 4, 1, c, cond); IF cond = 1 THEN Params[count, 0] := p END - |1: ChangeCond(0, 3, 1, c, cond); IF cond IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END - |3: ChangeCond(3, 1, 3, c, cond); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END - |4: ChangeCond(5, 0, 5, c, cond); IF cond = 5 THEN Params[count, 0] := p END - |5: ChangeCond(5, 1, 5, c, cond); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END - |6: - END; - INC(p) - END; - argc := count -END ParamParse; - - -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, j, len: INTEGER; - c: CHAR; - -BEGIN - j := 0; - IF n < argc THEN - len := LEN(s) - 1; - i := Params[n, 0]; - WHILE (j < len) & (i <= Params[n, 1]) DO - c := GetChar(i); - IF c # 22X THEN - s[j] := c; - INC(j) - END; - INC(i) - END - END; - s[j] := 0X -END GetArg; - - -PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); -VAR - n: INTEGER; - -BEGIN - n := K.sysfunc4(30, 2, SYSTEM.ADR(path[0]), LEN(path) - 2); - path[n - 1] := slash; - path[n] := 0X -END GetCurrentDirectory; - - -PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; - RETURN path[0] # slash -END isRelative; - - -PROCEDURE UnixTime* (): INTEGER; -VAR - date, time, year, month, day, hour, min, sec: INTEGER; - -BEGIN - date := K.sysfunc1(29); - time := K.sysfunc1(3); - - year := date MOD 16; - date := date DIV 16; - year := (date MOD 16) * 10 + year; - date := date DIV 16; - - month := date MOD 16; - date := date DIV 16; - month := (date MOD 16) * 10 + month; - date := date DIV 16; - - day := date MOD 16; - date := date DIV 16; - day := (date MOD 16) * 10 + day; - date := date DIV 16; - - hour := time MOD 16; - time := time DIV 16; - hour := (time MOD 16) * 10 + hour; - time := time DIV 16; - - min := time MOD 16; - time := time DIV 16; - min := (time MOD 16) * 10 + min; - time := time DIV 16; - - sec := time MOD 16; - time := time DIV 16; - sec := (time MOD 16) * 10 + sec; - time := time DIV 16; - - INC(year, 2000) - - RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec -END UnixTime; - - -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; -BEGIN - SYSTEM.GET32(SYSTEM.ADR(x), a); - SYSTEM.GET32(SYSTEM.ADR(x) + 4, b) - RETURN a -END splitf; - - -PROCEDURE d2s* (x: REAL): INTEGER; -VAR - h, l, s, e: INTEGER; - -BEGIN - e := splitf(x, l, h); - - s := ASR(h, 31) MOD 2; - e := (h DIV 100000H) MOD 2048; - IF e <= 896 THEN - h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; - REPEAT - h := h DIV 2; - INC(e) - UNTIL e = 897; - e := 896; - l := (h MOD 8) * 20000000H; - h := h DIV 8 - ELSIF (1151 <= e) & (e < 2047) THEN - e := 1151; - h := 0; - l := 0 - ELSIF e = 2047 THEN - e := 1151; - IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN - h := 80000H; - l := 0 - END - END; - DEC(e, 896) - - RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 -END d2s; - - -PROCEDURE init (VAR days: DAYS); -VAR - i, j, n0, n1: INTEGER; - -BEGIN - - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - days[i, j, 0] := 0; - days[i, j, 1] := 0; - END - END; - - days[ 1, 28, 0] := -1; - - FOR i := 0 TO 1 DO - days[ 1, 29, i] := -1; - days[ 1, 30, i] := -1; - days[ 3, 30, i] := -1; - days[ 5, 30, i] := -1; - days[ 8, 30, i] := -1; - days[10, 30, i] := -1; - END; - - n0 := 0; - n1 := 0; - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - IF days[i, j, 0] = 0 THEN - days[i, j, 0] := n0; - INC(n0) - END; - IF days[i, j, 1] = 0 THEN - days[i, j, 1] := n1; - INC(n1) - END - END - END; - - inf := SYSTEM.INF(); - maxreal := 1.9; - PACK(maxreal, 1023); - Console := TRUE; - IF Console THEN - con_init(-1, -1, -1, -1, SYSTEM.SADR("Oberon-07 for KolibriOS")) - END; - ParamParse -END init; - - -BEGIN - init(days) -END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/In.ob07 b/programs/develop/oberon07/lib/KolibriOS/In.ob07 deleted file mode 100644 index 50af0cb95..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/In.ob07 +++ /dev/null @@ -1,282 +0,0 @@ -(* - Copyright 2016, 2018 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 In; - -IMPORT sys := SYSTEM, ConsoleLib; - -TYPE - - STRING = ARRAY 260 OF CHAR; - -VAR - - Done* : BOOLEAN; - -PROCEDURE digit(ch: CHAR): BOOLEAN; - RETURN (ch >= "0") & (ch <= "9") -END digit; - -PROCEDURE CheckInt(s: STRING; VAR first, last: INTEGER; VAR neg: BOOLEAN; Point: BOOLEAN): BOOLEAN; -VAR i: INTEGER; -BEGIN - i := 0; - neg := FALSE; - WHILE (s[i] <= 20X) & (s[i] # 0X) DO - INC(i) - END; - IF s[i] = "-" THEN - neg := TRUE; - INC(i) - ELSIF s[i] = "+" THEN - INC(i) - END; - first := i; - WHILE digit(s[i]) DO - INC(i) - END; - last := i - RETURN ((s[i] <= 20X) OR (Point & (s[i] = "."))) & digit(s[first]) -END CheckInt; - -PROCEDURE IsMinInt(str: STRING; pos: INTEGER): BOOLEAN; -VAR i: INTEGER; min: STRING; -BEGIN - i := 0; - min := "2147483648"; - WHILE (min[i] # 0X) & (str[i] # 0X) & (min[i] = str[i + pos]) DO - INC(i) - END - RETURN i = 10 -END IsMinInt; - -PROCEDURE StrToInt(str: STRING; VAR err: BOOLEAN): INTEGER; -CONST maxINT = 7FFFFFFFH; -VAR i, n, res: INTEGER; flag, neg: BOOLEAN; -BEGIN - res := 0; - flag := CheckInt(str, i, n, neg, FALSE); - err := ~flag; - IF flag & neg & IsMinInt(str, i) THEN - flag := FALSE; - neg := FALSE; - res := 80000000H - END; - WHILE flag & digit(str[i]) DO - IF res > maxINT DIV 10 THEN - err := TRUE; - flag := FALSE; - res := 0 - ELSE - res := res * 10; - IF res > maxINT - (ORD(str[i]) - ORD("0")) THEN - err := TRUE; - flag := FALSE; - res := 0 - ELSE - res := res + (ORD(str[i]) - ORD("0")); - INC(i) - END - END - END; - IF neg THEN - res := -res - END - RETURN res -END StrToInt; - -PROCEDURE Space(s: STRING): BOOLEAN; -VAR i: INTEGER; -BEGIN - i := 0; - WHILE (s[i] # 0X) & (s[i] <= 20X) DO - INC(i) - END - RETURN s[i] = 0X -END Space; - -PROCEDURE CheckReal(s: STRING; VAR n: INTEGER; VAR neg: BOOLEAN): BOOLEAN; -VAR i: INTEGER; Res: BOOLEAN; -BEGIN - Res := CheckInt(s, n, i, neg, TRUE); - IF Res THEN - IF s[i] = "." THEN - INC(i); - WHILE digit(s[i]) DO - INC(i) - END; - IF (s[i] = "D") OR (s[i] = "E") OR (s[i] = "d") OR (s[i] = "e") THEN - INC(i); - IF (s[i] = "+") OR (s[i] = "-") THEN - INC(i) - END; - Res := digit(s[i]); - WHILE digit(s[i]) DO - INC(i) - END - END - END - END - RETURN Res & (s[i] <= 20X) -END CheckReal; - -PROCEDURE StrToFloat(str: STRING; VAR err: BOOLEAN): REAL; -CONST maxDBL = 1.69E308; maxINT = 7FFFFFFFH; -VAR i, scale: INTEGER; res, m, d: REAL; minus, neg: BOOLEAN; - - PROCEDURE part1 (str: STRING; VAR res, d: REAL; VAR i: INTEGER): BOOLEAN; - BEGIN - res := 0.0; - d := 1.0; - WHILE digit(str[i]) DO - res := res * 10.0 + FLT(ORD(str[i]) - ORD("0")); - INC(i) - END; - IF str[i] = "." THEN - INC(i); - WHILE digit(str[i]) DO - d := d / 10.0; - res := res + FLT(ORD(str[i]) - ORD("0")) * d; - INC(i) - END - END - RETURN str[i] # 0X - END part1; - - PROCEDURE part2 (str: STRING; VAR i, scale: INTEGER; VAR minus, err: BOOLEAN; VAR m, res: REAL): BOOLEAN; - BEGIN - INC(i); - m := 10.0; - minus := FALSE; - IF str[i] = "+" THEN - INC(i) - ELSIF str[i] = "-" THEN - minus := TRUE; - INC(i); - m := 0.1 - END; - scale := 0; - err := FALSE; - WHILE ~err & digit(str[i]) DO - IF scale > maxINT DIV 10 THEN - err := TRUE; - res := 0.0 - ELSE - scale := scale * 10; - IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN - err := TRUE; - res := 0.0 - ELSE - scale := scale + (ORD(str[i]) - ORD("0")); - INC(i) - END - END - END - RETURN ~err - END part2; - - PROCEDURE part3 (VAR err, minus: BOOLEAN; VAR res, m: REAL; VAR scale: INTEGER); - VAR i: INTEGER; - BEGIN - err := FALSE; - IF scale = maxINT THEN - err := TRUE; - res := 0.0 - END; - i := 1; - WHILE ~err & (i <= scale) DO - IF ~minus & (res > maxDBL / m) THEN - err := TRUE; - res := 0.0 - ELSE - res := res * m; - INC(i) - END - END - END part3; - -BEGIN - IF CheckReal(str, i, neg) THEN - IF part1(str, res, d, i) & part2(str, i, scale, minus, err, m, res) THEN - part3(err, minus, res, m, scale) - END; - IF neg THEN - res := -res - END - ELSE - res := 0.0; - err := TRUE - END - RETURN res -END StrToFloat; - -PROCEDURE String*(VAR s: ARRAY OF CHAR); -VAR res, length: INTEGER; str: STRING; -BEGIN - res := ConsoleLib.gets(sys.ADR(str[0]), LEN(str)); - length := LENGTH(str); - IF length > 0 THEN - str[length - 1] := 0X - END; - COPY(str, s); - Done := TRUE -END String; - -PROCEDURE Char*(VAR x: CHAR); -VAR str: STRING; -BEGIN - String(str); - x := str[0]; - Done := TRUE -END Char; - -PROCEDURE Ln*; -VAR str: STRING; -BEGIN - String(str); - Done := TRUE -END Ln; - -PROCEDURE Real* (VAR x: REAL); -VAR str: STRING; err: BOOLEAN; -BEGIN - err := FALSE; - REPEAT - String(str) - UNTIL ~Space(str); - x := StrToFloat(str, err); - Done := ~err -END Real; - - -PROCEDURE Int*(VAR x: INTEGER); -VAR str: STRING; err: BOOLEAN; -BEGIN - err := FALSE; - REPEAT - String(str) - UNTIL ~Space(str); - x := StrToInt(str, err); - Done := ~err -END Int; - -PROCEDURE Open*; -BEGIN - Done := TRUE -END Open; - -END In. diff --git a/programs/develop/oberon07/lib/KolibriOS/KOSAPI.ob07 b/programs/develop/oberon07/lib/KolibriOS/KOSAPI.ob07 deleted file mode 100644 index 57fed1dc1..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/KOSAPI.ob07 +++ /dev/null @@ -1,436 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2019, 2022 Anton Krotov - All rights reserved. -*) - -MODULE KOSAPI; - -IMPORT SYSTEM; - - -TYPE - - STRING = ARRAY 1024 OF CHAR; - - -VAR - - DLL_INIT: PROCEDURE [stdcall] (entry: INTEGER); - - -PROCEDURE [stdcall-] sysfunc1* (arg1: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 0CDH, 040H, (* int 64 *) - 0C9H, (* leave *) - 0C2H, 004H, 000H (* ret 4 *) - ) - RETURN 0 -END sysfunc1; - - -PROCEDURE [stdcall-] sysfunc2* (arg1, arg2: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 053H, (* push ebx *) - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *) - 0CDH, 040H, (* int 64 *) - 05BH, (* pop ebx *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 8 *) - ) - RETURN 0 -END sysfunc2; - - -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 [stdcall-] sysfunc4* (arg1, arg2, arg3, arg4: 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] *) - 08BH, 055H, 014H, (* mov edx, dword [ebp + 20] *) - 0CDH, 040H, (* int 64 *) - 05BH, (* pop ebx *) - 0C9H, (* leave *) - 0C2H, 010H, 000H (* ret 16 *) - ) - RETURN 0 -END sysfunc4; - - -PROCEDURE [stdcall-] sysfunc5* (arg1, arg2, arg3, arg4, arg5: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 053H, (* push ebx *) - 056H, (* push esi *) - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *) - 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *) - 08BH, 055H, 014H, (* mov edx, dword [ebp + 20] *) - 08BH, 075H, 018H, (* mov esi, dword [ebp + 24] *) - 0CDH, 040H, (* int 64 *) - 05EH, (* pop esi *) - 05BH, (* pop ebx *) - 0C9H, (* leave *) - 0C2H, 014H, 000H (* ret 20 *) - ) - RETURN 0 -END sysfunc5; - - -PROCEDURE [stdcall-] sysfunc6* (arg1, arg2, arg3, arg4, arg5, arg6: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 053H, (* push ebx *) - 056H, (* push esi *) - 057H, (* push edi *) - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *) - 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *) - 08BH, 055H, 014H, (* mov edx, dword [ebp + 20] *) - 08BH, 075H, 018H, (* mov esi, dword [ebp + 24] *) - 08BH, 07DH, 01CH, (* mov edi, dword [ebp + 28] *) - 0CDH, 040H, (* int 64 *) - 05FH, (* pop edi *) - 05EH, (* pop esi *) - 05BH, (* pop ebx *) - 0C9H, (* leave *) - 0C2H, 018H, 000H (* ret 24 *) - ) - RETURN 0 -END sysfunc6; - - -PROCEDURE [stdcall-] sysfunc7* (arg1, arg2, arg3, arg4, arg5, arg6, arg7: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 053H, (* push ebx *) - 056H, (* push esi *) - 057H, (* push edi *) - 055H, (* push ebp *) - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *) - 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *) - 08BH, 055H, 014H, (* mov edx, dword [ebp + 20] *) - 08BH, 075H, 018H, (* mov esi, dword [ebp + 24] *) - 08BH, 07DH, 01CH, (* mov edi, dword [ebp + 28] *) - 08BH, 06DH, 020H, (* mov ebp, dword [ebp + 32] *) - 0CDH, 040H, (* int 64 *) - 05DH, (* pop ebp *) - 05FH, (* pop edi *) - 05EH, (* pop esi *) - 05BH, (* pop ebx *) - 0C9H, (* leave *) - 0C2H, 01CH, 000H (* ret 28 *) - ) - RETURN 0 -END sysfunc7; - - -PROCEDURE [stdcall-] sysfunc22* (arg1, arg2: INTEGER; VAR res2: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 053H, (* push ebx *) - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *) - 0CDH, 040H, (* int 64 *) - 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *) - 089H, 019H, (* mov dword [ecx], ebx *) - 05BH, (* pop ebx *) - 0C9H, (* leave *) - 0C2H, 00CH, 000H (* ret 12 *) - ) - RETURN 0 -END sysfunc22; - - -PROCEDURE mem_commit (adr, size: INTEGER); -VAR - tmp: INTEGER; -BEGIN - FOR tmp := adr TO adr + size - 1 BY 4096 DO - SYSTEM.PUT(tmp, 0) - END -END mem_commit; - - -PROCEDURE [stdcall] malloc* (size: INTEGER): INTEGER; -VAR - ptr: INTEGER; -BEGIN - SYSTEM.CODE(060H); (* pusha *) - IF sysfunc2(18, 16) > ASR(size, 10) THEN - ptr := sysfunc3(68, 12, size); - IF ptr # 0 THEN - mem_commit(ptr, size) - END - ELSE - ptr := 0 - END; - SYSTEM.CODE(061H) (* popa *) - RETURN ptr -END malloc; - - -PROCEDURE [stdcall] free* (ptr: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE(060H); (* pusha *) - IF ptr # 0 THEN - ptr := sysfunc3(68, 13, ptr) - END; - SYSTEM.CODE(061H) (* popa *) - RETURN 0 -END free; - - -PROCEDURE [stdcall] realloc* (ptr, size: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE(060H); (* pusha *) - ptr := sysfunc4(68, 20, size, ptr); - SYSTEM.CODE(061H) (* popa *) - RETURN ptr -END realloc; - - -PROCEDURE AppAdr (): INTEGER; -VAR - buf: ARRAY 1024 OF CHAR; - a: INTEGER; -BEGIN - a := sysfunc3(9, SYSTEM.ADR(buf), -1); - SYSTEM.GET(SYSTEM.ADR(buf) + 22, a) - RETURN a -END AppAdr; - - -PROCEDURE GetCommandLine* (): INTEGER; -VAR - param: INTEGER; -BEGIN - SYSTEM.GET(28 + AppAdr(), param) - RETURN param -END GetCommandLine; - - -PROCEDURE GetName* (): INTEGER; -VAR - name: INTEGER; -BEGIN - SYSTEM.GET(32 + AppAdr(), name) - RETURN name -END GetName; - - -PROCEDURE [stdcall] dll_init2 (arg1, arg2, arg3, arg4, arg5: INTEGER); -BEGIN - SYSTEM.CODE( - 060H, (* pusha *) - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *) - 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *) - 08BH, 055H, 014H, (* mov edx, dword [ebp + 20] *) - 08BH, 075H, 018H, (* mov esi, dword [ebp + 24] *) - 0FFH, 0D6H, (* call esi *) - 061H, (* popa *) - 0C9H, (* leave *) - 0C2H, 014H, 000H (* ret 20 *) - ) -END dll_init2; - - -PROCEDURE GetProcAdr* (name: ARRAY OF CHAR; lib: INTEGER): INTEGER; -VAR - cur, procname, adr: INTEGER; - - PROCEDURE streq (str1, str2: INTEGER): BOOLEAN; - VAR - c1, c2: CHAR; - BEGIN - REPEAT - SYSTEM.GET(str1, c1); - SYSTEM.GET(str2, c2); - INC(str1); - INC(str2) - UNTIL (c1 # c2) OR (c1 = 0X) - - RETURN c1 = c2 - END streq; - -BEGIN - adr := 0; - IF (lib # 0) & (name # "") THEN - cur := lib; - REPEAT - SYSTEM.GET(cur, procname); - INC(cur, 8) - UNTIL (procname = 0) OR streq(procname, SYSTEM.ADR(name[0])); - IF procname # 0 THEN - SYSTEM.GET(cur - 4, adr) - END - END - - RETURN adr -END GetProcAdr; - - -PROCEDURE init (dll: INTEGER); -VAR - lib_init: INTEGER; -BEGIN - lib_init := GetProcAdr("lib_init", dll); - IF lib_init # 0 THEN - DLL_INIT(lib_init) - END; - lib_init := GetProcAdr("START", dll); - IF lib_init # 0 THEN - DLL_INIT(lib_init) - END -END init; - - -PROCEDURE OutChar* (c: CHAR); -BEGIN - sysfunc3(63, 1, ORD(c)) -END OutChar; - - -PROCEDURE OutLn*; -BEGIN - OutChar(0DX); - OutChar(0AX) -END OutLn; - - -PROCEDURE OutString (s: ARRAY OF CHAR); -VAR - i: INTEGER; -BEGIN - i := 0; - WHILE (i < LEN(s)) & (s[i] # 0X) DO - OutChar(s[i]); - INC(i) - END -END OutString; - - -PROCEDURE imp_error (lib, proc: STRING); -BEGIN - OutString("import error: "); - IF proc = "" THEN - OutString("can't load '") - ELSE - OutString("not found '"); OutString(proc); OutString("' in '") - END; - OutString(lib); - OutString("'" + 0DX + 0AX) -END imp_error; - - -PROCEDURE GetStr (adr, i: INTEGER; VAR str: STRING); -VAR - c: CHAR; -BEGIN - REPEAT - SYSTEM.GET(adr, c); INC(adr); - str[i] := c; INC(i) - UNTIL c = 0X -END GetStr; - - -PROCEDURE [stdcall-] dll_Load* (import_table: INTEGER): INTEGER; -CONST - path = "/sys/lib/"; -VAR - imp, lib, exp, proc, pathLen: INTEGER; - procname, libname: STRING; -BEGIN - SYSTEM.CODE(060H); (* pusha *) - libname := path; - pathLen := LENGTH(libname); - - SYSTEM.GET(import_table, imp); - WHILE imp # 0 DO - SYSTEM.GET(import_table + 4, lib); - GetStr(lib, pathLen, libname); - exp := sysfunc3(68, 19, SYSTEM.ADR(libname[0])); - IF exp = 0 THEN - imp_error(libname, "") - ELSE - REPEAT - SYSTEM.GET(imp, proc); - IF proc # 0 THEN - GetStr(proc, 0, procname); - proc := GetProcAdr(procname, exp); - IF proc # 0 THEN - SYSTEM.PUT(imp, proc) - ELSE - proc := 1; - imp_error(libname, procname) - END; - INC(imp, 4) - END - UNTIL proc = 0; - init(exp) - END; - INC(import_table, 8); - SYSTEM.GET(import_table, imp); - END; - - SYSTEM.CODE(061H) (* popa *) - RETURN 0 -END dll_Load; - - -PROCEDURE [stdcall] dll_Init (entry: INTEGER); -BEGIN - SYSTEM.CODE(060H); (* pusha *) - IF entry # 0 THEN - dll_init2(SYSTEM.ADR(malloc), SYSTEM.ADR(free), SYSTEM.ADR(realloc), SYSTEM.ADR(dll_Load), entry) - END; - SYSTEM.CODE(061H); (* popa *) -END dll_Init; - - -PROCEDURE LoadLib* (name: ARRAY OF CHAR): INTEGER; -VAR - Lib: INTEGER; -BEGIN - DLL_INIT := dll_Init; - Lib := sysfunc3(68, 19, SYSTEM.ADR(name[0])); - IF Lib # 0 THEN - init(Lib) - END - RETURN Lib -END LoadLib; - - -PROCEDURE _init* (import_table: INTEGER); -BEGIN - DLL_INIT := dll_Init; - dll_Load(import_table) -END _init; - - -END KOSAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/Math.ob07 b/programs/develop/oberon07/lib/KolibriOS/Math.ob07 deleted file mode 100644 index 03302f642..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/Math.ob07 +++ /dev/null @@ -1,449 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2013-2014, 2018-2022 Anton Krotov - All rights reserved. -*) - -MODULE Math; - -IMPORT SYSTEM; - - -CONST - - pi* = 3.141592653589793; - e* = 2.718281828459045; - - -PROCEDURE IsNan* (x: REAL): BOOLEAN; -VAR - h, l: SET; - -BEGIN - SYSTEM.GET(SYSTEM.ADR(x), l); - SYSTEM.GET(SYSTEM.ADR(x) + 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) = SYSTEM.INF() -END IsInf; - - -PROCEDURE Max (a, b: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF a > b THEN - res := a - ELSE - res := b - END - RETURN res -END Max; - - -PROCEDURE Min (a, b: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF a < b THEN - res := a - ELSE - res := b - END - RETURN res -END Min; - - -PROCEDURE SameValue (a, b: REAL): BOOLEAN; -VAR - eps: REAL; - res: BOOLEAN; - -BEGIN - eps := Max(Min(ABS(a), ABS(b)) * 1.0E-12, 1.0E-12); - IF a > b THEN - res := (a - b) <= eps - ELSE - res := (b - a) <= eps - END - RETURN res -END SameValue; - - -PROCEDURE IsZero (x: REAL): BOOLEAN; - RETURN ABS(x) <= 1.0E-12 -END IsZero; - - -PROCEDURE [stdcall] sqrt* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FAH, (* fsqrt *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END sqrt; - - -PROCEDURE [stdcall] sin* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FEH, (* fsin *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END sin; - - -PROCEDURE [stdcall] cos* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FFH, (* fcos *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END cos; - - -PROCEDURE [stdcall] tan* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FBH, (* fsincos *) - 0DEH, 0F9H, (* fdivp st1, st *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END tan; - - -PROCEDURE [stdcall] arctan2* (y, x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) - 0D9H, 0F3H, (* fpatan *) - 0C9H, (* leave *) - 0C2H, 010H, 000H (* ret 10h *) - ) - RETURN 0.0 -END arctan2; - - -PROCEDURE [stdcall] ln* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0D9H, 0EDH, (* fldln2 *) - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0F1H, (* fyl2x *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END ln; - - -PROCEDURE [stdcall] log* (base, x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0D9H, 0E8H, (* fld1 *) - 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) - 0D9H, 0F1H, (* fyl2x *) - 0D9H, 0E8H, (* fld1 *) - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0F1H, (* fyl2x *) - 0DEH, 0F9H, (* fdivp st1, st *) - 0C9H, (* leave *) - 0C2H, 010H, 000H (* ret 10h *) - ) - RETURN 0.0 -END log; - - -PROCEDURE [stdcall] exp* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0EAH, (* fldl2e *) - 0DEH, 0C9H, 0D9H, 0C0H, - 0D9H, 0FCH, 0DCH, 0E9H, - 0D9H, 0C9H, 0D9H, 0F0H, - 0D9H, 0E8H, 0DEH, 0C1H, - 0D9H, 0FDH, 0DDH, 0D9H, - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END exp; - - -PROCEDURE [stdcall] round* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 07DH, 0F4H, 0D9H, - 07DH, 0F6H, 066H, 081H, - 04DH, 0F6H, 000H, 003H, - 0D9H, 06DH, 0F6H, 0D9H, - 0FCH, 0D9H, 06DH, 0F4H, - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END round; - - -PROCEDURE [stdcall] frac* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 050H, - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0C0H, 0D9H, 03CH, - 024H, 0D9H, 07CH, 024H, - 002H, 066H, 081H, 04CH, - 024H, 002H, 000H, 00FH, - 0D9H, 06CH, 024H, 002H, - 0D9H, 0FCH, 0D9H, 02CH, - 024H, 0DEH, 0E9H, - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END frac; - - -PROCEDURE sqri* (x: INTEGER): INTEGER; - RETURN x * x -END sqri; - - -PROCEDURE sqrr* (x: REAL): REAL; - RETURN x * x -END sqrr; - - -PROCEDURE arcsin* (x: REAL): REAL; - RETURN arctan2(x, sqrt(1.0 - x * x)) -END arcsin; - - -PROCEDURE arccos* (x: REAL): REAL; - RETURN arctan2(sqrt(1.0 - x * x), x) -END arccos; - - -PROCEDURE arctan* (x: REAL): REAL; - RETURN arctan2(x, 1.0) -END arctan; - - -PROCEDURE sinh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x - 1.0 / x) * 0.5 -END sinh; - - -PROCEDURE cosh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x + 1.0 / x) * 0.5 -END cosh; - - -PROCEDURE tanh* (x: REAL): REAL; -BEGIN - IF x > 15.0 THEN - x := 1.0 - ELSIF x < -15.0 THEN - x := -1.0 - ELSE - x := 1.0 - 2.0 / (exp(2.0 * x) + 1.0) - END - - RETURN x -END tanh; - - -PROCEDURE arsinh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x + 1.0)) -END arsinh; - - -PROCEDURE arcosh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x - 1.0)) -END arcosh; - - -PROCEDURE artanh* (x: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF SameValue(x, 1.0) THEN - res := SYSTEM.INF() - ELSIF SameValue(x, -1.0) THEN - res := -SYSTEM.INF() - ELSE - res := 0.5 * ln((1.0 + x) / (1.0 - x)) - END - RETURN res -END artanh; - - -PROCEDURE floor* (x: REAL): REAL; -VAR - f: REAL; - -BEGIN - f := frac(x); - x := x - f; - IF f < 0.0 THEN - x := x - 1.0 - END - RETURN x -END floor; - - -PROCEDURE ceil* (x: REAL): REAL; -VAR - f: REAL; - -BEGIN - f := frac(x); - x := x - f; - IF f > 0.0 THEN - x := x + 1.0 - END - RETURN x -END ceil; - - -PROCEDURE power* (base, exponent: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF exponent = 0.0 THEN - res := 1.0 - ELSIF (base = 0.0) & (exponent > 0.0) THEN - res := 0.0 - ELSE - res := exp(exponent * ln(base)) - END - RETURN res -END power; - - -PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; -VAR - i: INTEGER; - a: REAL; - -BEGIN - a := 1.0; - - IF base # 0.0 THEN - IF exponent # 0 THEN - IF exponent < 0 THEN - base := 1.0 / base - END; - i := ABS(exponent); - WHILE i > 0 DO - WHILE ~ODD(i) DO - i := LSR(i, 1); - base := sqrr(base) - END; - DEC(i); - a := a * base - END - ELSE - a := 1.0 - END - ELSE - ASSERT(exponent > 0); - a := 0.0 - END - - RETURN a -END ipower; - - -PROCEDURE sgn* (x: REAL): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF x > 0.0 THEN - res := 1 - ELSIF x < 0.0 THEN - res := -1 - ELSE - res := 0 - END - - RETURN res -END sgn; - - -PROCEDURE fact* (n: INTEGER): REAL; -VAR - res: REAL; - -BEGIN - res := 1.0; - WHILE n > 1 DO - res := res * FLT(n); - DEC(n) - END - - RETURN res -END fact; - - -PROCEDURE DegToRad* (x: REAL): REAL; - RETURN x * (pi / 180.0) -END DegToRad; - - -PROCEDURE RadToDeg* (x: REAL): REAL; - RETURN x * (180.0 / pi) -END RadToDeg; - - -(* Return hypotenuse of triangle *) -PROCEDURE hypot* (x, y: REAL): REAL; -VAR - a: REAL; - -BEGIN - x := ABS(x); - y := ABS(y); - IF x > y THEN - a := x * sqrt(1.0 + sqrr(y / x)) - ELSE - IF x > 0.0 THEN - a := y * sqrt(1.0 + sqrr(x / y)) - ELSE - a := y - END - END - - RETURN a -END hypot; - - -END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/NetDevices.ob07 b/programs/develop/oberon07/lib/KolibriOS/NetDevices.ob07 deleted file mode 100644 index c0ed629f9..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/NetDevices.ob07 +++ /dev/null @@ -1,107 +0,0 @@ -(* - Copyright 2017 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 NetDevices; - -IMPORT sys := SYSTEM, K := KOSAPI; - - -CONST - - //net devices types - - LOOPBACK* = 0; - ETH* = 1; - SLIP* = 2; - - //Link status - - LINK_DOWN* = 0; - LINK_UNKNOWN* = 1; - LINK_FD* = 2; //full duplex flag - LINK_10M* = 4; - LINK_100M* = 8; - LINK_1G* = 12; - - -TYPE - - DEVICENAME* = ARRAY 64 OF CHAR; - - -PROCEDURE Number* (): INTEGER; - RETURN K.sysfunc2(74, -1) -END Number; - - -PROCEDURE Type* (num: INTEGER): INTEGER; - RETURN K.sysfunc2(74, num * 256) -END Type; - - -PROCEDURE Name* (num: INTEGER; VAR name: DEVICENAME): BOOLEAN; -VAR err: BOOLEAN; -BEGIN - err := K.sysfunc3(74, num * 256 + 1, sys.ADR(name[0])) = -1; - IF err THEN - name := "" - END - RETURN ~err -END Name; - - -PROCEDURE Reset* (num: INTEGER): BOOLEAN; - RETURN K.sysfunc2(74, num * 256 + 2) # -1 -END Reset; - - -PROCEDURE Stop* (num: INTEGER): BOOLEAN; - RETURN K.sysfunc2(74, num * 256 + 3) # -1 -END Stop; - - -PROCEDURE Pointer* (num: INTEGER): INTEGER; - RETURN K.sysfunc2(74, num * 256 + 4) -END Pointer; - - -PROCEDURE SentPackets* (num: INTEGER): INTEGER; - RETURN K.sysfunc2(74, num * 256 + 6) -END SentPackets; - - -PROCEDURE ReceivedPackets* (num: INTEGER): INTEGER; - RETURN K.sysfunc2(74, num * 256 + 7) -END ReceivedPackets; - - -PROCEDURE SentBytes* (num: INTEGER; VAR hValue: INTEGER): INTEGER; - RETURN K.sysfunc22(74, num * 256 + 8, hValue) -END SentBytes; - - -PROCEDURE ReceivedBytes* (num: INTEGER; VAR hValue: INTEGER): INTEGER; - RETURN K.sysfunc22(74, num * 256 + 9, hValue) -END ReceivedBytes; - - -PROCEDURE LinkStatus* (num: INTEGER): INTEGER; - RETURN K.sysfunc2(74, num * 256 + 10) -END LinkStatus; - - -END NetDevices. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/OpenDlg.ob07 b/programs/develop/oberon07/lib/KolibriOS/OpenDlg.ob07 deleted file mode 100644 index 79cfcea22..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/OpenDlg.ob07 +++ /dev/null @@ -1,158 +0,0 @@ -(* - Copyright 2016, 2018, 2020-2022 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 OpenDlg; - -IMPORT sys := SYSTEM, KOSAPI; - -CONST - topen* = 0; - tsave* = 1; - tdir* = 2; - -TYPE - - DRAW_WINDOW = PROCEDURE; - - TDialog = RECORD - _type*, - procinfo, - com_area_name, - com_area, - opendir_path, - dir_default_path, - start_path: INTEGER; - draw_window: DRAW_WINDOW; - status*, - openfile_path, - filename_area: INTEGER; - filter_area: - POINTER TO RECORD - size: INTEGER; - filter: ARRAY 4096 OF CHAR - END; - X, Y: INTEGER; - - procinf: ARRAY 1024 OF CHAR; - s_com_area_name: ARRAY 32 OF CHAR; - s_opendir_path, - s_dir_default_path, - FilePath*, - FileName*: ARRAY 4096 OF CHAR - END; - - Dialog* = POINTER TO TDialog; - -VAR - - Dialog_start, Dialog_init: PROCEDURE [stdcall] (od: Dialog); - - -PROCEDURE Show*(od: Dialog; Width, Height: INTEGER); -BEGIN - IF od # NIL THEN - od.X := Width; - od.Y := Height; - Dialog_start(od) - END -END Show; - -PROCEDURE Create*(draw_window: DRAW_WINDOW; _type: INTEGER; def_path, filter: ARRAY OF CHAR): Dialog; -VAR res: Dialog; n, i: INTEGER; - - PROCEDURE replace(VAR str: ARRAY OF CHAR; c1, c2: CHAR); - VAR i: INTEGER; - BEGIN - i := LENGTH(str) - 1; - WHILE i >= 0 DO - IF str[i] = c1 THEN - str[i] := c2 - END; - DEC(i) - END - END replace; - -BEGIN - NEW(res); - IF res # NIL THEN - NEW(res.filter_area); - IF res.filter_area # NIL THEN - res.s_com_area_name := "FFFFFFFF_open_dialog"; - res.com_area := 0; - res._type := _type; - res.draw_window := draw_window; - COPY(def_path, res.s_dir_default_path); - COPY(filter, res.filter_area.filter); - - n := LENGTH(res.filter_area.filter); - FOR i := 0 TO 3 DO - res.filter_area.filter[n + i] := "|" - END; - res.filter_area.filter[n + 4] := 0X; - - res.X := 0; - res.Y := 0; - res.s_opendir_path := res.s_dir_default_path; - res.FilePath := ""; - res.FileName := ""; - res.status := 0; - res.filter_area.size := LENGTH(res.filter_area.filter); - res.procinfo := sys.ADR(res.procinf[0]); - res.com_area_name := sys.ADR(res.s_com_area_name[0]); - res.start_path := sys.SADR("/sys/File managers/opendial"); - res.opendir_path := sys.ADR(res.s_opendir_path[0]); - res.dir_default_path := sys.ADR(res.s_dir_default_path[0]); - res.openfile_path := sys.ADR(res.FilePath[0]); - res.filename_area := sys.ADR(res.FileName[0]); - - replace(res.filter_area.filter, "|", 0X); - Dialog_init(res) - ELSE - DISPOSE(res) - END - END - RETURN res -END Create; - -PROCEDURE Destroy*(VAR od: Dialog); -BEGIN - IF od # NIL THEN - DISPOSE(od.filter_area); - DISPOSE(od) - END -END Destroy; - -PROCEDURE Load; -VAR Lib: INTEGER; - - PROCEDURE GetProc(Lib, v: INTEGER; name: ARRAY OF CHAR); - VAR a: INTEGER; - BEGIN - a := KOSAPI.GetProcAdr(name, Lib); - ASSERT(a # 0); - sys.PUT(v, a) - END GetProc; - -BEGIN - Lib := KOSAPI.LoadLib("/sys/Lib/Proc_lib.obj"); - GetProc(Lib, sys.ADR(Dialog_init), "OpenDialog_init"); - GetProc(Lib, sys.ADR(Dialog_start), "OpenDialog_start"); -END Load; - -BEGIN - Load -END OpenDlg. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/Out.ob07 b/programs/develop/oberon07/lib/KolibriOS/Out.ob07 deleted file mode 100644 index 02cc14e01..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/Out.ob07 +++ /dev/null @@ -1,267 +0,0 @@ -(* - Copyright 2016, 2018 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 Out; - -IMPORT ConsoleLib, sys := SYSTEM; - -CONST - - d = 1.0 - 5.0E-12; - -VAR - - Realp: PROCEDURE (x: REAL; width: INTEGER); - -PROCEDURE Char*(c: CHAR); -BEGIN - ConsoleLib.write_string(sys.ADR(c), 1) -END Char; - -PROCEDURE String*(s: ARRAY OF CHAR); -BEGIN - ConsoleLib.write_string(sys.ADR(s[0]), LENGTH(s)) -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*; -END Open; - -END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/RTL.ob07 b/programs/develop/oberon07/lib/KolibriOS/RTL.ob07 deleted file mode 100644 index 0818bca97..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/RTL.ob07 +++ /dev/null @@ -1,543 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE RTL; - -IMPORT SYSTEM, API; - - -CONST - - minint = ROR(1, 1); - - WORD = API.BIT_DEPTH DIV 8; - - -VAR - - name: INTEGER; - types: 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): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _isrec; - - -PROCEDURE [stdcall] _is* (t0, p: INTEGER): INTEGER; -BEGIN - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - END - - RETURN p MOD 2 -END _is; - - -PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _guardrec; - - -PROCEDURE [stdcall] _guard* (t0, p: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(p, p); - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - ELSE - p := 1 - END - - RETURN p MOD 2 -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); -VAR - t0, t1, i, j: INTEGER; - -BEGIN - SYSTEM.CODE(09BH, 0DBH, 0E3H); (* finit *) - API.init(param, code); - - types := API._NEW(tcount * tcount + SYSTEM.SIZE(INTEGER)); - ASSERT(types # 0); - FOR i := 0 TO tcount - 1 DO - FOR j := 0 TO tcount - 1 DO - t0 := i; t1 := j; - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(_types + t1 * WORD, t1) - END; - - SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) - END - END; - - name := modname -END _init; - - -END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/RasterWorks.ob07 b/programs/develop/oberon07/lib/KolibriOS/RasterWorks.ob07 deleted file mode 100644 index d9efd53cd..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/RasterWorks.ob07 +++ /dev/null @@ -1,124 +0,0 @@ -(* - Copyright 2016, 2018, 2022 KolibriOS team - - 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 RasterWorks; - -IMPORT sys := SYSTEM, KOSAPI; - - -CONST - -(* flags *) - - bold *= 1; - italic *= 2; - underline *= 4; - strike_through *= 8; - align_right *= 16; - align_center *= 32; - - bpp32 *= 128; - - -(* encoding *) - - cp866 *= 1; - utf16le *= 2; - utf8 *= 3; - - -VAR - - // draw text on 24bpp or 32bpp image - // autofits text between 'x' and 'xSize' - drawText *: PROCEDURE (canvas, x, y, string, charQuantity, fontColor, params: INTEGER): INTEGER; -(* - [canvas]: - xSize dd ? - ySize dd ? - picture rb xSize * ySize * bpp - - fontColor dd AARRGGBB - AA = alpha channel ; 0 = transparent, FF = non transparent - - params dd ffeewwhh - hh = char height - ww = char width ; 0 = auto (proportional) - ee = encoding ; 1 = cp866, 2 = UTF-16LE, 3 = UTF-8 - ff = flags ; 0001 = bold, 0010 = italic - ; 0100 = underline, 1000 = strike-through - 00010000 = align right, 00100000 = align center - 01000000 = set text area between higher and lower halfs of 'x' - 10000000 = 32bpp canvas insted of 24bpp - all flags combinable, except align right + align center - - returns: char width (0 = error) -*) - - // calculate amount of valid chars in UTF-8 string - // supports zero terminated string (set byteQuantity = -1) - countUTF8Z *: PROCEDURE (string, byteQuantity: INTEGER): INTEGER; - - - // calculate amount of chars that fits given width - charsFit *: PROCEDURE (areaWidth, charHeight: INTEGER): INTEGER; - - - // calculate string width in pixels - strWidth *: PROCEDURE (charQuantity, charHeight: INTEGER): INTEGER; - - -PROCEDURE params* (charHeight, charWidth, encoding, flags: INTEGER): INTEGER; -(* - hh = char height - ww = char width ; 0 = auto (proportional) - ee = encoding ; 1 = cp866, 2 = UTF-16LE, 3 = UTF-8 - ff = flags ; 0001 = bold, 0010 = italic - ; 0100 = underline, 1000 = strike-through - 00010000 = align right, 00100000 = align center - 01000000 = set text area between higher and lower halfs of 'x' - 10000000 = 32bpp canvas insted of 24bpp - all flags combinable, except align right + align center -*) - RETURN charHeight + LSL(charWidth, 8) + LSL(encoding, 16) + LSL(flags, 24) -END params; - - -PROCEDURE main; -VAR Lib: INTEGER; - - PROCEDURE GetProc(Lib, v: INTEGER; name: ARRAY OF CHAR); - VAR a: INTEGER; - BEGIN - a := KOSAPI.GetProcAdr(name, Lib); - ASSERT(a # 0); - sys.PUT(v, a) - END GetProc; - -BEGIN - Lib := KOSAPI.LoadLib("/sys/lib/RasterWorks.obj"); - ASSERT(Lib # 0); - GetProc(Lib, sys.ADR(drawText), "drawText"); - GetProc(Lib, sys.ADR(countUTF8Z), "countUTF8Z"); - GetProc(Lib, sys.ADR(charsFit), "charsFit"); - GetProc(Lib, sys.ADR(strWidth), "strWidth"); -END main; - - -BEGIN - main -END RasterWorks. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/Read.ob07 b/programs/develop/oberon07/lib/KolibriOS/Read.ob07 deleted file mode 100644 index c2e86e37d..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/Read.ob07 +++ /dev/null @@ -1,46 +0,0 @@ -(* - Copyright 2016, 2018 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 Read; - -IMPORT File, sys := SYSTEM; - -PROCEDURE Char*(F: File.FS; VAR x: CHAR): BOOLEAN; - RETURN File.Read(F, sys.ADR(x), sys.SIZE(CHAR)) = sys.SIZE(CHAR) -END Char; - -PROCEDURE Int*(F: File.FS; VAR x: INTEGER): BOOLEAN; - RETURN File.Read(F, sys.ADR(x), sys.SIZE(INTEGER)) = sys.SIZE(INTEGER) -END Int; - -PROCEDURE Real*(F: File.FS; VAR x: REAL): BOOLEAN; - RETURN File.Read(F, sys.ADR(x), sys.SIZE(REAL)) = sys.SIZE(REAL) -END Real; - -PROCEDURE Boolean*(F: File.FS; VAR x: BOOLEAN): BOOLEAN; - RETURN File.Read(F, sys.ADR(x), sys.SIZE(BOOLEAN)) = sys.SIZE(BOOLEAN) -END Boolean; - -PROCEDURE Set*(F: File.FS; VAR x: SET): BOOLEAN; - RETURN File.Read(F, sys.ADR(x), sys.SIZE(SET)) = sys.SIZE(SET) -END Set; - -PROCEDURE WChar*(F: File.FS; VAR x: WCHAR): BOOLEAN; - RETURN File.Read(F, sys.ADR(x), sys.SIZE(WCHAR)) = sys.SIZE(WCHAR) -END WChar; - -END Read. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/UnixTime.ob07 b/programs/develop/oberon07/lib/KolibriOS/UnixTime.ob07 deleted file mode 100644 index 1cca6ea55..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/UnixTime.ob07 +++ /dev/null @@ -1,64 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2019, Anton Krotov - All rights reserved. -*) - -MODULE UnixTime; - - -VAR - - days: ARRAY 12, 31, 2 OF INTEGER; - - -PROCEDURE init; -VAR - i, j, k, n0, n1: INTEGER; -BEGIN - - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - days[i, j, 0] := 0; - days[i, j, 1] := 0; - END - END; - - days[ 1, 28, 0] := -1; - - FOR k := 0 TO 1 DO - days[ 1, 29, k] := -1; - days[ 1, 30, k] := -1; - days[ 3, 30, k] := -1; - days[ 5, 30, k] := -1; - days[ 8, 30, k] := -1; - days[10, 30, k] := -1; - END; - - n0 := 0; - n1 := 0; - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - IF days[i, j, 0] = 0 THEN - days[i, j, 0] := n0; - INC(n0) - END; - IF days[i, j, 1] = 0 THEN - days[i, j, 1] := n1; - INC(n1) - END - END - END - -END init; - - -PROCEDURE time* (year, month, day, hour, min, sec: INTEGER): INTEGER; - RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec -END time; - - -BEGIN - init -END UnixTime. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/Vector.ob07 b/programs/develop/oberon07/lib/KolibriOS/Vector.ob07 deleted file mode 100644 index 46de391cc..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/Vector.ob07 +++ /dev/null @@ -1,121 +0,0 @@ -(* - Copyright 2016 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 Vector; - - -IMPORT sys := SYSTEM, K := KOSAPI; - - -TYPE - - DESC_VECTOR = RECORD - - data : INTEGER; - count : INTEGER; - size : INTEGER - - END; - - VECTOR* = POINTER TO DESC_VECTOR; - - ANYREC* = RECORD END; - - ANYPTR* = POINTER TO ANYREC; - - DESTRUCTOR* = PROCEDURE (VAR ptr: ANYPTR); - - -PROCEDURE count* (vector: VECTOR): INTEGER; -BEGIN - ASSERT(vector # NIL) - RETURN vector.count -END count; - - -PROCEDURE push* (vector: VECTOR; value: ANYPTR); -BEGIN - ASSERT(vector # NIL); - IF vector.count = vector.size THEN - vector.data := K.realloc(vector.data, (vector.size + 1024) * 4); - ASSERT(vector.data # 0); - vector.size := vector.size + 1024 - END; - sys.PUT(vector.data + vector.count * 4, value); - INC(vector.count) -END push; - - -PROCEDURE get* (vector: VECTOR; idx: INTEGER): ANYPTR; -VAR res: ANYPTR; -BEGIN - ASSERT(vector # NIL); - ASSERT( (0 <= idx) & (idx < vector.count) ); - sys.GET(vector.data + idx * 4, res) - RETURN res -END get; - - -PROCEDURE put* (vector: VECTOR; idx: INTEGER; value: ANYPTR); -BEGIN - ASSERT(vector # NIL); - ASSERT( (0 <= idx) & (idx < vector.count) ); - sys.PUT(vector.data + idx * 4, value) -END put; - - -PROCEDURE create* (size: INTEGER): VECTOR; -VAR vector: VECTOR; -BEGIN - NEW(vector); - IF vector # NIL THEN - vector.data := K.malloc(4 * size); - IF vector.data # 0 THEN - vector.size := size; - vector.count := 0 - ELSE - DISPOSE(vector) - END - END - RETURN vector -END create; - - -PROCEDURE def_destructor (VAR any: ANYPTR); -BEGIN - DISPOSE(any) -END def_destructor; - - -PROCEDURE destroy* (VAR vector: VECTOR; destructor: DESTRUCTOR); -VAR i: INTEGER; - any: ANYPTR; -BEGIN - ASSERT(vector # NIL); - IF destructor = NIL THEN - destructor := def_destructor - END; - FOR i := 0 TO vector.count - 1 DO - any := get(vector, i); - destructor(any) - END; - vector.data := K.free(vector.data); - DISPOSE(vector) -END destroy; - - -END Vector. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/Write.ob07 b/programs/develop/oberon07/lib/KolibriOS/Write.ob07 deleted file mode 100644 index 6730d799d..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/Write.ob07 +++ /dev/null @@ -1,46 +0,0 @@ -(* - Copyright 2016, 2018 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 Write; - -IMPORT File, sys := SYSTEM; - -PROCEDURE Char*(F: File.FS; x: CHAR): BOOLEAN; - RETURN File.Write(F, sys.ADR(x), sys.SIZE(CHAR)) = sys.SIZE(CHAR) -END Char; - -PROCEDURE Int*(F: File.FS; x: INTEGER): BOOLEAN; - RETURN File.Write(F, sys.ADR(x), sys.SIZE(INTEGER)) = sys.SIZE(INTEGER) -END Int; - -PROCEDURE Real*(F: File.FS; x: REAL): BOOLEAN; - RETURN File.Write(F, sys.ADR(x), sys.SIZE(REAL)) = sys.SIZE(REAL) -END Real; - -PROCEDURE Boolean*(F: File.FS; x: BOOLEAN): BOOLEAN; - RETURN File.Write(F, sys.ADR(x), sys.SIZE(BOOLEAN)) = sys.SIZE(BOOLEAN) -END Boolean; - -PROCEDURE Set*(F: File.FS; x: SET): BOOLEAN; - RETURN File.Write(F, sys.ADR(x), sys.SIZE(SET)) = sys.SIZE(SET) -END Set; - -PROCEDURE WChar*(F: File.FS; x: WCHAR): BOOLEAN; - RETURN File.Write(F, sys.ADR(x), sys.SIZE(WCHAR)) = sys.SIZE(WCHAR) -END WChar; - -END Write. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/kfonts.ob07 b/programs/develop/oberon07/lib/KolibriOS/kfonts.ob07 deleted file mode 100644 index 8ef267a00..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/kfonts.ob07 +++ /dev/null @@ -1,492 +0,0 @@ -(* - Copyright 2016, 2018 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 kfonts; - -IMPORT sys := SYSTEM, File, KOSAPI; - -CONST - - MIN_FONT_SIZE = 8; - MAX_FONT_SIZE = 46; - - bold *= 1; - italic *= 2; - underline *= 4; - strike_through *= 8; - smoothing *= 16; - bpp32 *= 32; - -TYPE - - Glyph = RECORD - base: INTEGER; - xsize, ysize: INTEGER; - width: INTEGER - END; - - TFont_desc = RECORD - - data, size, font, char_size, width, height, font_size, mem, mempos: INTEGER; - glyphs: ARRAY 4, 256 OF Glyph - - END; - - TFont* = POINTER TO TFont_desc; - - -PROCEDURE [stdcall] zeromem(size, adr: INTEGER); -BEGIN - sys.CODE(057H, 08BH, 07DH, 00CH, 08BH, 04DH, 008H, 033H, 0C0H, 09CH, 0FCH, 0F3H, 0ABH, 09DH, 05FH) -END zeromem; - -PROCEDURE pset(buf, x, y, color: INTEGER; bpp32: BOOLEAN); -VAR xsize, ysize: INTEGER; -BEGIN - sys.GET(buf, xsize); - sys.GET(buf + 4, ysize); - INC(buf, 8); - IF (0 <= x) & (x < xsize) & (0 <= y) & (y < ysize) THEN - IF bpp32 THEN - sys.PUT(buf + 4 * (xsize * y + x), color) - ELSE - sys.MOVE(sys.ADR(color), buf + 3 * (xsize * y + x), 3) - END - END -END pset; - -PROCEDURE pget(buf, x, y: INTEGER; bpp32: BOOLEAN): INTEGER; -VAR xsize, ysize, color: INTEGER; -BEGIN - sys.GET(buf, xsize); - sys.GET(buf + 4, ysize); - INC(buf, 8); - IF (0 <= x) & (x < xsize) & (0 <= y) & (y < ysize) THEN - IF bpp32 THEN - sys.GET(buf + 4 * (xsize * y + x), color) - ELSE - sys.MOVE(buf + 3 * (xsize * y + x), sys.ADR(color), 3) - END - END - RETURN color -END pget; - -PROCEDURE getrgb(color: INTEGER; VAR r, g, b: INTEGER); -BEGIN - b := LSR(LSL(color, 24), 24); - g := LSR(LSL(color, 16), 24); - r := LSR(LSL(color, 8), 24); -END getrgb; - -PROCEDURE rgb(r, g, b: INTEGER): INTEGER; - RETURN b + LSL(g, 8) + LSL(r, 16) -END rgb; - -PROCEDURE create_glyph(VAR Font: TFont_desc; VAR glyph: Glyph; xsize, ysize: INTEGER); -BEGIN - glyph.base := Font.mempos; - glyph.xsize := xsize; - glyph.ysize := ysize; - Font.mempos := Font.mempos + xsize * ysize -END create_glyph; - -PROCEDURE getpix(Font: TFont_desc; n, x, y, xsize: INTEGER): CHAR; -VAR res: CHAR; -BEGIN - sys.GET(Font.mem + n + x + y * xsize, res) - RETURN res -END getpix; - -PROCEDURE setpix(VAR Font: TFont_desc; n, x, y, xsize: INTEGER; c: CHAR); -BEGIN - sys.PUT(Font.mem + n + x + y * xsize, c) -END setpix; - -PROCEDURE smooth(VAR Font: TFont_desc; n, xsize, ysize: INTEGER); -VAR x, y: INTEGER; -BEGIN - FOR y := 1 TO ysize - 1 DO - FOR x := 1 TO xsize - 1 DO - IF (getpix(Font, n, x, y, xsize) = 1X) & (getpix(Font, n, x - 1, y - 1, xsize) = 1X) & - (getpix(Font, n, x - 1, y, xsize) = 0X) & (getpix(Font, n, x, y - 1, xsize) = 0X) THEN - setpix(Font, n, x - 1, y, xsize, 2X); - setpix(Font, n, x, y - 1, xsize, 2X) - END; - IF (getpix(Font, n, x, y, xsize) = 0X) & (getpix(Font, n, x - 1, y - 1, xsize) = 0X) & - (getpix(Font, n, x - 1, y, xsize) = 1X) & (getpix(Font, n, x, y - 1, xsize) = 1X) THEN - setpix(Font, n, x, y, xsize, 2X); - setpix(Font, n, x - 1, y - 1, xsize, 2X) - END - END - END -END smooth; - -PROCEDURE _bold(VAR Font: TFont_desc; src, dst, src_xsize, dst_xsize, n: INTEGER); -VAR i, j, k: INTEGER; pix: CHAR; -BEGIN - FOR i := 0 TO src_xsize - 1 DO - FOR j := 0 TO Font.height - 1 DO - pix := getpix(Font, src, i, j, src_xsize); - IF pix = 1X THEN - FOR k := 0 TO n DO - setpix(Font, dst, i + k, j, dst_xsize, pix) - END - END - END - END -END _bold; - -PROCEDURE make_glyph(VAR Font: TFont_desc; c: INTEGER); -VAR ptr, i, j, max, x, y: INTEGER; s: SET; eoc: BOOLEAN; - glyph: Glyph; pix: CHAR; bold_width: INTEGER; -BEGIN - create_glyph(Font, glyph, Font.width, Font.height); - x := 0; - y := 0; - max := 0; - ptr := Font.font + Font.char_size * c; - eoc := FALSE; - REPEAT - sys.GET(ptr, s); - INC(ptr, 4); - FOR i := 0 TO 31 DO - IF ~eoc THEN - IF i IN s THEN - setpix(Font, glyph.base, x, y, Font.width, 1X); - IF x > max THEN - max := x - END - ELSE - setpix(Font, glyph.base, x, y, Font.width, 0X) - END - END; - INC(x); - IF x = Font.width THEN - x := 0; - INC(y); - eoc := eoc OR (y = Font.height) - END - END - UNTIL eoc; - IF max = 0 THEN - max := Font.width DIV 3 - END; - - glyph.width := max; - smooth(Font, glyph.base, glyph.xsize, glyph.ysize); - Font.glyphs[0, c] := glyph; - - bold_width := 1; - - create_glyph(Font, glyph, Font.width + bold_width, Font.height); - _bold(Font, Font.glyphs[0, c].base, glyph.base, Font.glyphs[0, c].xsize, glyph.xsize, bold_width); - smooth(Font, glyph.base, glyph.xsize, glyph.ysize); - glyph.width := max + bold_width; - Font.glyphs[1, c] := glyph; - - create_glyph(Font, glyph, Font.width + (Font.height - 1) DIV 3, Font.height); - FOR i := 0 TO Font.glyphs[0, c].xsize - 1 DO - FOR j := 0 TO Font.height - 1 DO - pix := getpix(Font, Font.glyphs[0, c].base, i, j, Font.glyphs[0, c].xsize); - IF pix = 1X THEN - setpix(Font, glyph.base, i + (Font.height - 1 - j) DIV 3, j, glyph.xsize, pix) - END - END - END; - smooth(Font, glyph.base, glyph.xsize, glyph.ysize); - glyph.width := max; - Font.glyphs[2, c] := glyph; - - create_glyph(Font, glyph, Font.width + (Font.height - 1) DIV 3 + bold_width, Font.height); - _bold(Font, Font.glyphs[2, c].base, glyph.base, Font.glyphs[2, c].xsize, glyph.xsize, bold_width); - smooth(Font, glyph.base, glyph.xsize, glyph.ysize); - glyph.width := max + bold_width; - Font.glyphs[3, c] := glyph; - -END make_glyph; - -PROCEDURE OutChar(Font: TFont_desc; c: INTEGER; x, y: INTEGER; buf: INTEGER; bpp32, smoothing: BOOLEAN; color, style: INTEGER): INTEGER; -VAR i, x0, y0, xsize, mem, xmax: INTEGER; r, g, b, r0, g0, b0: INTEGER; ch: CHAR; glyph: Glyph; -BEGIN - x0 := x; - y0 := y; - style := style MOD 4; - glyph := Font.glyphs[style, c]; - xsize := glyph.xsize; - xmax := x0 + xsize; - mem := Font.mem + glyph.base; - getrgb(color, r0, g0, b0); - FOR i := mem TO mem + xsize * Font.height - 1 DO - sys.GET(i, ch); - IF ch = 1X THEN - pset(buf, x, y, color, bpp32); - ELSIF (ch = 2X) & smoothing THEN - getrgb(pget(buf, x, y, bpp32), r, g, b); - r := (r * 3 + r0) DIV 4; - g := (g * 3 + g0) DIV 4; - b := (b * 3 + b0) DIV 4; - pset(buf, x, y, rgb(r, g, b), bpp32) - END; - INC(x); - IF x = xmax THEN - x := x0; - INC(y) - END - END - RETURN glyph.width -END OutChar; - -PROCEDURE hline(buf, x, y, width, color: INTEGER; bpp32: BOOLEAN); -VAR i: INTEGER; -BEGIN - FOR i := x TO x + width - 1 DO - pset(buf, i, y, color, bpp32) - END -END hline; - -PROCEDURE TextWidth*(Font: TFont; str, length, params: INTEGER): INTEGER; -VAR res: INTEGER; c: CHAR; -BEGIN - res := 0; - params := params MOD 4; - IF Font # NIL THEN - sys.GET(str, c); - WHILE (length > 0) OR (length = -1) & (c # 0X) DO - INC(str); - res := res + Font.glyphs[params, ORD(c)].width; - IF length > 0 THEN - DEC(length) - END; - IF length # 0 THEN - sys.GET(str, c) - END - END - END - RETURN res -END TextWidth; - -PROCEDURE TextHeight*(Font: TFont): INTEGER; -VAR res: INTEGER; -BEGIN - IF Font # NIL THEN - res := Font.height - ELSE - res := 0 - END - RETURN res -END TextHeight; - -PROCEDURE TextClipLeft(Font: TFont; str, length, params: INTEGER; VAR x: INTEGER): INTEGER; -VAR x1: INTEGER; c: CHAR; -BEGIN - params := params MOD 4; - sys.GET(str, c); - WHILE (length > 0) OR (length = -1) & (c # 0X) DO - INC(str); - x1 := x; - x := x + Font.glyphs[params, ORD(c)].width; - IF x > 0 THEN - length := 0; - END; - IF length > 0 THEN - DEC(length) - END; - IF length # 0 THEN - sys.GET(str, c) - END - END; - x := x1 - RETURN str - 1 -END TextClipLeft; - -PROCEDURE TextOut*(Font: TFont; canvas, x, y, str, length, color, params: INTEGER); -VAR width, xsize, ysize, str1, n: INTEGER; c: CHAR; bpp32, smoothing, underline, strike: BOOLEAN; -BEGIN - IF Font # NIL THEN - sys.GET(canvas, xsize); - sys.GET(canvas + 4, ysize); - IF (y <= -TextHeight(Font)) OR (y >= ysize) THEN - length := 0 - END; - IF length # 0 THEN - smoothing := 4 IN BITS(params); - bpp32 := 5 IN BITS(params); - underline := 2 IN BITS(params); - strike := 3 IN BITS(params); - str1 := TextClipLeft(Font, str, length, params, x); - n := str1 - str; - str := str1; - IF length >= n THEN - length := length - n - END; - sys.GET(str, c) - END; - WHILE (length > 0) OR (length = -1) & (c # 0X) DO - INC(str); - width := OutChar(Font^, ORD(c), x, y, canvas, bpp32, smoothing, color, params); - IF strike THEN - hline(canvas, x + ORD(1 IN BITS(params)) * ((Font.height DIV 2) DIV 3), y + Font.height DIV 2, width + 2, color, bpp32) - END; - IF underline THEN - hline(canvas, x, y + Font.height - 1, width + 2, color, bpp32) - END; - x := x + width; - IF x > xsize THEN - length := 0 - END; - IF length > 0 THEN - DEC(length) - END; - IF length # 0 THEN - sys.GET(str, c) - END - END - END -END TextOut; - -PROCEDURE SetSize*(_Font: TFont; font_size: INTEGER): BOOLEAN; -VAR temp, offset, fsize, i, memsize, mem: INTEGER; - c: CHAR; Font, Font2: TFont_desc; -BEGIN - offset := -1; - IF (MIN_FONT_SIZE <= font_size) & (font_size <= MAX_FONT_SIZE) & (_Font # NIL) THEN - Font := _Font^; - Font2 := Font; - temp := Font.data + (font_size - 8) * 4; - IF (Font.data <= temp) & (temp <= Font.size + Font.data - 4) THEN - sys.GET(temp, offset); - IF offset # -1 THEN - Font.font_size := font_size; - INC(offset, 156); - offset := offset + Font.data; - IF (Font.data <= offset) & (offset <= Font.size + Font.data - 4) THEN - sys.GET(offset, fsize); - IF fsize > 256 + 6 THEN - temp := offset + fsize - 1; - IF (Font.data <= temp) & (temp <= Font.size + Font.data - 1) THEN - sys.GET(temp, c); - IF c # 0X THEN - Font.height := ORD(c); - DEC(temp); - sys.GET(temp, c); - IF c # 0X THEN - Font.width := ORD(c); - DEC(fsize, 6); - Font.char_size := fsize DIV 256; - IF fsize MOD 256 # 0 THEN - INC(Font.char_size) - END; - IF Font.char_size > 0 THEN - Font.font := offset + 4; - Font.mempos := 0; - memsize := (Font.width + 10) * Font.height * 1024; - mem := Font.mem; - Font.mem := KOSAPI.sysfunc3(68, 12, memsize); - IF Font.mem # 0 THEN - IF mem # 0 THEN - mem := KOSAPI.sysfunc3(68, 13, mem) - END; - zeromem(memsize DIV 4, Font.mem); - FOR i := 0 TO 255 DO - make_glyph(Font, i) - END - ELSE - offset := -1 - END - ELSE - offset := -1 - END - ELSE - offset := -1 - END - ELSE - offset := -1 - END - ELSE - offset := -1 - END - ELSE - offset := -1 - END - ELSE - offset := -1 - END - END; - ELSE - offset := -1 - END; - IF offset # -1 THEN - _Font^ := Font - ELSE - _Font^ := Font2 - END - END - RETURN offset # -1 -END SetSize; - -PROCEDURE Enabled*(Font: TFont; font_size: INTEGER): BOOLEAN; -VAR offset, temp: INTEGER; -BEGIN - offset := -1; - IF (MIN_FONT_SIZE <= font_size) & (font_size <= MAX_FONT_SIZE) & (Font # NIL) THEN - temp := Font.data + (font_size - 8) * 4; - IF (Font.data <= temp) & (temp <= Font.size + Font.data - 4) THEN - sys.GET(temp, offset) - END - END - RETURN offset # -1 -END Enabled; - -PROCEDURE Destroy*(VAR Font: TFont); -BEGIN - IF Font # NIL THEN - IF Font.mem # 0 THEN - Font.mem := KOSAPI.sysfunc3(68, 13, Font.mem) - END; - IF Font.data # 0 THEN - Font.data := KOSAPI.sysfunc3(68, 13, Font.data) - END; - DISPOSE(Font) - END -END Destroy; - -PROCEDURE LoadFont*(file_name: ARRAY OF CHAR): TFont; -VAR Font: TFont; data, size, n: INTEGER; -BEGIN - data := File.Load(file_name, size); - IF (data # 0) & (size > 156) THEN - NEW(Font); - Font.data := data; - Font.size := size; - Font.font_size := 0; - n := MIN_FONT_SIZE; - WHILE ~SetSize(Font, n) & (n <= MAX_FONT_SIZE) DO - INC(n) - END; - IF Font.font_size = 0 THEN - Destroy(Font) - END - ELSE - IF data # 0 THEN - data := KOSAPI.sysfunc3(68, 13, data) - END; - Font := NIL - END - RETURN Font -END LoadFont; - -END kfonts. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/KolibriOS/libimg.ob07 b/programs/develop/oberon07/lib/KolibriOS/libimg.ob07 deleted file mode 100644 index 0ff0c5993..000000000 --- a/programs/develop/oberon07/lib/KolibriOS/libimg.ob07 +++ /dev/null @@ -1,435 +0,0 @@ -(* - Copyright 2016, 2018, 2020, 2022 KolibriOS team - - 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 libimg; - -IMPORT sys := SYSTEM, KOSAPI; - - -CONST - - FLIP_VERTICAL *= 1; - FLIP_HORIZONTAL *= 2; - - - ROTATE_90_CW *= 1; - ROTATE_180 *= 2; - ROTATE_270_CW *= 3; - ROTATE_90_CCW *= ROTATE_270_CW; - ROTATE_270_CCW *= ROTATE_90_CW; - - - // scale type corresponding img_scale params - LIBIMG_SCALE_INTEGER *= 1; // scale factor ; reserved 0 - LIBIMG_SCALE_TILE *= 2; // new width ; new height - LIBIMG_SCALE_STRETCH *= 3; // new width ; new height - LIBIMG_SCALE_FIT_RECT *= 4; // new width ; new height - LIBIMG_SCALE_FIT_WIDTH *= 5; // new width ; new height - LIBIMG_SCALE_FIT_HEIGHT *= 6; // new width ; new height - LIBIMG_SCALE_FIT_MAX *= 7; // new width ; new height - - - // interpolation algorithm - LIBIMG_INTER_NONE *= 0; // use it with LIBIMG_SCALE_INTEGER, LIBIMG_SCALE_TILE, etc - LIBIMG_INTER_BILINEAR *= 1; - LIBIMG_INTER_DEFAULT *= LIBIMG_INTER_BILINEAR; - - - // list of format id's - LIBIMG_FORMAT_BMP *= 1; - LIBIMG_FORMAT_ICO *= 2; - LIBIMG_FORMAT_CUR *= 3; - LIBIMG_FORMAT_GIF *= 4; - LIBIMG_FORMAT_PNG *= 5; - LIBIMG_FORMAT_JPEG *= 6; - LIBIMG_FORMAT_TGA *= 7; - LIBIMG_FORMAT_PCX *= 8; - LIBIMG_FORMAT_XCF *= 9; - LIBIMG_FORMAT_TIFF *= 10; - LIBIMG_FORMAT_PNM *= 11; - LIBIMG_FORMAT_WBMP *= 12; - LIBIMG_FORMAT_XBM *= 13; - LIBIMG_FORMAT_Z80 *= 14; - - - // encode flags (byte 0x02 of common option) - LIBIMG_ENCODE_STRICT_SPECIFIC *= 01H; - LIBIMG_ENCODE_STRICT_BIT_DEPTH *= 02H; - LIBIMG_ENCODE_DELETE_ALPHA *= 08H; - LIBIMG_ENCODE_FLUSH_ALPHA *= 10H; - - - // values for Image.Type - // must be consecutive to allow fast switch on Image.Type in support functions - bpp8i *= 1; // indexed - bpp24 *= 2; - bpp32 *= 3; - bpp15 *= 4; - bpp16 *= 5; - bpp1 *= 6; - bpp8g *= 7; // grayscale - bpp2i *= 8; - bpp4i *= 9; - bpp8a *= 10; // grayscale with alpha channel; application layer only!!! kernel doesn't handle this image type, libimg can only create and destroy such images - - - // bits in Image.Flags - IsAnimated *= 1; - - -TYPE - - Image* = RECORD - - Checksum *: INTEGER; - Width *: INTEGER; - Height *: INTEGER; - Next *: INTEGER; - Previous *: INTEGER; - Type *: INTEGER; // one of bppN - Data *: INTEGER; - Palette *: INTEGER; // used iff Type eq bpp1, bpp2, bpp4 or bpp8i - Extended *: INTEGER; - Flags *: INTEGER; // bitfield - Delay *: INTEGER // used iff IsAnimated is set in Flags - - END; - - - ImageDecodeOptions* = RECORD - - UsedSize *: INTEGER; // if >=8, the field BackgroundColor is valid, and so on - BackgroundColor *: INTEGER // used for transparent images as background - - END; - - - FormatsTableEntry* = RECORD - - Format_id *: INTEGER; - Is *: INTEGER; - Decode *: INTEGER; - Encode *: INTEGER; - Capabilities *: INTEGER - - END; - - -VAR - - img_is_img *: PROCEDURE (data, length: INTEGER): INTEGER; - - - - img_to_rgb2 *: PROCEDURE (img: INTEGER; out: INTEGER); -(* -;;------------------------------------------------------------------------------------------------;; -;? decodes image data into RGB triplets and stores them where out points to ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to source image ;; -;> out = where to store RGB triplets ;; -;;================================================================================================;; -*) - - - - img_to_rgb *: PROCEDURE (img: INTEGER): INTEGER; -(* -;;------------------------------------------------------------------------------------------------;; -;? decodes image data into RGB triplets and returns pointer to memory area containing them ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to source image ;; -;;------------------------------------------------------------------------------------------------;; -;< 0 / pointer to rgb_data (array of [rgb] triplets) ;; -;;================================================================================================;; -*) - - - - img_decode *: PROCEDURE (data, length, options: INTEGER): INTEGER; -(* -;;------------------------------------------------------------------------------------------------;; -;? decodes loaded into memory graphic file ;; -;;------------------------------------------------------------------------------------------------;; -;> data = pointer to file in memory ;; -;> length = size in bytes of memory area pointed to by data ;; -;> options = 0 / pointer to the structure of additional options ;; -;;------------------------------------------------------------------------------------------------;; -;< 0 / pointer to image ;; -;;================================================================================================;; -*) - - - - img_encode *: PROCEDURE (img: INTEGER; common, specific: INTEGER): INTEGER; -(* -;;------------------------------------------------------------------------------------------------;; -;? encode image to some format ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to input image ;; -;> common = some most important options ;; -; 0x00 : byte : format id ;; -; 0x01 : byte : fast encoding (0) / best compression ratio (255) ;; -; 0 : store uncompressed data (if supported both by the format and libimg) ;; -; 1 - 255 : use compression, if supported ;; -; this option may be ignored if any format specific options are defined ;; -; i.e. the 0 here will be ignored if some compression algorithm is specified ;; -; 0x02 : byte : flags (bitfield) ;; -; 0x01 : return an error if format specific conditions cannot be met ;; -; 0x02 : preserve current bit depth. means 8bpp/16bpp/24bpp and so on ;; -; 0x04 : delete alpha channel, if any ;; -; 0x08 : flush alpha channel with 0xff, if any; add it if none ;; -; 0x03 : byte : reserved, must be 0 ;; -;> specific = 0 / pointer to the structure of format specific options ;; -; see .inc for description ;; -;;------------------------------------------------------------------------------------------------;; -;< 0 / pointer to encoded data ;; -;;================================================================================================;; - *) - - - - img_create *: PROCEDURE (width, height, _type: INTEGER): INTEGER; -(* -;;------------------------------------------------------------------------------------------------;; -;? creates an Image structure and initializes some its fields ;; -;;------------------------------------------------------------------------------------------------;; -;> width = width of an image in pixels ;; -;> height = height of an image in pixels ;; -;> type = one of the bppN constants ;; -;;------------------------------------------------------------------------------------------------;; -;< 0 / pointer to image ;; -;;================================================================================================;; -*) - - - - img_destroy *: PROCEDURE (img: INTEGER): BOOLEAN; -(* -;;------------------------------------------------------------------------------------------------;; -;? frees memory occupied by an image and all the memory regions its fields point to ;; -;? follows Previous/Next pointers and deletes all the images in sequence ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to image ;; -;;------------------------------------------------------------------------------------------------;; -;< FALSE (fail) / TRUE (success) ;; -;;================================================================================================;; -*) - - - - img_destroy_layer *: PROCEDURE (img: INTEGER): BOOLEAN; -(* -;;------------------------------------------------------------------------------------------------;; -;? frees memory occupied by an image and all the memory regions its fields point to ;; -;? for image sequences deletes only one frame and fixes Previous/Next pointers ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to image ;; -;;------------------------------------------------------------------------------------------------;; -;< FALSE (fail) / TRUE (success) ;; -;;================================================================================================;; -*) - - - - img_count *: PROCEDURE (img: INTEGER): INTEGER; -(* -;;------------------------------------------------------------------------------------------------;; -;? Get number of images in the list (e.g. in animated GIF file) ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to image ;; -;;------------------------------------------------------------------------------------------------;; -;< -1 (fail) / >0 (ok) ;; -;;================================================================================================;; -*) - - - - img_flip *: PROCEDURE (img: INTEGER; flip_kind: INTEGER): BOOLEAN; -(* -;;------------------------------------------------------------------------------------------------;; -;? Flip all layers of image ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to image ;; -;> flip_kind = one of FLIP_* constants ;; -;;------------------------------------------------------------------------------------------------;; -;< FALSE / TRUE ;; -;;================================================================================================;; -*) - - - - img_flip_layer *: PROCEDURE (img: INTEGER; flip_kind: INTEGER): BOOLEAN; -(* -;;------------------------------------------------------------------------------------------------;; -;? Flip image layer ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to image ;; -;> flip_kind = one of FLIP_* constants ;; -;;------------------------------------------------------------------------------------------------;; -;< FALSE / TRUE ;; -;;================================================================================================;; -*) - - - - img_rotate *: PROCEDURE (img: INTEGER; rotate_kind: INTEGER): BOOLEAN; -(* -;;------------------------------------------------------------------------------------------------;; -;? Rotate all layers of image ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to image ;; -;> rotate_kind = one of ROTATE_* constants ;; -;;------------------------------------------------------------------------------------------------;; -;< FALSE / TRUE ;; -;;================================================================================================;; -*) - - - - img_rotate_layer *: PROCEDURE (img: INTEGER; rotate_kind: INTEGER): BOOLEAN; -(* -;;------------------------------------------------------------------------------------------------;; -;? Rotate image layer ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to image ;; -;> rotate_kind = one of ROTATE_* constants ;; -;;------------------------------------------------------------------------------------------------;; -;< FALSE / TRUE ;; -;;================================================================================================;; -*) - - - - img_draw *: PROCEDURE (img: INTEGER; x, y, width, height, xpos, ypos: INTEGER); -(* -;;------------------------------------------------------------------------------------------------;; -;? Draw image in the window ;; -;;------------------------------------------------------------------------------------------------;; -;> img = pointer to image ;; -;> x = x-coordinate in the window ;; -;> y = y-coordinate in the window ;; -;> width = maximum width to draw ;; -;> height = maximum height to draw ;; -;> xpos = offset in image by x-axis ;; -;> ypos = offset in image by y-axis ;; -;;================================================================================================;; -*) - - - - img_scale *: PROCEDURE (src: INTEGER; crop_x, crop_y, crop_width, crop_height: INTEGER; dst: INTEGER; scale, inter, param1, param2: INTEGER ): INTEGER; -(* -;;------------------------------------------------------------------------------------------------;; -;? scale _image ;; -;;------------------------------------------------------------------------------------------------;; -;> src = pointer to source image ;; -;> crop_x = left coord of cropping rect ;; -;> crop_y = top coord of cropping rect ;; -;> crop_width = width of cropping rect ;; -;> crop_height = height of cropping rect ;; -;> dst = pointer to resulting image / 0 ;; -;> scale = how to change width and height. see libimg.inc ;; -;> inter = interpolation algorithm ;; -;> param1 = see libimg.inc ;; -;> param2 = see libimg.inc ;; -;;------------------------------------------------------------------------------------------------;; -;< 0 / pointer to scaled image ;; -;;================================================================================================;; -*) - - - - img_convert *: PROCEDURE (src, dst: INTEGER; dst_type, flags, param: INTEGER); -(* -;;------------------------------------------------------------------------------------------------;; -;? scale _image ;; -;;------------------------------------------------------------------------------------------------;; -;> src = pointer to source image ;; -;> flags = see libimg.inc ;; -;> dst_type = the Image.Type of converted image ;; -;> dst = pointer to destination image, if any ;; -;;------------------------------------------------------------------------------------------------;; -;< 0 / pointer to converted image ;; -;;================================================================================================;; -*) - - - img_formats_table *: ARRAY 20 OF FormatsTableEntry; - - - -PROCEDURE GetImageStruct* (img: INTEGER; VAR ImageStruct: Image): BOOLEAN; -BEGIN - IF img # 0 THEN - sys.MOVE(img, sys.ADR(ImageStruct), sys.SIZE(Image)) - END - RETURN img # 0 -END GetImageStruct; - - -PROCEDURE GetFormatsTable(ptr: INTEGER); -VAR i: INTEGER; eot: BOOLEAN; -BEGIN - i := 0; - REPEAT - sys.MOVE(ptr, sys.ADR(img_formats_table[i]), sys.SIZE(FormatsTableEntry)); - ptr := ptr + sys.SIZE(FormatsTableEntry); - eot := img_formats_table[i].Format_id = 0; - INC(i) - UNTIL eot OR (i = LEN(img_formats_table)) -END GetFormatsTable; - - -PROCEDURE main; -VAR Lib, formats_table_ptr: INTEGER; - - PROCEDURE GetProc(Lib, v: INTEGER; name: ARRAY OF CHAR); - VAR a: INTEGER; - BEGIN - a := KOSAPI.GetProcAdr(name, Lib); - ASSERT(a # 0); - sys.PUT(v, a) - END GetProc; - -BEGIN - Lib := KOSAPI.LoadLib("/sys/lib/libimg.obj"); - ASSERT(Lib # 0); - GetProc(Lib, sys.ADR(img_is_img) , "img_is_img"); - GetProc(Lib, sys.ADR(img_to_rgb) , "img_to_rgb"); - GetProc(Lib, sys.ADR(img_to_rgb2) , "img_to_rgb2"); - GetProc(Lib, sys.ADR(img_decode) , "img_decode"); - GetProc(Lib, sys.ADR(img_encode) , "img_encode"); - GetProc(Lib, sys.ADR(img_create) , "img_create"); - GetProc(Lib, sys.ADR(img_destroy) , "img_destroy"); - GetProc(Lib, sys.ADR(img_destroy_layer) , "img_destroy_layer"); - GetProc(Lib, sys.ADR(img_count) , "img_count"); - GetProc(Lib, sys.ADR(img_flip) , "img_flip"); - GetProc(Lib, sys.ADR(img_flip_layer) , "img_flip_layer"); - GetProc(Lib, sys.ADR(img_rotate) , "img_rotate"); - GetProc(Lib, sys.ADR(img_rotate_layer) , "img_rotate_layer"); - GetProc(Lib, sys.ADR(img_draw) , "img_draw"); - GetProc(Lib, sys.ADR(img_scale) , "img_scale"); - GetProc(Lib, sys.ADR(img_convert) , "img_convert"); - GetProc(Lib, sys.ADR(formats_table_ptr) , "img_formats_table"); - GetFormatsTable(formats_table_ptr) -END main; - - -BEGIN - main -END libimg. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/Math/CMath.ob07 b/programs/develop/oberon07/lib/Math/CMath.ob07 deleted file mode 100644 index adc7fb178..000000000 --- a/programs/develop/oberon07/lib/Math/CMath.ob07 +++ /dev/null @@ -1,462 +0,0 @@ -(* *********************************************** - Модуль работы с комплексными числами. - Вадим Исаев, 2020 - Module for complex numbers. - Vadim Isaev, 2020 -*************************************************** *) - -MODULE CMath; - -IMPORT Math, Out; - -TYPE - complex* = POINTER TO RECORD - re*: REAL; - im*: REAL - END; - -VAR - result: complex; - - i* : complex; - _0*: complex; - -(* Инициализация комплексного числа. - Init complex number. *) -PROCEDURE CInit* (re : REAL; im: REAL): complex; -VAR - temp: complex; -BEGIN - NEW(temp); - temp.re:=re; - temp.im:=im; - - RETURN temp -END CInit; - - -(* Четыре основных арифметических операций. - Four base operations +, -, * , / *) - -(* Сложение - addition : z := z1 + z2 *) -PROCEDURE CAdd* (z1, z2: complex): complex; -BEGIN - result.re := z1.re + z2.re; - result.im := z1.im + z2.im; - - RETURN result -END CAdd; - -(* Сложение с REAL. - addition : z := z1 + r1 *) -PROCEDURE CAdd_r* (z1: complex; r1: REAL): complex; -BEGIN - result.re := z1.re + r1; - result.im := z1.im; - - RETURN result -END CAdd_r; - -(* Сложение с INTEGER. - addition : z := z1 + i1 *) -PROCEDURE CAdd_i* (z1: complex; i1: INTEGER): complex; -BEGIN - result.re := z1.re + FLT(i1); - result.im := z1.im; - - RETURN result -END CAdd_i; - -(* Смена знака. - substraction : z := - z1 *) -PROCEDURE CNeg (z1 : complex): complex; -BEGIN - result.re := -z1.re; - result.im := -z1.im; - - RETURN result -END CNeg; - -(* Вычитание. - substraction : z := z1 - z2 *) -PROCEDURE CSub* (z1, z2 : complex): complex; -BEGIN - result.re := z1.re - z2.re; - result.im := z1.im - z2.im; - - RETURN result -END CSub; - -(* Вычитание REAL. - substraction : z := z1 - r1 *) -PROCEDURE CSub_r1* (z1 : complex; r1 : REAL): complex; -BEGIN - result.re := z1.re - r1; - result.im := z1.im; - - RETURN result -END CSub_r1; - -(* Вычитание из REAL. - substraction : z := r1 - z1 *) -PROCEDURE CSub_r2* (r1 : REAL; z1 : complex): complex; -BEGIN - result.re := r1 - z1.re; - result.im := - z1.im; - - RETURN result -END CSub_r2; - -(* Вычитание INTEGER. - substraction : z := z1 - i1 *) -PROCEDURE CSub_i* (z1 : complex; i1 : INTEGER): complex; -BEGIN - result.re := z1.re - FLT(i1); - result.im := z1.im; - - RETURN result -END CSub_i; - -(* Умножение. - multiplication : z := z1 * z2 *) -PROCEDURE CMul (z1, z2 : complex): complex; -BEGIN - result.re := (z1.re * z2.re) - (z1.im * z2.im); - result.im := (z1.re * z2.im) + (z1.im * z2.re); - - RETURN result -END CMul; - -(* Умножение с REAL. - multiplication : z := z1 * r1 *) -PROCEDURE CMul_r (z1 : complex; r1 : REAL): complex; -BEGIN - result.re := z1.re * r1; - result.im := z1.im * r1; - - RETURN result -END CMul_r; - -(* Умножение с INTEGER. - multiplication : z := z1 * i1 *) -PROCEDURE CMul_i (z1 : complex; i1 : INTEGER): complex; -BEGIN - result.re := z1.re * FLT(i1); - result.im := z1.im * FLT(i1); - - RETURN result -END CMul_i; - -(* Деление. - division : z := znum / zden *) -PROCEDURE CDiv (z1, z2 : complex): complex; - (* The following algorithm is used to properly handle - denominator overflow: - - | a + b(d/c) c - a(d/c) - | ---------- + ---------- I if |d| < |c| - a + b I | c + d(d/c) a + d(d/c) - ------- = | - c + d I | b + a(c/d) -a+ b(c/d) - | ---------- + ---------- I if |d| >= |c| - | d + c(c/d) d + c(c/d) - *) -VAR - tmp, denom : REAL; -BEGIN - IF ( ABS(z2.re) > ABS(z2.im) ) THEN - tmp := z2.im / z2.re; - denom := z2.re + z2.im * tmp; - result.re := (z1.re + z1.im * tmp) / denom; - result.im := (z1.im - z1.re * tmp) / denom; - ELSE - tmp := z2.re / z2.im; - denom := z2.im + z2.re * tmp; - result.re := (z1.im + z1.re * tmp) / denom; - result.im := (-z1.re + z1.im * tmp) / denom; - END; - - RETURN result -END CDiv; - -(* Деление на REAL. - division : z := znum / r1 *) -PROCEDURE CDiv_r* (z1 : complex; r1 : REAL): complex; -BEGIN - result.re := z1.re / r1; - result.im := z1.im / r1; - - RETURN result -END CDiv_r; - -(* Деление на INTEGER. - division : z := znum / i1 *) -PROCEDURE CDiv_i* (z1 : complex; i1 : INTEGER): complex; -BEGIN - result.re := z1.re / FLT(i1); - result.im := z1.im / FLT(i1); - - RETURN result -END CDiv_i; - -(* fonctions elementaires *) - -(* Вывод на экран. - out complex number *) -PROCEDURE CPrint* (z: complex; width: INTEGER); -BEGIN - Out.Real(z.re, width); - IF z.im>=0.0 THEN - Out.String("+"); - END; - Out.Real(z.im, width); - Out.String("i"); -END CPrint; - -PROCEDURE CPrintLn* (z: complex; width: INTEGER); -BEGIN - CPrint(z, width); - Out.Ln; -END CPrintLn; - -(* Вывод на экран с фиксированным кол-вом знаков - после запятой (p) *) -PROCEDURE CPrintFix* (z: complex; width, p: INTEGER); -BEGIN - Out.FixReal(z.re, width, p); - IF z.im>=0.0 THEN - Out.String("+"); - END; - Out.FixReal(z.im, width, p); - Out.String("i"); -END CPrintFix; - -PROCEDURE CPrintFixLn* (z: complex; width, p: INTEGER); -BEGIN - CPrintFix(z, width, p); - Out.Ln; -END CPrintFixLn; - -(* Модуль числа. - module : r = |z| *) -PROCEDURE CMod* (z1 : complex): REAL; -BEGIN - RETURN Math.sqrt((z1.re * z1.re) + (z1.im * z1.im)) -END CMod; - -(* Квадрат числа. - square : r := z*z *) -PROCEDURE CSqr* (z1: complex): complex; -BEGIN - result.re := z1.re * z1.re - z1.im * z1.im; - result.im := 2.0 * z1.re * z1.im; - - RETURN result -END CSqr; - -(* Квадратный корень числа. - square root : r := sqrt(z) *) -PROCEDURE CSqrt* (z1: complex): complex; -VAR - root, q: REAL; -BEGIN - IF (z1.re#0.0) OR (z1.im#0.0) THEN - root := Math.sqrt(0.5 * (ABS(z1.re) + CMod(z1))); - q := z1.im / (2.0 * root); - IF z1.re >= 0.0 THEN - result.re := root; - result.im := q; - ELSE - IF z1.im < 0.0 THEN - result.re := - q; - result.im := - root - ELSE - result.re := q; - result.im := root - END - END - ELSE - result := z1; - END; - - RETURN result -END CSqrt; - -(* Экспонента. - exponantial : r := exp(z) *) -(* exp(x + iy) = exp(x).exp(iy) = exp(x).[cos(y) + i sin(y)] *) -PROCEDURE CExp* (z: complex): complex; -VAR - expz : REAL; -BEGIN - expz := Math.exp(z.re); - result.re := expz * Math.cos(z.im); - result.im := expz * Math.sin(z.im); - - RETURN result -END CExp; - -(* Натуральный логарифм. - natural logarithm : r := ln(z) *) -(* ln( p exp(i0)) = ln(p) + i0 + 2kpi *) -PROCEDURE CLn* (z: complex): complex; -BEGIN - result.re := Math.ln(CMod(z)); - result.im := Math.arctan2(z.im, z.re); - - RETURN result -END CLn; - -(* Число в степени. - exp : z := z1^z2 *) -PROCEDURE CPower* (z1, z2 : complex): complex; -VAR - a: complex; -BEGIN - a:=CLn(z1); - a:=CMul(z2, a); - result:=CExp(a); - - RETURN result -END CPower; - -(* Число в степени REAL. - multiplication : z := z1^r *) -PROCEDURE CPower_r* (z1: complex; r: REAL): complex; -VAR - a: complex; -BEGIN - a:=CLn(z1); - a:=CMul_r(a, r); - result:=CExp(a); - - RETURN result -END CPower_r; - -(* Обратное число. - inverse : r := 1 / z *) -PROCEDURE CInv* (z: complex): complex; -VAR - denom : REAL; -BEGIN - denom := (z.re * z.re) + (z.im * z.im); - (* generates a fpu exception if denom=0 as for reals *) - result.re:=z.re/denom; - result.im:=-z.im/denom; - - RETURN result -END CInv; - -(* direct trigonometric functions *) - -(* Косинус. - complex cosinus *) -(* cos(x+iy) = cos(x).cos(iy) - sin(x).sin(iy) *) -(* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *) -PROCEDURE CCos* (z: complex): complex; -BEGIN - result.re := Math.cos(z.re) * Math.cosh(z.im); - result.im := - Math.sin(z.re) * Math.sinh(z.im); - - RETURN result -END CCos; - -(* Синус. - sinus complex *) -(* sin(x+iy) = sin(x).cos(iy) + cos(x).sin(iy) *) -(* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *) -PROCEDURE CSin (z: complex): complex; -BEGIN - result.re := Math.sin(z.re) * Math.cosh(z.im); - result.im := Math.cos(z.re) * Math.sinh(z.im); - - RETURN result -END CSin; - -(* Тангенс. - tangente *) -PROCEDURE CTg* (z: complex): complex; -VAR - temp1, temp2: complex; -BEGIN - temp1:=CSin(z); - temp2:=CCos(z); - result:=CDiv(temp1, temp2); - - RETURN result -END CTg; - -(* inverse complex hyperbolic functions *) - -(* Гиперболический арккосинус. - hyberbolic arg cosinus *) -(* _________ *) -(* argch(z) = -/+ ln(z + i.V 1 - z.z) *) -PROCEDURE CArcCosh* (z : complex): complex; -BEGIN - result:=CNeg(CLn(CAdd(z, CMul(i, CSqrt(CSub_r2(1.0, CMul(z, z))))))); - - RETURN result -END CArcCosh; - -(* Гиперболический арксинус. - hyperbolic arc sinus *) -(* ________ *) -(* argsh(z) = ln(z + V 1 + z.z) *) -PROCEDURE CArcSinh* (z : complex): complex; -BEGIN - result:=CLn(CAdd(z, CSqrt(CAdd_r(CMul(z, z), 1.0)))); - - RETURN result -END CArcSinh; - -(* Гиперболический арктангенс. - hyperbolic arc tangent *) -(* argth(z) = 1/2 ln((z + 1) / (1 - z)) *) -PROCEDURE CArcTgh (z : complex): complex; -BEGIN - result:=CDiv_r(CLn(CDiv(CAdd_r(z, 1.0), CSub_r2(1.0, z))), 2.0); - - RETURN result -END CArcTgh; - -(* trigonometriques inverses *) - -(* Арккосинус. - arc cosinus complex *) -(* arccos(z) = -i.argch(z) *) -PROCEDURE CArcCos* (z: complex): complex; -BEGIN - result := CNeg(CMul(i, CArcCosh(z))); - - RETURN result -END CArcCos; - -(* Арксинус. - arc sinus complex *) -(* arcsin(z) = -i.argsh(i.z) *) -PROCEDURE CArcSin* (z : complex): complex; -BEGIN - result := CNeg(CMul(i, CArcSinh(z))); - - RETURN result -END CArcSin; - -(* Арктангенс. - arc tangente complex *) -(* arctg(z) = -i.argth(i.z) *) -PROCEDURE CArcTg* (z : complex): complex; -BEGIN - result := CNeg(CMul(i, CArcTgh(CMul(i, z)))); - - RETURN result -END CArcTg; - -BEGIN - - result:=CInit(0.0, 0.0); - i :=CInit(0.0, 1.0); - _0:=CInit(0.0, 0.0); - -END CMath. diff --git a/programs/develop/oberon07/lib/Math/MathBits.ob07 b/programs/develop/oberon07/lib/Math/MathBits.ob07 deleted file mode 100644 index b339c06bd..000000000 --- a/programs/develop/oberon07/lib/Math/MathBits.ob07 +++ /dev/null @@ -1,33 +0,0 @@ -(* **************************************** - Дополнение к модулю Math. - Побитовые операции над целыми числами. - Вадим Исаев, 2020 - Additional functions to the module Math. - Bitwise operations on integers. - Vadim Isaev, 2020 -******************************************* *) - -MODULE MathBits; - - -PROCEDURE iand* (x, y: INTEGER): INTEGER; - RETURN ORD(BITS(x) * BITS(y)) -END iand; - - -PROCEDURE ior* (x, y: INTEGER): INTEGER; - RETURN ORD(BITS(x) + BITS(y)) -END ior; - - -PROCEDURE ixor* (x, y: INTEGER): INTEGER; - RETURN ORD(BITS(x) / BITS(y)) -END ixor; - - -PROCEDURE inot* (x: INTEGER): INTEGER; - RETURN ORD(-BITS(x)) -END inot; - - -END MathBits. diff --git a/programs/develop/oberon07/lib/Math/MathRound.ob07 b/programs/develop/oberon07/lib/Math/MathRound.ob07 deleted file mode 100644 index 3952e88b3..000000000 --- a/programs/develop/oberon07/lib/Math/MathRound.ob07 +++ /dev/null @@ -1,99 +0,0 @@ -(* ****************************************** - Дополнительные функции к модулю Math. - Функции округления. - Вадим Исаев, 2020 - ------------------------------------- - Additional functions to the module Math. - Rounding functions. - Vadim Isaev, 2020 -********************************************* *) - -MODULE MathRound; - -IMPORT Math; - - -(* Возвращается целая часть числа x. - Returns the integer part of a argument x.*) -PROCEDURE trunc* (x: REAL): REAL; -VAR - a: REAL; - -BEGIN - a := FLT(FLOOR(x)); - IF (x < 0.0) & (x # a) THEN - a := a + 1.0 - END - - RETURN a -END trunc; - - -(* Возвращается дробная часть числа x. - Returns the fractional part of the argument x *) -PROCEDURE frac* (x: REAL): REAL; - RETURN x - trunc(x) -END frac; - - -(* Округление к ближайшему целому. - Rounding to the nearest integer. *) -PROCEDURE round* (x: REAL): REAL; -VAR - a: REAL; - -BEGIN - a := trunc(x); - IF ABS(frac(x)) >= 0.5 THEN - a := a + FLT(Math.sgn(x)) - END - - RETURN a -END round; - - -(* Округление к бОльшему целому. - Rounding to a largest integer *) -PROCEDURE ceil* (x: REAL): REAL; -VAR - a: REAL; - -BEGIN - a := FLT(FLOOR(x)); - IF x # a THEN - a := a + 1.0 - END - - RETURN a -END ceil; - - -(* Округление к меньшему целому. - Rounding to a smallest integer *) -PROCEDURE floor* (x: REAL): REAL; - RETURN FLT(FLOOR(x)) -END floor; - - -(* Округление до определённого количества знаков: - - если Digits отрицательное, то округление - в знаках после десятичной запятой; - - если Digits положительное, то округление - в знаках до запятой *) -PROCEDURE SimpleRoundTo* (AValue: REAL; Digits: INTEGER): REAL; -VAR - RV, a : REAL; - -BEGIN - RV := Math.ipower(10.0, -Digits); - IF AValue < 0.0 THEN - a := trunc((AValue * RV) - 0.5) - ELSE - a := trunc((AValue * RV) + 0.5) - END - - RETURN a / RV -END SimpleRoundTo; - - -END MathRound. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/Math/MathStat.ob07 b/programs/develop/oberon07/lib/Math/MathStat.ob07 deleted file mode 100644 index 9e56d93a2..000000000 --- a/programs/develop/oberon07/lib/Math/MathStat.ob07 +++ /dev/null @@ -1,238 +0,0 @@ -(* ******************************************** - Дополнение к модулю Math. - Статистические процедуры. - ------------------------------------- - Additional functions to the module Math. - Statistical functions -*********************************************** *) - -MODULE MathStat; - -IMPORT Math; - - -(*Минимальное значение. Нецелое *) -PROCEDURE MinValue* (data: ARRAY OF REAL; N: INTEGER): REAL; -VAR - i: INTEGER; - a: REAL; - -BEGIN - a := data[0]; - FOR i := 1 TO N - 1 DO - IF data[i] < a THEN - a := data[i] - END - END - - RETURN a -END MinValue; - - -(*Минимальное значение. Целое *) -PROCEDURE MinIntValue* (data: ARRAY OF INTEGER; N: INTEGER): INTEGER; -VAR - i: INTEGER; - a: INTEGER; - -BEGIN - a := data[0]; - FOR i := 1 TO N - 1 DO - IF data[i] < a THEN - a := data[i] - END - END - - RETURN a -END MinIntValue; - - -(*Максимальное значение. Нецелое *) -PROCEDURE MaxValue* (data: ARRAY OF REAL; N: INTEGER): REAL; -VAR - i: INTEGER; - a: REAL; - -BEGIN - a := data[0]; - FOR i := 1 TO N - 1 DO - IF data[i] > a THEN - a := data[i] - END - END - - RETURN a -END MaxValue; - - -(*Максимальное значение. Целое *) -PROCEDURE MaxIntValue* (data: ARRAY OF INTEGER; N: INTEGER): INTEGER; -VAR - i: INTEGER; - a: INTEGER; - -BEGIN - a := data[0]; - FOR i := 1 TO N - 1 DO - IF data[i] > a THEN - a := data[i] - END - END - - RETURN a -END MaxIntValue; - - -(* Сумма значений массива *) -PROCEDURE Sum* (data: ARRAY OF REAL; Count: INTEGER): REAL; -VAR - a: REAL; - i: INTEGER; - -BEGIN - a := 0.0; - FOR i := 0 TO Count - 1 DO - a := a + data[i] - END - - RETURN a -END Sum; - - -(* Сумма целых значений массива *) -PROCEDURE SumInt* (data: ARRAY OF INTEGER; Count: INTEGER): INTEGER; -VAR - a: INTEGER; - i: INTEGER; - -BEGIN - a := 0; - FOR i := 0 TO Count - 1 DO - a := a + data[i] - END - - RETURN a -END SumInt; - - -(* Сумма квадратов значений массива *) -PROCEDURE SumOfSquares* (data : ARRAY OF REAL; Count: INTEGER): REAL; -VAR - a: REAL; - i: INTEGER; - -BEGIN - a := 0.0; - FOR i := 0 TO Count - 1 DO - a := a + Math.sqrr(data[i]) - END - - RETURN a -END SumOfSquares; - - -(* Сумма значений и сумма квадратов значений массмва *) -PROCEDURE SumsAndSquares* (data: ARRAY OF REAL; Count : INTEGER; - VAR sum, sumofsquares : REAL); -VAR - i: INTEGER; - temp: REAL; - -BEGIN - sumofsquares := 0.0; - sum := 0.0; - FOR i := 0 TO Count - 1 DO - temp := data[i]; - sumofsquares := sumofsquares + Math.sqrr(temp); - sum := sum + temp - END -END SumsAndSquares; - - -(* Средниее значений массива *) -PROCEDURE Mean* (data: ARRAY OF REAL; Count: INTEGER): REAL; - RETURN Sum(data, Count) / FLT(Count) -END Mean; - - -PROCEDURE MeanAndTotalVariance* (data: ARRAY OF REAL; Count: INTEGER; - VAR mu: REAL; VAR variance: REAL); -VAR - i: INTEGER; - -BEGIN - mu := Mean(data, Count); - variance := 0.0; - FOR i := 0 TO Count - 1 DO - variance := variance + Math.sqrr(data[i] - mu) - END -END MeanAndTotalVariance; - - -(* Вычисление статистической дисперсии равной сумме квадратов разницы - между каждым конкретным значением массива Data и средним значением *) -PROCEDURE TotalVariance* (data: ARRAY OF REAL; Count: INTEGER): REAL; -VAR - mu, tv: REAL; - -BEGIN - MeanAndTotalVariance(data, Count, mu, tv) - RETURN tv -END TotalVariance; - - -(* Типовая дисперсия всех значений массива *) -PROCEDURE Variance* (data: ARRAY OF REAL; Count: INTEGER): REAL; -VAR - a: REAL; - -BEGIN - IF Count = 1 THEN - a := 0.0 - ELSE - a := TotalVariance(data, Count) / FLT(Count - 1) - END - - RETURN a -END Variance; - - -(* Стандартное среднеквадратичное отклонение *) -PROCEDURE StdDev* (data: ARRAY OF REAL; Count: INTEGER): REAL; - RETURN Math.sqrt(Variance(data, Count)) -END StdDev; - - -(* Среднее арифметическое всех значений массива, и среднее отклонение *) -PROCEDURE MeanAndStdDev* (data: ARRAY OF REAL; Count: INTEGER; - VAR mean: REAL; VAR stdDev: REAL); -VAR - totalVariance: REAL; - -BEGIN - MeanAndTotalVariance(data, Count, mean, totalVariance); - IF Count < 2 THEN - stdDev := 0.0 - ELSE - stdDev := Math.sqrt(totalVariance / FLT(Count - 1)) - END -END MeanAndStdDev; - - -(* Евклидова норма для всех значений массива *) -PROCEDURE Norm* (data: ARRAY OF REAL; Count: INTEGER): REAL; -VAR - a: REAL; - i: INTEGER; - -BEGIN - a := 0.0; - FOR i := 0 TO Count - 1 DO - a := a + Math.sqrr(data[i]) - END - - RETURN Math.sqrt(a) -END Norm; - - -END MathStat. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/Math/Rand.ob07 b/programs/develop/oberon07/lib/Math/Rand.ob07 deleted file mode 100644 index a8372eb08..000000000 --- a/programs/develop/oberon07/lib/Math/Rand.ob07 +++ /dev/null @@ -1,81 +0,0 @@ -(* ************************************ - Генератор какбыслучайных чисел, - Линейный конгруэнтный метод, - алгоритм Лемера. - Вадим Исаев, 2020 - ------------------------------- - Generator pseudorandom numbers, - Linear congruential generator, - Algorithm by D. H. Lehmer. - Vadim Isaev, 2020 -*************************************** *) - -MODULE Rand; - -IMPORT HOST, Math; - - -CONST - - RAND_MAX = 2147483647; - - -VAR - seed: INTEGER; - - -PROCEDURE Randomize*; -BEGIN - seed := HOST.GetTickCount() -END Randomize; - - -(* Целые какбыслучайные числа до RAND_MAX *) -PROCEDURE RandomI* (): INTEGER; -CONST - a = 630360016; - -BEGIN - seed := (a * seed) MOD RAND_MAX - RETURN seed -END RandomI; - - -(* Какбыслучайные числа с плавающей запятой от 0 до 1 *) -PROCEDURE RandomR* (): REAL; - RETURN FLT(RandomI()) / FLT(RAND_MAX) -END RandomR; - - -(* Какбыслучайное число в диапазоне от 0 до l. - Return a random number in a range 0 ... l *) -PROCEDURE RandomITo* (aTo: INTEGER): INTEGER; - RETURN FLOOR(RandomR() * FLT(aTo)) -END RandomITo; - - -(* Какбыслучайное число в диапазоне. - Return a random number in a range *) -PROCEDURE RandomIRange* (aFrom, aTo: INTEGER): INTEGER; - RETURN FLOOR(RandomR() * FLT(aTo - aFrom)) + aFrom -END RandomIRange; - - -(* Какбыслучайное число. Распределение Гаусса *) -PROCEDURE RandG* (mean, stddev: REAL): REAL; -VAR - U, S: REAL; - -BEGIN - REPEAT - U := 2.0 * RandomR() - 1.0; - S := Math.sqrr(U) + Math.sqrr(2.0 * RandomR() - 1.0) - UNTIL (1.0E-20 < S) & (S <= 1.0) - - RETURN Math.sqrt(-2.0 * Math.ln(S) / S) * U * stddev + mean -END RandG; - - -BEGIN - seed := 654321 -END Rand. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/Math/RandExt.ob07 b/programs/develop/oberon07/lib/Math/RandExt.ob07 deleted file mode 100644 index 4990a4f4c..000000000 --- a/programs/develop/oberon07/lib/Math/RandExt.ob07 +++ /dev/null @@ -1,298 +0,0 @@ -(* ************************************************************ - Дополнительные алгоритмы генераторов какбыслучайных чисел. - Вадим Исаев, 2020 - - Additional generators of pseudorandom numbers. - Vadim Isaev, 2020 - ************************************************************ *) - -MODULE RandExt; - -IMPORT HOST, MathRound, MathBits; - -CONST - (* Для алгоритма Мерсена-Твистера *) - N = 624; - M = 397; - MATRIX_A = 9908B0DFH; (* constant vector a *) - UPPER_MASK = 80000000H; (* most significant w-r bits *) - LOWER_MASK = 7FFFFFFFH; (* least significant r bits *) - INT_MAX = 4294967295; - - -TYPE -(* структура служебных данных, для алгоритма mrg32k3a *) - random_t = RECORD - mrg32k3a_seed : REAL; - mrg32k3a_x : ARRAY 3 OF REAL; - mrg32k3a_y : ARRAY 3 OF REAL - END; - - (* Для алгоритма Мерсена-Твистера *) - MTKeyArray = ARRAY N OF INTEGER; - -VAR - (* Для алгоритма mrg32k3a *) - prndl: random_t; - (* Для алгоритма Мерсена-Твистера *) - mt : MTKeyArray; (* the array for the state vector *) - mti : INTEGER; (* mti == N+1 means mt[N] is not initialized *) - -(* --------------------------------------------------------------------------- - Генератор какбыслучайных чисел в диапазоне [a,b]. - Алгоритм 133б из книги "Агеев и др. - Бибилотека алгоритмов 101б-150б", - стр. 53. - Переделка из Algol на Oberon и доработка, Вадим Исаев, 2020 - - Generator pseudorandom numbers, algorithm 133b from - Comm ACM 5,10 (Oct 1962) 553. - Convert from Algol to Oberon Vadim Isaev, 2020. - - Входные параметры: - a - начальное вычисляемое значение, тип REAL; - b - конечное вычисляемое значение, тип REAL; - seed - начальное значение для генерации случайного числа. - Должно быть в диапазоне от 10 000 000 000 до 34 359 738 368 (2^35), - нечётное. - --------------------------------------------------------------------------- *) -PROCEDURE alg133b* (a, b: REAL; VAR seed: INTEGER): REAL; -CONST - m35 = 34359738368; - m36 = 68719476736; - m37 = 137438953472; - -VAR - x: INTEGER; -BEGIN - IF seed # 0 THEN - IF (seed MOD 2 = 0) THEN - seed := seed + 1 - END; - x:=seed; - seed:=0; - END; - - x:=5*x; - IF x>=m37 THEN - x:=x-m37 - END; - IF x>=m36 THEN - x:=x-m36 - END; - IF x>=m35 THEN - x:=x-m35 - END; - - RETURN FLT(x) / FLT(m35) * (b - a) + a -END alg133b; - -(* ---------------------------------------------------------- - Генератор почти равномерно распределённых - какбыслучайных чисел mrg32k3a - (Combined Multiple Recursive Generator) от 0 до 1. - Период повторения последовательности = 2^127 - - Generator pseudorandom numbers, - algorithm mrg32k3a. - - Переделка из FreePascal на Oberon, Вадим Исаев, 2020 - Convert from FreePascal to Oberon, Vadim Isaev, 2020 - ---------------------------------------------------------- *) -(* Инициализация генератора. - - Входные параметры: - seed - значение для инициализации. Любое. Если передать - ноль, то вместо ноля будет подставлено кол-во - процессорных тиков. *) -PROCEDURE mrg32k3a_init* (seed: REAL); -BEGIN - prndl.mrg32k3a_x[0] := 1.0; - prndl.mrg32k3a_x[1] := 1.0; - prndl.mrg32k3a_y[0] := 1.0; - prndl.mrg32k3a_y[1] := 1.0; - prndl.mrg32k3a_y[2] := 1.0; - - IF seed # 0.0 THEN - prndl.mrg32k3a_x[2] := seed; - ELSE - prndl.mrg32k3a_x[2] := FLT(HOST.GetTickCount()); - END; - -END mrg32k3a_init; - -(* Генератор какбыслучайных чисел от 0.0 до 1.0. *) -PROCEDURE mrg32k3a* (): REAL; - -CONST - (* random MRG32K3A algorithm constants *) - MRG32K3A_NORM = 2.328306549295728E-10; - MRG32K3A_M1 = 4294967087.0; - MRG32K3A_M2 = 4294944443.0; - MRG32K3A_A12 = 1403580.0; - MRG32K3A_A13 = 810728.0; - MRG32K3A_A21 = 527612.0; - MRG32K3A_A23 = 1370589.0; - RAND_BUFSIZE = 512; - -VAR - - xn, yn, result: REAL; - -BEGIN - (* Часть 1 *) - xn := MRG32K3A_A12 * prndl.mrg32k3a_x[1] - MRG32K3A_A13 * prndl.mrg32k3a_x[2]; - xn := xn - MathRound.trunc(xn / MRG32K3A_M1) * MRG32K3A_M1; - IF xn < 0.0 THEN - xn := xn + MRG32K3A_M1; - END; - - prndl.mrg32k3a_x[2] := prndl.mrg32k3a_x[1]; - prndl.mrg32k3a_x[1] := prndl.mrg32k3a_x[0]; - prndl.mrg32k3a_x[0] := xn; - - (* Часть 2 *) - yn := MRG32K3A_A21 * prndl.mrg32k3a_y[0] - MRG32K3A_A23 * prndl.mrg32k3a_y[2]; - yn := yn - MathRound.trunc(yn / MRG32K3A_M2) * MRG32K3A_M2; - IF yn < 0.0 THEN - yn := yn + MRG32K3A_M2; - END; - - prndl.mrg32k3a_y[2] := prndl.mrg32k3a_y[1]; - prndl.mrg32k3a_y[1] := prndl.mrg32k3a_y[0]; - prndl.mrg32k3a_y[0] := yn; - - (* Смешение частей *) - IF xn <= yn THEN - result := ((xn - yn + MRG32K3A_M1) * MRG32K3A_NORM) - ELSE - result := (xn - yn) * MRG32K3A_NORM; - END; - - RETURN result -END mrg32k3a; - - -(* ------------------------------------------------------------------- - Генератор какбыслучайных чисел, алгоритм Мерсена-Твистера (MT19937). - Переделка из Delphi в Oberon Вадим Исаев, 2020. - - Mersenne Twister Random Number Generator. - - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Adapted for DMath by Jean Debord - Feb. 2007 - Adapted for Oberon-07 by Vadim Isaev - May 2020 - ------------------------------------------------------------ *) -(* Initializes MT generator with a seed *) -PROCEDURE InitMT(Seed : INTEGER); -VAR - i : INTEGER; -BEGIN - mt[0] := MathBits.iand(Seed, INT_MAX); - FOR i := 1 TO N-1 DO - mt[i] := (1812433253 * MathBits.ixor(mt[i-1], LSR(mt[i-1], 30)) + i); - (* See Knuth TAOCP Vol2. 3rd Ed. P.106 For multiplier. - In the previous versions, MSBs of the seed affect - only MSBs of the array mt[]. - 2002/01/09 modified by Makoto Matsumoto *) - mt[i] := MathBits.iand(mt[i], INT_MAX); - (* For >32 Bit machines *) - END; - mti := N; -END InitMT; - -(* Initialize MT generator with an array InitKey[0..(KeyLength - 1)] *) -PROCEDURE InitMTbyArray(InitKey : MTKeyArray; KeyLength : INTEGER); -VAR - i, j, k, k1 : INTEGER; -BEGIN - InitMT(19650218); - - i := 1; - j := 0; - - IF N > KeyLength THEN - k1 := N - ELSE - k1 := KeyLength; - END; - - FOR k := k1 TO 1 BY -1 DO - (* non linear *) - mt[i] := MathBits.ixor(mt[i], (MathBits.ixor(mt[i-1], LSR(mt[i-1], 30)) * 1664525)) + InitKey[j] + j; - mt[i] := MathBits.iand(mt[i], INT_MAX); (* for WORDSIZE > 32 machines *) - INC(i); - INC(j); - IF i >= N THEN - mt[0] := mt[N-1]; - i := 1; - END; - IF j >= KeyLength THEN - j := 0; - END; - END; - - FOR k := N-1 TO 1 BY -1 DO - (* non linear *) - mt[i] := MathBits.ixor(mt[i], (MathBits.ixor(mt[i-1], LSR(mt[i-1], 30)) * 1566083941)) - i; - mt[i] := MathBits.iand(mt[i], INT_MAX); (* for WORDSIZE > 32 machines *) - INC(i); - IF i >= N THEN - mt[0] := mt[N-1]; - i := 1; - END; - END; - - mt[0] := UPPER_MASK; (* MSB is 1; assuring non-zero initial array *) - -END InitMTbyArray; - -(* Generates a integer Random number on [-2^31 .. 2^31 - 1] interval *) -PROCEDURE IRanMT(): INTEGER; -VAR - mag01 : ARRAY 2 OF INTEGER; - y,k : INTEGER; -BEGIN - IF mti >= N THEN (* generate N words at one Time *) - (* If IRanMT() has not been called, a default initial seed is used *) - IF mti = N + 1 THEN - InitMT(5489); - END; - - FOR k := 0 TO (N-M)-1 DO - y := MathBits.ior(MathBits.iand(mt[k], UPPER_MASK), MathBits.iand(mt[k+1], LOWER_MASK)); - mt[k] := MathBits.ixor(MathBits.ixor(mt[k+M], LSR(y, 1)), mag01[MathBits.iand(y, 1H)]); - END; - - FOR k := (N-M) TO (N-2) DO - y := MathBits.ior(MathBits.iand(mt[k], UPPER_MASK), MathBits.iand(mt[k+1], LOWER_MASK)); - mt[k] := MathBits.ixor(mt[k - (N - M)], MathBits.ixor(LSR(y, 1), mag01[MathBits.iand(y, 1H)])); - END; - - y := MathBits.ior(MathBits.iand(mt[N-1], UPPER_MASK), MathBits.iand(mt[0], LOWER_MASK)); - mt[N-1] := MathBits.ixor(mt[M-1], MathBits.ixor(LSR(y, 1), mag01[MathBits.iand(y, 1H)])); - - mti := 0; - END; - - y := mt[mti]; - INC(mti); - - (* Tempering *) - y := MathBits.ixor(y, LSR(y, 11)); - y := MathBits.ixor(y, MathBits.iand(LSL(y, 7), 9D2C5680H)); - y := MathBits.ixor(y, MathBits.iand(LSL(y, 15), 4022730752)); - y := MathBits.ixor(y, LSR(y, 18)); - - RETURN y -END IRanMT; - -(* Generates a real Random number on [0..1] interval *) -PROCEDURE RRanMT(): REAL; -BEGIN - RETURN FLT(IRanMT())/FLT(INT_MAX) -END RRanMT; - - -END RandExt. diff --git a/programs/develop/oberon07/samples/BUILD_ALL.SH b/programs/develop/oberon07/samples/BUILD_ALL.SH deleted file mode 100644 index 16828c5f8..000000000 --- a/programs/develop/oberon07/samples/BUILD_ALL.SH +++ /dev/null @@ -1,5 +0,0 @@ -#SHS -/kolibrios/develop/oberon07/compiler.kex HW.ob07 kosexe -out /tmp0/1/HW.kex -stk 1 -/kolibrios/develop/oberon07/compiler.kex HW_con.ob07 kosexe -out /tmp0/1/HW_con.kex -stk 1 -/kolibrios/develop/oberon07/compiler.kex Dialogs.ob07 kosexe -out /tmp0/1/Dialogs.kex -stk 1 -exit \ No newline at end of file diff --git a/programs/develop/oberon07/samples/Dialogs.ob07 b/programs/develop/oberon07/samples/Dialogs.ob07 deleted file mode 100644 index 57452a10c..000000000 --- a/programs/develop/oberon07/samples/Dialogs.ob07 +++ /dev/null @@ -1,159 +0,0 @@ -MODULE Dialogs; - -IMPORT - KOSAPI, SYSTEM, OpenDlg, ColorDlg; - - -CONST - btnNone = 0; - btnClose = 1; - btnOpen = 17; - btnColor = 18; - - -VAR - header: ARRAY 1024 OF CHAR; - back_color: INTEGER; - - -PROCEDURE BeginDraw; -BEGIN - KOSAPI.sysfunc2(12, 1) -END BeginDraw; - - -PROCEDURE EndDraw; -BEGIN - KOSAPI.sysfunc2(12, 2) -END EndDraw; - - -PROCEDURE DefineAndDrawWindow (left, top, width, height, color, style, hcolor, hstyle: INTEGER; header: ARRAY OF CHAR); -BEGIN - KOSAPI.sysfunc6(0, left*65536 + width, top*65536 + height, color + LSL(style, 24), hcolor + LSL(hstyle, 24), SYSTEM.ADR(header[0])) -END DefineAndDrawWindow; - - -PROCEDURE WaitForEvent (): INTEGER; - RETURN KOSAPI.sysfunc1(10) -END WaitForEvent; - - -PROCEDURE ExitApp; -BEGIN - KOSAPI.sysfunc1(-1) -END ExitApp; - - -PROCEDURE pause (t: INTEGER); -BEGIN - KOSAPI.sysfunc2(5, t) -END pause; - - -PROCEDURE Buttons; - - PROCEDURE Button (id, X, Y, W, H: INTEGER; Caption: ARRAY OF CHAR); - VAR - n: INTEGER; - BEGIN - n := LENGTH(Caption); - KOSAPI.sysfunc5(8, X*65536 + W, Y*65536 + H, id, 00C0C0C0H); - X := X + (W - 8*n) DIV 2; - Y := Y + (H - 14) DIV 2; - KOSAPI.sysfunc6(4, X*65536 + Y, LSL(48, 24), SYSTEM.ADR(Caption[0]), n, 0) - END Button; - -BEGIN - Button(btnOpen, 5, 5, 70, 25, "open"); - Button(btnColor, 85, 5, 70, 25, "color"); -END Buttons; - - -PROCEDURE draw_window; -BEGIN - BeginDraw; - DefineAndDrawWindow(200, 200, 500, 100, back_color, 51, 0, 0, header); - Buttons; - EndDraw; -END draw_window; - - -PROCEDURE OpenFile (Open: OpenDlg.Dialog); -BEGIN - IF Open # NIL THEN - OpenDlg.Show(Open, 500, 450); - WHILE Open.status = 2 DO - pause(30) - END; - IF Open.status = 1 THEN - COPY(Open.FilePath, header) - END - END -END OpenFile; - - -PROCEDURE SelColor (Color: ColorDlg.Dialog); -BEGIN - IF Color # NIL THEN - ColorDlg.Show(Color); - WHILE Color.status = 2 DO - pause(30) - END; - IF Color.status = 1 THEN - back_color := Color.color - END - END -END SelColor; - - -PROCEDURE GetButton (): INTEGER; -VAR - btn: INTEGER; -BEGIN - btn := KOSAPI.sysfunc1(17); - IF btn MOD 256 = 0 THEN - btn := btn DIV 256 - ELSE - btn := btnNone - END - RETURN btn -END GetButton; - - -PROCEDURE main; -CONST - EVENT_REDRAW = 1; - EVENT_KEY = 2; - EVENT_BUTTON = 3; -VAR - Open: OpenDlg.Dialog; - Color: ColorDlg.Dialog; -BEGIN - back_color := 00FFFFFFH; - header := "Dialogs"; - Open := OpenDlg.Create(draw_window, 0, "/sys", "ASM|TXT|INI"); - Color := ColorDlg.Create(draw_window); - - WHILE TRUE DO - CASE WaitForEvent() OF - |EVENT_REDRAW: - draw_window - - |EVENT_KEY: - - |EVENT_BUTTON: - CASE GetButton() OF - |btnNone: - |btnClose: ExitApp - |btnOpen: OpenFile(Open) - |btnColor: SelColor(Color) - END - END - END -END main; - - -BEGIN - main -END Dialogs. \ No newline at end of file diff --git a/programs/develop/oberon07/samples/HW.ob07 b/programs/develop/oberon07/samples/HW.ob07 deleted file mode 100644 index 72a9c49c9..000000000 --- a/programs/develop/oberon07/samples/HW.ob07 +++ /dev/null @@ -1,78 +0,0 @@ -MODULE HW; - -IMPORT - SYSTEM, KOSAPI; - - -PROCEDURE BeginDraw; -BEGIN - KOSAPI.sysfunc2(12, 1) -END BeginDraw; - - -PROCEDURE EndDraw; -BEGIN - KOSAPI.sysfunc2(12, 2) -END EndDraw; - - -PROCEDURE DefineAndDrawWindow (left, top, width, height, color, style, hcolor, hstyle: INTEGER; header: ARRAY OF CHAR); -BEGIN - KOSAPI.sysfunc6(0, left*65536 + width, top*65536 + height, color + LSL(style, 24), hcolor + LSL(hstyle, 24), SYSTEM.ADR(header[0])) -END DefineAndDrawWindow; - - -PROCEDURE WriteTextToWindow (x, y, color: INTEGER; text: ARRAY OF CHAR); -BEGIN - KOSAPI.sysfunc6(4, x*65536 + y, color + LSL(48, 24), SYSTEM.ADR(text[0]), LENGTH(text), 0) -END WriteTextToWindow; - - -PROCEDURE WaitForEvent (): INTEGER; - RETURN KOSAPI.sysfunc1(10) -END WaitForEvent; - - -PROCEDURE ExitApp; -BEGIN - KOSAPI.sysfunc1(-1) -END ExitApp; - - -PROCEDURE draw_window (header, text: ARRAY OF CHAR); -CONST - WHITE = 0FFFFFFH; - RED = 0C00000H; - GREEN = 0008000H; - BLUE = 00000C0H; - GRAY = 0808080H; -BEGIN - BeginDraw; - DefineAndDrawWindow(200, 200, 300, 150, WHITE, 51, 0, 0, header); - WriteTextToWindow( 5, 10, RED, text); - WriteTextToWindow(35, 30, GREEN, text); - WriteTextToWindow(65, 50, BLUE, text); - WriteTextToWindow(95, 70, GRAY, text); - EndDraw -END draw_window; - - -PROCEDURE main (header, text: ARRAY OF CHAR); -CONST - EVENT_REDRAW = 1; - EVENT_KEY = 2; - EVENT_BUTTON = 3; -BEGIN - WHILE TRUE DO - CASE WaitForEvent() OF - |EVENT_REDRAW: draw_window(header, text) - |EVENT_KEY: ExitApp - |EVENT_BUTTON: ExitApp - END - END -END main; - - -BEGIN - main("Hello", "Hello, world!") -END HW. \ No newline at end of file diff --git a/programs/develop/oberon07/samples/HW_con.ob07 b/programs/develop/oberon07/samples/HW_con.ob07 deleted file mode 100644 index 94ac7e8ad..000000000 --- a/programs/develop/oberon07/samples/HW_con.ob07 +++ /dev/null @@ -1,59 +0,0 @@ -MODULE HW_con; - -IMPORT - Out, In, Console, DateTime; - - -PROCEDURE OutInt2 (n: INTEGER); -BEGIN - ASSERT((0 <= n) & (n <= 99)); - IF n < 10 THEN - Out.Char("0") - END; - Out.Int(n, 0) -END OutInt2; - - -PROCEDURE OutMonth (n: INTEGER); -VAR - str: ARRAY 4 OF CHAR; -BEGIN - CASE n OF - | 1: str := "jan" - | 2: str := "feb" - | 3: str := "mar" - | 4: str := "apr" - | 5: str := "may" - | 6: str := "jun" - | 7: str := "jul" - | 8: str := "aug" - | 9: str := "sep" - |10: str := "oct" - |11: str := "nov" - |12: str := "dec" - END; - Out.String(str) -END OutMonth; - - -PROCEDURE main; -VAR - Year, Month, Day, - Hour, Min, Sec, Msec: INTEGER; -BEGIN - Out.String("Hello, world!"); Out.Ln; - Console.SetColor(Console.White, Console.Red); - DateTime.Now(Year, Month, Day, Hour, Min, Sec, Msec); - OutInt2(Day); Out.Char("-"); OutMonth(Month); Out.Char("-"); Out.Int(Year, 0); Out.Char(" "); - OutInt2(Hour); Out.Char(":"); OutInt2(Min); Out.Char(":"); OutInt2(Sec); Out.Ln; - Console.SetColor(Console.Blue, Console.LightGray); - Out.Ln; Out.String("press enter..."); - In.Ln -END main; - - -BEGIN - Console.open; - main; - Console.exit(TRUE) -END HW_con. \ No newline at end of file diff --git a/programs/develop/oberon07/source/AMD64.ob07 b/programs/develop/oberon07/source/AMD64.ob07 deleted file mode 100644 index 9242cb193..000000000 --- a/programs/develop/oberon07/source/AMD64.ob07 +++ /dev/null @@ -1,2424 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2023, Anton Krotov - All rights reserved. -*) - -MODULE AMD64; - -IMPORT IL, BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PATHS, PROG, TARGETS, - REG, UTILS, S := STRINGS, PE32, ELF, X86, ERRORS; - - -CONST - - rax = REG.R0; - r10 = REG.R10; - r11 = REG.R11; - - rcx = REG.R1; - rdx = REG.R2; - r8 = REG.R8; - r9 = REG.R9; - - rsp = 4; - rbp = 5; - rsi = 6; - rdi = 7; - - MAX_XMM = 5; - - je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H; - - sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H; - - shl = IL.opLSL2; shr = IL.opLSR2; sar = IL.opASR2; ror = IL.opROR2; - - sCODE = BIN.PICCODE; - sDATA = BIN.PICDATA; - sBSS = BIN.PICBSS; - sIMP = BIN.PICIMP; - - FPR_ERR = 41; - - -TYPE - - COMMAND = IL.COMMAND; - - Number = POINTER TO RECORD (LISTS.ITEM) value: INTEGER END; - - OPRR = PROCEDURE (reg1, reg2: INTEGER); - - -VAR - - R: REG.REGS; - - Numbers: LISTS.LIST; - Numbers_Count: INTEGER; - Numbers_Offs: INTEGER; - - prog: BIN.PROGRAM; - - tcount: INTEGER; - - dllret, sofinit: INTEGER; - - Win64RegPar: ARRAY 4 OF INTEGER; - SystemVRegPar: ARRAY 6 OF INTEGER; - - Xmm: ARRAY 1000 OF INTEGER; - - fname: PATHS.PATH; - - -PROCEDURE OutByte (b: BYTE); -BEGIN - X86.OutByte(b) -END OutByte; - - -PROCEDURE OutByte2 (a, b: BYTE); -BEGIN - X86.OutByte(a); - X86.OutByte(b) -END OutByte2; - - -PROCEDURE OutByte3 (a, b, c: BYTE); -BEGIN - X86.OutByte(a); - X86.OutByte(b); - X86.OutByte(c) -END OutByte3; - - -PROCEDURE OutInt (n: INTEGER); -BEGIN - X86.OutByte(n MOD 256); - X86.OutByte(UTILS.Byte(n, 1)); - X86.OutByte(UTILS.Byte(n, 2)); - X86.OutByte(UTILS.Byte(n, 3)) -END OutInt; - - -PROCEDURE short (n: INTEGER): INTEGER; - RETURN 2 * ORD(X86.isByte(n)) -END short; - - -PROCEDURE long (n: INTEGER): INTEGER; - RETURN 40H * ORD(~X86.isByte(n)) -END long; - - -PROCEDURE OutIntByte (n: INTEGER); -BEGIN - IF X86.isByte(n) THEN - OutByte(n MOD 256) - ELSE - OutInt(n) - END -END OutIntByte; - - -PROCEDURE isLong (n: INTEGER): BOOLEAN; - RETURN (n > UTILS.max32) OR (n < UTILS.min32) -END isLong; - - -PROCEDURE NewNumber (value: INTEGER); -VAR - number: Number; - -BEGIN - NEW(number); - number.value := value; - LISTS.push(Numbers, number); - INC(Numbers_Count) -END NewNumber; - - -PROCEDURE NewLabel (): INTEGER; -BEGIN - BIN.NewLabel(prog) - RETURN IL.NewLabel() -END NewLabel; - - -PROCEDURE Rex (reg1, reg2: INTEGER); -BEGIN - OutByte(48H + reg1 DIV 8 + 4 * (reg2 DIV 8)) -END Rex; - - -PROCEDURE lea (reg, offset, section: INTEGER); -BEGIN - Rex(0, reg); - OutByte2(8DH, 05H + 8 * (reg MOD 8)); (* lea reg, [rip + offset] *) - X86.Reloc(section, offset) -END lea; - - -PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *) -BEGIN - Rex(reg1, reg2); - OutByte2(op, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8) -END oprr; - - -PROCEDURE oprr2 (op1, op2: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *) -BEGIN - Rex(reg1, reg2); - OutByte3(op1, op2, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8) -END oprr2; - - -PROCEDURE mov (reg1, reg2: INTEGER); (* mov reg1, reg2 *) -BEGIN - oprr(89H, reg1, reg2) -END mov; - - -PROCEDURE xor (reg1, reg2: INTEGER); (* xor reg1, reg2 *) -BEGIN - oprr(31H, reg1, reg2) -END xor; - - -PROCEDURE and (reg1, reg2: INTEGER); (* and reg1, reg2 *) -BEGIN - oprr(21H, reg1, reg2) -END and; - - -PROCEDURE _or (reg1, reg2: INTEGER); (* or reg1, reg2 *) -BEGIN - oprr(09H, reg1, reg2) -END _or; - - -PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *) -BEGIN - oprr(01H, reg1, reg2) -END add; - - -PROCEDURE sub (reg1, reg2: INTEGER); (* sub reg1, reg2 *) -BEGIN - oprr(29H, reg1, reg2) -END sub; - - -PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *) -BEGIN - IF rax IN {reg1, reg2} THEN - Rex(reg1 + reg2, 0); - OutByte(90H + (reg1 + reg2) MOD 8) - ELSE - oprr(87H, reg1, reg2) - END -END xchg; - - -PROCEDURE cmprr (reg1, reg2: INTEGER); (* cmp reg1, reg2 *) -BEGIN - oprr(39H, reg1, reg2) -END cmprr; - - -PROCEDURE pop (reg: INTEGER); (* pop reg *) -BEGIN - IF reg >= 8 THEN - OutByte(41H) - END; - OutByte(58H + reg MOD 8) -END pop; - - -PROCEDURE push (reg: INTEGER); (* push reg *) -BEGIN - IF reg >= 8 THEN - OutByte(41H) - END; - OutByte(50H + reg MOD 8) -END push; - - -PROCEDURE decr (reg: INTEGER); -BEGIN - Rex(reg, 0); - OutByte2(0FFH, 0C8H + reg MOD 8) (* dec reg1 *) -END decr; - - -PROCEDURE incr (reg: INTEGER); -BEGIN - Rex(reg, 0); - OutByte2(0FFH, 0C0H + reg MOD 8) (* inc reg1 *) -END incr; - - -PROCEDURE drop; -BEGIN - REG.Drop(R) -END drop; - - -PROCEDURE GetAnyReg (): INTEGER; - RETURN REG.GetAnyReg(R) -END GetAnyReg; - - -PROCEDURE callimp (label: INTEGER); -BEGIN - OutByte2(0FFH, 15H); (* call qword[rip + label + IMP] *) - X86.Reloc(sIMP, label) -END callimp; - - -PROCEDURE pushDA (offs: INTEGER); -VAR - reg: INTEGER; - -BEGIN - reg := GetAnyReg(); - lea(reg, offs, sDATA); - push(reg); - drop -END pushDA; - - -PROCEDURE CallRTL (proc: INTEGER); -VAR - label: INTEGER; - -BEGIN - label := IL.codes.rtl[proc]; - IF label < 0 THEN - callimp(-label) - ELSE - X86.call(label) - END -END CallRTL; - - -PROCEDURE UnOp (VAR reg: INTEGER); -BEGIN - REG.UnOp(R, reg) -END UnOp; - - -PROCEDURE BinOp (VAR reg1, reg2: INTEGER); -BEGIN - REG.BinOp(R, reg1, reg2) -END BinOp; - - -PROCEDURE PushAll (NumberOfParameters: INTEGER); -BEGIN - REG.PushAll(R); - DEC(R.pushed, NumberOfParameters) -END PushAll; - - -PROCEDURE movabs (reg, n: INTEGER); -VAR - i: INTEGER; - -BEGIN - Rex(reg, 0); - OutByte(0B8H + reg MOD 8); (* movabs reg, n *) - FOR i := 0 TO 7 DO - OutByte(UTILS.Byte(n, i)) - END -END movabs; - - -PROCEDURE movrc (reg, n: INTEGER); (* mov reg, n *) -BEGIN - IF isLong(n) THEN - movabs(reg, n) - ELSIF n = 0 THEN - xor(reg, reg) - ELSE - Rex(reg, 0); - OutByte2(0C7H, 0C0H + reg MOD 8); - OutInt(n) - END -END movrc; - - -PROCEDURE test (reg: INTEGER); (* test reg, reg *) -BEGIN - oprr(85H, reg, reg) -END test; - - -PROCEDURE oprlongc (reg, n: INTEGER; oprr: OPRR); -VAR - reg2: INTEGER; - -BEGIN - reg2 := GetAnyReg(); - ASSERT(reg2 # reg); - movabs(reg2, n); - oprr(reg, reg2); - drop -END oprlongc; - - -PROCEDURE oprc (op, reg, n: INTEGER; oprr: OPRR); -BEGIN - IF isLong(n) THEN - oprlongc(reg, n, oprr) - ELSE - Rex(reg, 0); - X86.oprc(op, reg, n) - END -END oprc; - - -PROCEDURE cmprc (reg, n: INTEGER); (* cmp reg, n *) -BEGIN - IF n = 0 THEN - test(reg) - ELSE - oprc(0F8H, reg, n, cmprr) - END -END cmprc; - - -PROCEDURE addrc (reg, n: INTEGER); (* add reg, n *) -BEGIN - oprc(0C0H, reg, n, add) -END addrc; - - -PROCEDURE subrc (reg, n: INTEGER); (* sub reg, n *) -BEGIN - oprc(0E8H, reg, n, sub) -END subrc; - - -PROCEDURE andrc (reg, n: INTEGER); (* and reg, n *) -BEGIN - oprc(0E0H, reg, n, and) -END andrc; - - -PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *) -BEGIN - oprc(0C8H, reg, n, _or) -END orrc; - - -PROCEDURE xorrc (reg, n: INTEGER); (* xor reg, n *) -BEGIN - oprc(0F0H, reg, n, xor) -END xorrc; - - -PROCEDURE pushc (n: INTEGER); -VAR - reg2: INTEGER; - -BEGIN - IF isLong(n) THEN - reg2 := GetAnyReg(); - movabs(reg2, n); - push(reg2); - drop - ELSE - X86.pushc(n) - END -END pushc; - - -PROCEDURE not (reg: INTEGER); (* not reg *) -BEGIN - Rex(reg, 0); - OutByte2(0F7H, 0D0H + reg MOD 8) -END not; - - -PROCEDURE neg (reg: INTEGER); (* neg reg *) -BEGIN - Rex(reg, 0); - OutByte2(0F7H, 0D8H + reg MOD 8) -END neg; - - -PROCEDURE movzx (reg1, reg2, offs: INTEGER; word: BOOLEAN); (* movzx reg1, byte/word[reg2 + offs] *) -BEGIN - Rex(reg2, reg1); - X86.movzx(reg1, reg2, offs, word) -END movzx; - - -PROCEDURE movmr32 (reg1, offs, reg2: INTEGER); (* mov dword[reg1+offs], reg2_32 *) -BEGIN - X86._movrm(reg2, reg1, offs, 32, TRUE) -END movmr32; - - -PROCEDURE movrm32 (reg1, reg2, offs: INTEGER); (* mov reg1_32, dword[reg2+offs] *) -BEGIN - X86._movrm(reg1, reg2, offs, 32, FALSE) -END movrm32; - - -PROCEDURE movmr (reg1, offs, reg2: INTEGER); (* mov qword[reg1+offs], reg2 *) -BEGIN - X86._movrm(reg2, reg1, offs, 64, TRUE) -END movmr; - - -PROCEDURE movrm (reg1, reg2, offs: INTEGER); (* mov reg1, qword[reg2+offs] *) -BEGIN - X86._movrm(reg1, reg2, offs, 64, FALSE) -END movrm; - - -PROCEDURE comisd (xmm1, xmm2: INTEGER); (* comisd xmm1, xmm2 *) -BEGIN - OutByte(66H); - IF (xmm1 >= 8) OR (xmm2 >= 8) THEN - OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8) - END; - OutByte3(0FH, 2FH, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8) -END comisd; - - -PROCEDURE _movsdrm (xmm, reg, offs: INTEGER; mr: BOOLEAN); -VAR - b: BYTE; - -BEGIN - OutByte(0F2H); - IF (xmm >= 8) OR (reg >= 8) THEN - OutByte(40H + (xmm DIV 8) * 4 + reg DIV 8) - END; - OutByte2(0FH, 10H + ORD(mr)); - IF (offs = 0) & (reg # rbp) THEN - b := 0 - ELSE - b := 40H + long(offs) - END; - OutByte(b + (xmm MOD 8) * 8 + reg MOD 8); - IF reg = rsp THEN - OutByte(24H) - END; - IF b # 0 THEN - OutIntByte(offs) - END -END _movsdrm; - - -PROCEDURE movsdrm (xmm, reg, offs: INTEGER); (* movsd xmm, qword[reg+offs] *) -BEGIN - _movsdrm(xmm, reg, offs, FALSE) -END movsdrm; - - -PROCEDURE movsdmr (reg, offs, xmm: INTEGER); (* movsd qword[reg+offs], xmm *) -BEGIN - _movsdrm(xmm, reg, offs, TRUE) -END movsdmr; - - -PROCEDURE opxx (op, xmm1, xmm2: INTEGER); -BEGIN - OutByte(0F2H); - IF (xmm1 >= 8) OR (xmm2 >= 8) THEN - OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8) - END; - OutByte3(0FH, op, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8) -END opxx; - - -PROCEDURE jcc (cc, label: INTEGER); (* jcc label *) -BEGIN - X86.jcc(cc, label) -END jcc; - - -PROCEDURE shiftrc (op, reg, n: INTEGER); -BEGIN - Rex(reg, 0); - IF n = 1 THEN - OutByte(0D1H) - ELSE - OutByte(0C1H) - END; - X86.shift(op, reg MOD 8); - IF n # 1 THEN - OutByte(n) - END -END shiftrc; - - -PROCEDURE GetRegA; -BEGIN - ASSERT(REG.GetReg(R, rax)) -END GetRegA; - - -PROCEDURE Win64Passing (params: INTEGER); -VAR - n, i: INTEGER; - -BEGIN - n := params MOD 32; - params := params DIV 32; - FOR i := 0 TO n - 1 DO - IF i IN BITS(params) THEN - movsdrm(i, rsp, i * 8) - ELSE - movrm(Win64RegPar[i], rsp, i * 8) - END - END -END Win64Passing; - - -PROCEDURE SysVPassing (params: INTEGER); -VAR - n, i, s, p, ofs: INTEGER; - i_count, f_count: INTEGER; - reg: BOOLEAN; - -BEGIN - ASSERT(r11 IN R.regs); - n := params MOD 32; - params := params DIV 32; - s := 0; - - i_count := 0; - f_count := 0; - FOR i := 0 TO n - 1 DO - IF i IN BITS(params) THEN - INC(f_count) - ELSE - INC(i_count) - END - END; - - s := MAX(0, f_count - 8) + MAX(0, i_count - 6); - p := 0; - - subrc(rsp, s * 8); - - i_count := 0; - f_count := 0; - FOR i := 0 TO n - 1 DO - ofs := (i + s) * 8; - IF i IN BITS(params) THEN - reg := f_count <= 7; - IF reg THEN - movsdrm(f_count, rsp, ofs); - INC(f_count) - END - ELSE - reg := i_count <= 5; - IF reg THEN - movrm(SystemVRegPar[i_count], rsp, ofs); - INC(i_count) - END - END; - - IF ~reg THEN - movrm(r11, rsp, ofs); - movmr(rsp, p, r11); - INC(p, 8) - END - END -END SysVPassing; - - -PROCEDURE fcmp (op: INTEGER; xmm: INTEGER); -VAR - cc, reg: INTEGER; - -BEGIN - reg := GetAnyReg(); - xor(reg, reg); - CASE op OF - |IL.opEQF: - comisd(xmm - 1, xmm); - cc := sete - - |IL.opNEF: - comisd(xmm - 1, xmm); - cc := setne - - |IL.opLTF: - comisd(xmm - 1, xmm); - cc := setc - - |IL.opGTF: - comisd(xmm, xmm - 1); - cc := setc - - |IL.opLEF: - comisd(xmm, xmm - 1); - cc := setnc - - |IL.opGEF: - comisd(xmm - 1, xmm); - cc := setnc - END; - OutByte2(7AH, 3 + reg DIV 8); (* jp L *) - X86.setcc(cc, reg) - (* L: *) -END fcmp; - - -PROCEDURE translate (commands: LISTS.LIST; stroffs: INTEGER); -VAR - cmd, next: COMMAND; - - opcode, param1, param2, param3, a, b, c, n, label, L, i, cc: INTEGER; - - reg1, reg2, reg3, xmm: INTEGER; - - float: REAL; - -BEGIN - xmm := -1; - cmd := commands.first(COMMAND); - WHILE cmd # NIL DO - - param1 := cmd.param1; - param2 := cmd.param2; - - opcode := cmd.opcode; - - CASE opcode OF - - |IL.opJMP: - X86.jmp(param1) - - |IL.opCALL, IL.opWIN64CALL, IL.opSYSVCALL: - CASE opcode OF - |IL.opCALL: - |IL.opWIN64CALL: Win64Passing(param2) - |IL.opSYSVCALL: SysVPassing(param2) - END; - X86.call(param1) - - |IL.opCALLP, IL.opWIN64CALLP, IL.opSYSVCALLP: - UnOp(reg1); - IF reg1 # rax THEN - mov(rax, reg1) - END; - drop; - CASE opcode OF - |IL.opCALLP: - |IL.opWIN64CALLP: Win64Passing(param2) - |IL.opSYSVCALLP: SysVPassing(param2) - END; - OutByte2(0FFH, 0D0H); (* call rax *) - ASSERT(R.top = -1) - - |IL.opCALLI, IL.opWIN64CALLI, IL.opSYSVCALLI: - CASE opcode OF - |IL.opCALLI: - |IL.opWIN64CALLI: Win64Passing(param2) - |IL.opSYSVCALLI: SysVPassing(param2) - END; - callimp(param1) - - |IL.opLABEL: - X86.SetLabel(param1) - - |IL.opERR: - CallRTL(IL._error) - - |IL.opONERR: - pushc(param2); - X86.jmp(param1) - - |IL.opPUSHC: - pushc(param2) - - |IL.opPRECALL: - PushAll(0); - IF (param2 # 0) & (xmm >= 0) THEN - subrc(rsp, 8) - END; - INC(Xmm[0]); - Xmm[Xmm[0]] := xmm + 1; - WHILE xmm >= 0 DO - subrc(rsp, 8); - movsdmr(rsp, 0, xmm); - DEC(xmm) - END; - ASSERT(xmm = -1) - - |IL.opWIN64ALIGN16: - ASSERT(rax IN R.regs); - mov(rax, rsp); - andrc(rsp, -16); - push(rax); - subrc(rsp, (MAX(param2 - 4, 0) MOD 2 + MAX(4 - param2, 0) + 1) * 8) - - |IL.opSYSVALIGN16: - ASSERT(rax IN R.regs); - mov(rax, rsp); - andrc(rsp, -16); - push(rax); - IF ~ODD(param2) THEN - push(rax) - END - - |IL.opRESF, IL.opRES: - ASSERT(R.top = -1); - ASSERT(xmm = -1); - n := Xmm[Xmm[0]]; DEC(Xmm[0]); - - IF opcode = IL.opRESF THEN - INC(xmm); - IF n > 0 THEN - movsdmr(rsp, n * 8, 0); - DEC(xmm); - INC(n) - END; - - IF xmm + n > MAX_XMM THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END - ELSE - GetRegA - END; - - WHILE n > 0 DO - INC(xmm); - movsdrm(xmm, rsp, 0); - addrc(rsp, 8); - DEC(n) - END - - |IL.opENTER: - ASSERT(R.top = -1); - - X86.SetLabel(param1); - - param3 := cmd.param3; - - IF param3 > 0 THEN - push(rbp); - mov(rbp, rsp); - - n := param3 MOD 32; - param3 := param3 DIV 32; - - FOR i := 0 TO n - 1 DO - IF i IN BITS(param3) THEN - movsdmr(rbp, i * 8 + 16, i) - ELSE - movmr(rbp, i * 8 + 16, Win64RegPar[i]) - END - END - ELSIF param3 < 0 THEN - param3 := -param3; - n := (param3 MOD 32) * 8; - param3 := param3 DIV 32; - pop(r11); - subrc(rsp, n); - push(r11); - push(rbp); - mov(rbp, rsp); - - a := 0; - b := 0; - c := 0; - - INC(n, 16); - - FOR i := 16 TO n - 8 BY 8 DO - IF ODD(param3) THEN - IF b <= 7 THEN - movsdmr(rbp, i, b); - INC(b) - ELSE - movrm(r11, rbp, n + c); - movmr(rbp, i, r11); - INC(c, 8) - END - ELSE - IF a <= 5 THEN - movmr(rbp, i, SystemVRegPar[a]); - INC(a) - ELSE - movrm(r11, rbp, n + c); - movmr(rbp, i, r11); - INC(c, 8) - END - END; - param3 := param3 DIV 2 - END - ELSE - push(rbp); - mov(rbp, rsp) - END; - - n := param2; - IF n > 4 THEN - movrc(rcx, n); - (* L: *) - pushc(0); - OutByte2(0E2H, 0FCH) (* loop L *) - ELSE - WHILE n > 0 DO - pushc(0); - DEC(n) - END - END - - |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: - IF opcode = IL.opLEAVER THEN - UnOp(reg1); - IF reg1 # rax THEN - mov(rax, reg1) - END; - drop - END; - - ASSERT(R.top = -1); - - IF opcode = IL.opLEAVEF THEN - DEC(xmm) - END; - - ASSERT(xmm = -1); - - IF param1 > 0 THEN - mov(rsp, rbp) - END; - - pop(rbp); - IF param2 > 0 THEN - OutByte3(0C2H, (param2 * 8) MOD 256, (param2 * 8) DIV 256) (* ret param2*8 *) - ELSE - X86.ret - END - - |IL.opSAVES: - UnOp(reg1); - REG.PushAll_1(R); - pushDA(stroffs + param2); - push(reg1); - drop; - pushc(param1); - CallRTL(IL._move) - - |IL.opSADR: - lea(GetAnyReg(), stroffs + param2, sDATA) - - |IL.opLOAD8: - UnOp(reg1); - movzx(reg1, reg1, 0, FALSE) - - |IL.opLOAD16: - UnOp(reg1); - movzx(reg1, reg1, 0, TRUE) - - |IL.opLOAD32: - UnOp(reg1); - movrm32(reg1, reg1, 0); - shiftrc(shl, reg1, 32); - shiftrc(shr, reg1, 32) - - |IL.opLOAD64: - UnOp(reg1); - movrm(reg1, reg1, 0) - - |IL.opLLOAD64: - reg1 := GetAnyReg(); - movrm(reg1, rbp, param2 * 8) - - |IL.opLLOAD8, - IL.opLLOAD16: - reg1 := GetAnyReg(); - movzx(reg1, rbp, param2 * 8, opcode = IL.opLLOAD16) - - |IL.opLLOAD32: - reg1 := GetAnyReg(); - movrm32(reg1, rbp, param2 * 8); - shiftrc(shl, reg1, 32); - shiftrc(shr, reg1, 32) - - |IL.opGLOAD64: - reg1 := GetAnyReg(); - Rex(0, reg1); (* mov reg1, qword[rip + param2 + BSS] *) - OutByte2(8BH, 05H + 8 * (reg1 MOD 8)); - X86.Reloc(sBSS, param2) - - |IL.opGLOAD8, IL.opGLOAD16: - reg1 := GetAnyReg(); - Rex(0, reg1); (* movzx reg1, byte/word[rip + param2 + BSS] *) - OutByte3(0FH, 0B6H + ORD(opcode = IL.opGLOAD16), 05H + 8 * (reg1 MOD 8)); - X86.Reloc(sBSS, param2) - - |IL.opGLOAD32: - reg1 := GetAnyReg(); - lea(reg1, param2, sBSS); - movrm32(reg1, reg1, 0); - shiftrc(shl, reg1, 32); - shiftrc(shr, reg1, 32) - - |IL.opVLOAD64: - reg1 := GetAnyReg(); - movrm(reg1, rbp, param2 * 8); - movrm(reg1, reg1, 0) - - |IL.opVLOAD8, - IL.opVLOAD16: - reg1 := GetAnyReg(); - movrm(reg1, rbp, param2 * 8); - movzx(reg1, reg1, 0, opcode = IL.opVLOAD16) - - |IL.opVLOAD32: - reg1 := GetAnyReg(); - reg2 := GetAnyReg(); - movrm(reg2, rbp, param2 * 8); - movrm32(reg1, reg2, 0); - shiftrc(shl, reg1, 32); - shiftrc(shr, reg1, 32); - drop - - |IL.opLADR: - n := param2 * 8; - next := cmd.next(COMMAND); - IF (next.opcode = IL.opSAVEF) OR (next.opcode = IL.opSAVEFI) THEN - ASSERT(xmm >= 0); - movsdmr(rbp, n, xmm); - DEC(xmm); - cmd := next - ELSIF next.opcode = IL.opLOADF THEN - INC(xmm); - IF xmm > MAX_XMM THEN - ERRORS.ErrorMsg(fname, next.param1, next.param2, FPR_ERR) - END; - movsdrm(xmm, rbp, n); - cmd := next - ELSE - IF (next.opcode = IL.opADDC) & ~isLong(n + next.param2) THEN - INC(n, next.param2); - cmd := next - END; - reg1 := GetAnyReg(); - Rex(0, reg1); - OutByte2(8DH, 45H + long(n) + (reg1 MOD 8) * 8); (* lea reg1, qword[rbp+n] *) - OutIntByte(n) - END - - |IL.opGADR: - next := cmd.next(COMMAND); - IF (next.opcode = IL.opADDC) & ~isLong(param2 + next.param2) THEN - INC(param2, next.param2); - cmd := next - END; - lea(GetAnyReg(), param2, sBSS) - - |IL.opVADR: - movrm(GetAnyReg(), rbp, param2 * 8) - - |IL.opSAVE8C: - UnOp(reg1); - IF reg1 >= 8 THEN - OutByte(41H) - END; - OutByte3(0C6H, reg1 MOD 8, param2); (* mov byte[reg1], param2 *) - drop - - |IL.opSAVE16C: - UnOp(reg1); - OutByte(66H); - IF reg1 >= 8 THEN - OutByte(41H) - END; - OutByte2(0C7H, reg1 MOD 8); - OutByte2(param2 MOD 256, param2 DIV 256); (* mov word[reg1], param2 *) - drop - - |IL.opSAVEC: - UnOp(reg1); - IF isLong(param2) THEN - reg2 := GetAnyReg(); - movrc(reg2, param2); - movmr(reg1, 0, reg2); - drop - ELSE - Rex(reg1, 0); - OutByte2(0C7H, reg1 MOD 8); (* mov qword[reg1], param2 *) - OutInt(param2) - END; - drop - - |IL.opRSET: - PushAll(2); - CallRTL(IL._set); - GetRegA - - |IL.opRSETR: - PushAll(1); - pushc(param2); - CallRTL(IL._set); - GetRegA - - |IL.opRSETL: - UnOp(reg1); - REG.PushAll_1(R); - pushc(param2); - push(reg1); - drop; - CallRTL(IL._set); - GetRegA - - |IL.opRSET1: - PushAll(1); - CallRTL(IL._set1); - GetRegA - - |IL.opINCL, IL.opEXCL: - BinOp(reg1, reg2); - cmprc(reg1, 64); - OutByte2(73H, 04H); (* jnb L *) - Rex(reg2, reg1); - OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opEXCL), 8 * (reg1 MOD 8) + reg2 MOD 8); (* bts/btr qword[reg2], reg1 *) - (* L: *) - drop; - drop - - |IL.opINCLC, IL.opEXCLC: - UnOp(reg1); - Rex(reg1, 0); - OutByte2(0FH, 0BAH); (* bts/btr qword[reg1], param2 *) - OutByte2(28H + 8 * ORD(opcode = IL.opEXCLC) + reg1 MOD 8, param2); - drop - - |IL.opEQS .. IL.opGES: - PushAll(4); - pushc(opcode - IL.opEQS); - CallRTL(IL._strcmp); - GetRegA - - |IL.opEQSW .. IL.opGESW: - PushAll(4); - pushc(opcode - IL.opEQSW); - CallRTL(IL._strcmpw); - GetRegA - - |IL.opCONST: - movrc(GetAnyReg(), param2) - - |IL.opEQ..IL.opGE, - IL.opEQC..IL.opGEC: - - IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN - BinOp(reg1, reg2); - cmprr(reg1, reg2); - drop - ELSE - UnOp(reg1); - cmprc(reg1, param2) - END; - - drop; - cc := X86.cond(opcode); - - next := cmd.next(COMMAND); - IF next.opcode = IL.opJNZ THEN - jcc(cc, next.param1); - cmd := next - ELSIF next.opcode = IL.opJZ THEN - jcc(X86.inv0(cc), next.param1); - cmd := next - ELSE - reg1 := GetAnyReg(); - X86.setcc(cc + 16, reg1); - andrc(reg1, 1) - END - - |IL.opCODE: - OutByte(param2) - - |IL.opPUSHIP: - reg1 := GetAnyReg(); - lea(reg1, param2, sIMP); - movrm(reg1, reg1, 0) - - |IL.opPARAM: - IF param2 = 1 THEN - UnOp(reg1); - push(reg1); - drop - ELSE - ASSERT(R.top + 1 <= param2); - PushAll(param2) - END - - |IL.opJNZ1: - UnOp(reg1); - test(reg1); - jcc(jne, param1) - - |IL.opJG: - UnOp(reg1); - test(reg1); - jcc(jg, param1) - - |IL.opJNZ: - UnOp(reg1); - test(reg1); - jcc(jne, param1); - drop - - |IL.opJZ: - UnOp(reg1); - test(reg1); - jcc(je, param1); - drop - - |IL.opIN, IL.opINR: - IF opcode = IL.opINR THEN - reg2 := GetAnyReg(); - movrc(reg2, param2) - END; - label := NewLabel(); - L := NewLabel(); - BinOp(reg1, reg2); - cmprc(reg1, 64); - jcc(jb, L); - xor(reg1, reg1); - X86.jmp(label); - X86.SetLabel(L); - Rex(reg2, reg1); - OutByte3(0FH, 0A3H, 0C0H + 8 * (reg1 MOD 8) + reg2 MOD 8); (* bt reg2, reg1 *) - X86.setcc(setc, reg1); - andrc(reg1, 1); - X86.SetLabel(label); - drop - - |IL.opINL: - UnOp(reg1); - Rex(reg1, 0); - OutByte2(0FH, 0BAH); (* bt reg1, param2 *) - OutByte2(0E0H + reg1 MOD 8, param2); - X86.setcc(setc, reg1); - andrc(reg1, 1) - - |IL.opNOT: - UnOp(reg1); - test(reg1); - X86.setcc(sete, reg1); - andrc(reg1, 1) - - |IL.opORD: - UnOp(reg1); - test(reg1); - X86.setcc(setne, reg1); - andrc(reg1, 1) - - |IL.opABS: - UnOp(reg1); - test(reg1); - OutByte2(7DH, 03H); (* jge L *) - neg(reg1) - (* L: *) - - |IL.opEQB, IL.opNEB: - BinOp(reg1, reg2); - drop; - test(reg1); - label := NewLabel(); - jcc(je, label); - movrc(reg1, 1); - X86.SetLabel(label); - test(reg2); - label := NewLabel(); - jcc(je, label); - movrc(reg2, 1); - X86.SetLabel(label); - cmprr(reg1, reg2); - IF opcode = IL.opEQB THEN - X86.setcc(sete, reg1) - ELSE - X86.setcc(setne, reg1) - END; - andrc(reg1, 1) - - |IL.opMULSC: - UnOp(reg1); - andrc(reg1, param2) - - |IL.opDIVSC: - UnOp(reg1); - xorrc(reg1, param2) - - |IL.opADDSC: - UnOp(reg1); - orrc(reg1, param2) - - |IL.opSUBSL: - UnOp(reg1); - not(reg1); - andrc(reg1, param2) - - |IL.opSUBSR: - UnOp(reg1); - andrc(reg1, ORD(-BITS(param2))) - - |IL.opMULS: - BinOp(reg1, reg2); - and(reg1, reg2); - drop - - |IL.opDIVS: - BinOp(reg1, reg2); - xor(reg1, reg2); - drop - - |IL.opUMINS: - UnOp(reg1); - not(reg1) - - |IL.opCOPY: - IF (0 < param2) & (param2 <= 256) THEN - BinOp(reg1, reg2); - reg3 := GetAnyReg(); - FOR n := 0 TO param2 - param2 MOD 8 - 1 BY 8 DO - movrm(reg3, reg1, n); - movmr(reg2, n, reg3) - END; - n := param2 - param2 MOD 8; - IF param2 MOD 8 >= 4 THEN - movrm32(reg3, reg1, n); - movmr32(reg2, n, reg3); - INC(n, 4); - DEC(param2, 4) - END; - IF param2 MOD 8 >= 2 THEN - X86.movrm16(reg3, reg1, n); - X86.movmr16(reg2, n, reg3); - INC(n, 2); - DEC(param2, 2) - END; - IF param2 MOD 8 = 1 THEN - X86.movrm8(reg3, reg1, n); - X86.movmr8(reg2, n, reg3); - END; - drop; - drop; - drop - ELSE - PushAll(2); - pushc(param2); - CallRTL(IL._move) - END - - |IL.opMOVE: - PushAll(3); - CallRTL(IL._move) - - |IL.opCOPYA: - PushAll(4); - pushc(param2); - CallRTL(IL._arrcpy); - GetRegA - - |IL.opCOPYS: - PushAll(4); - pushc(param2); - CallRTL(IL._strcpy) - - |IL.opROT: - PushAll(0); - push(rsp); - pushc(param2); - CallRTL(IL._rot) - - |IL.opNEW: - PushAll(1); - n := param2 + 16; - ASSERT(UTILS.Align(n, 16)); - pushc(n); - pushc(param1); - CallRTL(IL._new) - - |IL.opDISP: - PushAll(1); - CallRTL(IL._dispose) - - |IL.opPUSHT: - UnOp(reg1); - movrm(GetAnyReg(), reg1, -8) - - |IL.opISREC: - PushAll(2); - pushc(param2 * tcount); - CallRTL(IL._isrec); - GetRegA - - |IL.opIS: - PushAll(1); - pushc(param2 * tcount); - CallRTL(IL._is); - GetRegA - - |IL.opTYPEGR: - PushAll(1); - pushc(param2 * tcount); - CallRTL(IL._guardrec); - GetRegA - - |IL.opTYPEGP: - UnOp(reg1); - PushAll(0); - push(reg1); - pushc(param2 * tcount); - CallRTL(IL._guard); - GetRegA - - |IL.opTYPEGD: - UnOp(reg1); - PushAll(0); - X86.pushm(reg1, -8); - pushc(param2 * tcount); - CallRTL(IL._guardrec); - GetRegA - - |IL.opCASET: - push(rcx); - push(rcx); - pushc(param2 * tcount); - CallRTL(IL._guardrec); - pop(rcx); - test(rax); - jcc(jne, param1) - - |IL.opSAVEP: - UnOp(reg1); - reg2 := GetAnyReg(); - lea(reg2, param2, sCODE); - movmr(reg1, 0, reg2); - drop; - drop - - |IL.opPUSHP: - lea(GetAnyReg(), param2, sCODE) - - |IL.opINC, IL.opDEC: - BinOp(reg1, reg2); - (* add/sub qword[reg2], reg1 *) - Rex(reg2, reg1); - OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg2 MOD 8 + (reg1 MOD 8) * 8); - drop; - drop - - |IL.opINCC: - UnOp(reg1); - IF isLong(param2) THEN - reg2 := GetAnyReg(); - movrc(reg2, param2); - (* add qword[reg1], reg2 *) - Rex(reg1, reg2); - OutByte2(01H, reg1 MOD 8 + (reg2 MOD 8) * 8); - drop - ELSIF ABS(param2) = 1 THEN - Rex(reg1, 0); - OutByte2(0FFH, reg1 MOD 8 + 8 * ORD(param2 = -1)) (* inc/dec qword[reg1] *) - ELSE - (* add qword[reg1], param2 *) - Rex(reg1, 0); - OutByte2(81H + short(param2), reg1 MOD 8); - OutIntByte(param2) - END; - drop - - |IL.opDROP: - UnOp(reg1); - drop - - |IL.opSAVE, IL.opSAVE64: - BinOp(reg2, reg1); - movmr(reg1, 0, reg2); - drop; - drop - - |IL.opSAVE8: - BinOp(reg2, reg1); - X86.movmr8(reg1, 0, reg2); - drop; - drop - - |IL.opSAVE16: - BinOp(reg2, reg1); - X86.movmr16(reg1, 0, reg2); - drop; - drop - - |IL.opSAVE32: - BinOp(reg2, reg1); - movmr32(reg1, 0, reg2); - drop; - drop - - |IL.opMAX, IL.opMIN: - BinOp(reg1, reg2); - cmprr(reg1, reg2); - OutByte2(7DH + ORD(opcode = IL.opMIN), 3); (* jge/jle L *) - mov(reg1, reg2); - (* L: *) - drop - - |IL.opMAXC, IL.opMINC: - UnOp(reg1); - cmprc(reg1, param2); - label := NewLabel(); - IF opcode = IL.opMINC THEN - cc := jle - ELSE - cc := jge - END; - jcc(cc, label); - movrc(reg1, param2); - X86.SetLabel(label) - - |IL.opSBOOL: - BinOp(reg2, reg1); - test(reg2); - IF reg1 >= 8 THEN - OutByte(41H) - END; - OutByte3(0FH, 95H, reg1 MOD 8); (* setne byte[reg1] *) - drop; - drop - - |IL.opSBOOLC: - UnOp(reg1); - IF reg1 >= 8 THEN - OutByte(41H) - END; - OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *) - drop - - |IL.opUMINUS: - UnOp(reg1); - neg(reg1) - - |IL.opADD: - BinOp(reg1, reg2); - add(reg1, reg2); - drop - - |IL.opSUB: - BinOp(reg1, reg2); - sub(reg1, reg2); - drop - - |IL.opSUBR, IL.opSUBL: - UnOp(reg1); - IF param2 = 1 THEN - decr(reg1) - ELSIF param2 = -1 THEN - incr(reg1) - ELSIF param2 # 0 THEN - subrc(reg1, param2) - END; - IF opcode = IL.opSUBL THEN - neg(reg1) - END - - |IL.opADDC: - IF (param2 # 0) & ~isLong(param2) THEN - UnOp(reg1); - next := cmd.next(COMMAND); - CASE next.opcode OF - |IL.opLOAD64: - movrm(reg1, reg1, param2); - cmd := next - |IL.opLOAD32: - movrm32(reg1, reg1, param2); - shiftrc(shl, reg1, 32); - shiftrc(shr, reg1, 32); - cmd := next - |IL.opLOAD16: - movzx(reg1, reg1, param2, TRUE); - cmd := next - |IL.opLOAD8: - movzx(reg1, reg1, param2, FALSE); - cmd := next - |IL.opLOAD64_PARAM: - X86.pushm(reg1, param2); - drop; - cmd := next - ELSE - IF param2 = 1 THEN - incr(reg1) - ELSIF param2 = -1 THEN - decr(reg1) - ELSE - addrc(reg1, param2) - END - END - ELSIF isLong(param2) THEN - UnOp(reg1); - addrc(reg1, param2) - END - - |IL.opDIV: - PushAll(2); - CallRTL(IL._divmod); - GetRegA - - |IL.opDIVR: - n := UTILS.Log2(param2); - IF n > 0 THEN - UnOp(reg1); - shiftrc(sar, reg1, n) - ELSIF n < 0 THEN - PushAll(1); - pushc(param2); - CallRTL(IL._divmod); - GetRegA - END - - |IL.opDIVL: - UnOp(reg1); - REG.PushAll_1(R); - pushc(param2); - push(reg1); - drop; - CallRTL(IL._divmod); - GetRegA - - |IL.opMOD: - PushAll(2); - CallRTL(IL._divmod); - mov(rax, rdx); - GetRegA - - |IL.opMODR: - n := UTILS.Log2(param2); - IF n > 0 THEN - UnOp(reg1); - andrc(reg1, param2 - 1); - ELSIF n < 0 THEN - PushAll(1); - pushc(param2); - CallRTL(IL._divmod); - mov(rax, rdx); - GetRegA - ELSE - UnOp(reg1); - xor(reg1, reg1) - END - - |IL.opMODL: - UnOp(reg1); - REG.PushAll_1(R); - pushc(param2); - push(reg1); - drop; - CallRTL(IL._divmod); - mov(rax, rdx); - GetRegA - - |IL.opMUL: - BinOp(reg1, reg2); - oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *) - drop - - |IL.opMULC: - IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN - BinOp(reg1, reg2); - OutByte2(48H + 5 * (reg1 DIV 8) + 2 * (reg2 DIV 8), 8DH); (* lea reg1, [reg1 + reg2 * param2] *) - reg1 := reg1 MOD 8; - reg2 := reg2 MOD 8; - OutByte2(04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2)); - drop; - cmd := cmd.next(COMMAND) - ELSE - UnOp(reg1); - - a := param2; - IF a > 1 THEN - n := UTILS.Log2(a) - ELSIF a < -1 THEN - n := UTILS.Log2(-a) - ELSE - n := -1 - END; - - IF a = 1 THEN - - ELSIF a = -1 THEN - neg(reg1) - ELSIF a = 0 THEN - xor(reg1, reg1) - ELSE - IF n > 0 THEN - IF a < 0 THEN - neg(reg1) - END; - shiftrc(shl, reg1, n) - ELSE - IF isLong(a) THEN - reg2 := GetAnyReg(); - movabs(reg2, a); - ASSERT(reg1 # reg2); - oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *) - drop - ELSE - (* imul reg1, a *) - Rex(reg1, reg1); - OutByte2(69H + short(a), 0C0H + (reg1 MOD 8) * 9); - OutIntByte(a) - END - END - END - END - - |IL.opADDS: - BinOp(reg1, reg2); - _or(reg1, reg2); - drop - - |IL.opSUBS: - BinOp(reg1, reg2); - not(reg2); - and(reg1, reg2); - drop - - |IL.opNOP, IL.opAND, IL.opOR: - - |IL.opSWITCH: - UnOp(reg1); - IF param2 = 0 THEN - reg2 := rax - ELSE - reg2 := rcx - END; - IF reg1 # reg2 THEN - ASSERT(REG.GetReg(R, reg2)); - ASSERT(REG.Exchange(R, reg1, reg2)); - drop - END; - drop - - |IL.opENDSW: - - |IL.opCASEL: - GetRegA; - cmprc(rax, param1); - jcc(jl, param2); - drop - - |IL.opCASER: - GetRegA; - cmprc(rax, param1); - jcc(jg, param2); - drop - - |IL.opCASELR: - GetRegA; - cmprc(rax, param1); - IF param2 = cmd.param3 THEN - jcc(jne, param2) - ELSE - jcc(jl, param2); - jcc(jg, cmd.param3) - END; - drop - - |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: - UnOp(reg1); - IF reg1 # rcx THEN - ASSERT(REG.GetReg(R, rcx)); - ASSERT(REG.Exchange(R, reg1, rcx)); - drop - END; - - BinOp(reg1, reg2); - ASSERT(reg2 = rcx); - Rex(reg1, 0); - OutByte(0D3H); - X86.shift(opcode, reg1 MOD 8); (* shift reg1, cl *) - drop - - |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: - UnOp(reg1); - IF reg1 # rcx THEN - ASSERT(REG.GetReg(R, rcx)); - ASSERT(REG.Exchange(R, reg1, rcx)); - drop - END; - - reg1 := GetAnyReg(); - movrc(reg1, param2); - BinOp(reg1, reg2); - ASSERT(reg1 = rcx); - Rex(reg2, 0); - OutByte(0D3H); - X86.shift(opcode, reg2 MOD 8); (* shift reg2, cl *) - drop; - drop; - ASSERT(REG.GetReg(R, reg2)) - - |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: - UnOp(reg1); - shiftrc(opcode, reg1, param2 MOD 64) - - |IL.opGET, IL.opGETC: - IF opcode = IL.opGET THEN - BinOp(reg1, reg2) - ELSIF opcode = IL.opGETC THEN - UnOp(reg2); - reg1 := GetAnyReg(); - movrc(reg1, param1) - END; - drop; - drop; - X86._movrm(reg1, reg1, 0, param2 * 8, FALSE); - X86._movrm(reg1, reg2, 0, param2 * 8, TRUE) - - |IL.opCHKIDX: - UnOp(reg1); - cmprc(reg1, param2); - jcc(jb, param1) - - |IL.opCHKIDX2: - BinOp(reg1, reg2); - IF param2 # -1 THEN - cmprr(reg2, reg1); - jcc(jb, param1); - END; - INCL(R.regs, reg1); - DEC(R.top); - R.stk[R.top] := reg2 - - |IL.opLENGTH: - PushAll(2); - CallRTL(IL._length); - GetRegA - - |IL.opLENGTHW: - PushAll(2); - CallRTL(IL._lengthw); - GetRegA - - |IL.opLEN: - n := param2; - UnOp(reg1); - drop; - EXCL(R.regs, reg1); - - WHILE n > 0 DO - UnOp(reg2); - drop; - DEC(n) - END; - - INCL(R.regs, reg1); - ASSERT(REG.GetReg(R, reg1)) - - |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP: - UnOp(reg1); - reg2 := GetAnyReg(); - - CASE opcode OF - |IL.opEQP, IL.opNEP: - lea(reg2, param1, sCODE) - - |IL.opEQIP, IL.opNEIP: - lea(reg2, param1, sIMP); - movrm(reg2, reg2, 0) - END; - - cmprr(reg1, reg2); - drop; - drop; - reg1 := GetAnyReg(); - - CASE opcode OF - |IL.opEQP, IL.opEQIP: X86.setcc(sete, reg1) - |IL.opNEP, IL.opNEIP: X86.setcc(setne, reg1) - END; - - andrc(reg1, 1) - - |IL.opINCCB, IL.opDECCB: - UnOp(reg1); - IF reg1 >= 8 THEN - OutByte(41H) - END; - OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1 MOD 8, param2 MOD 256); (* add/sub byte[reg1], param2 MOD 256 *) - drop - - |IL.opINCB, IL.opDECB: - BinOp(reg1, reg2); - IF (reg1 >= 8) OR (reg2 >= 8) THEN - OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8)) - END; - OutByte2(28H * ORD(opcode = IL.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); (* add/sub byte[reg2], reg1_8 *) - drop; - drop - - |IL.opSAVEIP: - UnOp(reg1); - reg2 := GetAnyReg(); - lea(reg2, param2, sIMP); - movrm(reg2, reg2, 0); - push(reg2); - drop; - IF reg1 >= 8 THEN - OutByte(41H) - END; - OutByte2(8FH, reg1 MOD 8); (* pop qword[reg1] *) - drop - - |IL.opCLEANUP: - IF param2 # 0 THEN - addrc(rsp, param2 * 8) - END - - |IL.opPOPSP: - pop(rsp) - - |IL.opLOADF: - UnOp(reg1); - INC(xmm); - IF xmm > MAX_XMM THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END; - movsdrm(xmm, reg1, 0); - drop - - |IL.opPUSHF: - ASSERT(xmm >= 0); - subrc(rsp, 8); - movsdmr(rsp, 0, xmm); - DEC(xmm) - - |IL.opCONSTF: - float := cmd.float; - INC(xmm); - IF xmm > MAX_XMM THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END; - (* movsd xmm, qword ptr [rip + Numbers_Offs + Numbers_Count * 8 + DATA] *) - OutByte(0F2H); - IF xmm >= 8 THEN - OutByte(44H) - END; - OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8)); - X86.Reloc(sDATA, Numbers_Offs + Numbers_Count * 8); - NewNumber(UTILS.splitf(float, a, b)) - - |IL.opSAVEF, IL.opSAVEFI: - ASSERT(xmm >= 0); - UnOp(reg1); - movsdmr(reg1, 0, xmm); - DEC(xmm); - drop - - |IL.opADDF: - ASSERT(xmm >= 1); - opxx(58H, xmm - 1, xmm); - DEC(xmm) - - |IL.opSUBF: - ASSERT(xmm >= 1); - opxx(5CH, xmm - 1, xmm); - DEC(xmm) - - |IL.opSUBFI: - ASSERT(xmm >= 1); - opxx(5CH, xmm, xmm - 1); - opxx(10H, xmm - 1, xmm); - DEC(xmm) - - |IL.opMULF: - ASSERT(xmm >= 1); - opxx(59H, xmm - 1, xmm); - DEC(xmm) - - |IL.opDIVF: - ASSERT(xmm >= 1); - opxx(5EH, xmm - 1, xmm); - DEC(xmm) - - |IL.opDIVFI: - ASSERT(xmm >= 1); - opxx(5EH, xmm, xmm - 1); - opxx(10H, xmm - 1, xmm); - DEC(xmm) - - |IL.opFABS, IL.opUMINF: (* andpd/xorpd xmm, xmmword[rip + Numbers_Offs + (16) + DATA] *) - ASSERT(xmm >= 0); - OutByte(66H); - IF xmm >= 8 THEN - OutByte(44H) - END; - OutByte3(0FH, 54H + 3 * ORD(opcode = IL.opUMINF), 05H + (xmm MOD 8) * 8); - X86.Reloc(sDATA, Numbers_Offs + 16 * ORD(opcode = IL.opFABS)) - - |IL.opFLT: - UnOp(reg1); - INC(xmm); - IF xmm > MAX_XMM THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END; - OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); (* cvtsi2sd xmm, reg1 *) - OutByte2(2AH, 0C0H + (xmm MOD 8) * 8 + reg1 MOD 8); - drop - - |IL.opFLOOR: - ASSERT(xmm >= 0); - reg1 := GetAnyReg(); - subrc(rsp, 8); - OutByte3(00FH, 0AEH, 05CH); OutByte2(024H, 004H); (* stmxcsr dword[rsp+4]; *) - OutByte2(00FH, 0AEH); OutByte2(01CH, 024H); (* stmxcsr dword[rsp]; *) - OutByte3(081H, 024H, 024H); OutByte2(0FFH, 09FH); OutByte2(0FFH, 0FFH); (* and dword[rsp],11111111111111111001111111111111b; *) - OutByte3(081H, 00CH, 024H); OutByte2(000H, 020H); OutByte2(000H, 000H); (* or dword[rsp],00000000000000000010000000000000b; *) - OutByte2(00FH, 0AEH); OutByte2(014H, 024H); (* ldmxcsr dword[rsp]; *) - OutByte(0F2H); Rex(xmm, reg1); OutByte(0FH); (* cvtsd2si reg1, xmm *) - OutByte2(2DH, 0C0H + xmm MOD 8 + (reg1 MOD 8) * 8); - OutByte3(00FH, 0AEH, 054H); OutByte2(024H, 004H); (* ldmxcsr dword[rsp+4]; *) - addrc(rsp, 8); - DEC(xmm) - - |IL.opEQF .. IL.opGEF: - ASSERT(xmm >= 1); - fcmp(opcode, xmm); - DEC(xmm, 2) - - |IL.opINF: - INC(xmm); - IF xmm > MAX_XMM THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END; - (* movsd xmm, qword ptr [rip + Numbers_Offs + 32 + DATA] *) - OutByte(0F2H); - IF xmm >= 8 THEN - OutByte(44H) - END; - OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8)); - X86.Reloc(sDATA, Numbers_Offs + 32) - - |IL.opPACK, IL.opPACKC: - IF opcode = IL.opPACK THEN - BinOp(reg1, reg2) - ELSE - UnOp(reg1); - reg2 := GetAnyReg(); - movrc(reg2, param2) - END; - push(reg1); - movrm(reg1, reg1, 0); - shiftrc(shl, reg1, 1); - shiftrc(shr, reg1, 53); - add(reg1, reg2); - andrc(reg1, ORD({0..10})); - shiftrc(shl, reg1, 52); - movrm(reg2, rsp, 0); - movrm(reg2, reg2, 0); - - push(reg1); - lea(reg1, Numbers_Offs + 40, sDATA); (* {0..51, 63} *) - movrm(reg1, reg1, 0); - and(reg2, reg1); - pop(reg1); - - _or(reg2, reg1); - pop(reg1); - movmr(reg1, 0, reg2); - drop; - drop - - |IL.opUNPK, IL.opLADR_UNPK: - - IF opcode = IL.opLADR_UNPK THEN - n := param2 * 8; - UnOp(reg1); - reg2 := GetAnyReg(); - Rex(0, reg2); - OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); (* lea reg2, qword[rbp+n] *) - OutIntByte(n) - ELSE - BinOp(reg1, reg2) - END; - - push(reg1); - movrm(reg1, reg1, 0); - shiftrc(shl, reg1, 1); - shiftrc(shr, reg1, 53); - subrc(reg1, 1023); - - movmr(reg2, 0, reg1); - - pop(reg2); - movrm(reg1, reg2, 0); - - push(reg2); - lea(reg2, Numbers_Offs + 48, sDATA); (* {52..61} *) - movrm(reg2, reg2, 0); - _or(reg1, reg2); - pop(reg2); - - Rex(reg1, 0); - OutByte2(0FH, 0BAH); - OutByte2(0F0H + reg1 MOD 8, 3EH); (* btr reg1, 62 *) - movmr(reg2, 0, reg1); - drop; - drop - - |IL.opSADR_PARAM: - pushDA(stroffs + param2) - - |IL.opVADR_PARAM: - X86.pushm(rbp, param2 * 8) - - |IL.opLOAD64_PARAM: - UnOp(reg1); - X86.pushm(reg1, 0); - drop - - |IL.opLLOAD64_PARAM: - X86.pushm(rbp, param2 * 8) - - |IL.opGLOAD64_PARAM: - OutByte2(0FFH, 35H); (* push qword[rip + param2 + BSS] *) - X86.Reloc(sBSS, param2) - - |IL.opCONST_PARAM: - pushc(param2) - - |IL.opGLOAD32_PARAM, IL.opLOAD32_PARAM: - IF opcode = IL.opGLOAD32_PARAM THEN - reg1 := GetAnyReg(); - lea(reg1, param2, sBSS) - ELSE - UnOp(reg1) - END; - movrm32(reg1, reg1, 0); - shiftrc(shl, reg1, 32); - shiftrc(shr, reg1, 32); - push(reg1); - drop - - |IL.opLLOAD32_PARAM: - reg1 := GetAnyReg(); - movrm32(reg1, rbp, param2 * 8); - shiftrc(shl, reg1, 32); - shiftrc(shr, reg1, 32); - push(reg1); - drop - - |IL.opLADR_SAVEC: - n := param1 * 8; - IF isLong(param2) THEN - reg2 := GetAnyReg(); - movrc(reg2, param2); - movmr(rbp, n, reg2); - drop - ELSE - OutByte3(48H, 0C7H, 45H + long(n)); (* mov qword[rbp+n], param2 *) - OutIntByte(n); - OutInt(param2) - END - - |IL.opGADR_SAVEC: - IF isLong(param2) THEN - reg1 := GetAnyReg(); - movrc(reg1, param2); - reg2 := GetAnyReg(); - lea(reg2, param1, sBSS); - movmr(reg2, 0, reg1); - drop; - drop - ELSE - (* mov qword[rip + param1 - 4 + BSS], param2 *) - OutByte3(48H, 0C7H, 05H); - X86.Reloc(sBSS, param1 - 4); - OutInt(param2) - END - - |IL.opLADR_SAVE: - UnOp(reg1); - movmr(rbp, param2 * 8, reg1); - drop - - |IL.opLADR_INCC: - IF isLong(param2) THEN - reg2 := GetAnyReg(); - movrc(reg2, param2); - n := param1 * 8; - Rex(0, reg2); - OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8); - OutIntByte(n); (* add qword[rbp+n], reg2 *) - drop - ELSIF ABS(param2) = 1 THEN - n := param1 * 8; - OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec qword[rbp+n] *) - OutIntByte(n) - ELSE - n := param1 * 8; - OutByte3(48H, 81H + short(param2), 45H + long(n)); - OutIntByte(n); - OutIntByte(param2) (* add qword[rbp+n], param2 *) - END - - |IL.opLADR_INCCB, IL.opLADR_DECCB: - param2 := param2 MOD 256; - n := param1 * 8; - OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB)); - OutIntByte(n); - OutByte(param2) (* add/sub byte[rbp+n], param2 *) - - |IL.opLADR_INC, IL.opLADR_DEC: - UnOp(reg1); - n := param2 * 8; - Rex(0, reg1); - OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8); - OutIntByte(n); (* add/sub qword[rbp+n], reg1 *) - drop - - |IL.opLADR_INCB, IL.opLADR_DECB: - UnOp(reg1); - n := param2 * 8; - IF reg1 >= 8 THEN - OutByte(44H) - END; - OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8)); - OutIntByte(n); (* add/sub byte[rbp+n], reg1_8 *) - drop - - |IL.opLADR_INCL, IL.opLADR_EXCL: - UnOp(reg1); - cmprc(reg1, 64); - n := param2 * 8; - OutByte2(73H, 5 + 3 * ORD(~X86.isByte(n))); (* jnb L *) - Rex(0, reg1); - OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8)); - OutIntByte(n); (* bts/btr qword[rbp+n], reg1 *) - (* L: *) - drop - - |IL.opLADR_INCLC, IL.opLADR_EXCLC: - n := param1 * 8; - OutByte3(48H, 0FH, 0BAH); (* bts/btr qword[rbp+n], param2 *) - OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); - OutIntByte(n); - OutByte(param2) - - |IL.opFNAME: - fname := cmd(IL.FNAMECMD).fname - - END; - - cmd := cmd.next(COMMAND) - END; - - ASSERT(R.pushed = 0); - ASSERT(R.top = -1); - ASSERT(xmm = -1) -END translate; - - -PROCEDURE prolog (modname: ARRAY OF CHAR; target, stack_size: INTEGER); -VAR - ModName_Offs, entry, L: INTEGER; - -BEGIN - ModName_Offs := tcount * 8 + CHL.Length(IL.codes.data); - Numbers_Offs := ModName_Offs + LENGTH(modname) + 1; - ASSERT(UTILS.Align(Numbers_Offs, 16)); - - entry := NewLabel(); - X86.SetLabel(entry); - - IF target = TARGETS.Win64DLL THEN - dllret := NewLabel(); - push(r8); - push(rdx); - push(rcx); - CallRTL(IL._dllentry); - test(rax); - jcc(je, dllret); - pushc(0) - ELSIF target = TARGETS.Linux64 THEN - push(rsp) - ELSE - pushc(0) - END; - - lea(rax, entry, sCODE); - push(rax); - pushDA(0); (* TYPES *) - pushc(tcount); - pushDA(ModName_Offs); (* MODNAME *) - CallRTL(IL._init); - - IF target IN {TARGETS.Win64C, TARGETS.Win64GUI, TARGETS.Linux64} THEN - L := NewLabel(); - pushc(0); - push(rsp); - pushc(1024 * 1024 * stack_size); - pushc(0); - CallRTL(IL._new); - pop(rax); - test(rax); - jcc(je, L); - GetRegA; - addrc(rax, 1024 * 1024 * stack_size - 8); - drop; - mov(rsp, rax); - X86.SetLabel(L) - END -END prolog; - - -PROCEDURE epilog (modname: ARRAY OF CHAR; target: INTEGER); -VAR - i, n: INTEGER; - number: Number; - exp: IL.EXPORT_PROC; - - - PROCEDURE _import (imp: LISTS.LIST); - VAR - lib: IL.IMPORT_LIB; - proc: IL.IMPORT_PROC; - - BEGIN - - lib := imp.first(IL.IMPORT_LIB); - WHILE lib # NIL DO - BIN.Import(prog, lib.name, 0); - proc := lib.procs.first(IL.IMPORT_PROC); - WHILE proc # NIL DO - BIN.Import(prog, proc.name, proc.label); - proc := proc.next(IL.IMPORT_PROC) - END; - lib := lib.next(IL.IMPORT_LIB) - END - - END _import; - - -BEGIN - IF target = TARGETS.Win64DLL THEN - X86.SetLabel(dllret); - X86.ret - ELSIF target = TARGETS.Linux64SO THEN - sofinit := NewLabel(); - X86.ret; - X86.SetLabel(sofinit); - CallRTL(IL._sofinit); - X86.ret - ELSE - pushc(0); - CallRTL(IL._exit) - END; - - X86.fixup; - - i := 0; - WHILE i < tcount DO - BIN.PutData64LE(prog, CHL.GetInt(IL.codes.types, i)); - INC(i) - END; - - i := 0; - WHILE i < CHL.Length(IL.codes.data) DO - BIN.PutData(prog, CHL.GetByte(IL.codes.data, i)); - INC(i) - END; - - BIN.PutDataStr(prog, modname); - BIN.PutData(prog, 0); - n := CHL.Length(prog.data); - ASSERT(UTILS.Align(n, 16)); - i := n - CHL.Length(prog.data); - WHILE i > 0 DO - BIN.PutData(prog, 0); - DEC(i) - END; - number := Numbers.first(Number); - FOR i := 0 TO Numbers_Count - 1 DO - BIN.PutData64LE(prog, number.value); - number := number.next(Number) - END; - - exp := IL.codes.export.first(IL.EXPORT_PROC); - WHILE exp # NIL DO - BIN.Export(prog, exp.name, exp.label); - exp := exp.next(IL.EXPORT_PROC) - END; - - _import(IL.codes._import) -END epilog; - - -PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); -VAR - path, modname, ext: PATHS.PATH; - -BEGIN - Xmm[0] := 0; - X86.align16(TRUE); - tcount := CHL.Length(IL.codes.types); - - Win64RegPar[0] := rcx; - Win64RegPar[1] := rdx; - Win64RegPar[2] := r8; - Win64RegPar[3] := r9; - - SystemVRegPar[0] := rdi; - SystemVRegPar[1] := rsi; - SystemVRegPar[2] := rdx; - SystemVRegPar[3] := rcx; - SystemVRegPar[4] := r8; - SystemVRegPar[5] := r9; - - PATHS.split(outname, path, modname, ext); - S.append(modname, ext); - - REG.Init(R, push, pop, mov, xchg, {rax, rcx, rdx, r8, r9, r10, r11}); - - IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 8))); - - Numbers := LISTS.create(NIL); - Numbers_Count := 0; - NewNumber(ROR(1, 1)); (* 8000000000000000H *) - NewNumber(0); - NewNumber(ROR(-2, 1)); (* 7FFFFFFFFFFFFFFFH *) - NewNumber(-1); - NewNumber(ROR(7FFH, 12)); (* +Infinity *) - NewNumber(ORD(-BITS(LSR(ASR(ROR(1, 1), 10), 1)))); (* {0..51, 63} *) - NewNumber(LSR(ASR(ROR(1, 1), 9), 2)); (* {52..61} *) - - prog := BIN.create(IL.codes.lcount); - BIN.SetParams(prog, IL.codes.bss, 1, WCHR(1), WCHR(0)); - - X86.SetProgram(prog); - - prolog(modname, target, options.stack); - translate(IL.codes.commands, tcount * 8); - epilog(modname, target); - - BIN.fixup(prog); - IF TARGETS.OS = TARGETS.osWIN64 THEN - PE32.write(prog, outname, target = TARGETS.Win64C, target = TARGETS.Win64DLL, TRUE) - ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN - ELF.write(prog, outname, sofinit, target = TARGETS.Linux64SO, TRUE) - END -END CodeGen; - - -END AMD64. \ No newline at end of file diff --git a/programs/develop/oberon07/source/ARITH.ob07 b/programs/develop/oberon07/source/ARITH.ob07 deleted file mode 100644 index c0fc19564..000000000 --- a/programs/develop/oberon07/source/ARITH.ob07 +++ /dev/null @@ -1,797 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2022, Anton Krotov - All rights reserved. -*) - -MODULE ARITH; - -IMPORT STRINGS, UTILS, LISTS; - - -CONST - - tINTEGER* = 1; tREAL* = 2; tSET* = 3; - tBOOLEAN* = 4; tCHAR* = 5; tWCHAR* = 6; - tSTRING* = 7; - - opEQ* = 0; opNE* = 1; opLT* = 2; opLE* = 3; opGT* = 4; opGE* = 5; - opIN* = 6; opIS* = 7; - - -TYPE - - VALUE* = RECORD - - typ*: INTEGER; - - int: INTEGER; - float: REAL; - set: SET; - bool: BOOLEAN; - - string*: LISTS.ITEM - - END; - - -VAR - - digit: ARRAY 256 OF INTEGER; - - -PROCEDURE Int* (v: VALUE): INTEGER; -VAR - res: INTEGER; - -BEGIN - - CASE v.typ OF - |tINTEGER, tCHAR, tWCHAR: - res := v.int - |tSET: - res := UTILS.Long(ORD(v.set)) - |tBOOLEAN: - res := ORD(v.bool) - END - - RETURN res -END Int; - - -PROCEDURE getBool* (v: VALUE): BOOLEAN; -BEGIN - ASSERT(v.typ = tBOOLEAN); - - RETURN v.bool -END getBool; - - -PROCEDURE Float* (v: VALUE): REAL; -BEGIN - ASSERT(v.typ = tREAL); - - RETURN v.float -END Float; - - -PROCEDURE range* (i: VALUE; a, b: INTEGER): BOOLEAN; - RETURN (a <= i.int) & (i.int <= b) -END range; - - -PROCEDURE check* (v: VALUE): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - CASE v.typ OF - |tINTEGER: res := range(v, UTILS.target.minInt, UTILS.target.maxInt) - |tCHAR: res := range(v, 0, 255) - |tWCHAR: res := range(v, 0, 65535) - |tREAL: res := (-UTILS.target.maxReal <= v.float) & (v.float <= UTILS.target.maxReal) - END - - RETURN res -END check; - - -PROCEDURE isZero* (v: VALUE): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - CASE v.typ OF - |tINTEGER: res := v.int = 0 - |tREAL: res := v.float = 0.0 - END - - RETURN res -END isZero; - - -PROCEDURE iconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER); -VAR - value: INTEGER; - i: INTEGER; - d: INTEGER; - -BEGIN - error := 0; - value := 0; - - i := 0; - WHILE STRINGS.digit(s[i]) & (error = 0) DO - d := digit[ORD(s[i])]; - IF value <= (UTILS.maxint - d) DIV 10 THEN - value := value * 10 + d; - INC(i) - ELSE - error := 1 - END - END; - - IF error = 0 THEN - v.int := value; - v.typ := tINTEGER; - IF ~check(v) THEN - error := 1 - END - END - -END iconv; - - -PROCEDURE hconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER); -VAR - value: INTEGER; - i: INTEGER; - n: INTEGER; - d: INTEGER; - -BEGIN - ASSERT(STRINGS.digit(s[0])); - - error := 0; - value := 0; - - n := -1; - i := 0; - WHILE (s[i] # "H") & (s[i] # "X") & (s[i] # "h") & (s[i] # "x") & (error = 0) DO - - d := digit[ORD(s[i])]; - IF (n = -1) & (d # 0) THEN - n := i - END; - - IF (n # -1) & (i - n + 1 > UTILS.target.maxHex) THEN - error := 2 - ELSE - value := value * 16 + d; - INC(i) - END - - END; - - value := UTILS.Long(value); - - IF ((s[i] = "X") OR (s[i] = "x")) & (n # -1) & (i - n > 4) THEN - error := 3 - END; - - IF error = 0 THEN - v.int := value; - IF (s[i] = "X") OR (s[i] = "x") THEN - v.typ := tCHAR; - IF ~check(v) THEN - v.typ := tWCHAR; - IF ~check(v) THEN - error := 3 - END - END - ELSE - v.typ := tINTEGER; - IF ~check(v) THEN - error := 2 - END - END - END - -END hconv; - - -PROCEDURE opFloat2 (VAR a: REAL; b: REAL; op: CHAR): BOOLEAN; -BEGIN - CASE op OF - |"+": a := a + b - |"-": a := a - b - |"*": a := a * b - |"/": a := a / b - END - - RETURN (-UTILS.maxreal <= a) & (a <= UTILS.maxreal) (* +inf > UTILS.maxreal *) -END opFloat2; - - -PROCEDURE fconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER); -VAR - value: REAL; - exp10: REAL; - i, n, d: INTEGER; - minus: BOOLEAN; - -BEGIN - error := 0; - value := 0.0; - minus := FALSE; - n := 0; - - exp10 := 0.0; - WHILE (error = 0) & (STRINGS.digit(s[i]) OR (s[i] = ".")) DO - IF s[i] = "." THEN - exp10 := 1.0; - INC(i) - ELSE - IF opFloat2(value, 10.0, "*") & opFloat2(value, FLT(digit[ORD(s[i])]), "+") & opFloat2(exp10, 10.0, "*") THEN - INC(i) - ELSE - error := 4 - END - END - END; - - IF ~opFloat2(value, exp10, "/") THEN - error := 4 - END; - - IF (s[i] = "E") OR (s[i] = "e") THEN - INC(i) - END; - - IF (s[i] = "-") OR (s[i] = "+") THEN - minus := s[i] = "-"; - INC(i) - END; - - WHILE (error = 0) & STRINGS.digit(s[i]) DO - d := digit[ORD(s[i])]; - IF n <= (UTILS.maxint - d) DIV 10 THEN - n := n * 10 + d; - INC(i) - ELSE - error := 5 - END - END; - - exp10 := 1.0; - WHILE (error = 0) & (n > 0) DO - IF opFloat2(exp10, 10.0, "*") THEN - DEC(n) - ELSE - error := 4 - END - END; - - IF error = 0 THEN - IF minus THEN - IF ~opFloat2(value, exp10, "/") THEN - error := 4 - END - ELSE - IF ~opFloat2(value, exp10, "*") THEN - error := 4 - END - END - END; - - IF error = 0 THEN - v.float := value; - v.typ := tREAL; - IF ~check(v) THEN - error := 4 - END - END - -END fconv; - - -PROCEDURE setChar* (VAR v: VALUE; ord: INTEGER); -BEGIN - v.typ := tCHAR; - v.int := ord -END setChar; - - -PROCEDURE setWChar* (VAR v: VALUE; ord: INTEGER); -BEGIN - v.typ := tWCHAR; - v.int := ord -END setWChar; - - -PROCEDURE addInt (VAR a: INTEGER; b: INTEGER): BOOLEAN; -VAR - error: BOOLEAN; - -BEGIN - IF (a > 0) & (b > 0) THEN - error := a > UTILS.maxint - b - ELSIF (a < 0) & (b < 0) THEN - error := a < UTILS.minint - b - ELSE - error := FALSE - END; - - IF ~error THEN - a := a + b - ELSE - a := 0 - END - - RETURN ~error -END addInt; - - -PROCEDURE subInt (VAR a: INTEGER; b: INTEGER): BOOLEAN; -VAR - error: BOOLEAN; - -BEGIN - IF (a > 0) & (b < 0) THEN - error := a > UTILS.maxint + b - ELSIF (a < 0) & (b > 0) THEN - error := a < UTILS.minint + b - ELSIF (a = 0) & (b < 0) THEN - error := b = UTILS.minint - ELSE - error := FALSE - END; - - IF ~error THEN - a := a - b - ELSE - a := 0 - END - - RETURN ~error -END subInt; - - -PROCEDURE lg2 (x: INTEGER): INTEGER; -VAR - n: INTEGER; - -BEGIN - ASSERT(x > 0); - - n := UTILS.Log2(x); - IF n = -1 THEN - n := 255 - END - - RETURN n -END lg2; - - -PROCEDURE mulInt* (VAR a: INTEGER; b: INTEGER): BOOLEAN; -VAR - error: BOOLEAN; - min, max: INTEGER; - -BEGIN - min := UTILS.minint; - max := UTILS.maxint; - - IF ((a > 1) & (b > 1)) OR ((a < 0) & (b < 0)) THEN - error := (a = min) OR (b = min) OR (ABS(a) > max DIV ABS(b)) - - ELSIF ((a > 1) & (b < 0)) OR ((a < 0) & (b > 1)) THEN - error := (a = min) OR (b = min); - IF ~error THEN - IF lg2(ABS(a)) + lg2(ABS(b)) >= UTILS.bit_depth THEN - error := ABS(a) > max DIV ABS(b) - END - END - - ELSE - error := FALSE - END; - - IF ~error THEN - a := a * b - ELSE - a := 0 - END - - RETURN ~error -END mulInt; - - -PROCEDURE _ASR (x, n: INTEGER): INTEGER; - RETURN ASR(UTILS.Long(x), n) -END _ASR; - - -PROCEDURE _LSR (x, n: INTEGER): INTEGER; - RETURN UTILS.Long(LSR(UTILS.Short(x), n)) -END _LSR; - - -PROCEDURE _LSL (x, n: INTEGER): INTEGER; - RETURN UTILS.Long(LSL(x, n)) -END _LSL; - - -PROCEDURE _ROR1_32 (x: INTEGER): INTEGER; -BEGIN - x := UTILS.Short(x); - x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31))) - RETURN UTILS.Long(x) -END _ROR1_32; - - -PROCEDURE _ROR1_16 (x: INTEGER): INTEGER; -BEGIN - x := x MOD 65536; - x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 15))) - RETURN UTILS.Long(x) -END _ROR1_16; - - -PROCEDURE _ROR (x, n: INTEGER): INTEGER; -BEGIN - - CASE UTILS.bit_diff OF - |0: x := ROR(x, n) - |16, 48: - n := n MOD 16; - WHILE n > 0 DO - x := _ROR1_16(x); - DEC(n) - END - |32: - n := n MOD 32; - WHILE n > 0 DO - x := _ROR1_32(x); - DEC(n) - END - END - - RETURN x -END _ROR; - - -PROCEDURE opInt* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN; -VAR - success: BOOLEAN; - -BEGIN - success := TRUE; - - CASE op OF - |"+": success := addInt(a.int, b.int) - |"-": success := subInt(a.int, b.int) - |"*": success := mulInt(a.int, b.int) - |"/": success := FALSE - |"D": a.int := a.int DIV b.int - |"M": a.int := a.int MOD b.int - |"L": a.int := _LSL(a.int, b.int) - |"A": a.int := _ASR(a.int, b.int) - |"O": a.int := _ROR(a.int, b.int) - |"R": a.int := _LSR(a.int, b.int) - |"m": a.int := MIN(a.int, b.int) - |"x": a.int := MAX(a.int, b.int) - END; - a.typ := tINTEGER - - RETURN success & check(a) -END opInt; - - -PROCEDURE charToStr* (c: VALUE; VAR s: ARRAY OF CHAR); -BEGIN - s[0] := CHR(c.int); - s[1] := 0X -END charToStr; - - -PROCEDURE opSet* (VAR a: VALUE; b: VALUE; op: CHAR); -BEGIN - CASE op OF - |"+": a.set := a.set + b.set - |"-": a.set := a.set - b.set - |"*": a.set := a.set * b.set - |"/": a.set := a.set / b.set - END; - a.typ := tSET -END opSet; - - -PROCEDURE opFloat* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN; -BEGIN - a.typ := tREAL - RETURN opFloat2(a.float, b.float, op) & check(a) -END opFloat; - - -PROCEDURE ord* (VAR v: VALUE); -BEGIN - CASE v.typ OF - |tCHAR, tWCHAR: - |tBOOLEAN: v.int := ORD(v.bool) - |tSET: v.int := UTILS.Long(ORD(v.set)) - END; - v.typ := tINTEGER -END ord; - - -PROCEDURE odd* (VAR v: VALUE); -BEGIN - v.typ := tBOOLEAN; - v.bool := ODD(v.int) -END odd; - - -PROCEDURE bits* (VAR v: VALUE); -BEGIN - v.typ := tSET; - v.set := BITS(v.int) -END bits; - - -PROCEDURE abs* (VAR v: VALUE): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - res := FALSE; - - CASE v.typ OF - |tREAL: - v.float := ABS(v.float); - res := TRUE - |tINTEGER: - IF v.int # UTILS.minint THEN - v.int := ABS(v.int); - res := TRUE - END - END - - RETURN res -END abs; - - -PROCEDURE floor* (VAR v: VALUE): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - v.typ := tINTEGER; - res := (FLT(UTILS.minint) <= v.float) & (v.float <= FLT(UTILS.maxint)); - IF res THEN - v.int := FLOOR(v.float) - END - - RETURN res -END floor; - - -PROCEDURE flt* (VAR v: VALUE); -BEGIN - v.typ := tREAL; - v.float := FLT(v.int) -END flt; - - -PROCEDURE neg* (VAR v: VALUE): BOOLEAN; -VAR - z: VALUE; - res: BOOLEAN; - -BEGIN - res := TRUE; - - z.typ := tINTEGER; - z.int := 0; - - CASE v.typ OF - |tREAL: v.float := -v.float - |tSET: v.set := -v.set - |tINTEGER: res := opInt(z, v, "-"); v := z - |tBOOLEAN: v.bool := ~v.bool - END - - RETURN res -END neg; - - -PROCEDURE setbool* (VAR v: VALUE; b: BOOLEAN); -BEGIN - v.bool := b; - v.typ := tBOOLEAN -END setbool; - - -PROCEDURE opBoolean* (VAR a: VALUE; b: VALUE; op: CHAR); -BEGIN - CASE op OF - |"&": a.bool := a.bool & b.bool - |"|": a.bool := a.bool OR b.bool - END; - a.typ := tBOOLEAN -END opBoolean; - - -PROCEDURE less (v, v2: VALUE; VAR error: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - res := FALSE; - - IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN - CASE v.typ OF - |tINTEGER, - tWCHAR, - tCHAR: res := v.int < v2.int - |tREAL: res := v.float < v2.float - |tBOOLEAN, - tSET: error := 1 - END - ELSE - error := 1 - END - - RETURN res -END less; - - -PROCEDURE equal (v, v2: VALUE; VAR error: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - res := FALSE; - - IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN - CASE v.typ OF - |tINTEGER, - tWCHAR, - tCHAR: res := v.int = v2.int - |tREAL: res := v.float = v2.float - |tBOOLEAN: res := v.bool = v2.bool - |tSET: res := v.set = v2.set - END - ELSE - error := 1 - END - - RETURN res -END equal; - - -PROCEDURE relation* (VAR v: VALUE; v2: VALUE; op: INTEGER; VAR error: INTEGER); -VAR - res: BOOLEAN; - -BEGIN - error := 0; - - res := FALSE; - - CASE op OF - - |opEQ: - res := equal(v, v2, error) - - |opNE: - res := ~equal(v, v2, error) - - |opLT: - res := less(v, v2, error) - - |opLE: - res := less(v, v2, error); - IF error = 0 THEN - res := equal(v, v2, error) OR res - END - - |opGE: - res := ~less(v, v2, error) - - |opGT: - res := less(v, v2, error); - IF error = 0 THEN - res := equal(v, v2, error) OR res - END; - res := ~res - - |opIN: - IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN - IF range(v, 0, UTILS.target.maxSet) THEN - res := v.int IN v2.set - ELSE - error := 2 - END - ELSE - error := 1 - END - - END; - - IF error = 0 THEN - v.bool := res; - v.typ := tBOOLEAN - END - -END relation; - - -PROCEDURE emptySet* (VAR v: VALUE); -BEGIN - v.typ := tSET; - v.set := {} -END emptySet; - - -PROCEDURE constrSet* (VAR v: VALUE; a, b: VALUE); -BEGIN - v.typ := tSET; - v.set := {a.int .. b.int} -END constrSet; - - -PROCEDURE getInt* (v: VALUE): INTEGER; -BEGIN - ASSERT(check(v)) - - RETURN v.int -END getInt; - - -PROCEDURE setInt* (VAR v: VALUE; i: INTEGER): BOOLEAN; -BEGIN - v.int := i; - v.typ := tINTEGER - - RETURN check(v) -END setInt; - - -PROCEDURE concat* (VAR s: ARRAY OF CHAR; s1: ARRAY OF CHAR): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - res := LENGTH(s) + LENGTH(s1) < LEN(s); - IF res THEN - STRINGS.append(s, s1) - END - - RETURN res -END concat; - - -PROCEDURE init; -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO LEN(digit) - 1 DO - digit[i] := -1 - END; - - FOR i := ORD("0") TO ORD("9") DO - digit[i] := i - ORD("0") - END; - - FOR i := ORD("A") TO ORD("F") DO - digit[i] := i - ORD("A") + 10 - END -END init; - - -BEGIN - init -END ARITH. \ No newline at end of file diff --git a/programs/develop/oberon07/source/AVLTREES.ob07 b/programs/develop/oberon07/source/AVLTREES.ob07 deleted file mode 100644 index 64b1990b6..000000000 --- a/programs/develop/oberon07/source/AVLTREES.ob07 +++ /dev/null @@ -1,197 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2019, Anton Krotov - All rights reserved. -*) - -MODULE AVLTREES; - -IMPORT C := COLLECTIONS; - - -TYPE - - DATA* = POINTER TO RECORD (C.ITEM) END; - - NODE* = POINTER TO RECORD (C.ITEM) - - data*: DATA; - - height: INTEGER; - - left*, right*: NODE - - END; - - CMP* = PROCEDURE (a, b: DATA): INTEGER; - - DESTRUCTOR* = PROCEDURE (VAR data: DATA); - - -VAR - - nodes: C.COLLECTION; - - -PROCEDURE NewNode (data: DATA): NODE; -VAR - node: NODE; - citem: C.ITEM; - -BEGIN - citem := C.pop(nodes); - IF citem = NIL THEN - NEW(node) - ELSE - node := citem(NODE) - END; - - node.data := data; - node.left := NIL; - node.right := NIL; - node.height := 1 - - RETURN node -END NewNode; - - -PROCEDURE height (p: NODE): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF p = NIL THEN - res := 0 - ELSE - res := p.height - END - - RETURN res -END height; - - -PROCEDURE bfactor (p: NODE): INTEGER; - RETURN height(p.right) - height(p.left) -END bfactor; - - -PROCEDURE fixheight (p: NODE); -BEGIN - p.height := MAX(height(p.left), height(p.right)) + 1 -END fixheight; - - -PROCEDURE rotateright (p: NODE): NODE; -VAR - q: NODE; - -BEGIN - q := p.left; - p.left := q.right; - q.right := p; - fixheight(p); - fixheight(q) - - RETURN q -END rotateright; - - -PROCEDURE rotateleft (q: NODE): NODE; -VAR - p: NODE; - -BEGIN - p := q.right; - q.right := p.left; - p.left := q; - fixheight(q); - fixheight(p) - - RETURN p -END rotateleft; - - -PROCEDURE balance (p: NODE): NODE; -VAR - res: NODE; - -BEGIN - fixheight(p); - - IF bfactor(p) = 2 THEN - IF bfactor(p.right) < 0 THEN - p.right := rotateright(p.right) - END; - res := rotateleft(p) - - ELSIF bfactor(p) = -2 THEN - IF bfactor(p.left) > 0 THEN - p.left := rotateleft(p.left) - END; - res := rotateright(p) - - ELSE - res := p - END - - RETURN res -END balance; - - -PROCEDURE insert* (p: NODE; data: DATA; cmp: CMP; VAR newnode: BOOLEAN; VAR node: NODE): NODE; -VAR - res: NODE; - rescmp: INTEGER; - -BEGIN - IF p = NIL THEN - res := NewNode(data); - node := res; - newnode := TRUE - ELSE - - rescmp := cmp(data, p.data); - IF rescmp < 0 THEN - p.left := insert(p.left, data, cmp, newnode, node); - res := balance(p) - ELSIF rescmp > 0 THEN - p.right := insert(p.right, data, cmp, newnode, node); - res := balance(p) - ELSE - res := p; - node := res; - newnode := FALSE - END - - END - - RETURN res -END insert; - - -PROCEDURE destroy* (VAR node: NODE; destructor: DESTRUCTOR); -VAR - left, right: NODE; - -BEGIN - IF node # NIL THEN - left := node.left; - right := node.right; - - IF destructor # NIL THEN - destructor(node.data) - END; - - C.push(nodes, node); - node := NIL; - - destroy(left, destructor); - destroy(right, destructor) - END -END destroy; - - -BEGIN - nodes := C.create() -END AVLTREES. \ No newline at end of file diff --git a/programs/develop/oberon07/source/BIN.ob07 b/programs/develop/oberon07/source/BIN.ob07 deleted file mode 100644 index d7fe3334a..000000000 --- a/programs/develop/oberon07/source/BIN.ob07 +++ /dev/null @@ -1,384 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE BIN; - -IMPORT LISTS, CHL := CHUNKLISTS, ARITH, UTILS; - - -CONST - - RCODE* = 0; PICCODE* = RCODE + 1; - RDATA* = 2; PICDATA* = RDATA + 1; - RBSS* = 4; PICBSS* = RBSS + 1; - RIMP* = 6; PICIMP* = RIMP + 1; - - IMPTAB* = 8; - - -TYPE - - RELOC* = POINTER TO RECORD (LISTS.ITEM) - - opcode*: INTEGER; - offset*: INTEGER - - END; - - IMPRT* = POINTER TO RECORD (LISTS.ITEM) - - nameoffs*: INTEGER; - label*: INTEGER; - - OriginalFirstThunk*, - FirstThunk*: INTEGER - - END; - - EXPRT* = POINTER TO RECORD (LISTS.ITEM) - - nameoffs*: INTEGER; - label*: INTEGER - - END; - - PROGRAM* = POINTER TO RECORD - - code*: CHL.BYTELIST; - data*: CHL.BYTELIST; - labels: CHL.INTLIST; - bss*: INTEGER; - stack*: INTEGER; - vmajor*, - vminor*: WCHAR; - modname*: INTEGER; - _import*: CHL.BYTELIST; - export*: CHL.BYTELIST; - rel_list*: LISTS.LIST; - imp_list*: LISTS.LIST; - exp_list*: LISTS.LIST - - END; - - -PROCEDURE create* (NumberOfLabels: INTEGER): PROGRAM; -VAR - program: PROGRAM; - i: INTEGER; - -BEGIN - NEW(program); - - program.bss := 0; - - program.labels := CHL.CreateIntList(); - FOR i := 0 TO NumberOfLabels - 1 DO - CHL.PushInt(program.labels, 0) - END; - - program.rel_list := LISTS.create(NIL); - program.imp_list := LISTS.create(NIL); - program.exp_list := LISTS.create(NIL); - - program.data := CHL.CreateByteList(); - program.code := CHL.CreateByteList(); - program._import := CHL.CreateByteList(); - program.export := CHL.CreateByteList() - - RETURN program -END create; - - -PROCEDURE SetParams* (program: PROGRAM; bss, stack: INTEGER; vmajor, vminor: WCHAR); -BEGIN - program.bss := bss; - program.stack := stack; - program.vmajor := vmajor; - program.vminor := vminor -END SetParams; - - -PROCEDURE PutReloc* (program: PROGRAM; opcode: INTEGER); -VAR - cmd: RELOC; - -BEGIN - NEW(cmd); - cmd.opcode := opcode; - cmd.offset := CHL.Length(program.code); - LISTS.push(program.rel_list, cmd) -END PutReloc; - - -PROCEDURE PutData* (program: PROGRAM; b: BYTE); -BEGIN - CHL.PushByte(program.data, b) -END PutData; - - -PROCEDURE get32le* (_array: CHL.BYTELIST; idx: INTEGER): INTEGER; -VAR - i: INTEGER; - x: INTEGER; - -BEGIN - x := 0; - - FOR i := 3 TO 0 BY -1 DO - x := LSL(x, 8) + CHL.GetByte(_array, idx + i) - END; - - IF UTILS.bit_depth = 64 THEN - x := LSL(x, 16); - x := LSL(x, 16); - x := ASR(x, 16); - x := ASR(x, 16) - END - - RETURN x -END get32le; - - -PROCEDURE put32le* (_array: CHL.BYTELIST; idx: INTEGER; x: INTEGER); -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO 3 DO - CHL.SetByte(_array, idx + i, UTILS.Byte(x, i)) - END -END put32le; - - -PROCEDURE PutData32LE* (program: PROGRAM; x: INTEGER); -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO 3 DO - CHL.PushByte(program.data, UTILS.Byte(x, i)) - END -END PutData32LE; - - -PROCEDURE PutData64LE* (program: PROGRAM; x: INTEGER); -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO 7 DO - CHL.PushByte(program.data, UTILS.Byte(x, i)) - END -END PutData64LE; - - -PROCEDURE PutDataStr* (program: PROGRAM; s: ARRAY OF CHAR); -VAR - i: INTEGER; - -BEGIN - i := 0; - WHILE s[i] # 0X DO - PutData(program, ORD(s[i])); - INC(i) - END -END PutDataStr; - - -PROCEDURE PutCode* (program: PROGRAM; b: BYTE); -BEGIN - CHL.PushByte(program.code, b) -END PutCode; - - -PROCEDURE PutCode32LE* (program: PROGRAM; x: INTEGER); -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO 3 DO - CHL.PushByte(program.code, UTILS.Byte(x, i)) - END -END PutCode32LE; - - -PROCEDURE PutCode16LE* (program: PROGRAM; x: INTEGER); -BEGIN - CHL.PushByte(program.code, UTILS.Byte(x, 0)); - CHL.PushByte(program.code, UTILS.Byte(x, 1)) -END PutCode16LE; - - -PROCEDURE SetLabel* (program: PROGRAM; label, offset: INTEGER); -BEGIN - CHL.SetInt(program.labels, label, offset) -END SetLabel; - - -PROCEDURE Import* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER); -VAR - imp: IMPRT; - -BEGIN - CHL.PushByte(program._import, 0); - CHL.PushByte(program._import, 0); - - IF ODD(CHL.Length(program._import)) THEN - CHL.PushByte(program._import, 0) - END; - - NEW(imp); - imp.nameoffs := CHL.PushStr(program._import, name); - imp.label := label; - LISTS.push(program.imp_list, imp) -END Import; - - -PROCEDURE less (bytes: CHL.BYTELIST; a, b: EXPRT): BOOLEAN; -VAR - i, j: INTEGER; - -BEGIN - i := a.nameoffs; - j := b.nameoffs; - - WHILE (CHL.GetByte(bytes, i) # 0) & (CHL.GetByte(bytes, j) # 0) & - (CHL.GetByte(bytes, i) = CHL.GetByte(bytes, j)) DO - INC(i); - INC(j) - END - - RETURN CHL.GetByte(bytes, i) < CHL.GetByte(bytes, j) -END less; - - -PROCEDURE Export* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER); -VAR - exp, cur: EXPRT; - -BEGIN - NEW(exp); - exp.label := CHL.GetInt(program.labels, label); - exp.nameoffs := CHL.PushStr(program.export, name); - - cur := program.exp_list.first(EXPRT); - WHILE (cur # NIL) & less(program.export, cur, exp) DO - cur := cur.next(EXPRT) - END; - - IF cur # NIL THEN - IF cur.prev # NIL THEN - LISTS.insert(program.exp_list, cur.prev, exp) - ELSE - LISTS.insertL(program.exp_list, cur, exp) - END - ELSE - LISTS.push(program.exp_list, exp) - END - -END Export; - - -PROCEDURE GetIProc* (program: PROGRAM; n: INTEGER): IMPRT; -VAR - _import, res: IMPRT; - -BEGIN - _import := program.imp_list.first(IMPRT); - - res := NIL; - WHILE (_import # NIL) & (n >= 0) DO - IF _import.label # 0 THEN - res := _import; - DEC(n) - END; - _import := _import.next(IMPRT) - END; - - ASSERT(n = -1) - RETURN res -END GetIProc; - - -PROCEDURE GetLabel* (program: PROGRAM; label: INTEGER): INTEGER; - RETURN CHL.GetInt(program.labels, label) -END GetLabel; - - -PROCEDURE NewLabel* (program: PROGRAM); -BEGIN - CHL.PushInt(program.labels, 0) -END NewLabel; - - -PROCEDURE fixup* (program: PROGRAM); -VAR - rel: RELOC; - imp: IMPRT; - nproc: INTEGER; - L: INTEGER; - -BEGIN - - nproc := 0; - imp := program.imp_list.first(IMPRT); - WHILE imp # NIL DO - IF imp.label # 0 THEN - CHL.SetInt(program.labels, imp.label, nproc); - INC(nproc) - END; - imp := imp.next(IMPRT) - END; - - rel := program.rel_list.first(RELOC); - WHILE rel # NIL DO - - IF rel.opcode IN {RIMP, PICIMP} THEN - L := get32le(program.code, rel.offset); - put32le(program.code, rel.offset, GetLabel(program, L)) - END; - - rel := rel.next(RELOC) - END - -END fixup; - - -PROCEDURE InitArray* (VAR _array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR); -VAR - i, k: INTEGER; - - - PROCEDURE hexdgt (dgt: CHAR): INTEGER; - VAR - res: INTEGER; - - BEGIN - IF dgt < "A" THEN - res := ORD(dgt) - ORD("0") - ELSE - res := ORD(dgt) - ORD("A") + 10 - END - - RETURN res - END hexdgt; - - -BEGIN - k := LENGTH(hex); - ASSERT(~ODD(k)); - k := k DIV 2; - - FOR i := 0 TO k - 1 DO - _array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1]) - END; - - INC(idx, k) -END InitArray; - - -END BIN. \ No newline at end of file diff --git a/programs/develop/oberon07/source/CHUNKLISTS.ob07 b/programs/develop/oberon07/source/CHUNKLISTS.ob07 deleted file mode 100644 index 4137b5a00..000000000 --- a/programs/develop/oberon07/source/CHUNKLISTS.ob07 +++ /dev/null @@ -1,255 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE CHUNKLISTS; - -IMPORT LISTS, WR := WRITER; - - -CONST - - LENOFBYTECHUNK = 65536; - LENOFINTCHUNK = 16384; - - -TYPE - - ANYLIST = POINTER TO RECORD (LISTS.LIST) - - length: INTEGER - - END; - - BYTELIST* = POINTER TO RECORD (ANYLIST) END; - - BYTECHUNK = POINTER TO RECORD (LISTS.ITEM) - - data: ARRAY LENOFBYTECHUNK OF BYTE; - count: INTEGER - - END; - - - INTLIST* = POINTER TO RECORD (ANYLIST) END; - - INTCHUNK = POINTER TO RECORD (LISTS.ITEM) - - data: ARRAY LENOFINTCHUNK OF INTEGER; - count: INTEGER - - END; - - -PROCEDURE SetByte* (list: BYTELIST; idx: INTEGER; byte: BYTE); -VAR - chunk: BYTECHUNK; - item: LISTS.ITEM; - -BEGIN - ASSERT(idx >= 0); - ASSERT(list # NIL); - - item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK); - ASSERT(item # NIL); - chunk := item(BYTECHUNK); - idx := idx MOD LENOFBYTECHUNK; - ASSERT(idx < chunk.count); - chunk.data[idx] := byte -END SetByte; - - -PROCEDURE GetByte* (list: BYTELIST; idx: INTEGER): BYTE; -VAR - chunk: BYTECHUNK; - item: LISTS.ITEM; - -BEGIN - ASSERT(idx >= 0); - ASSERT(list # NIL); - - item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK); - ASSERT(item # NIL); - chunk := item(BYTECHUNK); - idx := idx MOD LENOFBYTECHUNK; - ASSERT(idx < chunk.count) - RETURN chunk.data[idx] -END GetByte; - - -PROCEDURE PushByte* (list: BYTELIST; byte: BYTE); -VAR - chunk: BYTECHUNK; - -BEGIN - ASSERT(list # NIL); - - chunk := list.last(BYTECHUNK); - - IF chunk.count = LENOFBYTECHUNK THEN - NEW(chunk); - chunk.count := 0; - LISTS.push(list, chunk) - END; - - chunk.data[chunk.count] := byte; - INC(chunk.count); - - INC(list.length) -END PushByte; - - -PROCEDURE PushStr* (list: BYTELIST; str: ARRAY OF CHAR): INTEGER; -VAR - i, res: INTEGER; - -BEGIN - res := list.length; - i := 0; - REPEAT - PushByte(list, ORD(str[i])); - INC(i) - UNTIL str[i - 1] = 0X - - RETURN res -END PushStr; - - -PROCEDURE GetStr* (list: BYTELIST; pos: INTEGER; VAR str: ARRAY OF CHAR): BOOLEAN; -VAR - i: INTEGER; - res: BOOLEAN; - -BEGIN - res := FALSE; - i := 0; - WHILE (pos < list.length) & (i < LEN(str)) & ~res DO - str[i] := CHR(GetByte(list, pos)); - res := str[i] = 0X; - INC(pos); - INC(i) - END - - RETURN res -END GetStr; - - -PROCEDURE WriteToFile* (list: BYTELIST); -VAR - chunk: BYTECHUNK; - -BEGIN - chunk := list.first(BYTECHUNK); - WHILE chunk # NIL DO - WR.Write(chunk.data, chunk.count); - chunk := chunk.next(BYTECHUNK) - END -END WriteToFile; - - -PROCEDURE CreateByteList* (): BYTELIST; -VAR - bytelist: BYTELIST; - list: LISTS.LIST; - chunk: BYTECHUNK; - -BEGIN - NEW(bytelist); - list := LISTS.create(bytelist); - bytelist.length := 0; - - NEW(chunk); - chunk.count := 0; - LISTS.push(list, chunk) - - RETURN list(BYTELIST) -END CreateByteList; - - -PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER); -VAR - chunk: INTCHUNK; - item: LISTS.ITEM; - -BEGIN - ASSERT(idx >= 0); - ASSERT(list # NIL); - - item := LISTS.getidx(list, idx DIV LENOFINTCHUNK); - ASSERT(item # NIL); - chunk := item(INTCHUNK); - idx := idx MOD LENOFINTCHUNK; - ASSERT(idx < chunk.count); - chunk.data[idx] := int -END SetInt; - - -PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER; - -VAR - chunk: INTCHUNK; - item: LISTS.ITEM; - -BEGIN - ASSERT(idx >= 0); - ASSERT(list # NIL); - - item := LISTS.getidx(list, idx DIV LENOFINTCHUNK); - ASSERT(item # NIL); - chunk := item(INTCHUNK); - idx := idx MOD LENOFINTCHUNK; - ASSERT(idx < chunk.count) - RETURN chunk.data[idx] -END GetInt; - - -PROCEDURE PushInt* (list: INTLIST; int: INTEGER); -VAR - chunk: INTCHUNK; - -BEGIN - ASSERT(list # NIL); - - chunk := list.last(INTCHUNK); - - IF chunk.count = LENOFINTCHUNK THEN - NEW(chunk); - chunk.count := 0; - LISTS.push(list, chunk) - END; - - chunk.data[chunk.count] := int; - INC(chunk.count); - - INC(list.length) -END PushInt; - - -PROCEDURE CreateIntList* (): INTLIST; -VAR - intlist: INTLIST; - list: LISTS.LIST; - chunk: INTCHUNK; - -BEGIN - NEW(intlist); - list := LISTS.create(intlist); - intlist.length := 0; - - NEW(chunk); - chunk.count := 0; - LISTS.push(list, chunk) - - RETURN list(INTLIST) -END CreateIntList; - - -PROCEDURE Length* (list: ANYLIST): INTEGER; - RETURN list.length -END Length; - - -END CHUNKLISTS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/COLLECTIONS.ob07 b/programs/develop/oberon07/source/COLLECTIONS.ob07 deleted file mode 100644 index f9b713a0b..000000000 --- a/programs/develop/oberon07/source/COLLECTIONS.ob07 +++ /dev/null @@ -1,59 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2019, Anton Krotov - All rights reserved. -*) - -MODULE COLLECTIONS; - - -TYPE - - ITEM* = POINTER TO RECORD - - link: ITEM - - END; - - COLLECTION* = POINTER TO RECORD - - last: ITEM - - END; - - -PROCEDURE push* (collection: COLLECTION; item: ITEM); -BEGIN - item.link := collection.last; - collection.last := item -END push; - - -PROCEDURE pop* (collection: COLLECTION): ITEM; -VAR - item: ITEM; - -BEGIN - item := collection.last; - IF item # NIL THEN - collection.last := item.link - END - - RETURN item -END pop; - - -PROCEDURE create* (): COLLECTION; -VAR - collection: COLLECTION; - -BEGIN - NEW(collection); - collection.last := NIL - - RETURN collection -END create; - - -END COLLECTIONS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/CONSOLE.ob07 b/programs/develop/oberon07/source/CONSOLE.ob07 deleted file mode 100644 index f5091cca3..000000000 --- a/programs/develop/oberon07/source/CONSOLE.ob07 +++ /dev/null @@ -1,78 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE CONSOLE; - -IMPORT UTILS, STRINGS; - - -PROCEDURE String* (s: ARRAY OF CHAR); -VAR - i: INTEGER; - -BEGIN - i := 0; - WHILE (i < LEN(s)) & (s[i] # 0X) DO - UTILS.OutChar(s[i]); - INC(i) - END -END String; - - -PROCEDURE Int* (x: INTEGER); -VAR - s: ARRAY 24 OF CHAR; - -BEGIN - STRINGS.IntToStr(x, s); - String(s) -END Int; - - -PROCEDURE Int2* (x: INTEGER); -BEGIN - IF x < 10 THEN - String("0") - END; - Int(x) -END Int2; - - -PROCEDURE Ln*; -BEGIN - String(UTILS.eol) -END Ln; - - -PROCEDURE StringLn* (s: ARRAY OF CHAR); -BEGIN - String(s); - Ln -END StringLn; - - -PROCEDURE IntLn* (x: INTEGER); -BEGIN - Int(x); - Ln -END IntLn; - - -PROCEDURE Int2Ln* (x: INTEGER); -BEGIN - Int2(x); - Ln -END Int2Ln; - - -PROCEDURE Dashes*; -BEGIN - StringLn("------------------------------------------------") -END Dashes; - - -END CONSOLE. \ No newline at end of file diff --git a/programs/develop/oberon07/source/Compiler.ob07 b/programs/develop/oberon07/source/Compiler.ob07 deleted file mode 100644 index 7ea35d6e8..000000000 --- a/programs/develop/oberon07/source/Compiler.ob07 +++ /dev/null @@ -1,352 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2023, Anton Krotov - All rights reserved. -*) - -MODULE Compiler; - -IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, PROG, C := CONSOLE, - ERRORS, STRINGS, WRITER, MSP430, THUMB, TARGETS, SCAN, TEXTDRV; - - -CONST - - DEF_WINDOWS = "WINDOWS"; - DEF_LINUX = "LINUX"; - DEF_KOLIBRIOS = "KOLIBRIOS"; - DEF_CPU_X86 = "CPU_X86"; - DEF_CPU_X8664 = "CPU_X8664"; - - -PROCEDURE keys (VAR options: PROG.OPTIONS; VAR out: PARS.PATH); -VAR - param: PARS.PATH; - i, j: INTEGER; - _end: BOOLEAN; - value: INTEGER; - minor, - major: INTEGER; - checking: SET; - - - PROCEDURE getVal (VAR i: INTEGER; VAR value: INTEGER); - VAR - param: PARS.PATH; - val: INTEGER; - BEGIN - INC(i); - UTILS.GetArg(i, param); - IF STRINGS.StrToInt(param, val) THEN - value := val - END; - IF param[0] = "-" THEN - DEC(i) - END - END getVal; - - -BEGIN - options.lower := TRUE; - out := ""; - checking := options.checking; - _end := FALSE; - i := 3; - REPEAT - UTILS.GetArg(i, param); - - IF param = "-stk" THEN - INC(i); - UTILS.GetArg(i, param); - IF STRINGS.StrToInt(param, value) & (1 <= value) & (value <= 32) THEN - options.stack := value - END; - IF param[0] = "-" THEN - DEC(i) - END - - ELSIF param = "-out" THEN - INC(i); - UTILS.GetArg(i, param); - IF param[0] = "-" THEN - DEC(i) - ELSE - out := param - END - - ELSIF param = "-tab" THEN - getVal(i, options.tab) - - ELSIF param = "-ram" THEN - getVal(i, options.ram) - - ELSIF param = "-rom" THEN - getVal(i, options.rom) - - ELSIF param = "-nochk" THEN - INC(i); - UTILS.GetArg(i, param); - - IF param[0] = "-" THEN - DEC(i) - ELSE - j := 0; - WHILE param[j] # 0X DO - - IF param[j] = "p" THEN - EXCL(checking, ST.chkPTR) - ELSIF param[j] = "t" THEN - EXCL(checking, ST.chkGUARD) - ELSIF param[j] = "i" THEN - EXCL(checking, ST.chkIDX) - ELSIF param[j] = "b" THEN - EXCL(checking, ST.chkBYTE) - ELSIF param[j] = "c" THEN - EXCL(checking, ST.chkCHR) - ELSIF param[j] = "w" THEN - EXCL(checking, ST.chkWCHR) - ELSIF param[j] = "r" THEN - EXCL(checking, ST.chkCHR); - EXCL(checking, ST.chkWCHR); - EXCL(checking, ST.chkBYTE) - ELSIF param[j] = "s" THEN - EXCL(checking, ST.chkSTK) - ELSIF param[j] = "a" THEN - checking := {} - END; - - INC(j) - END; - - END - - ELSIF param = "-ver" THEN - INC(i); - UTILS.GetArg(i, param); - IF STRINGS.StrToVer(param, major, minor) THEN - options.version := major * 65536 + minor - END; - IF param[0] = "-" THEN - DEC(i) - END - - ELSIF param = "-lower" THEN - options.lower := TRUE - - ELSIF param = "-upper" THEN - options.lower := FALSE - - ELSIF param = "-pic" THEN - options.pic := TRUE - - ELSIF param = "-uses" THEN - options.uses := TRUE - - ELSIF param = "-def" THEN - INC(i); - UTILS.GetArg(i, param); - SCAN.NewDef(param) - - ELSIF param = "" THEN - _end := TRUE - - ELSE - ERRORS.BadParam(param) - END; - - INC(i) - UNTIL _end; - - options.checking := checking -END keys; - - -PROCEDURE OutTargetItem (target: INTEGER; text: ARRAY OF CHAR); -VAR - width: INTEGER; - -BEGIN - width := 15; - width := width - LENGTH(TARGETS.Targets[target].ComLinePar) - 4; - C.String(" '"); C.String(TARGETS.Targets[target].ComLinePar); C.String("'"); - WHILE width > 0 DO - C.String(20X); - DEC(width) - END; - C.StringLn(text) -END OutTargetItem; - - -PROCEDURE main; -VAR - path: PARS.PATH; - inname: PARS.PATH; - ext: PARS.PATH; - app_path: PARS.PATH; - lib_path: PARS.PATH; - modname: PARS.PATH; - outname: PARS.PATH; - param: PARS.PATH; - temp: PARS.PATH; - target: INTEGER; - time: INTEGER; - options: PROG.OPTIONS; - -BEGIN - options.stack := 2; - options.tab := TEXTDRV.defTabSize; - options.version := 65536; - options.pic := FALSE; - options.lower := FALSE; - options.uses := FALSE; - options.checking := ST.chkALL; - - PATHS.GetCurrentDirectory(app_path); - - UTILS.GetArg(0, temp); - PATHS.split(temp, path, modname, ext); - IF PATHS.isRelative(path) THEN - PATHS.RelPath(app_path, path, temp); - path := temp - END; - lib_path := path; - - UTILS.GetArg(1, inname); - STRINGS.replace(inname, "\", UTILS.slash); - STRINGS.replace(inname, "/", UTILS.slash); - - C.Ln; - C.String("Akron Oberon Compiler v"); C.Int(UTILS.vMajor); C.String("."); C.Int2(UTILS.vMinor); - C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit) " + UTILS.Date); - C.StringLn("Copyright (c) 2018-2023, Anton Krotov"); - - IF inname = "" THEN - C.Ln; - C.StringLn("Usage: Compiler

[optional settings]"); C.Ln; - C.StringLn("target ="); - IF UTILS.bit_depth = 64 THEN - OutTargetItem(TARGETS.Win64C, "Windows64 Console"); - OutTargetItem(TARGETS.Win64GUI, "Windows64 GUI"); - OutTargetItem(TARGETS.Win64DLL, "Windows64 DLL"); - OutTargetItem(TARGETS.Linux64, "Linux64 Exec"); - OutTargetItem(TARGETS.Linux64SO, "Linux64 SO") - END; - OutTargetItem(TARGETS.Win32C, "Windows32 Console"); - OutTargetItem(TARGETS.Win32GUI, "Windows32 GUI"); - OutTargetItem(TARGETS.Win32DLL, "Windows32 DLL"); - OutTargetItem(TARGETS.Linux32, "Linux32 Exec"); - OutTargetItem(TARGETS.Linux32SO, "Linux32 SO"); - OutTargetItem(TARGETS.KolibriOS, "KolibriOS Exec"); - OutTargetItem(TARGETS.KolibriOSDLL, "KolibriOS DLL"); - OutTargetItem(TARGETS.MSP430, "MSP430x{1,2}xx microcontrollers"); - OutTargetItem(TARGETS.STM32CM3, "STM32 Cortex-M3 microcontrollers"); - C.Ln; - C.StringLn("optional settings:"); C.Ln; - C.StringLn(" -out output"); C.Ln; - C.StringLn(" -stk set size of stack in Mbytes (Windows, Linux, KolibriOS)"); C.Ln; - C.StringLn(" -nochk <'ptibcwra'> disable runtime checking (pointers, types, indexes,"); - C.StringLn(" BYTE, CHR, WCHR)"); C.Ln; - C.StringLn(" -lower allow lower case for keywords (default)"); C.Ln; - C.StringLn(" -upper only upper case for keywords"); C.Ln; - C.StringLn(" -def define conditional compilation symbol"); C.Ln; - C.StringLn(" -ver set version of program (KolibriOS DLL)"); C.Ln; - C.StringLn(" -ram set size of RAM in bytes (MSP430) or Kbytes (STM32)"); C.Ln; - C.StringLn(" -rom set size of ROM in bytes (MSP430) or Kbytes (STM32)"); C.Ln; - C.StringLn(" -tab set width for tabs"); C.Ln; - C.StringLn(" -uses list imported modules"); C.Ln; - UTILS.Exit(0) - END; - - C.Dashes; - PATHS.split(inname, path, modname, ext); - - IF ext # UTILS.FILE_EXT THEN - ERRORS.Error(207) - END; - - IF PATHS.isRelative(path) THEN - PATHS.RelPath(app_path, path, temp); - path := temp - END; - - UTILS.GetArg(2, param); - IF param = "" THEN - ERRORS.Error(205) - END; - - SCAN.NewDef(param); - - IF TARGETS.Select(param) THEN - target := TARGETS.target - ELSE - ERRORS.Error(206) - END; - - IF TARGETS.CPU = TARGETS.cpuMSP430 THEN - options.ram := MSP430.minRAM; - options.rom := MSP430.minROM - END; - - IF (TARGETS.CPU = TARGETS.cpuTHUMB) & (TARGETS.OS = TARGETS.osNONE) THEN - options.ram := THUMB.minRAM; - options.rom := THUMB.minROM - END; - - IF UTILS.bit_depth < TARGETS.BitDepth THEN - ERRORS.Error(206) - END; - - STRINGS.append(lib_path, "lib"); - STRINGS.append(lib_path, UTILS.slash); - STRINGS.append(lib_path, TARGETS.LibDir); - STRINGS.append(lib_path, UTILS.slash); - - keys(options, outname); - TEXTDRV.setTabSize(options.tab); - IF outname = "" THEN - outname := path; - STRINGS.append(outname, modname); - STRINGS.append(outname, TARGETS.FileExt) - ELSE - IF PATHS.isRelative(outname) THEN - PATHS.RelPath(app_path, outname, temp); - outname := temp - END - END; - - PARS.init(options); - - CASE TARGETS.OS OF - |TARGETS.osNONE: - |TARGETS.osWIN32, - TARGETS.osWIN64: SCAN.NewDef(DEF_WINDOWS) - |TARGETS.osLINUX32, - TARGETS.osLINUX64: SCAN.NewDef(DEF_LINUX) - |TARGETS.osKOS: SCAN.NewDef(DEF_KOLIBRIOS) - END; - - CASE TARGETS.CPU OF - |TARGETS.cpuX86: SCAN.NewDef(DEF_CPU_X86) - |TARGETS.cpuAMD64: SCAN.NewDef(DEF_CPU_X8664) - |TARGETS.cpuMSP430: - |TARGETS.cpuTHUMB: - |TARGETS.cpuRVM32I: - |TARGETS.cpuRVM64I: - END; - - ST.compile(path, lib_path, modname, outname, target, options); - - time := UTILS.GetTickCount() - UTILS.time; - C.Dashes; - C.Int(PARS.lines); C.String(" lines, "); - C.Int(time DIV 100); C.String("."); C.Int2(time MOD 100); C.String(" sec, "); - C.Int(WRITER.counter); C.StringLn(" bytes"); - - UTILS.Exit(0) -END main; - - -BEGIN - main -END Compiler. \ No newline at end of file diff --git a/programs/develop/oberon07/source/ELF.ob07 b/programs/develop/oberon07/source/ELF.ob07 deleted file mode 100644 index b62c6d0a1..000000000 --- a/programs/develop/oberon07/source/ELF.ob07 +++ /dev/null @@ -1,592 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2021, Anton Krotov - All rights reserved. -*) - -MODULE ELF; - -IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PE32, UTILS, STRINGS; - - -CONST - - EI_NIDENT = 16; - ET_EXEC = 2; - ET_DYN = 3; - - EM_386 = 3; - EM_8664 = 3EH; - - ELFCLASS32 = 1; - ELFCLASS64 = 2; - - ELFDATA2LSB = 1; - ELFDATA2MSB = 2; - - PF_X = 1; - PF_W = 2; - PF_R = 4; - - -TYPE - - Elf32_Ehdr = RECORD - - e_ident: ARRAY EI_NIDENT OF BYTE; - - e_type, - e_machine: WCHAR; - - e_version, - e_entry, - e_phoff, - e_shoff, - e_flags: INTEGER; - - e_ehsize, - e_phentsize, - e_phnum, - e_shentsize, - e_shnum, - e_shstrndx: WCHAR - - END; - - - Elf32_Phdr = RECORD - - p_type, - p_offset, - p_vaddr, - p_paddr, - p_filesz, - p_memsz, - p_flags, - p_align: INTEGER - - END; - - - Elf32_Dyn = POINTER TO RECORD (LISTS.ITEM) - - d_tag, d_val: INTEGER - - END; - - - Elf32_Sym = POINTER TO RECORD (LISTS.ITEM) - - name, value, size: INTEGER; - info, other: CHAR; - shndx: WCHAR - - END; - - -VAR - - dynamic: LISTS.LIST; - strtab: CHL.BYTELIST; - symtab: LISTS.LIST; - - hashtab, bucket, chain: CHL.INTLIST; - - -PROCEDURE Write16 (w: WCHAR); -BEGIN - WR.Write16LE(ORD(w)) -END Write16; - - -PROCEDURE WritePH (ph: Elf32_Phdr); -BEGIN - WR.Write32LE(ph.p_type); - WR.Write32LE(ph.p_offset); - WR.Write32LE(ph.p_vaddr); - WR.Write32LE(ph.p_paddr); - WR.Write32LE(ph.p_filesz); - WR.Write32LE(ph.p_memsz); - WR.Write32LE(ph.p_flags); - WR.Write32LE(ph.p_align) -END WritePH; - - -PROCEDURE WritePH64 (ph: Elf32_Phdr); -BEGIN - WR.Write32LE(ph.p_type); - WR.Write32LE(ph.p_flags); - WR.Write64LE(ph.p_offset); - WR.Write64LE(ph.p_vaddr); - WR.Write64LE(ph.p_paddr); - WR.Write64LE(ph.p_filesz); - WR.Write64LE(ph.p_memsz); - WR.Write64LE(ph.p_align) -END WritePH64; - - -PROCEDURE NewDyn (tag, val: INTEGER); -VAR - dyn: Elf32_Dyn; - -BEGIN - NEW(dyn); - dyn.d_tag := tag; - dyn.d_val := val; - LISTS.push(dynamic, dyn) -END NewDyn; - - -PROCEDURE NewSym (name, value, size: INTEGER; info, other: CHAR; shndx: WCHAR); -VAR - sym: Elf32_Sym; - -BEGIN - NEW(sym); - sym.name := name; - sym.value := value; - sym.size := size; - sym.info := info; - sym.other := other; - sym.shndx := shndx; - - LISTS.push(symtab, sym) -END NewSym; - - -PROCEDURE MakeHash (bucket, chain: CHL.INTLIST; symCount: INTEGER); -VAR - symi, hi, k: INTEGER; - -BEGIN - FOR symi := 0 TO symCount - 1 DO - CHL.SetInt(chain, symi, 0); - hi := CHL.GetInt(hashtab, symi) MOD symCount; - IF CHL.GetInt(bucket, hi) # 0 THEN - k := symi; - WHILE CHL.GetInt(chain, k) # 0 DO - k := CHL.GetInt(chain, k) - END; - CHL.SetInt(chain, k, CHL.GetInt(bucket, hi)) - END; - CHL.SetInt(bucket, hi, symi) - END -END MakeHash; - - -PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; fini: INTEGER; so, amd64: BOOLEAN); -CONST - interp = 0; - dyn = 1; - header = 2; - text = 3; - data = 4; - bss = 5; - - linuxInterpreter64 = "/lib64/ld-linux-x86-64.so.2"; - linuxInterpreter32 = "/lib/ld-linux.so.2"; - - exeBaseAddress32 = 8048000H; - exeBaseAddress64 = 400000H; - dllBaseAddress = 0; - - DT_NULL = 0; - DT_NEEDED = 1; - DT_HASH = 4; - DT_STRTAB = 5; - DT_SYMTAB = 6; - DT_RELA = 7; - DT_RELASZ = 8; - DT_RELAENT = 9; - DT_STRSZ = 10; - DT_SYMENT = 11; - DT_INIT = 12; - DT_FINI = 13; - DT_SONAME = 14; - DT_REL = 17; - DT_RELSZ = 18; - DT_RELENT = 19; - -VAR - ehdr: Elf32_Ehdr; - phdr: ARRAY 16 OF Elf32_Phdr; - - i, BaseAdr, DynAdr, offset, pad, VA, symCount: INTEGER; - - SizeOf: RECORD header, code, data, bss: INTEGER END; - - Offset: RECORD symtab, reltab, hash, strtab: INTEGER END; - - Interpreter: ARRAY 40 OF CHAR; lenInterpreter: INTEGER; - - item: LISTS.ITEM; - - Name: ARRAY 2048 OF CHAR; - - Address: PE32.VIRTUAL_ADDR; - -BEGIN - dynamic := LISTS.create(NIL); - symtab := LISTS.create(NIL); - strtab := CHL.CreateByteList(); - - IF amd64 THEN - BaseAdr := exeBaseAddress64; - Interpreter := linuxInterpreter64 - ELSE - BaseAdr := exeBaseAddress32; - Interpreter := linuxInterpreter32 - END; - - IF so THEN - BaseAdr := dllBaseAddress - END; - - lenInterpreter := LENGTH(Interpreter) + 1; - - SizeOf.code := CHL.Length(program.code); - SizeOf.data := CHL.Length(program.data); - SizeOf.bss := program.bss; - - ehdr.e_ident[0] := 7FH; - ehdr.e_ident[1] := ORD("E"); - ehdr.e_ident[2] := ORD("L"); - ehdr.e_ident[3] := ORD("F"); - IF amd64 THEN - ehdr.e_ident[4] := ELFCLASS64 - ELSE - ehdr.e_ident[4] := ELFCLASS32 - END; - ehdr.e_ident[5] := ELFDATA2LSB; - ehdr.e_ident[6] := 1; - ehdr.e_ident[7] := 3; - FOR i := 8 TO EI_NIDENT - 1 DO - ehdr.e_ident[i] := 0 - END; - - IF so THEN - ehdr.e_type := WCHR(ET_DYN) - ELSE - ehdr.e_type := WCHR(ET_EXEC) - END; - - ehdr.e_version := 1; - ehdr.e_shoff := 0; - ehdr.e_flags := 0; - ehdr.e_shnum := WCHR(0); - ehdr.e_shstrndx := WCHR(0); - ehdr.e_phnum := WCHR(6); - - IF amd64 THEN - ehdr.e_machine := WCHR(EM_8664); - ehdr.e_phoff := 40H; - ehdr.e_ehsize := WCHR(40H); - ehdr.e_phentsize := WCHR(38H); - ehdr.e_shentsize := WCHR(40H) - ELSE - ehdr.e_machine := WCHR(EM_386); - ehdr.e_phoff := 34H; - ehdr.e_ehsize := WCHR(34H); - ehdr.e_phentsize := WCHR(20H); - ehdr.e_shentsize := WCHR(28H) - END; - - SizeOf.header := ORD(ehdr.e_ehsize) + ORD(ehdr.e_phentsize) * ORD(ehdr.e_phnum); - - phdr[interp].p_type := 3; - phdr[interp].p_offset := SizeOf.header; - phdr[interp].p_vaddr := BaseAdr + phdr[interp].p_offset; - phdr[interp].p_paddr := phdr[interp].p_vaddr; - phdr[interp].p_filesz := lenInterpreter; - phdr[interp].p_memsz := lenInterpreter; - phdr[interp].p_flags := PF_R; - phdr[interp].p_align := 1; - - phdr[dyn].p_type := 2; - phdr[dyn].p_offset := phdr[interp].p_offset + phdr[interp].p_filesz; - phdr[dyn].p_vaddr := BaseAdr + phdr[dyn].p_offset; - phdr[dyn].p_paddr := phdr[dyn].p_vaddr; - - hashtab := CHL.CreateIntList(); - - CHL.PushInt(hashtab, STRINGS.HashStr("")); - NewSym(CHL.PushStr(strtab, ""), 0, 0, 0X, 0X, 0X); - CHL.PushInt(hashtab, STRINGS.HashStr("dlopen")); - NewSym(CHL.PushStr(strtab, "dlopen"), 0, 0, 12X, 0X, 0X); - CHL.PushInt(hashtab, STRINGS.HashStr("dlsym")); - NewSym(CHL.PushStr(strtab, "dlsym"), 0, 0, 12X, 0X, 0X); - - IF so THEN - item := program.exp_list.first; - WHILE item # NIL DO - ASSERT(CHL.GetStr(program.export, item(BIN.EXPRT).nameoffs, Name)); - CHL.PushInt(hashtab, STRINGS.HashStr(Name)); - NewSym(CHL.PushStr(strtab, Name), item(BIN.EXPRT).label, 0, 12X, 0X, 0X); - item := item.next - END; - ASSERT(CHL.GetStr(program.data, program.modname, Name)) - END; - - symCount := LISTS.count(symtab); - - bucket := CHL.CreateIntList(); - chain := CHL.CreateIntList(); - - FOR i := 1 TO symCount DO - CHL.PushInt(bucket, 0); - CHL.PushInt(chain, 0) - END; - - MakeHash(bucket, chain, symCount); - - NewDyn(DT_NEEDED, CHL.PushStr(strtab, "libdl.so.2")); - NewDyn(DT_STRTAB, 0); - NewDyn(DT_STRSZ, CHL.Length(strtab)); - NewDyn(DT_SYMTAB, 0); - - IF amd64 THEN - NewDyn(DT_SYMENT, 24); - NewDyn(DT_RELA, 0); - NewDyn(DT_RELASZ, 48); - NewDyn(DT_RELAENT, 24) - ELSE - NewDyn(DT_SYMENT, 16); - NewDyn(DT_REL, 0); - NewDyn(DT_RELSZ, 16); - NewDyn(DT_RELENT, 8) - END; - - NewDyn(DT_HASH, 0); - - IF so THEN - NewDyn(DT_SONAME, CHL.PushStr(strtab, Name)); - NewDyn(DT_INIT, 0); - NewDyn(DT_FINI, 0) - END; - - NewDyn(DT_NULL, 0); - - Offset.symtab := LISTS.count(dynamic) * (8 + 8 * ORD(amd64)); - Offset.reltab := Offset.symtab + symCount * (16 + 8 * ORD(amd64)); - Offset.hash := Offset.reltab + (8 + 16 * ORD(amd64)) * 2; - Offset.strtab := Offset.hash + (symCount * 2 + 2) * 4; - - DynAdr := phdr[dyn].p_offset + BaseAdr; - - item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + DynAdr; - item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + DynAdr; - item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + DynAdr; - item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash + DynAdr; - - phdr[dyn].p_filesz := Offset.strtab + CHL.Length(strtab) + 8 + 8 * ORD(amd64); - phdr[dyn].p_memsz := phdr[dyn].p_filesz; - - phdr[dyn].p_flags := PF_R; - phdr[dyn].p_align := 1; - - offset := 0; - - phdr[header].p_type := 1; - phdr[header].p_offset := offset; - phdr[header].p_vaddr := BaseAdr; - phdr[header].p_paddr := BaseAdr; - phdr[header].p_filesz := SizeOf.header + lenInterpreter + phdr[dyn].p_filesz; - phdr[header].p_memsz := phdr[header].p_filesz; - phdr[header].p_flags := PF_R + PF_W; - phdr[header].p_align := 1000H; - - INC(offset, phdr[header].p_filesz); - VA := BaseAdr + offset + 1000H; - - phdr[text].p_type := 1; - phdr[text].p_offset := offset; - phdr[text].p_vaddr := VA; - phdr[text].p_paddr := VA; - phdr[text].p_filesz := SizeOf.code; - phdr[text].p_memsz := SizeOf.code; - phdr[text].p_flags := PF_X + PF_R; - phdr[text].p_align := 1000H; - - ehdr.e_entry := phdr[text].p_vaddr; - - INC(offset, phdr[text].p_filesz); - VA := BaseAdr + offset + 2000H; - pad := (16 - VA MOD 16) MOD 16; - - phdr[data].p_type := 1; - phdr[data].p_offset := offset; - phdr[data].p_vaddr := VA; - phdr[data].p_paddr := VA; - phdr[data].p_filesz := SizeOf.data + pad; - phdr[data].p_memsz := SizeOf.data + pad; - phdr[data].p_flags := PF_R + PF_W; - phdr[data].p_align := 1000H; - - INC(offset, phdr[data].p_filesz); - VA := BaseAdr + offset + 3000H; - - phdr[bss].p_type := 1; - phdr[bss].p_offset := offset; - phdr[bss].p_vaddr := VA; - phdr[bss].p_paddr := VA; - phdr[bss].p_filesz := 0; - phdr[bss].p_memsz := SizeOf.bss + 16; - phdr[bss].p_flags := PF_R + PF_W; - phdr[bss].p_align := 1000H; - - Address.Code := ehdr.e_entry; - Address.Data := phdr[data].p_vaddr + pad; - Address.Bss := WR.align(phdr[bss].p_vaddr, 16); - Address.Import := 0; - - PE32.fixup(program, Address, amd64); - - item := symtab.first; - WHILE item # NIL DO - IF item(Elf32_Sym).value # 0 THEN - INC(item(Elf32_Sym).value, ehdr.e_entry) - END; - item := item.next - END; - - IF so THEN - item := LISTS.getidx(dynamic, 10); item(Elf32_Dyn).d_val := ehdr.e_entry; - item := LISTS.getidx(dynamic, 11); item(Elf32_Dyn).d_val := BIN.GetLabel(program, fini) + ehdr.e_entry - END; - - WR.Create(FileName); - - FOR i := 0 TO EI_NIDENT - 1 DO - WR.WriteByte(ehdr.e_ident[i]) - END; - - Write16(ehdr.e_type); - Write16(ehdr.e_machine); - - WR.Write32LE(ehdr.e_version); - IF amd64 THEN - WR.Write64LE(ehdr.e_entry); - WR.Write64LE(ehdr.e_phoff); - WR.Write64LE(ehdr.e_shoff) - ELSE - WR.Write32LE(ehdr.e_entry); - WR.Write32LE(ehdr.e_phoff); - WR.Write32LE(ehdr.e_shoff) - END; - WR.Write32LE(ehdr.e_flags); - - Write16(ehdr.e_ehsize); - Write16(ehdr.e_phentsize); - Write16(ehdr.e_phnum); - Write16(ehdr.e_shentsize); - Write16(ehdr.e_shnum); - Write16(ehdr.e_shstrndx); - - IF amd64 THEN - WritePH64(phdr[interp]); - WritePH64(phdr[dyn]); - WritePH64(phdr[header]); - WritePH64(phdr[text]); - WritePH64(phdr[data]); - WritePH64(phdr[bss]) - ELSE - WritePH(phdr[interp]); - WritePH(phdr[dyn]); - WritePH(phdr[header]); - WritePH(phdr[text]); - WritePH(phdr[data]); - WritePH(phdr[bss]) - END; - - FOR i := 0 TO lenInterpreter - 1 DO - WR.WriteByte(ORD(Interpreter[i])) - END; - - IF amd64 THEN - item := dynamic.first; - WHILE item # NIL DO - WR.Write64LE(item(Elf32_Dyn).d_tag); - WR.Write64LE(item(Elf32_Dyn).d_val); - item := item.next - END; - - item := symtab.first; - WHILE item # NIL DO - WR.Write32LE(item(Elf32_Sym).name); - WR.WriteByte(ORD(item(Elf32_Sym).info)); - WR.WriteByte(ORD(item(Elf32_Sym).other)); - Write16(item(Elf32_Sym).shndx); - WR.Write64LE(item(Elf32_Sym).value); - WR.Write64LE(item(Elf32_Sym).size); - item := item.next - END; - - WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 16); - WR.Write32LE(1); - WR.Write32LE(1); - WR.Write64LE(0); - WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 8); - WR.Write32LE(1); - WR.Write32LE(2); - WR.Write64LE(0) - - ELSE - item := dynamic.first; - WHILE item # NIL DO - WR.Write32LE(item(Elf32_Dyn).d_tag); - WR.Write32LE(item(Elf32_Dyn).d_val); - item := item.next - END; - - item := symtab.first; - WHILE item # NIL DO - WR.Write32LE(item(Elf32_Sym).name); - WR.Write32LE(item(Elf32_Sym).value); - WR.Write32LE(item(Elf32_Sym).size); - WR.WriteByte(ORD(item(Elf32_Sym).info)); - WR.WriteByte(ORD(item(Elf32_Sym).other)); - Write16(item(Elf32_Sym).shndx); - item := item.next - END; - - WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 8); - WR.Write32LE(00000101H); - WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 4); - WR.Write32LE(00000201H) - - END; - - WR.Write32LE(symCount); - WR.Write32LE(symCount); - - FOR i := 0 TO symCount - 1 DO - WR.Write32LE(CHL.GetInt(bucket, i)) - END; - - FOR i := 0 TO symCount - 1 DO - WR.Write32LE(CHL.GetInt(chain, i)) - END; - - CHL.WriteToFile(strtab); - - IF amd64 THEN - WR.Write64LE(0); - WR.Write64LE(0) - ELSE - WR.Write32LE(0); - WR.Write32LE(0) - END; - - CHL.WriteToFile(program.code); - WHILE pad > 0 DO - WR.WriteByte(0); - DEC(pad) - END; - CHL.WriteToFile(program.data); - WR.Close; - UTILS.chmod(FileName) -END write; - - -END ELF. \ No newline at end of file diff --git a/programs/develop/oberon07/source/ERRORS.ob07 b/programs/develop/oberon07/source/ERRORS.ob07 deleted file mode 100644 index ca95f1eb0..000000000 --- a/programs/develop/oberon07/source/ERRORS.ob07 +++ /dev/null @@ -1,222 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2022, Anton Krotov - All rights reserved. -*) - -MODULE ERRORS; - -IMPORT C := CONSOLE, UTILS; - - -PROCEDURE HintMsg* (name: ARRAY OF CHAR; line, col, hint: INTEGER); -BEGIN - IF hint = 0 THEN - C.String(" hint ("); C.Int(line); C.String(":"); C.Int(col); C.String(") "); - C.String("variable '"); C.String(name); C.StringLn("' never used") - END -END HintMsg; - - -PROCEDURE WarningMsg* (line, col, warning: INTEGER); -BEGIN - C.String(" warning ("); C.Int(line); C.String(":"); C.Int(col); C.String(") "); - CASE warning OF - |0: C.StringLn("passing a string value as a fixed array") - |1: C.StringLn("endless FOR loop") - |2: C.StringLn("identifier too long") - END -END WarningMsg; - - -PROCEDURE ErrorMsg* (fname: ARRAY OF CHAR; line, col, errno: INTEGER); -VAR - str: ARRAY 80 OF CHAR; - -BEGIN - C.Ln; - C.String(" error ("); C.Int(errno); C.String(") ("); C.Int(line); C.String(":"); C.Int(col); C.String(") "); - - CASE errno OF - | 1: str := "missing 'H' or 'X'" - | 2: str := "missing scale" - | 3: str := "unclosed string" - | 4: str := "illegal character" - | 5: str := "string too long" - - | 7: str := "number too long" - | 8..12: str := "number too large" - | 13: str := "real numbers not supported" - - | 21: str := "'MODULE' expected" - | 22: str := "identifier expected" - | 23: str := "module name does not match file name" - | 24: str := "';' expected" - | 25: str := "identifier does not match module name" - | 26: str := "'.' expected" - | 27: str := "'END' expected" - | 28: str := "',', ';' or ':=' expected" - | 29: str := "module not found" - | 30: str := "multiply defined identifier" - | 31: str := "recursive import" - | 32: str := "'=' expected" - | 33: str := "')' expected" - | 34: str := "syntax error in expression" - | 35: str := "'}' expected" - | 36: str := "incompatible operand" - | 37: str := "incompatible operands" - | 38: str := "'RETURN' expected" - | 39: str := "integer overflow" - | 40: str := "floating point overflow" - | 41: str := "not enough floating point registers; simplify expression" - | 42: str := "out of range 0..255" - | 43: str := "expression is not an integer" - | 44: str := "out of range 0..MAXSET" - | 45: str := "division by zero" - | 46: str := "IV out of range" - | 47: str := "'OF' or ',' expected" - | 48: str := "undeclared identifier" - | 49: str := "type expected" - | 50: str := "recursive type definition" - | 51: str := "illegal value of constant" - | 52: str := "not a record type" - | 53: str := "':' expected" - | 54: str := "need to import SYSTEM" - | 55: str := "pointer type not defined" - | 56: str := "out of range 0..MAXSET" - | 57: str := "'TO' expected" - | 58: str := "not a record type" - | 59: str := "this expression cannot be a procedure" - | 60: str := "identifier does not match procedure name" - | 61: str := "illegally marked identifier" - | 62: str := "expression should be constant" - | 63: str := "not enough RAM" - | 64: str := "'(' expected" - | 65: str := "',' expected" - | 66: str := "incompatible parameter" - | 67: str := "'OF' expected" - | 68: str := "type expected" - | 69: str := "result type of procedure is not a basic type" - | 70: str := "import not supported" - | 71: str := "']' expected" - | 72: str := "expression is not BOOLEAN" - | 73: str := "not a record" - | 74: str := "undefined record field" - | 75: str := "not an array" - | 76: str := "expression is not an integer" - | 77: str := "not a pointer" - | 78: str := "type guard not allowed" - | 79: str := "not a type" - | 80: str := "not a record type" - | 81: str := "not a pointer type" - | 82: str := "type guard not allowed" - | 83: str := "index out of range" - | 84: str := "dimension too large" - | 85: str := "procedure must have level 0" - | 86: str := "not a procedure" - | 87: str := "incompatible expression (RETURN)" - | 88: str := "'THEN' expected" - | 89: str := "'DO' expected" - | 90: str := "'UNTIL' expected" - | 91: str := "incompatible assignment" - | 92: str := "procedure call of a function" - | 93: str := "not a variable" - | 94: str := "read only variable" - | 95: str := "invalid type of expression (CASE)" - | 96: str := "':=' expected" - | 97: str := "not INTEGER variable" - | 98: str := "illegal value of constant (0)" - | 99: str := "incompatible label" - |100: str := "multiply defined label" - |101: str := "too large parameter of WCHR" - |102: str := "label expected" - |103: str := "illegal value of constant" - |104: str := "type too large" - |105: str := "access to intermediate variables not allowed" - |106: str := "qualified identifier expected" - |107: str := "too large parameter of CHR" - |108: str := "a variable or a procedure expected" - |109: str := "expression should be constant" - |110: str := "out of range 0..65535" - |111: str := "record [noalign] cannot have a base type" - |112: str := "record [noalign] cannot be a base type" - |113: str := "result type of procedure should not be REAL" - |114: str := "identifiers 'lib_init' and 'version' are reserved" - |115: str := "recursive constant definition" - |116: str := "procedure too deep nested" - |117: str := "string expected" - |118: str := "'$END', '$ELSE' or '$ELSIF' without '$IF'" - |119: str := "'$IF', '$ELSIF', '$ELSE' or '$END' expected" - |120: str := "too many formal parameters" - |121: str := "multiply defined handler" - |122: str := "bad divisor" - |123: str := "illegal flag" - |124: str := "unknown flag" - |125: str := "flag not supported" - |126: str := "type of formal parameter should not be REAL" - END; - C.StringLn(str); - C.String(" file: "); C.StringLn(fname); - UTILS.Exit(1) -END ErrorMsg; - - -PROCEDURE Error1 (s1: ARRAY OF CHAR); -BEGIN - C.Ln; - C.StringLn(s1); - UTILS.Exit(1) -END Error1; - - -PROCEDURE Error3 (s1, s2, s3: ARRAY OF CHAR); -BEGIN - C.Ln; - C.String(s1); C.String(s2); C.StringLn(s3); - UTILS.Exit(1) -END Error3; - - -PROCEDURE Error5 (s1, s2, s3, s4, s5: ARRAY OF CHAR); -BEGIN - C.Ln; - C.String(s1); C.String(s2); C.String(s3); C.String(s4); C.StringLn(s5); - UTILS.Exit(1) -END Error5; - - -PROCEDURE WrongRTL* (ProcName: ARRAY OF CHAR); -BEGIN - Error5("procedure ", UTILS.RTL_NAME, ".", ProcName, " not found") -END WrongRTL; - - -PROCEDURE BadParam* (param: ARRAY OF CHAR); -BEGIN - Error3("bad parameter: ", param, "") -END BadParam; - - -PROCEDURE FileNotFound* (Path, Name, Ext: ARRAY OF CHAR); -BEGIN - Error5("file ", Path, Name, Ext, " not found") -END FileNotFound; - - -PROCEDURE Error* (n: INTEGER); -BEGIN - CASE n OF - |201: Error1("writing file error") - |202: Error1("too many relocations") - |203: Error1("size of program is too large") - |204: Error1("size of variables is too large") - |205: Error1("not enough parameters") - |206: Error1("bad parameter ") - |207: Error3('inputfile name extension must be "', UTILS.FILE_EXT, '"') - |208: Error1("not enough RAM") - END -END Error; - - -END ERRORS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/FILES.ob07 b/programs/develop/oberon07/source/FILES.ob07 deleted file mode 100644 index 646def3e3..000000000 --- a/programs/develop/oberon07/source/FILES.ob07 +++ /dev/null @@ -1,200 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2022, Anton Krotov - All rights reserved. -*) - -MODULE FILES; - -IMPORT UTILS, C := COLLECTIONS; - - -TYPE - - FILE* = POINTER TO RECORD (C.ITEM) - - ptr: INTEGER; - - buffer: ARRAY 64*1024 OF BYTE; - count: INTEGER - - END; - -VAR - - files: C.COLLECTION; - - -PROCEDURE copy (src: ARRAY OF BYTE; src_idx: INTEGER; VAR dst: ARRAY OF BYTE; dst_idx: INTEGER; bytes: INTEGER); -BEGIN - WHILE bytes > 0 DO - dst[dst_idx] := src[src_idx]; - INC(dst_idx); - INC(src_idx); - DEC(bytes) - END -END copy; - - -PROCEDURE flush (file: FILE): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF file # NIL THEN - res := UTILS.FileWrite(file.ptr, file.buffer, file.count); - IF res < 0 THEN - res := 0 - END - ELSE - res := 0 - END - - RETURN res -END flush; - - -PROCEDURE NewFile (): FILE; -VAR - file: FILE; - citem: C.ITEM; - -BEGIN - citem := C.pop(files); - IF citem = NIL THEN - NEW(file) - ELSE - file := citem(FILE) - END - - RETURN file -END NewFile; - - -PROCEDURE create* (name: ARRAY OF CHAR): FILE; -VAR - file: FILE; - ptr: INTEGER; - -BEGIN - ptr := UTILS.FileCreate(name); - - IF ptr > 0 THEN - file := NewFile(); - file.ptr := ptr; - file.count := 0 - ELSE - file := NIL - END - - RETURN file -END create; - - -PROCEDURE open* (name: ARRAY OF CHAR): FILE; -VAR - file: FILE; - ptr: INTEGER; - -BEGIN - ptr := UTILS.FileOpen(name); - - IF ptr > 0 THEN - file := NewFile(); - file.ptr := ptr; - file.count := -1 - ELSE - file := NIL - END - - RETURN file -END open; - - -PROCEDURE close* (VAR file: FILE); -VAR - n: INTEGER; - -BEGIN - IF file # NIL THEN - - IF file.count > 0 THEN - n := flush(file) - END; - - file.count := -1; - - UTILS.FileClose(file.ptr); - file.ptr := 0; - - C.push(files, file); - file := NIL - END -END close; - - -PROCEDURE read* (file: FILE; VAR chunk: ARRAY OF CHAR; bytes: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF file # NIL THEN - res := UTILS.FileRead(file.ptr, chunk, MAX(MIN(bytes, LEN(chunk)), 0)); - IF res < 0 THEN - res := 0 - END - ELSE - res := 0 - END - - RETURN res -END read; - - -PROCEDURE write* (file: FILE; chunk: ARRAY OF BYTE; bytes: INTEGER): INTEGER; -VAR - free, n, idx: INTEGER; - -BEGIN - idx := 0; - IF (file # NIL) & (file.count >= 0) THEN - - free := LEN(file.buffer) - file.count; - WHILE bytes > 0 DO - n := MIN(free, bytes); - copy(chunk, idx, file.buffer, file.count, n); - DEC(free, n); - DEC(bytes, n); - INC(idx, n); - INC(file.count, n); - IF free = 0 THEN - IF flush(file) # LEN(file.buffer) THEN - bytes := 0; - DEC(idx, n) - ELSE - file.count := 0; - free := LEN(file.buffer) - END - END - END - - END - - RETURN idx -END write; - - -PROCEDURE WriteByte* (file: FILE; byte: BYTE): BOOLEAN; -VAR - arr: ARRAY 1 OF BYTE; - -BEGIN - arr[0] := byte - RETURN write(file, arr, 1) = 1 -END WriteByte; - - -BEGIN - files := C.create() -END FILES. \ No newline at end of file diff --git a/programs/develop/oberon07/source/HEX.ob07 b/programs/develop/oberon07/source/HEX.ob07 deleted file mode 100644 index f8d246951..000000000 --- a/programs/develop/oberon07/source/HEX.ob07 +++ /dev/null @@ -1,117 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE HEX; - -IMPORT WRITER, CHL := CHUNKLISTS, UTILS; - - -VAR - - chksum: INTEGER; - - -PROCEDURE Byte (byte: BYTE); -BEGIN - WRITER.WriteByte(UTILS.hexdgt(byte DIV 16)); - WRITER.WriteByte(UTILS.hexdgt(byte MOD 16)); - INC(chksum, byte) -END Byte; - - -PROCEDURE Byte4 (a, b, c, d: BYTE); -BEGIN - Byte(a); - Byte(b); - Byte(c); - Byte(d) -END Byte4; - - -PROCEDURE NewLine; -BEGIN - Byte((-chksum) MOD 256); - chksum := 0; - WRITER.WriteByte(0DH); - WRITER.WriteByte(0AH) -END NewLine; - - -PROCEDURE StartCode; -BEGIN - WRITER.WriteByte(ORD(":")); - chksum := 0 -END StartCode; - - -PROCEDURE Data* (mem: ARRAY OF BYTE; idx, cnt: INTEGER); -VAR - i, len: INTEGER; - -BEGIN - WHILE cnt > 0 DO - len := MIN(cnt, 16); - StartCode; - Byte4(len, idx DIV 256, idx MOD 256, 0); - FOR i := 1 TO len DO - Byte(mem[idx]); - INC(idx) - END; - DEC(cnt, len); - NewLine - END -END Data; - - -PROCEDURE ExtLA* (LA: INTEGER); -BEGIN - ASSERT((0 <= LA) & (LA <= 0FFFFH)); - StartCode; - Byte4(2, 0, 0, 4); - Byte(LA DIV 256); - Byte(LA MOD 256); - NewLine -END ExtLA; - - -PROCEDURE Data2* (mem: CHL.BYTELIST; idx, cnt, LA: INTEGER); -VAR - i, len, offset: INTEGER; - -BEGIN - ExtLA(LA); - offset := 0; - WHILE cnt > 0 DO - ASSERT(offset <= 65536); - IF offset = 65536 THEN - INC(LA); - ExtLA(LA); - offset := 0 - END; - len := MIN(cnt, 16); - StartCode; - Byte4(len, offset DIV 256, offset MOD 256, 0); - FOR i := 1 TO len DO - Byte(CHL.GetByte(mem, idx)); - INC(idx); - INC(offset) - END; - DEC(cnt, len); - NewLine - END -END Data2; - - -PROCEDURE End*; -BEGIN - StartCode; - Byte4(0, 0, 0, 1); - NewLine -END End; - - -END HEX. \ No newline at end of file diff --git a/programs/develop/oberon07/source/IL.ob07 b/programs/develop/oberon07/source/IL.ob07 deleted file mode 100644 index f07160c45..000000000 --- a/programs/develop/oberon07/source/IL.ob07 +++ /dev/null @@ -1,1201 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2023, Anton Krotov - All rights reserved. -*) - -MODULE IL; - -IMPORT LISTS, SCAN, STRINGS, CHL := CHUNKLISTS, C := COLLECTIONS, TARGETS, PATHS; - - -CONST - - call_stack* = 0; - call_win64* = 1; - call_sysv* = 2; - call_fast1* = 3; - call_fast2* = 4; - - begin_loop* = 1; end_loop* = 2; - - opJMP* = 0; opLABEL* = 1; opCOPYS* = 2; opGADR* = 3; opCONST* = 4; opLLOAD32* = 5; - opCOPYA* = 6; opCASET* = 7; opMULC* = 8; opMUL* = 9; opDIV* = 10; opMOD* = 11; - opDIVL* = 12; opMODL* = 13; opDIVR* = 14; opMODR* = 15; opUMINUS* = 16; - opADD* = 17; opSUB* = 18; opONERR* = 19; opSUBL* = 20; opADDC* = 21; opSUBR* = 22; - opSAVE* = 23; opSAVEC* = 24; opSAVE8* = 25; opSAVE8C* = 26; (*opCHKBYTE* = 27;*) opDROP* = 28; - opNOT* = 29; - - opEQ* = 30; opNE* = opEQ + 1; opLT* = opEQ + 2; opLE* = opEQ + 3; opGT* = opEQ + 4; opGE* = opEQ + 5 (* 35 *); - opEQC* = 36; opNEC* = opEQC + 1; opLTC* = opEQC + 2; opLEC* = opEQC + 3; opGTC* = opEQC + 4; opGEC* = opEQC + 5; (* 41 *) - opEQF* = 42; opNEF* = opEQF + 1; opLTF* = opEQF + 2; opLEF* = opEQF + 3; opGTF* = opEQF + 4; opGEF* = opEQF + 5; (* 47 *) - opEQS* = 48; opNES* = opEQS + 1; opLTS* = opEQS + 2; opLES* = opEQS + 3; opGTS* = opEQS + 4; opGES* = opEQS + 5; (* 53 *) - opEQSW* = 54; opNESW* = opEQSW + 1; opLTSW* = opEQSW + 2; opLESW* = opEQSW + 3; opGTSW* = opEQSW + 4; opGESW* = opEQSW + 5 (* 59 *); - - opVLOAD32* = 60; opGLOAD32* = 61; - - opJZ* = 62; opJNZ* = 63; - - opSAVE32* = 64; opLLOAD8* = 65; - - opCONSTF* = 66; opLOADF* = 67; opSAVEF* = 68; opMULF* = 69; opDIVF* = 70; opDIVFI* = 71; - opUMINF* = 72; opSAVEFI* = 73; opSUBFI* = 74; opADDF* = 75; opSUBF* = 76; - - opJNZ1* = 77; opJG* = 78; - opINCCB* = 79; opDECCB* = 80; opINCB* = 81; opDECB* = 82; - - opCASEL* = 83; opCASER* = 84; opCASELR* = 85; - - opPOPSP* = 86; - opWIN64CALL* = 87; opWIN64CALLI* = 88; opWIN64CALLP* = 89; opAND* = 90; opOR* = 91; - - opLOAD8* = 92; opLOAD16* = 93; opLOAD32* = 94; opPRECALL* = 95; opRES* = 96; opRESF* = 97; - opPUSHC* = 98; opSWITCH* = 99; - - opSBOOL* = 100; opSBOOLC* = 101; opNOP* = 102; - - opMULS* = 103; opMULSC* = 104; opDIVS* = 105; opDIVSC* = 106; - opADDS* = 107; opSUBS* = 108; opERR* = 109; opSUBSL* = 110; opADDSC* = 111; opSUBSR* = 112; - opUMINS* = 113; opIN* = 114; opINL* = 115; opINR* = 116; - opRSET* = 117; opRSETL* = 118; opRSETR* = 119; opRSET1* = 120; opLENGTH* = 121; - - opLEAVEC* = 122; opCODE* = 123; opALIGN16* = 124; - opINCC* = 125; opINC* = 126; opDEC* = 127; - opINCL* = 128; opEXCL* = 129; opINCLC* = 130; opEXCLC* = 131; opNEW* = 132; opDISP* = 133; - opPACK* = 134; opPACKC* = 135; opUNPK* = 136; opCOPY* = 137; opENTER* = 138; opLEAVE* = 139; - opCALL* = 140; opSAVEP* = 141; opCALLP* = 142; opEQP* = 143; opNEP* = 144; opLEAVER* = 145; - opGET* = 146; opSAVE16* = 147; opABS* = 148; opFABS* = 149; opFLOOR* = 150; opFLT* = 151; - opGETC* = 152; opORD* = 153; opASR* = 154; opLSL* = 155; opROR* = 156; - opASR1* = 157; opLSL1* = 158; opROR1* = 159; opASR2* = 160; opLSL2* = 161; opROR2* = 162; - opPUSHP* = 163; opLADR* = 164; opTYPEGP* = 165; opIS* = 166; opPUSHF* = 167; opVADR* = 168; - opPUSHT* = 169; opTYPEGR* = 170; opISREC* = 171; opCHKIDX* = 172; opPARAM* = 173; - opCHKIDX2* = 174; opLEN* = 175; opROT* = 176; opSAVES* = 177; opSADR* = 178; opLENGTHW* = 179; - - (*opCHR* = 180;*) opENDSW* = 181; opLEAVEF* = 182; opCLEANUP* = 183; opMOVE* = 184; - opLSR* = 185; opLSR1* = 186; opLSR2* = 187; - opMIN* = 188; opMINC* = 189; opMAX* = 190; opMAXC* = 191; opSYSVALIGN16* = 192; - opEQB* = 193; opNEB* = 194; opINF* = 195; opWIN64ALIGN16* = 196; opVLOAD8* = 197; opGLOAD8* = 198; - opLLOAD16* = 199; opVLOAD16* = 200; opGLOAD16* = 201; - opLOAD64* = 202; opLLOAD64* = 203; opVLOAD64* = 204; opGLOAD64* = 205; opSAVE64* = 206; - - opTYPEGD* = 207; opCALLI* = 208; opPUSHIP* = 209; opSAVEIP* = 210; opEQIP* = 211; opNEIP* = 212; - opSAVE16C* = 213; (*opWCHR* = 214;*) opHANDLER* = 215; - - opSYSVCALL* = 216; opSYSVCALLI* = 217; opSYSVCALLP* = 218; opFNAME* = 219; opFASTCALL* = 220; - - - opSADR_PARAM* = -1; opLOAD64_PARAM* = -2; opLLOAD64_PARAM* = -3; opGLOAD64_PARAM* = -4; - opVADR_PARAM* = -5; opCONST_PARAM* = -6; opGLOAD32_PARAM* = -7; opLLOAD32_PARAM* = -8; - opLOAD32_PARAM* = -9; - - opLADR_SAVEC* = -10; opGADR_SAVEC* = -11; opLADR_SAVE* = -12; - - opLADR_INCC* = -13; opLADR_INCCB* = -14; opLADR_DECCB* = -15; - opLADR_INC* = -16; opLADR_DEC* = -17; opLADR_INCB* = -18; opLADR_DECB* = -19; - opLADR_INCL* = -20; opLADR_EXCL* = -21; opLADR_INCLC* = -22; opLADR_EXCLC* = -23; - opLADR_UNPK* = -24; - - - _init *= 0; - _move *= 1; - _strcmpw *= 2; - _exit *= 3; - _set *= 4; - _set1 *= 5; - _lengthw *= 6; - _strcpy *= 7; - _length *= 8; - _divmod *= 9; - _dllentry *= 10; - _sofinit *= 11; - _arrcpy *= 12; - _rot *= 13; - _new *= 14; - _dispose *= 15; - _strcmp *= 16; - _error *= 17; - _is *= 18; - _isrec *= 19; - _guard *= 20; - _guardrec *= 21; - - _fmul *= 22; - _fdiv *= 23; - _fdivi *= 24; - _fadd *= 25; - _fsub *= 26; - _fsubi *= 27; - _fcmp *= 28; - _floor *= 29; - _flt *= 30; - _pack *= 31; - _unpk *= 32; - - -TYPE - - COMMAND* = POINTER TO RECORD (LISTS.ITEM) - - opcode*: INTEGER; - param1*: INTEGER; - param2*: INTEGER; - param3*: INTEGER; - float*: REAL - - END; - - FNAMECMD* = POINTER TO RECORD (COMMAND) - - fname*: PATHS.PATH - - END; - - CMDSTACK = POINTER TO RECORD - - data: ARRAY 1000 OF COMMAND; - top: INTEGER - - END; - - EXPORT_PROC* = POINTER TO RECORD (LISTS.ITEM) - - label*: INTEGER; - name*: SCAN.IDSTR - - END; - - IMPORT_LIB* = POINTER TO RECORD (LISTS.ITEM) - - name*: SCAN.TEXTSTR; - procs*: LISTS.LIST - - END; - - IMPORT_PROC* = POINTER TO RECORD (LISTS.ITEM) - - label*: INTEGER; - lib*: IMPORT_LIB; - name*: SCAN.TEXTSTR; - count: INTEGER - - END; - - - CODES = RECORD - - last: COMMAND; - begcall: CMDSTACK; - endcall: CMDSTACK; - commands*: LISTS.LIST; - export*: LISTS.LIST; - _import*: LISTS.LIST; - types*: CHL.INTLIST; - data*: CHL.BYTELIST; - dmin*: INTEGER; - lcount*: INTEGER; - bss*: INTEGER; - rtl*: ARRAY 33 OF INTEGER; - errlabels*: ARRAY 12 OF INTEGER; - - charoffs: ARRAY 256 OF INTEGER; - wcharoffs: ARRAY 65536 OF INTEGER; - - wstr: ARRAY 4*1024 OF WCHAR - END; - - -VAR - - codes*: CODES; - CPU: INTEGER; - - commands: C.COLLECTION; - - -PROCEDURE set_dmin* (value: INTEGER); -BEGIN - codes.dmin := value -END set_dmin; - - -PROCEDURE set_bss* (value: INTEGER); -BEGIN - codes.bss := value -END set_bss; - - -PROCEDURE set_rtl* (idx, label: INTEGER); -BEGIN - codes.rtl[idx] := label -END set_rtl; - - -PROCEDURE NewCmd (): COMMAND; -VAR - cmd: COMMAND; - citem: C.ITEM; - -BEGIN - citem := C.pop(commands); - IF citem = NIL THEN - NEW(cmd) - ELSE - cmd := citem(COMMAND) - END - - RETURN cmd -END NewCmd; - - -PROCEDURE setlast* (cmd: COMMAND); -BEGIN - codes.last := cmd -END setlast; - - -PROCEDURE getlast* (): COMMAND; - RETURN codes.last -END getlast; - - -PROCEDURE PutByte (b: BYTE); -BEGIN - CHL.PushByte(codes.data, b) -END PutByte; - - -PROCEDURE AlignData (n: INTEGER); -BEGIN - WHILE CHL.Length(codes.data) MOD n # 0 DO - PutByte(0) - END -END AlignData; - - -PROCEDURE putstr* (s: ARRAY OF CHAR): INTEGER; -VAR - i, n, res: INTEGER; -BEGIN - IF TARGETS.WinLin THEN - AlignData(16) - END; - res := CHL.Length(codes.data); - i := 0; - n := LENGTH(s); - WHILE i < n DO - PutByte(ORD(s[i])); - INC(i) - END; - - PutByte(0) - - RETURN res -END putstr; - - -PROCEDURE putstr1* (c: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF codes.charoffs[c] = -1 THEN - IF TARGETS.WinLin THEN - AlignData(16) - END; - res := CHL.Length(codes.data); - PutByte(c); - PutByte(0); - codes.charoffs[c] := res - ELSE - res := codes.charoffs[c] - END - - RETURN res -END putstr1; - - -PROCEDURE putstrW* (s: ARRAY OF CHAR): INTEGER; -VAR - i, n, res: INTEGER; - -BEGIN - IF TARGETS.WinLin THEN - AlignData(16) - ELSE - AlignData(2) - END; - res := CHL.Length(codes.data); - - n := STRINGS.Utf8To16(s, codes.wstr); - - i := 0; - WHILE i < n DO - IF TARGETS.LittleEndian THEN - PutByte(ORD(codes.wstr[i]) MOD 256); - PutByte(ORD(codes.wstr[i]) DIV 256) - ELSE - PutByte(ORD(codes.wstr[i]) DIV 256); - PutByte(ORD(codes.wstr[i]) MOD 256) - END; - INC(i) - END; - - PutByte(0); - PutByte(0) - - RETURN res -END putstrW; - - -PROCEDURE putstrW1* (c: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF codes.wcharoffs[c] = -1 THEN - IF TARGETS.WinLin THEN - AlignData(16) - ELSE - AlignData(2) - END; - res := CHL.Length(codes.data); - - IF TARGETS.LittleEndian THEN - PutByte(c MOD 256); - PutByte(c DIV 256) - ELSE - PutByte(c DIV 256); - PutByte(c MOD 256) - END; - - PutByte(0); - PutByte(0); - - codes.wcharoffs[c] := res - ELSE - res := codes.wcharoffs[c] - END - - RETURN res -END putstrW1; - - -PROCEDURE push (stk: CMDSTACK; cmd: COMMAND); -BEGIN - INC(stk.top); - stk.data[stk.top] := cmd -END push; - - -PROCEDURE pop (stk: CMDSTACK): COMMAND; -VAR - res: COMMAND; -BEGIN - res := stk.data[stk.top]; - DEC(stk.top) - RETURN res -END pop; - - -PROCEDURE pushBegEnd* (VAR beg, _end: COMMAND); -BEGIN - push(codes.begcall, beg); - push(codes.endcall, _end); - beg := codes.last; - _end := beg.next(COMMAND) -END pushBegEnd; - - -PROCEDURE popBegEnd* (VAR beg, _end: COMMAND); -BEGIN - beg := pop(codes.begcall); - _end := pop(codes.endcall) -END popBegEnd; - - -PROCEDURE AddRec* (base: INTEGER); -BEGIN - CHL.PushInt(codes.types, base) -END AddRec; - - -PROCEDURE insert (cur, nov: COMMAND); -VAR - old_opcode, param2: INTEGER; - - - PROCEDURE set (cur: COMMAND; opcode, param2: INTEGER); - BEGIN - cur.opcode := opcode; - cur.param1 := cur.param2; - cur.param2 := param2 - END set; - - -BEGIN - IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64, TARGETS.cpuMSP430} THEN - - old_opcode := cur.opcode; - param2 := nov.param2; - - IF (nov.opcode = opPARAM) & (param2 = 1) THEN - - CASE old_opcode OF - |opGLOAD64: cur.opcode := opGLOAD64_PARAM - |opLLOAD64: cur.opcode := opLLOAD64_PARAM - |opLOAD64: cur.opcode := opLOAD64_PARAM - |opGLOAD32: cur.opcode := opGLOAD32_PARAM - |opLLOAD32: cur.opcode := opLLOAD32_PARAM - |opLOAD32: cur.opcode := opLOAD32_PARAM - |opSADR: cur.opcode := opSADR_PARAM - |opVADR: cur.opcode := opVADR_PARAM - |opCONST: cur.opcode := opCONST_PARAM - ELSE - old_opcode := -1 - END - - ELSIF old_opcode = opLADR THEN - - CASE nov.opcode OF - |opSAVEC: set(cur, opLADR_SAVEC, param2) - |opSAVE: cur.opcode := opLADR_SAVE - |opINC: cur.opcode := opLADR_INC - |opDEC: cur.opcode := opLADR_DEC - |opINCB: cur.opcode := opLADR_INCB - |opDECB: cur.opcode := opLADR_DECB - |opINCL: cur.opcode := opLADR_INCL - |opEXCL: cur.opcode := opLADR_EXCL - |opUNPK: cur.opcode := opLADR_UNPK - |opINCC: set(cur, opLADR_INCC, param2) - |opINCCB: set(cur, opLADR_INCCB, param2) - |opDECCB: set(cur, opLADR_DECCB, param2) - |opINCLC: set(cur, opLADR_INCLC, param2) - |opEXCLC: set(cur, opLADR_EXCLC, param2) - ELSE - old_opcode := -1 - END - - ELSIF (nov.opcode = opSAVEC) & (old_opcode = opGADR) THEN - set(cur, opGADR_SAVEC, param2) - - ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN - cur.param2 := cur.param2 * param2 - - ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN - INC(cur.param2, param2) - - ELSE - old_opcode := -1 - END - - ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN - - old_opcode := cur.opcode; - param2 := nov.param2; - - IF (old_opcode = opLADR) & (nov.opcode = opSAVE) THEN - cur.opcode := opLADR_SAVE - ELSIF (old_opcode = opLADR) & (nov.opcode = opINCC) THEN - set(cur, opLADR_INCC, param2) - ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN - cur.param2 := cur.param2 * param2 - ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN - INC(cur.param2, param2) - ELSE - old_opcode := -1 - END - - ELSE - old_opcode := -1 - END; - - IF old_opcode = -1 THEN - LISTS.insert(codes.commands, cur, nov); - codes.last := nov - ELSE - C.push(commands, nov); - codes.last := cur - END -END insert; - - -PROCEDURE AddCmd* (opcode: INTEGER; param: INTEGER); -VAR - cmd: COMMAND; -BEGIN - cmd := NewCmd(); - cmd.opcode := opcode; - cmd.param1 := 0; - cmd.param2 := param; - insert(codes.last, cmd) -END AddCmd; - - -PROCEDURE AddCmd2* (opcode: INTEGER; param1, param2: INTEGER); -VAR - cmd: COMMAND; -BEGIN - cmd := NewCmd(); - cmd.opcode := opcode; - cmd.param1 := param1; - cmd.param2 := param2; - insert(codes.last, cmd) -END AddCmd2; - - -PROCEDURE Const* (val: INTEGER); -BEGIN - AddCmd(opCONST, val) -END Const; - - -PROCEDURE StrAdr* (adr: INTEGER); -BEGIN - AddCmd(opSADR, adr) -END StrAdr; - - -PROCEDURE Param1*; -BEGIN - AddCmd(opPARAM, 1) -END Param1; - - -PROCEDURE NewLabel* (): INTEGER; -BEGIN - INC(codes.lcount) - RETURN codes.lcount - 1 -END NewLabel; - - -PROCEDURE SetLabel* (label: INTEGER); -BEGIN - AddCmd2(opLABEL, label, 0) -END SetLabel; - - -PROCEDURE SetErrLabel* (errno: INTEGER); -BEGIN - codes.errlabels[errno] := NewLabel(); - SetLabel(codes.errlabels[errno]) -END SetErrLabel; - - -PROCEDURE AddCmd0* (opcode: INTEGER); -BEGIN - AddCmd(opcode, 0) -END AddCmd0; - - -PROCEDURE delete (cmd: COMMAND); -BEGIN - LISTS.delete(codes.commands, cmd); - C.push(commands, cmd) -END delete; - - -PROCEDURE delete2* (first, last: LISTS.ITEM); -VAR - cur, next: LISTS.ITEM; - -BEGIN - cur := first; - - IF first # last THEN - REPEAT - next := cur.next; - LISTS.delete(codes.commands, cur); - C.push(commands, cur); - cur := next - UNTIL cur = last - END; - - LISTS.delete(codes.commands, cur); - C.push(commands, cur) -END delete2; - - -PROCEDURE Jmp* (opcode: INTEGER; label: INTEGER); -VAR - prev: COMMAND; - not: BOOLEAN; - -BEGIN - prev := codes.last; - not := prev.opcode = opNOT; - IF not THEN - IF opcode = opJNZ THEN - opcode := opJZ - ELSIF opcode = opJZ THEN - opcode := opJNZ - ELSE - not := FALSE - END - END; - - AddCmd2(opcode, label, label); - - IF not THEN - delete(prev) - END -END Jmp; - - -PROCEDURE AndOrOpt* (VAR label: INTEGER); -VAR - cur, prev: COMMAND; - i, op, l: INTEGER; - jz, not: BOOLEAN; - -BEGIN - cur := codes.last; - not := cur.opcode = opNOT; - IF not THEN - cur := cur.prev(COMMAND) - END; - - IF cur.opcode = opAND THEN - op := opAND - ELSIF cur.opcode = opOR THEN - op := opOR - ELSE - op := -1 - END; - - cur := codes.last; - - IF op # -1 THEN - IF not THEN - IF op = opAND THEN - op := opOR - ELSE (* op = opOR *) - op := opAND - END; - prev := cur.prev(COMMAND); - delete(cur); - cur := prev - END; - - FOR i := 1 TO 9 DO - IF i = 8 THEN - l := cur.param1 - ELSIF i = 9 THEN - jz := cur.opcode = opJZ - END; - prev := cur.prev(COMMAND); - delete(cur); - cur := prev - END; - - setlast(cur); - - IF op = opAND THEN - label := l; - jz := ~jz - END; - - IF jz THEN - Jmp(opJZ, label) - ELSE - Jmp(opJNZ, label) - END; - - IF op = opOR THEN - SetLabel(l) - END - ELSE - Jmp(opJZ, label) - END; - - setlast(codes.last) -END AndOrOpt; - - -PROCEDURE OnError* (line, error: INTEGER); -BEGIN - AddCmd2(opONERR, codes.errlabels[error], line) -END OnError; - - -PROCEDURE TypeGuard* (op, t: INTEGER; line, error: INTEGER); -VAR - label: INTEGER; -BEGIN - AddCmd(op, t); - label := NewLabel(); - Jmp(opJNZ, label); - OnError(line, error); - SetLabel(label) -END TypeGuard; - - -PROCEDURE TypeCheck* (t: INTEGER); -BEGIN - AddCmd(opIS, t) -END TypeCheck; - - -PROCEDURE TypeCheckRec* (t: INTEGER); -BEGIN - AddCmd(opISREC, t) -END TypeCheckRec; - - -PROCEDURE New* (size, typenum: INTEGER); -BEGIN - AddCmd2(opNEW, typenum, size) -END New; - - -PROCEDURE not*; -VAR - prev: COMMAND; -BEGIN - prev := codes.last; - IF prev.opcode = opNOT THEN - codes.last := prev.prev(COMMAND); - delete(prev) - ELSE - AddCmd0(opNOT) - END -END not; - - -PROCEDURE _ord*; -BEGIN - IF (codes.last.opcode # opAND) & (codes.last.opcode # opOR) THEN - AddCmd0(opORD) - END -END _ord; - - -PROCEDURE Enter* (label, params: INTEGER): COMMAND; -VAR - cmd: COMMAND; - -BEGIN - cmd := NewCmd(); - cmd.opcode := opENTER; - cmd.param1 := label; - cmd.param3 := params; - insert(codes.last, cmd) - - RETURN codes.last -END Enter; - - -PROCEDURE Leave* (result, float: BOOLEAN; locsize, paramsize: INTEGER): COMMAND; -BEGIN - IF result THEN - IF float THEN - AddCmd2(opLEAVEF, locsize, paramsize) - ELSE - AddCmd2(opLEAVER, locsize, paramsize) - END - ELSE - AddCmd2(opLEAVE, locsize, paramsize) - END - - RETURN codes.last -END Leave; - - -PROCEDURE EnterC* (label: INTEGER): COMMAND; -BEGIN - SetLabel(label) - RETURN codes.last -END EnterC; - - -PROCEDURE LeaveC* (): COMMAND; -BEGIN - AddCmd0(opLEAVEC) - RETURN codes.last -END LeaveC; - - -PROCEDURE fastcall (VAR callconv: INTEGER); -BEGIN - IF callconv = call_fast1 THEN - AddCmd(opFASTCALL, 1); - callconv := call_stack - ELSIF callconv = call_fast2 THEN - AddCmd(opFASTCALL, 2); - callconv := call_stack - END -END fastcall; - - -PROCEDURE Call* (proc, callconv, fparams: INTEGER); -BEGIN - fastcall(callconv); - CASE callconv OF - |call_stack: Jmp(opCALL, proc) - |call_win64: Jmp(opWIN64CALL, proc) - |call_sysv: Jmp(opSYSVCALL, proc) - END; - codes.last(COMMAND).param2 := fparams -END Call; - - -PROCEDURE CallImp* (proc: LISTS.ITEM; callconv, fparams: INTEGER); -BEGIN - fastcall(callconv); - CASE callconv OF - |call_stack: Jmp(opCALLI, proc(IMPORT_PROC).label) - |call_win64: Jmp(opWIN64CALLI, proc(IMPORT_PROC).label) - |call_sysv: Jmp(opSYSVCALLI, proc(IMPORT_PROC).label) - END; - codes.last(COMMAND).param2 := fparams -END CallImp; - - -PROCEDURE CallP* (callconv, fparams: INTEGER); -BEGIN - fastcall(callconv); - CASE callconv OF - |call_stack: AddCmd0(opCALLP) - |call_win64: AddCmd(opWIN64CALLP, fparams) - |call_sysv: AddCmd(opSYSVCALLP, fparams) - END -END CallP; - - -PROCEDURE AssignProc* (proc: INTEGER); -BEGIN - Jmp(opSAVEP, proc) -END AssignProc; - - -PROCEDURE AssignImpProc* (proc: LISTS.ITEM); -BEGIN - Jmp(opSAVEIP, proc(IMPORT_PROC).label) -END AssignImpProc; - - -PROCEDURE PushProc* (proc: INTEGER); -BEGIN - Jmp(opPUSHP, proc) -END PushProc; - - -PROCEDURE PushImpProc* (proc: LISTS.ITEM); -BEGIN - Jmp(opPUSHIP, proc(IMPORT_PROC).label) -END PushImpProc; - - -PROCEDURE ProcCmp* (proc: INTEGER; eq: BOOLEAN); -BEGIN - IF eq THEN - Jmp(opEQP, proc) - ELSE - Jmp(opNEP, proc) - END -END ProcCmp; - - -PROCEDURE ProcImpCmp* (proc: LISTS.ITEM; eq: BOOLEAN); -BEGIN - IF eq THEN - Jmp(opEQIP, proc(IMPORT_PROC).label) - ELSE - Jmp(opNEIP, proc(IMPORT_PROC).label) - END -END ProcImpCmp; - - -PROCEDURE load* (size: INTEGER); -VAR - last: COMMAND; - -BEGIN - last := codes.last; - CASE size OF - |1: - IF last.opcode = opLADR THEN - last.opcode := opLLOAD8 - ELSIF last.opcode = opVADR THEN - last.opcode := opVLOAD8 - ELSIF last.opcode = opGADR THEN - last.opcode := opGLOAD8 - ELSE - AddCmd0(opLOAD8) - END - - |2: - IF last.opcode = opLADR THEN - last.opcode := opLLOAD16 - ELSIF last.opcode = opVADR THEN - last.opcode := opVLOAD16 - ELSIF last.opcode = opGADR THEN - last.opcode := opGLOAD16 - ELSE - AddCmd0(opLOAD16) - END - - |4: - IF last.opcode = opLADR THEN - last.opcode := opLLOAD32 - ELSIF last.opcode = opVADR THEN - last.opcode := opVLOAD32 - ELSIF last.opcode = opGADR THEN - last.opcode := opGLOAD32 - ELSE - AddCmd0(opLOAD32) - END - - |8: - IF last.opcode = opLADR THEN - last.opcode := opLLOAD64 - ELSIF last.opcode = opVADR THEN - last.opcode := opVLOAD64 - ELSIF last.opcode = opGADR THEN - last.opcode := opGLOAD64 - ELSE - AddCmd0(opLOAD64) - END - END -END load; - - -PROCEDURE SysPut* (size: INTEGER); -BEGIN - CASE size OF - |1: AddCmd0(opSAVE8) - |2: AddCmd0(opSAVE16) - |4: AddCmd0(opSAVE32) - |8: AddCmd0(opSAVE64) - END -END SysPut; - - -PROCEDURE savef* (inv: BOOLEAN); -BEGIN - IF inv THEN - AddCmd0(opSAVEFI) - ELSE - AddCmd0(opSAVEF) - END -END savef; - - -PROCEDURE saves* (offset, length: INTEGER); -BEGIN - AddCmd2(opSAVES, length, offset) -END saves; - - -PROCEDURE abs* (real: BOOLEAN); -BEGIN - IF real THEN - AddCmd0(opFABS) - ELSE - AddCmd0(opABS) - END -END abs; - - -PROCEDURE shift_minmax* (op: CHAR); -BEGIN - CASE op OF - |"A": AddCmd0(opASR) - |"L": AddCmd0(opLSL) - |"O": AddCmd0(opROR) - |"R": AddCmd0(opLSR) - |"m": AddCmd0(opMIN) - |"x": AddCmd0(opMAX) - END -END shift_minmax; - - -PROCEDURE shift_minmax1* (op: CHAR; x: INTEGER); -BEGIN - CASE op OF - |"A": AddCmd(opASR1, x) - |"L": AddCmd(opLSL1, x) - |"O": AddCmd(opROR1, x) - |"R": AddCmd(opLSR1, x) - |"m": AddCmd(opMINC, x) - |"x": AddCmd(opMAXC, x) - END -END shift_minmax1; - - -PROCEDURE shift_minmax2* (op: CHAR; x: INTEGER); -BEGIN - CASE op OF - |"A": AddCmd(opASR2, x) - |"L": AddCmd(opLSL2, x) - |"O": AddCmd(opROR2, x) - |"R": AddCmd(opLSR2, x) - |"m": AddCmd(opMINC, x) - |"x": AddCmd(opMAXC, x) - END -END shift_minmax2; - - -PROCEDURE len* (dim: INTEGER); -BEGIN - AddCmd(opLEN, dim) -END len; - - -PROCEDURE Float* (r: REAL; line, col: INTEGER); -VAR - cmd: COMMAND; - -BEGIN - cmd := NewCmd(); - cmd.opcode := opCONSTF; - cmd.float := r; - cmd.param1 := line; - cmd.param2 := col; - insert(codes.last, cmd) -END Float; - - -PROCEDURE drop*; -BEGIN - AddCmd0(opDROP) -END drop; - - -PROCEDURE _case* (a, b, L, R: INTEGER); -VAR - cmd: COMMAND; - -BEGIN - IF a = b THEN - cmd := NewCmd(); - cmd.opcode := opCASELR; - cmd.param1 := a; - cmd.param2 := L; - cmd.param3 := R; - insert(codes.last, cmd) - ELSE - AddCmd2(opCASEL, a, L); - AddCmd2(opCASER, b, R) - END -END _case; - - -PROCEDURE fname* (name: PATHS.PATH); -VAR - cmd: FNAMECMD; - -BEGIN - NEW(cmd); - cmd.opcode := opFNAME; - cmd.fname := name; - insert(codes.last, cmd) -END fname; - - -PROCEDURE AddExp* (label: INTEGER; name: SCAN.IDSTR); -VAR - exp: EXPORT_PROC; - -BEGIN - NEW(exp); - exp.label := label; - exp.name := name; - LISTS.push(codes.export, exp) -END AddExp; - - -PROCEDURE AddImp* (dll, proc: SCAN.TEXTSTR): IMPORT_PROC; -VAR - lib: IMPORT_LIB; - p: IMPORT_PROC; - -BEGIN - lib := codes._import.first(IMPORT_LIB); - WHILE (lib # NIL) & (lib.name # dll) DO - lib := lib.next(IMPORT_LIB) - END; - - IF lib = NIL THEN - NEW(lib); - lib.name := dll; - lib.procs := LISTS.create(NIL); - LISTS.push(codes._import, lib) - END; - - p := lib.procs.first(IMPORT_PROC); - WHILE (p # NIL) & (p.name # proc) DO - p := p.next(IMPORT_PROC) - END; - - IF p = NIL THEN - NEW(p); - p.name := proc; - p.label := NewLabel(); - p.lib := lib; - p.count := 1; - LISTS.push(lib.procs, p) - ELSE - INC(p.count) - END - - RETURN p -END AddImp; - - -PROCEDURE DelImport* (imp: LISTS.ITEM); -VAR - lib: IMPORT_LIB; - -BEGIN - DEC(imp(IMPORT_PROC).count); - IF imp(IMPORT_PROC).count = 0 THEN - lib := imp(IMPORT_PROC).lib; - LISTS.delete(lib.procs, imp); - IF lib.procs.first = NIL THEN - LISTS.delete(codes._import, lib) - END - END -END DelImport; - - -PROCEDURE init* (pCPU: INTEGER); -VAR - cmd: COMMAND; - i: INTEGER; - -BEGIN - commands := C.create(); - - CPU := pCPU; - - NEW(codes.begcall); - codes.begcall.top := -1; - NEW(codes.endcall); - codes.endcall.top := -1; - codes.commands := LISTS.create(NIL); - codes.export := LISTS.create(NIL); - codes._import := LISTS.create(NIL); - codes.types := CHL.CreateIntList(); - codes.data := CHL.CreateByteList(); - - NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd); - codes.last := cmd; - NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd); - - AddRec(0); - - codes.lcount := 0; - - FOR i := 0 TO LEN(codes.charoffs) - 1 DO - codes.charoffs[i] := -1 - END; - - FOR i := 0 TO LEN(codes.wcharoffs) - 1 DO - codes.wcharoffs[i] := -1 - END - -END init; - - -END IL. \ No newline at end of file diff --git a/programs/develop/oberon07/source/KOS.ob07 b/programs/develop/oberon07/source/KOS.ob07 deleted file mode 100644 index 979a8cfeb..000000000 --- a/programs/develop/oberon07/source/KOS.ob07 +++ /dev/null @@ -1,206 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE KOS; - -IMPORT BIN, WR := WRITER, LISTS, CHL := CHUNKLISTS; - - -CONST - - HEADER_SIZE = 36; - - SIZE_OF_DWORD = 4; - - -TYPE - - HEADER = RECORD - - menuet01: ARRAY 9 OF CHAR; - ver, start, size, mem, sp, param, path: INTEGER - - END; - - -PROCEDURE Import* (program: BIN.PROGRAM; idata: INTEGER; VAR ImportTable: CHL.INTLIST; VAR len, libcount, size: INTEGER); -VAR - i: INTEGER; - imp: BIN.IMPRT; - -BEGIN - libcount := 0; - imp := program.imp_list.first(BIN.IMPRT); - WHILE imp # NIL DO - IF imp.label = 0 THEN - INC(libcount) - END; - imp := imp.next(BIN.IMPRT) - END; - - len := libcount * 2 + 2; - size := (LISTS.count(program.imp_list) + len + 1) * SIZE_OF_DWORD; - - ImportTable := CHL.CreateIntList(); - FOR i := 0 TO size DIV SIZE_OF_DWORD - 1 DO - CHL.PushInt(ImportTable, 0) - END; - - i := 0; - imp := program.imp_list.first(BIN.IMPRT); - WHILE imp # NIL DO - - IF imp.label = 0 THEN - CHL.SetInt(ImportTable, len, 0); - INC(len); - CHL.SetInt(ImportTable, i, idata + len * SIZE_OF_DWORD); - INC(i); - CHL.SetInt(ImportTable, i, imp.nameoffs + size + idata); - INC(i) - ELSE - CHL.SetInt(ImportTable, len, imp.nameoffs + size + idata); - imp.label := len * SIZE_OF_DWORD; - INC(len) - END; - - imp := imp.next(BIN.IMPRT) - END; - CHL.SetInt(ImportTable, len, 0); - CHL.SetInt(ImportTable, i, 0); - CHL.SetInt(ImportTable, i + 1, 0); - INC(len); - INC(size, CHL.Length(program._import)) -END Import; - - -PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR); - -CONST - - PARAM_SIZE = 2048; - FileAlignment = 16; - - -VAR - header: HEADER; - - base, text, data, idata, bss, offset: INTEGER; - - reloc: BIN.RELOC; - iproc: BIN.IMPRT; - L: INTEGER; - delta: INTEGER; - - i: INTEGER; - - ImportTable: CHL.INTLIST; - ILen, libcount, isize: INTEGER; - - icount, dcount, ccount: INTEGER; - - code: CHL.BYTELIST; - -BEGIN - base := 0; - - icount := CHL.Length(program._import); - dcount := CHL.Length(program.data); - ccount := CHL.Length(program.code); - - text := base + HEADER_SIZE; - data := WR.align(text + ccount, FileAlignment); - idata := WR.align(data + dcount, FileAlignment); - - Import(program, idata, ImportTable, ILen, libcount, isize); - - bss := WR.align(idata + isize, FileAlignment); - - header.menuet01 := "MENUET01"; - header.ver := 1; - header.start := text; - header.size := idata + isize - base; - header.mem := WR.align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment); - header.sp := base + header.mem - PARAM_SIZE * 2; - header.param := header.sp; - header.path := header.param + PARAM_SIZE; - - code := program.code; - reloc := program.rel_list.first(BIN.RELOC); - WHILE reloc # NIL DO - - offset := reloc.offset; - L := BIN.get32le(code, offset); - delta := 3 - offset - text; - - CASE reloc.opcode OF - - |BIN.RIMP: - iproc := BIN.GetIProc(program, L); - delta := idata + iproc.label - - |BIN.RBSS: - delta := L + bss - - |BIN.RDATA: - delta := L + data - - |BIN.RCODE: - delta := BIN.GetLabel(program, L) + text - - |BIN.PICDATA: - INC(delta, L + data) - - |BIN.PICCODE: - INC(delta, BIN.GetLabel(program, L) + text) - - |BIN.PICBSS: - INC(delta, L + bss) - - |BIN.PICIMP: - iproc := BIN.GetIProc(program, L); - INC(delta, idata + iproc.label) - - |BIN.IMPTAB: - INC(delta, idata) - - END; - BIN.put32le(code, offset, delta); - - reloc := reloc.next(BIN.RELOC) - END; - - WR.Create(FileName); - - 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); - - CHL.WriteToFile(code); - WR.Padding(FileAlignment); - - CHL.WriteToFile(program.data); - WR.Padding(FileAlignment); - - FOR i := 0 TO ILen - 1 DO - WR.Write32LE(CHL.GetInt(ImportTable, i)) - END; - - CHL.WriteToFile(program._import); - - WR.Close -END write; - - -END KOS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/LISTS.ob07 b/programs/develop/oberon07/source/LISTS.ob07 deleted file mode 100644 index f57e3fd6f..000000000 --- a/programs/develop/oberon07/source/LISTS.ob07 +++ /dev/null @@ -1,199 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE LISTS; - -IMPORT C := COLLECTIONS; - - -TYPE - - ITEM* = POINTER TO RECORD (C.ITEM) - - prev*, next*: ITEM - - END; - - LIST* = POINTER TO RECORD - - first*, last*: ITEM - - END; - - -PROCEDURE push* (list: LIST; item: ITEM); -BEGIN - ASSERT(list # NIL); - ASSERT(item # NIL); - - IF list.first = NIL THEN - list.first := item; - item.prev := NIL - ELSE - ASSERT(list.last # NIL); - item.prev := list.last; - list.last.next := item - END; - list.last := item; - item.next := NIL -END push; - - -PROCEDURE pop* (list: LIST): ITEM; -VAR - last: ITEM; - -BEGIN - ASSERT(list # NIL); - - last := list.last; - - IF last # NIL THEN - IF last = list.first THEN - list.first := NIL; - list.last := NIL - ELSE - list.last := last.prev; - list.last.next := NIL - END; - - last.next := NIL; - last.prev := NIL - END - - RETURN last -END pop; - - -PROCEDURE insert* (list: LIST; cur, nov: ITEM); -VAR - next: ITEM; - -BEGIN - ASSERT(list # NIL); - ASSERT(nov # NIL); - ASSERT(cur # NIL); - - next := cur.next; - - IF next # NIL THEN - next.prev := nov; - nov.next := next; - cur.next := nov; - nov.prev := cur - ELSE - push(list, nov) - END - -END insert; - - -PROCEDURE insertL* (list: LIST; cur, nov: ITEM); -VAR - prev: ITEM; - -BEGIN - ASSERT(list # NIL); - ASSERT(nov # NIL); - ASSERT(cur # NIL); - - prev := cur.prev; - - IF prev # NIL THEN - prev.next := nov; - nov.prev := prev - ELSE - nov.prev := NIL; - list.first := nov - END; - cur.prev := nov; - nov.next := cur -END insertL; - - -PROCEDURE delete* (list: LIST; item: ITEM); -VAR - prev, next: ITEM; - -BEGIN - ASSERT(list # NIL); - ASSERT(item # NIL); - - prev := item.prev; - next := item.next; - - IF next # NIL THEN - IF prev # NIL THEN - prev.next := next; - next.prev := prev - ELSE - next.prev := NIL; - list.first := next - END - ELSE - IF prev # NIL THEN - prev.next := NIL; - list.last := prev - ELSE - list.first := NIL; - list.last := NIL - END - END -END delete; - - -PROCEDURE count* (list: LIST): INTEGER; -VAR - item: ITEM; - res: INTEGER; - -BEGIN - ASSERT(list # NIL); - res := 0; - - item := list.first; - WHILE item # NIL DO - INC(res); - item := item.next - END - - RETURN res -END count; - - -PROCEDURE getidx* (list: LIST; idx: INTEGER): ITEM; -VAR - item: ITEM; - -BEGIN - ASSERT(list # NIL); - ASSERT(idx >= 0); - - item := list.first; - WHILE (item # NIL) & (idx > 0) DO - item := item.next; - DEC(idx) - END - - RETURN item -END getidx; - - -PROCEDURE create* (list: LIST): LIST; -BEGIN - IF list = NIL THEN - NEW(list) - END; - - list.first := NIL; - list.last := NIL - - RETURN list -END create; - - -END LISTS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/MSCOFF.ob07 b/programs/develop/oberon07/source/MSCOFF.ob07 deleted file mode 100644 index d6b878b39..000000000 --- a/programs/develop/oberon07/source/MSCOFF.ob07 +++ /dev/null @@ -1,309 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE MSCOFF; - -IMPORT BIN, PE32, KOS, WR := WRITER, UTILS, ERRORS, LISTS, CHL := CHUNKLISTS; - - -CONST - - SIZE_OF_DWORD = 4; - - (* SectionHeader.Characteristics *) - - SHC_flat = 040500020H; - SHC_data = 0C0500040H; - SHC_bss = 0C03000C0H; - - -TYPE - - FH = PE32.IMAGE_FILE_HEADER; - - SH = PE32.IMAGE_SECTION_HEADER; - - -PROCEDURE WriteReloc (VirtualAddress, SymbolTableIndex, Type: INTEGER); -BEGIN - WR.Write32LE(VirtualAddress); - WR.Write32LE(SymbolTableIndex); - WR.Write16LE(Type) -END WriteReloc; - - -PROCEDURE Reloc (program: BIN.PROGRAM); -VAR - reloc: BIN.RELOC; - offset: INTEGER; - -BEGIN - reloc := program.rel_list.first(BIN.RELOC); - WHILE reloc # NIL DO - - offset := reloc.offset; - CASE reloc.opcode OF - |BIN.RIMP, - BIN.IMPTAB: WriteReloc(offset, 4, 6) - |BIN.RBSS: WriteReloc(offset, 5, 6) - |BIN.RDATA: WriteReloc(offset, 2, 6) - |BIN.RCODE: WriteReloc(offset, 1, 6) - END; - - reloc := reloc.next(BIN.RELOC) - END; -END Reloc; - - -PROCEDURE RelocCount (program: BIN.PROGRAM): INTEGER; -VAR - reloc: BIN.RELOC; - iproc: BIN.IMPRT; - res, L: INTEGER; - offset: INTEGER; - code: CHL.BYTELIST; - -BEGIN - res := 0; - code := program.code; - reloc := program.rel_list.first(BIN.RELOC); - WHILE reloc # NIL DO - - INC(res); - offset := reloc.offset; - - IF reloc.opcode = BIN.RIMP THEN - L := BIN.get32le(code, offset); - iproc := BIN.GetIProc(program, L); - BIN.put32le(code, offset, iproc.label) - END; - - IF reloc.opcode = BIN.RCODE THEN - L := BIN.get32le(code, offset); - BIN.put32le(code, offset, BIN.GetLabel(program, L)) - END; - - reloc := reloc.next(BIN.RELOC) - END - - RETURN res -END RelocCount; - - -PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; ver: INTEGER); -VAR - exp: BIN.EXPRT; - n, i: INTEGER; - - szversion: PE32.NAME; - - ImportTable: CHL.INTLIST; - ILen, LibCount, isize: INTEGER; - - ExpCount: INTEGER; - - icount, ecount, dcount, ccount: INTEGER; - - FileHeader: FH; - - flat, data, edata, idata, bss: SH; - - - PROCEDURE ICount (ImportTable: CHL.INTLIST; ILen: INTEGER): INTEGER; - VAR - i, res: INTEGER; - - BEGIN - res := 0; - - FOR i := 0 TO ILen - 1 DO - IF CHL.GetInt(ImportTable, i) # 0 THEN - INC(res) - END - END - - RETURN res - END ICount; - - - PROCEDURE SetNumberOfRelocations (VAR section: SH; NumberOfRelocations: INTEGER); - BEGIN - IF NumberOfRelocations >= 65536 THEN - ERRORS.Error(202) - END; - section.NumberOfRelocations := WCHR(NumberOfRelocations) - END SetNumberOfRelocations; - - -BEGIN - - szversion := "version"; - - ASSERT(LENGTH(szversion) = 7); - - KOS.Import(program, 0, ImportTable, ILen, LibCount, isize); - ExpCount := LISTS.count(program.exp_list); - - icount := CHL.Length(program._import); - dcount := CHL.Length(program.data); - ccount := CHL.Length(program.code); - ecount := CHL.Length(program.export); - - FileHeader.Machine := 014CX; - FileHeader.NumberOfSections := 5X; - FileHeader.TimeDateStamp := UTILS.UnixTime(); - (* FileHeader.PointerToSymbolTable := 0; *) - FileHeader.NumberOfSymbols := 6; - FileHeader.SizeOfOptionalHeader := 0X; - FileHeader.Characteristics := 0184X; - - flat.Name := ".flat"; - flat.VirtualSize := 0; - flat.VirtualAddress := 0; - flat.SizeOfRawData := ccount; - flat.PointerToRawData := ORD(FileHeader.NumberOfSections) * PE32.SIZE_OF_IMAGE_SECTION_HEADER + PE32.SIZE_OF_IMAGE_FILE_HEADER; - (* flat.PointerToRelocations := 0; *) - flat.PointerToLinenumbers := 0; - SetNumberOfRelocations(flat, RelocCount(program)); - flat.NumberOfLinenumbers := 0X; - flat.Characteristics := SHC_flat; - - data.Name := ".data"; - data.VirtualSize := 0; - data.VirtualAddress := 0; - data.SizeOfRawData := dcount; - data.PointerToRawData := flat.PointerToRawData + flat.SizeOfRawData; - data.PointerToRelocations := 0; - data.PointerToLinenumbers := 0; - data.NumberOfRelocations := 0X; - data.NumberOfLinenumbers := 0X; - data.Characteristics := SHC_data; - - edata.Name := ".edata"; - edata.VirtualSize := 0; - edata.VirtualAddress := 0; - edata.SizeOfRawData := ((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD + LENGTH(szversion) + 1 + ecount; - edata.PointerToRawData := data.PointerToRawData + data.SizeOfRawData; - (* edata.PointerToRelocations := 0; *) - edata.PointerToLinenumbers := 0; - SetNumberOfRelocations(edata, ExpCount * 2 + 1); - edata.NumberOfLinenumbers := 0X; - edata.Characteristics := SHC_data; - - idata.Name := ".idata"; - idata.VirtualSize := 0; - idata.VirtualAddress := 0; - idata.SizeOfRawData := isize; - idata.PointerToRawData := edata.PointerToRawData + edata.SizeOfRawData; - (* idata.PointerToRelocations := 0; *) - idata.PointerToLinenumbers := 0; - SetNumberOfRelocations(idata, ICount(ImportTable, ILen)); - idata.NumberOfLinenumbers := 0X; - idata.Characteristics := SHC_data; - - bss.Name := ".bss"; - bss.VirtualSize := 0; - bss.VirtualAddress := 0; - bss.SizeOfRawData := program.bss; - bss.PointerToRawData := 0; - bss.PointerToRelocations := 0; - bss.PointerToLinenumbers := 0; - bss.NumberOfRelocations := 0X; - bss.NumberOfLinenumbers := 0X; - bss.Characteristics := SHC_bss; - - flat.PointerToRelocations := idata.PointerToRawData + idata.SizeOfRawData; - edata.PointerToRelocations := flat.PointerToRelocations + ORD(flat.NumberOfRelocations) * 10; - idata.PointerToRelocations := edata.PointerToRelocations + ORD(edata.NumberOfRelocations) * 10; - - FileHeader.PointerToSymbolTable := idata.PointerToRelocations + ORD(idata.NumberOfRelocations) * 10; - - WR.Create(FileName); - - PE32.WriteFileHeader(FileHeader); - - PE32.WriteSectionHeader(flat); - PE32.WriteSectionHeader(data); - PE32.WriteSectionHeader(edata); - PE32.WriteSectionHeader(idata); - PE32.WriteSectionHeader(bss); - - CHL.WriteToFile(program.code); - CHL.WriteToFile(program.data); - - exp := program.exp_list.first(BIN.EXPRT); - WHILE exp # NIL DO - WR.Write32LE(exp.nameoffs + edata.SizeOfRawData - ecount); - WR.Write32LE(exp.label); - exp := exp.next(BIN.EXPRT) - END; - - WR.Write32LE(((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD); - WR.Write32LE(ver); - - WR.Write32LE(0); - - PE32.WriteName(szversion); - CHL.WriteToFile(program.export); - - FOR i := 0 TO ILen - 1 DO - WR.Write32LE(CHL.GetInt(ImportTable, i)) - END; - - CHL.WriteToFile(program._import); - - Reloc(program); - - n := 0; - exp := program.exp_list.first(BIN.EXPRT); - WHILE exp # NIL DO - WriteReloc(n, 3, 6); - INC(n, 4); - - WriteReloc(n, 1, 6); - INC(n, 4); - - exp := exp.next(BIN.EXPRT) - END; - - WriteReloc(n, 3, 6); - - FOR i := 0 TO LibCount * 2 - 1 DO - WriteReloc(i * SIZE_OF_DWORD, 4, 6) - END; - - FOR i := LibCount * 2 TO ILen - 1 DO - IF CHL.GetInt(ImportTable, i) # 0 THEN - WriteReloc(i * SIZE_OF_DWORD, 4, 6) - END - END; - - PE32.WriteName("EXPORTS"); - WriteReloc(0, 3, 2); - - PE32.WriteName(".flat"); - WriteReloc(0, 1, 3); - - PE32.WriteName(".data"); - WriteReloc(0, 2, 3); - - PE32.WriteName(".edata"); - WriteReloc(0, 3, 3); - - PE32.WriteName(".idata"); - WriteReloc(0, 4, 3); - - PE32.WriteName(".bss"); - WriteReloc(0, 5, 3); - - WR.Write32LE(4); - - WR.Close -END write; - - -END MSCOFF. \ No newline at end of file diff --git a/programs/develop/oberon07/source/MSP430.ob07 b/programs/develop/oberon07/source/MSP430.ob07 deleted file mode 100644 index acec51fe4..000000000 --- a/programs/develop/oberon07/source/MSP430.ob07 +++ /dev/null @@ -1,1771 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2022, Anton Krotov - All rights reserved. -*) - -MODULE MSP430; - -IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX, - UTILS, C := CONSOLE, PROG, RTL := MSP430RTL; - - -CONST - - chkSTK* = 6; - - minRAM* = 128; maxRAM* = 2048; - minROM* = 2048; maxROM* = 24576; - - StkReserve = RTL.StkReserve; - - IntVectorSize* = RTL.IntVectorSize; - - PC = 0; SP = 1; SR = 2; CG = 3; - - R4 = 4; R5 = 5; R6 = 6; R7 = 7; - - HP = RTL.HP; - - ACC = R4; - - opRRC = 1000H; opSWPB = 1080H; opRRA = 1100H; opSXT = 1180H; - opPUSH = 1200H; opCALL = 1280H; opRETI = 1300H; - - opMOV = 04000H; opADD = 05000H; opADDC = 06000H; opSUBC = 07000H; - opSUB = 08000H; opCMP = 09000H; opDADD = 0A000H; opBIT = 0B000H; - opBIC = 0C000H; opBIS = 0D000H; opXOR = 0E000H; opAND = 0F000H; - - opJNE = 2000H; opJEQ = 2400H; opJNC = 2800H; opJC = 2C00H; - opJN = 3000H; opJGE = 3400H; opJL = 3800H; opJMP = 3C00H; - - sREG = 0; sIDX = 16; sINDIR = 32; sINCR = 48; BW = 64; dIDX = 128; - - NOWORD = 10000H; - - RCODE = 0; RDATA = 1; RBSS = 2; - - je = 0; jne = je + 1; - jge = 2; jl = jge + 1; - jle = 4; jg = jle + 1; - jb = 6; - - -TYPE - - ANYCODE = POINTER TO RECORD (LISTS.ITEM) - - offset: INTEGER - - END; - - WORD = POINTER TO RECORD (ANYCODE) - - val: INTEGER - - END; - - LABEL = POINTER TO RECORD (ANYCODE) - - num: INTEGER - - END; - - JMP = POINTER TO RECORD (ANYCODE) - - cc, label: INTEGER; - short: BOOLEAN - - END; - - CALL = POINTER TO RECORD (ANYCODE) - - label: INTEGER - - END; - - COMMAND = IL.COMMAND; - - RELOC = POINTER TO RECORD (LISTS.ITEM) - - section: INTEGER; - WordPtr: WORD - - END; - - -VAR - - R: REG.REGS; - - CodeList: LISTS.LIST; - RelList: LISTS.LIST; - - mem: ARRAY 65536 OF BYTE; - - Labels: CHL.INTLIST; - - IV: ARRAY RTL.LenIV OF INTEGER; - - IdxWords: RECORD src, dst: INTEGER END; - - StkCnt, MaxStkCnt: INTEGER; - - -PROCEDURE CheckProcDataSize* (VarSize, RamSize: INTEGER): BOOLEAN; - RETURN (VarSize + 1) * 2 + StkReserve + RTL.VarSize < RamSize -END CheckProcDataSize; - - -PROCEDURE EmitLabel (L: INTEGER); -VAR - label: LABEL; - -BEGIN - NEW(label); - label.num := L; - LISTS.push(CodeList, label) -END EmitLabel; - - -PROCEDURE EmitWord (val: INTEGER); -VAR - word: WORD; - -BEGIN - IF val < 0 THEN - ASSERT(val >= -32768); - val := val MOD 65536 - ELSE - ASSERT(val <= 65535) - END; - NEW(word); - word.val := val; - LISTS.push(CodeList, word) -END EmitWord; - - -PROCEDURE EmitJmp (cc, label: INTEGER); -VAR - jmp: JMP; - -BEGIN - NEW(jmp); - jmp.cc := cc; - jmp.label := label; - jmp.short := FALSE; - LISTS.push(CodeList, jmp) -END EmitJmp; - - -PROCEDURE EmitCall (label: INTEGER); -VAR - call: CALL; - -BEGIN - NEW(call); - call.label := label; - LISTS.push(CodeList, call) -END EmitCall; - - -PROCEDURE IncStk; -BEGIN - INC(StkCnt); - MaxStkCnt := MAX(StkCnt, MaxStkCnt) -END IncStk; - - -PROCEDURE bw (b: BOOLEAN): INTEGER; - RETURN BW * ORD(b) -END bw; - - -PROCEDURE src_x (x, Rn: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF (x = 0) & ~(Rn IN {PC, SR, CG}) THEN - res := Rn * 256 + sINDIR - ELSE - IdxWords.src := x; - res := Rn * 256 + sIDX - END - - RETURN res -END src_x; - - -PROCEDURE dst_x (x, Rn: INTEGER): INTEGER; -BEGIN - IdxWords.dst := x - RETURN Rn + dIDX -END dst_x; - - -PROCEDURE indir (Rn: INTEGER): INTEGER; - RETURN Rn * 256 + sINDIR -END indir; - - -PROCEDURE incr (Rn: INTEGER): INTEGER; - RETURN Rn * 256 + sINCR -END incr; - - -PROCEDURE imm (x: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - CASE x OF - | 0: res := CG * 256 - | 1: res := CG * 256 + sIDX - | 2: res := indir(CG) - | 4: res := indir(SR) - | 8: res := incr(SR) - |-1: res := incr(CG) - ELSE - res := incr(PC); - IdxWords.src := x - END - - RETURN res -END imm; - - -PROCEDURE Op2 (op, src, dst: INTEGER); -BEGIN - ASSERT(BITS(op) - {6, 12..15} = {}); - ASSERT(BITS(src) - {4, 5, 8..11} = {}); - ASSERT(BITS(dst) - {0..3, 7} = {}); - - EmitWord(op + src + dst); - - IF IdxWords.src # NOWORD THEN - EmitWord(IdxWords.src); - IdxWords.src := NOWORD - END; - - IF IdxWords.dst # NOWORD THEN - EmitWord(IdxWords.dst); - IdxWords.dst := NOWORD - END -END Op2; - - -PROCEDURE Op1 (op, reg, As: INTEGER); -BEGIN - EmitWord(op + reg + As) -END Op1; - - -PROCEDURE MovRR (src, dst: INTEGER); -BEGIN - Op2(opMOV, src * 256, dst) -END MovRR; - - -PROCEDURE PushImm (imm: INTEGER); -BEGIN - imm := UTILS.Long(imm); - CASE imm OF - | 0: Op1(opPUSH, CG, sREG) - | 1: Op1(opPUSH, CG, sIDX) - | 2: Op1(opPUSH, CG, sINDIR) - |-1: Op1(opPUSH, CG, sINCR) - ELSE - Op1(opPUSH, PC, sINCR); - EmitWord(imm) - END; - IncStk -END PushImm; - - -PROCEDURE PutWord (word: INTEGER; VAR adr: INTEGER); -BEGIN - ASSERT(~ODD(adr)); - ASSERT((0 <= word) & (word <= 65535)); - mem[adr] := word MOD 256; - mem[adr + 1] := word DIV 256; - INC(adr, 2) -END PutWord; - - -PROCEDURE NewLabel (): INTEGER; -BEGIN - CHL.PushInt(Labels, 0) - RETURN IL.NewLabel() -END NewLabel; - - -PROCEDURE LabelOffs (n: INTEGER): INTEGER; - RETURN CHL.GetInt(Labels, n) -END LabelOffs; - - -PROCEDURE Fixup (CodeAdr, IntVectorSize: INTEGER): INTEGER; -VAR - cmd: ANYCODE; - adr: INTEGER; - offset: INTEGER; - diff: INTEGER; - cc: INTEGER; - shorted: BOOLEAN; - -BEGIN - REPEAT - shorted := FALSE; - offset := CodeAdr DIV 2; - - cmd := CodeList.first(ANYCODE); - WHILE cmd # NIL DO - cmd.offset := offset; - CASE cmd OF - |LABEL: CHL.SetInt(Labels, cmd.num, offset) - |JMP: INC(offset); - IF ~cmd.short THEN - INC(offset); - IF cmd.cc # opJMP THEN - INC(offset) - END - END - - |CALL: INC(offset, 2) - |WORD: INC(offset) - END; - cmd := cmd.next(ANYCODE) - END; - - cmd := CodeList.first(ANYCODE); - WHILE cmd # NIL DO - IF (cmd IS JMP) & ~cmd(JMP).short THEN - diff := LabelOffs(cmd(JMP).label) - cmd.offset - 1; - IF ABS(diff) <= 512 THEN - cmd(JMP).short := TRUE; - shorted := TRUE - END - END; - cmd := cmd.next(ANYCODE) - END - - UNTIL ~shorted; - - IF offset * 2 > 10000H - IntVectorSize THEN - ERRORS.Error(203) - END; - - adr := CodeAdr; - cmd := CodeList.first(ANYCODE); - WHILE cmd # NIL DO - CASE cmd OF - |LABEL: - - |JMP: IF ~cmd.short THEN - CASE cmd.cc OF - |opJNE: cc := opJEQ - |opJEQ: cc := opJNE - |opJNC: cc := opJC - |opJC: cc := opJNC - |opJGE: cc := opJL - |opJL: cc := opJGE - |opJMP: cc := opJMP - END; - - IF cc # opJMP THEN - PutWord(cc + 2, adr) (* jcc L *) - END; - - PutWord(4030H, adr); (* MOV @PC+, PC *) - PutWord(LabelOffs(cmd.label) * 2, adr) - (* L: *) - ELSE - diff := LabelOffs(cmd.label) - cmd.offset - 1; - ASSERT((-512 <= diff) & (diff <= 511)); - PutWord(cmd.cc + diff MOD 1024, adr) - END - - |CALL: PutWord(12B0H, adr); (* CALL @PC+ *) - PutWord(LabelOffs(cmd.label) * 2, adr) - - |WORD: PutWord(cmd.val, adr) - - END; - cmd := cmd.next(ANYCODE) - END - - RETURN adr - CodeAdr -END Fixup; - - -PROCEDURE Push (reg: INTEGER); -BEGIN - Op1(opPUSH, reg, sREG); - IncStk -END Push; - - -PROCEDURE Pop (reg: INTEGER); -BEGIN - Op2(opMOV, incr(SP), reg); - DEC(StkCnt) -END Pop; - - -PROCEDURE Test (reg: INTEGER); -BEGIN - Op2(opCMP, imm(0), reg) -END Test; - - -PROCEDURE Clear (reg: INTEGER); -BEGIN - Op2(opMOV, imm(0), reg) -END Clear; - - -PROCEDURE mov (dst, src: INTEGER); -BEGIN - MovRR(src, dst) -END mov; - - -PROCEDURE xchg (reg1, reg2: INTEGER); -BEGIN - Push(reg1); - mov(reg1, reg2); - Pop(reg2) -END xchg; - - -PROCEDURE Reloc (section: INTEGER); -VAR - reloc: RELOC; - -BEGIN - NEW(reloc); - reloc.section := section; - reloc.WordPtr := CodeList.last(WORD); - LISTS.push(RelList, reloc) -END Reloc; - - -PROCEDURE CallRTL (proc, params: INTEGER); -BEGIN - IncStk; - DEC(StkCnt); - EmitCall(RTL.rtl[proc].label); - RTL.Used(proc); - IF params > 0 THEN - Op2(opADD, imm(params * 2), SP); - DEC(StkCnt, params) - END -END CallRTL; - - -PROCEDURE UnOp (VAR reg: INTEGER); -BEGIN - REG.UnOp(R, reg) -END UnOp; - - -PROCEDURE BinOp (VAR reg1, reg2: INTEGER); -BEGIN - REG.BinOp(R, reg1, reg2) -END BinOp; - - -PROCEDURE GetRegA; -BEGIN - ASSERT(REG.GetReg(R, ACC)) -END GetRegA; - - -PROCEDURE drop; -BEGIN - REG.Drop(R) -END drop; - - -PROCEDURE GetAnyReg (): INTEGER; - RETURN REG.GetAnyReg(R) -END GetAnyReg; - - -PROCEDURE PushAll (NumberOfParameters: INTEGER); -BEGIN - REG.PushAll(R); - DEC(R.pushed, NumberOfParameters) -END PushAll; - - -PROCEDURE PushAll_1; -BEGIN - REG.PushAll_1(R) -END PushAll_1; - - -PROCEDURE cond (op: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - CASE op OF - |IL.opGT, IL.opGTC: res := jg - |IL.opGE, IL.opGEC: res := jge - |IL.opLT, IL.opLTC: res := jl - |IL.opLE, IL.opLEC: res := jle - |IL.opEQ, IL.opEQC: res := je - |IL.opNE, IL.opNEC: res := jne - END - - RETURN res -END cond; - - -PROCEDURE jcc (cc, label: INTEGER); -VAR - L: INTEGER; - -BEGIN - CASE cc OF - |jne: - EmitJmp(opJNE, label) - |je: - EmitJmp(opJEQ, label) - |jge: - EmitJmp(opJGE, label) - |jl: - EmitJmp(opJL, label) - |jle: - EmitJmp(opJL, label); - EmitJmp(opJEQ, label) - |jg: - L := NewLabel(); - EmitJmp(opJEQ, L); - EmitJmp(opJGE, label); - EmitLabel(L) - |jb: - EmitJmp(opJNC, label) - END -END jcc; - - -PROCEDURE setcc (cc, reg: INTEGER); -VAR - L: INTEGER; - -BEGIN - L := NewLabel(); - Op2(opMOV, imm(1), reg); - jcc(cc, L); - Clear(reg); - EmitLabel(L) -END setcc; - - -PROCEDURE Shift2 (op, reg, n: INTEGER); -VAR - reg2: INTEGER; - -BEGIN - IF n >= 8 THEN - CASE op OF - |IL.opASR2: Op1(opSWPB, reg, sREG); Op1(opSXT, reg, sREG) - |IL.opROR2: Op1(opSWPB, reg, sREG) - |IL.opLSL2: Op1(opSWPB, reg, sREG); Op2(opBIC, imm(255), reg) - |IL.opLSR2: Op2(opBIC, imm(255), reg); Op1(opSWPB, reg, sREG) - END; - DEC(n, 8) - END; - - IF (op = IL.opROR2) & (n > 0) THEN - reg2 := GetAnyReg(); - MovRR(reg, reg2) - ELSE - reg2 := -1 - END; - - WHILE n > 0 DO - CASE op OF - |IL.opASR2: Op1(opRRA, reg, sREG) - |IL.opROR2: Op1(opRRC, reg2, sREG); Op1(opRRC, reg, sREG) - |IL.opLSL2: Op2(opADD, reg * 256, reg) - |IL.opLSR2: Op2(opBIC, imm(1), SR); Op1(opRRC, reg, sREG) - END; - DEC(n) - END; - - IF reg2 # -1 THEN - drop - END - -END Shift2; - - -PROCEDURE Neg (reg: INTEGER); -BEGIN - Op2(opXOR, imm(-1), reg); - Op2(opADD, imm(1), reg) -END Neg; - - -PROCEDURE LocalOffset (offset: INTEGER): INTEGER; - RETURN (offset + StkCnt - ORD(offset > 0)) * 2 -END LocalOffset; - - -PROCEDURE LocalDst (offset: INTEGER): INTEGER; - RETURN dst_x(LocalOffset(offset), SP) -END LocalDst; - - -PROCEDURE LocalSrc (offset: INTEGER): INTEGER; - RETURN src_x(LocalOffset(offset), SP) -END LocalSrc; - - -PROCEDURE translate (chk_stk: BOOLEAN); -VAR - cmd, next: COMMAND; - - opcode, param1, param2, L, a, n, c1, c2: INTEGER; - - reg1, reg2: INTEGER; - - cc: INTEGER; - - word: WORD; - -BEGIN - cmd := IL.codes.commands.first(COMMAND); - - WHILE cmd # NIL DO - - param1 := cmd.param1; - param2 := cmd.param2; - - opcode := cmd.opcode; - - CASE opcode OF - |IL.opJMP: - EmitJmp(opJMP, param1) - - |IL.opCALL: - IncStk; - DEC(StkCnt); - EmitCall(param1) - - |IL.opCALLP: - IncStk; - DEC(StkCnt); - UnOp(reg1); - Op1(opCALL, reg1, sREG); - drop; - ASSERT(R.top = -1) - - |IL.opPRECALL: - PushAll(0) - - |IL.opLABEL: - EmitLabel(param1) - - |IL.opSADR_PARAM: - Op1(opPUSH, PC, sINCR); - IncStk; - EmitWord(param2); - Reloc(RDATA) - - |IL.opERR: - CallRTL(RTL._error, 2) - - |IL.opPUSHC: - PushImm(param2) - - |IL.opONERR: - DEC(StkCnt); - EmitWord(0C232H); (* BIC #8, SR; DINT *) - EmitWord(4303H); (* MOV R3, R3; NOP *) - PushImm(param2); - EmitJmp(opJMP, param1) - - |IL.opLEAVEC: - Pop(PC) - - |IL.opENTER: - ASSERT(R.top = -1); - EmitLabel(param1); - n := param2 MOD 65536; - param2 := param2 DIV 65536; - StkCnt := 0; - IF chk_stk THEN - L := NewLabel(); - Op2(opMOV, SP * 256, R4); - Op2(opSUB, HP * 256, R4); - Op2(opCMP, imm(StkReserve), R4); - word := CodeList.last(WORD); - jcc(jge, L); - DEC(StkCnt); - EmitWord(0C232H); (* BIC #8, SR; DINT *) - EmitWord(4303H); (* MOV R3, R3; NOP *) - PushImm(n); - EmitJmp(opJMP, cmd.param3); - EmitLabel(L) - END; - - IF param2 > 8 THEN - Op2(opMOV, imm(param2), R4); - L := NewLabel(); - EmitLabel(L); - Push(CG); - Op2(opSUB, imm(1), R4); - jcc(jne, L) - ELSE - FOR n := 1 TO param2 DO - Push(CG) - END - END; - StkCnt := param2; - MaxStkCnt := StkCnt - - |IL.opLEAVE, IL.opLEAVER: - ASSERT(param2 = 0); - IF opcode = IL.opLEAVER THEN - UnOp(reg1); - IF reg1 # ACC THEN - mov(ACC, reg1) - END; - drop - END; - ASSERT(R.top = -1); - ASSERT(StkCnt = param1); - IF chk_stk THEN - INC(word.val, MaxStkCnt * 2) - END; - IF param1 > 0 THEN - Op2(opADD, imm(param1 * 2), SP) - END; - Pop(PC) - - |IL.opRES: - ASSERT(R.top = -1); - GetRegA - - |IL.opCLEANUP: - IF param2 # 0 THEN - Op2(opADD, imm(param2 * 2), SP); - DEC(StkCnt, param2) - END - - |IL.opCONST: - next := cmd.next(COMMAND); - IF next.opcode = IL.opCONST THEN - c1 := param2; - c2 := next.param2; - next := next.next(COMMAND); - IF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN - Op2(opMOV + bw(next.opcode = IL.opSAVE8), imm(c1), dst_x(c2, SR)); - cmd := next - ELSE - Op2(opMOV, imm(param2), GetAnyReg()) - END - ELSIF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN - UnOp(reg1); - Op2(opMOV + bw(next.opcode = IL.opSAVE8), reg1 * 256, dst_x(param2, SR)); - drop; - cmd := next - ELSE - Op2(opMOV, imm(param2), GetAnyReg()) - END - - |IL.opSADR: - Op2(opMOV, incr(PC), GetAnyReg()); - EmitWord(param2); - Reloc(RDATA) - - |IL.opGADR: - Op2(opMOV, incr(PC), GetAnyReg()); - EmitWord(param2); - Reloc(RBSS) - - |IL.opLADR: - reg1 := GetAnyReg(); - n := LocalOffset(param2); - Op2(opMOV, SP * 256, reg1); - IF n # 0 THEN - Op2(opADD, imm(n), reg1) - END - - |IL.opLLOAD8: - Op2(opMOV + BW, LocalSrc(param2), GetAnyReg()) - - |IL.opLLOAD16, IL.opVADR: - Op2(opMOV, LocalSrc(param2), GetAnyReg()) - - |IL.opGLOAD8: - Op2(opMOV + BW, src_x(param2, SR), GetAnyReg()); - Reloc(RBSS) - - |IL.opGLOAD16: - Op2(opMOV, src_x(param2, SR), GetAnyReg()); - Reloc(RBSS) - - |IL.opLOAD8: - UnOp(reg1); - Op2(opMOV + BW, indir(reg1), reg1) - - |IL.opLOAD16: - UnOp(reg1); - Op2(opMOV, indir(reg1), reg1) - - |IL.opVLOAD8: - reg1 := GetAnyReg(); - Op2(opMOV, LocalSrc(param2), reg1); - Op2(opMOV + BW, indir(reg1), reg1) - - |IL.opVLOAD16: - reg1 := GetAnyReg(); - Op2(opMOV, LocalSrc(param2), reg1); - Op2(opMOV, indir(reg1), reg1) - - |IL.opSAVE, IL.opSAVE16: - BinOp(reg2, reg1); - Op2(opMOV, reg2 * 256, dst_x(0, reg1)); - drop; - drop - - |IL.opSAVE8: - BinOp(reg2, reg1); - Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1)); - drop; - drop - - |IL.opSAVE8C: - UnOp(reg1); - Op2(opMOV + BW, imm(param2), dst_x(0, reg1)); - drop - - |IL.opSAVE16C, IL.opSAVEC: - UnOp(reg1); - Op2(opMOV, imm(param2), dst_x(0, reg1)); - drop - - |IL.opUMINUS: - UnOp(reg1); - Neg(reg1) - - |IL.opADD: - BinOp(reg1, reg2); - Op2(opADD, reg2 * 256, reg1); - drop - - |IL.opADDC: - IF param2 # 0 THEN - UnOp(reg1); - Op2(opADD, imm(param2), reg1) - END - - |IL.opSUB: - BinOp(reg1, reg2); - Op2(opSUB, reg2 * 256, reg1); - drop - - |IL.opSUBR, IL.opSUBL: - UnOp(reg1); - IF param2 # 0 THEN - Op2(opSUB, imm(param2), reg1) - END; - IF opcode = IL.opSUBL THEN - Neg(reg1) - END - - |IL.opLADR_SAVEC: - Op2(opMOV, imm(param2), LocalDst(param1)) - - |IL.opLADR_SAVE: - UnOp(reg1); - Op2(opMOV, reg1 * 256, LocalDst(param2)); - drop - - |IL.opGADR_SAVEC: - Op2(opMOV, imm(param2), dst_x(param1, SR)); - Reloc(RBSS) - - |IL.opCONST_PARAM: - PushImm(param2) - - |IL.opPARAM: - IF param2 = 1 THEN - UnOp(reg1); - Push(reg1); - drop - ELSE - ASSERT(R.top + 1 <= param2); - PushAll(param2) - END - - |IL.opEQ..IL.opGE, - IL.opEQC..IL.opGEC: - - IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN - BinOp(reg1, reg2); - Op2(opCMP, reg2 * 256, reg1); - drop - ELSE - UnOp(reg1); - Op2(opCMP, imm(param2), reg1) - END; - - drop; - cc := cond(opcode); - next := cmd.next(COMMAND); - - IF next.opcode = IL.opJNZ THEN - jcc(cc, next.param1); - cmd := next - ELSIF next.opcode = IL.opJZ THEN - jcc(ORD(BITS(cc) / {0}), next.param1); - cmd := next - ELSE - setcc(cc, GetAnyReg()) - END - - |IL.opNOP, IL.opAND, IL.opOR: - - |IL.opCODE: - EmitWord(param2) - - |IL.opDROP: - UnOp(reg1); - drop - - |IL.opJNZ1: - UnOp(reg1); - Test(reg1); - jcc(jne, param1) - - |IL.opJG: - UnOp(reg1); - Test(reg1); - jcc(jg, param1) - - |IL.opJNZ: - UnOp(reg1); - Test(reg1); - jcc(jne, param1); - drop - - |IL.opJZ: - UnOp(reg1); - Test(reg1); - jcc(je, param1); - drop - - |IL.opNOT: - UnOp(reg1); - Test(reg1); - setcc(je, reg1) - - |IL.opORD: - UnOp(reg1); - Test(reg1); - setcc(jne, reg1) - - |IL.opGET: - BinOp(reg1, reg2); - drop; - drop; - Op2(opMOV + bw(param2 = 1), indir(reg1), dst_x(0, reg2)) - - |IL.opGETC: - UnOp(reg2); - drop; - Op2(opMOV + bw(param2 = 1), src_x(param1, SR), dst_x(0, reg2)) - - |IL.opCHKIDX: - UnOp(reg1); - Op2(opCMP, imm(param2), reg1); - jcc(jb, param1) - - |IL.opCHKIDX2: - BinOp(reg1, reg2); - IF param2 # -1 THEN - Op2(opCMP, reg1 * 256, reg2); - jcc(jb, param1) - END; - INCL(R.regs, reg1); - DEC(R.top); - R.stk[R.top] := reg2 - - |IL.opINCC, IL.opINCCB: - UnOp(reg1); - Op2(opADD + bw(opcode = IL.opINCCB), imm(param2), dst_x(0, reg1)); - drop - - |IL.opDECCB: - UnOp(reg1); - Op2(opSUB + BW, imm(param2), dst_x(0, reg1)); - drop - - |IL.opINC, IL.opINCB: - BinOp(reg1, reg2); - Op2(opADD + bw(opcode = IL.opINCB), reg1 * 256, dst_x(0, reg2)); - drop; - drop - - |IL.opDEC, IL.opDECB: - BinOp(reg1, reg2); - Op2(opSUB + bw(opcode = IL.opDECB), reg1 * 256, dst_x(0, reg2)); - drop; - drop - - |IL.opLADR_INCC, IL.opLADR_INCCB: - Op2(opADD + bw(opcode = IL.opLADR_INCCB), imm(param2), LocalDst(param1)) - - |IL.opLADR_DECCB: - Op2(opSUB + BW, imm(param2), LocalDst(param1)) - - |IL.opLADR_INC, IL.opLADR_INCB: - UnOp(reg1); - Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, LocalDst(param2)); - drop - - |IL.opLADR_DEC, IL.opLADR_DECB: - UnOp(reg1); - Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, LocalDst(param2)); - drop - - |IL.opPUSHT: - UnOp(reg1); - Op2(opMOV, src_x(-2, reg1), GetAnyReg()) - - |IL.opISREC: - PushAll(2); - PushImm(param2); - CallRTL(RTL._guardrec, 3); - GetRegA - - |IL.opIS: - PushAll(1); - PushImm(param2); - CallRTL(RTL._is, 2); - GetRegA - - |IL.opTYPEGR: - PushAll(1); - PushImm(param2); - CallRTL(RTL._guardrec, 2); - GetRegA - - |IL.opTYPEGP: - UnOp(reg1); - PushAll(0); - Push(reg1); - PushImm(param2); - CallRTL(RTL._guard, 2); - GetRegA - - |IL.opTYPEGD: - UnOp(reg1); - PushAll(0); - Op1(opPUSH, reg1, sIDX); - IncStk; - EmitWord(-2); - PushImm(param2); - CallRTL(RTL._guardrec, 2); - GetRegA - - |IL.opMULS: - BinOp(reg1, reg2); - Op2(opAND, reg2 * 256, reg1); - drop - - |IL.opMULSC: - UnOp(reg1); - Op2(opAND, imm(param2), reg1) - - |IL.opDIVS: - BinOp(reg1, reg2); - Op2(opXOR, reg2 * 256, reg1); - drop - - |IL.opDIVSC: - UnOp(reg1); - Op2(opXOR, imm(param2), reg1) - - |IL.opADDS: - BinOp(reg1, reg2); - Op2(opBIS, reg2 * 256, reg1); - drop - - |IL.opSUBS: - BinOp(reg1, reg2); - Op2(opBIC, reg2 * 256, reg1); - drop - - |IL.opADDSC: - UnOp(reg1); - Op2(opBIS, imm(param2), reg1) - - |IL.opSUBSL: - UnOp(reg1); - Op2(opXOR, imm(-1), reg1); - Op2(opAND, imm(param2), reg1) - - |IL.opSUBSR: - UnOp(reg1); - Op2(opBIC, imm(param2), reg1) - - |IL.opUMINS: - UnOp(reg1); - Op2(opXOR, imm(-1), reg1) - - |IL.opLENGTH: - PushAll(2); - CallRTL(RTL._length, 2); - GetRegA - - |IL.opMAX,IL.opMIN: - BinOp(reg1, reg2); - Op2(opCMP, reg2 * 256, reg1); - IF opcode = IL.opMIN THEN - cc := opJL + 1 - ELSE - cc := opJGE + 1 - END; - EmitWord(cc); (* jge/jl L *) - MovRR(reg2, reg1); - (* L: *) - drop - - |IL.opMAXC, IL.opMINC: - UnOp(reg1); - Op2(opCMP, imm(param2), reg1); - L := NewLabel(); - IF opcode = IL.opMINC THEN - cc := jl - ELSE - cc := jge - END; - jcc(cc, L); - Op2(opMOV, imm(param2), reg1); - EmitLabel(L) - - |IL.opSWITCH: - UnOp(reg1); - IF param2 = 0 THEN - reg2 := ACC - ELSE - reg2 := R5 - END; - IF reg1 # reg2 THEN - ASSERT(REG.GetReg(R, reg2)); - ASSERT(REG.Exchange(R, reg1, reg2)); - drop - END; - drop - - |IL.opENDSW: - - |IL.opCASEL: - Op2(opCMP, imm(param1), ACC); - jcc(jl, param2) - - |IL.opCASER: - Op2(opCMP, imm(param1), ACC); - jcc(jg, param2) - - |IL.opCASELR: - Op2(opCMP, imm(param1), ACC); - IF param2 = cmd.param3 THEN - jcc(jne, param2) - ELSE - jcc(jl, param2); - jcc(jg, cmd.param3) - END - - |IL.opSBOOL: - BinOp(reg2, reg1); - Test(reg2); - setcc(jne, reg2); - Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1)); - drop; - drop - - |IL.opSBOOLC: - UnOp(reg1); - Op2(opMOV + BW, imm(param2), dst_x(0, reg1)); - drop - - |IL.opEQS .. IL.opGES: - PushAll(4); - PushImm((opcode - IL.opEQS) * 12); - CallRTL(RTL._strcmp, 5); - GetRegA - - |IL.opLEN: - UnOp(reg1); - drop; - EXCL(R.regs, reg1); - - WHILE param2 > 0 DO - UnOp(reg2); - drop; - DEC(param2) - END; - - INCL(R.regs, reg1); - ASSERT(REG.GetReg(R, reg1)) - - |IL.opLSL, IL.opASR, IL.opROR, IL.opLSR: - PushAll(2); - CASE opcode OF - |IL.opLSL: CallRTL(RTL._lsl, 2) - |IL.opASR: CallRTL(RTL._asr, 2) - |IL.opROR: CallRTL(RTL._ror, 2) - |IL.opLSR: CallRTL(RTL._lsr, 2) - END; - GetRegA - - |IL.opLSL1, IL.opASR1, IL.opROR1, IL.opLSR1: - UnOp(reg1); - PushAll_1; - PushImm(param2); - Push(reg1); - drop; - CASE opcode OF - |IL.opLSL1: CallRTL(RTL._lsl, 2) - |IL.opASR1: CallRTL(RTL._asr, 2) - |IL.opROR1: CallRTL(RTL._ror, 2) - |IL.opLSR1: CallRTL(RTL._lsr, 2) - END; - GetRegA - - |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: - param2 := param2 MOD 16; - IF param2 # 0 THEN - UnOp(reg1); - Shift2(opcode, reg1, param2) - END - - |IL.opMUL: - PushAll(2); - CallRTL(RTL._mul, 2); - GetRegA - - |IL.opMULC: - UnOp(reg1); - - a := param2; - IF a > 1 THEN - n := UTILS.Log2(a) - ELSIF a < -1 THEN - n := UTILS.Log2(-a) - ELSE - n := -1 - END; - - IF a = 1 THEN - - ELSIF a = -1 THEN - Neg(reg1) - ELSIF a = 0 THEN - Clear(reg1) - ELSE - IF n > 0 THEN - IF a < 0 THEN - Neg(reg1) - END; - Shift2(IL.opLSL2, reg1, n) - ELSE - PushAll(1); - PushImm(a); - CallRTL(RTL._mul, 2); - GetRegA - END - END - - |IL.opDIV: - PushAll(2); - CallRTL(RTL._divmod, 2); - GetRegA - - |IL.opDIVR: - ASSERT(param2 > 0); - - IF param2 > 1 THEN - n := UTILS.Log2(param2); - IF n > 0 THEN - UnOp(reg1); - Shift2(IL.opASR2, reg1, n) - ELSE - PushAll(1); - PushImm(param2); - CallRTL(RTL._divmod, 2); - GetRegA - END - END - - |IL.opDIVL: - UnOp(reg1); - PushAll_1; - PushImm(param2); - Push(reg1); - drop; - CallRTL(RTL._divmod, 2); - GetRegA - - |IL.opMOD: - PushAll(2); - CallRTL(RTL._divmod, 2); - ASSERT(REG.GetReg(R, R5)) - - |IL.opMODR: - ASSERT(param2 > 0); - - IF param2 = 1 THEN - UnOp(reg1); - Clear(reg1) - ELSE - IF UTILS.Log2(param2) > 0 THEN - UnOp(reg1); - Op2(opAND, imm(param2 - 1), reg1) - ELSE - PushAll(1); - PushImm(param2); - CallRTL(RTL._divmod, 2); - ASSERT(REG.GetReg(R, R5)) - END - END - - |IL.opMODL: - UnOp(reg1); - PushAll_1; - PushImm(param2); - Push(reg1); - drop; - CallRTL(RTL._divmod, 2); - ASSERT(REG.GetReg(R, R5)) - - |IL.opCOPYS: - ASSERT(R.top = 3); - Push(R.stk[2]); - Push(R.stk[0]); - Op2(opCMP, R.stk[1] * 256, R.stk[3]); - EmitWord(3801H); (* JL L1 *) - MovRR(R.stk[1], R.stk[3]); - (* L1: *) - Push(R.stk[3]); - drop; - drop; - drop; - drop; - CallRTL(RTL._move, 3) - - |IL.opCOPY: - PushAll(2); - PushImm(param2); - CallRTL(RTL._move, 3) - - |IL.opMOVE: - PushAll(3); - CallRTL(RTL._move, 3) - - |IL.opCOPYA: - PushAll(4); - PushImm(param2); - CallRTL(RTL._arrcpy, 5); - GetRegA - - |IL.opROT: - PushAll(0); - MovRR(SP, ACC); - Push(ACC); - PushImm(param2); - CallRTL(RTL._rot, 2) - - |IL.opSAVES: - UnOp(reg1); - PushAll_1; - Op1(opPUSH, PC, sINCR); - IncStk; - EmitWord(param2); - Reloc(RDATA); - Push(reg1); - drop; - PushImm(param1); - CallRTL(RTL._move, 3) - - |IL.opCASET: - Push(R5); - Push(R5); - PushImm(param2); - CallRTL(RTL._guardrec, 2); - Pop(R5); - Test(ACC); - jcc(jne, param1) - - |IL.opABS: - UnOp(reg1); - Test(reg1); - L := NewLabel(); - jcc(jge, L); - Neg(reg1); - EmitLabel(L) - - |IL.opEQB, IL.opNEB: - BinOp(reg1, reg2); - drop; - - Test(reg1); - L := NewLabel(); - jcc(je, L); - Op2(opMOV, imm(1), reg1); - EmitLabel(L); - - Test(reg2); - L := NewLabel(); - jcc(je, L); - Op2(opMOV, imm(1), reg2); - EmitLabel(L); - - Op2(opCMP, reg2 * 256, reg1); - IF opcode = IL.opEQB THEN - setcc(je, reg1) - ELSE - setcc(jne, reg1) - END - - |IL.opSAVEP: - UnOp(reg1); - Op2(opMOV, incr(PC), reg1 + dIDX); - EmitWord(param2); - Reloc(RCODE); - EmitWord(0); - drop - - |IL.opPUSHP: - Op2(opMOV, incr(PC), GetAnyReg()); - EmitWord(param2); - Reloc(RCODE) - - |IL.opEQP, IL.opNEP: - UnOp(reg1); - Op2(opCMP, incr(PC), reg1); - EmitWord(param1); - Reloc(RCODE); - drop; - reg1 := GetAnyReg(); - - IF opcode = IL.opEQP THEN - setcc(je, reg1) - ELSIF opcode = IL.opNEP THEN - setcc(jne, reg1) - END - - |IL.opVADR_PARAM: - reg1 := GetAnyReg(); - Op2(opMOV, LocalSrc(param2), reg1); - Push(reg1); - drop - - |IL.opNEW: - PushAll(1); - n := param2 + 2; - ASSERT(UTILS.Align(n, 2)); - PushImm(n); - PushImm(param1); - CallRTL(RTL._new, 3) - - |IL.opRSET: - PushAll(2); - CallRTL(RTL._set, 2); - GetRegA - - |IL.opRSETR: - PushAll(1); - PushImm(param2); - CallRTL(RTL._set, 2); - GetRegA - - |IL.opRSETL: - UnOp(reg1); - PushAll_1; - PushImm(param2); - Push(reg1); - drop; - CallRTL(RTL._set, 2); - GetRegA - - |IL.opRSET1: - PushAll(1); - CallRTL(RTL._set1, 1); - GetRegA - - |IL.opINCLC: - UnOp(reg1); - Op2(opBIS, imm(ORD({param2})), dst_x(0, reg1)); - drop - - |IL.opEXCLC: - UnOp(reg1); - Op2(opBIC, imm(ORD({param2})), dst_x(0, reg1)); - drop - - |IL.opIN: - PushAll(2); - CallRTL(RTL._in, 2); - GetRegA - - |IL.opINR: - PushAll(1); - PushImm(param2); - CallRTL(RTL._in, 2); - GetRegA - - |IL.opINL: - PushAll(1); - PushImm(param2); - CallRTL(RTL._in2, 2); - GetRegA - - |IL.opINCL: - PushAll(2); - CallRTL(RTL._incl, 2) - - |IL.opEXCL: - PushAll(2); - CallRTL(RTL._excl, 2) - - |IL.opLADR_INCL, IL.opLADR_EXCL: - PushAll(1); - MovRR(SP, ACC); - n := LocalOffset(param2); - IF n # 0 THEN - Op2(opADD, imm(n), ACC) - END; - Push(ACC); - IF opcode = IL.opLADR_INCL THEN - CallRTL(RTL._incl, 2) - ELSIF opcode = IL.opLADR_EXCL THEN - CallRTL(RTL._excl, 2) - END - - |IL.opLADR_INCLC: - Op2(opBIS, imm(ORD({param2})), LocalDst(param1)) - - |IL.opLADR_EXCLC: - Op2(opBIC, imm(ORD({param2})), LocalDst(param1)) - - END; - - cmd := cmd.next(COMMAND) - END; - - ASSERT(R.pushed = 0); - ASSERT(R.top = -1) -END translate; - - -PROCEDURE prolog; -VAR - i: INTEGER; - -BEGIN - RTL.Init(EmitLabel, EmitWord, EmitCall); - FOR i := 0 TO LEN(RTL.rtl) - 1 DO - RTL.Set(i, NewLabel()) - END; - - IV[LEN(IV) - 1] := NewLabel(); - EmitLabel(IV[LEN(IV) - 1]); - Op2(opMOV, incr(PC), SP); - EmitWord(0); - Op2(opMOV, incr(PC), HP); - EmitWord(0); - Op2(opMOV, imm(5A80H), dst_x(0120H, SR)); (* stop WDT *) - Op2(opMOV, imm(RTL.empty_proc), dst_x(0, SP)); - Op2(opMOV, imm(RTL.empty_proc), dst_x(2, SP)); -END prolog; - - -PROCEDURE epilog; -VAR - L1, i, n: INTEGER; - -BEGIN - Op2(opBIS, imm(10H), SR); (* CPUOFF *) - - L1 := NewLabel(); - FOR i := 0 TO LEN(IV) - 2 DO - IV[i] := NewLabel(); - EmitLabel(IV[i]); - PushImm(i); - IF i # LEN(IV) - 2 THEN - EmitJmp(opJMP, L1) - END - END; - - EmitLabel(L1); - - n := 0; - FOR i := 0 TO 15 DO - IF i IN R.regs THEN - Push(i); - INC(n) - END - END; - - MovRR(SP, R4); - Op2(opADD, imm(n * 2), R4); - - Push(R4); - Op1(opPUSH, R4, sINDIR); - Op1(opCALL, SR, sIDX); EmitWord(-RTL.VarSize); Reloc(RBSS); (* call int *) - Op2(opADD, imm(4), SP); - - FOR i := 15 TO 0 BY -1 DO - IF i IN R.regs THEN - Pop(i) - END - END; - - Op2(opADD, imm(2), SP); - Op1(opRETI, 0, 0); - - RTL.Gen -END epilog; - - -PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); -VAR - i, adr, heap, stack, TextSize, TypesSize, bits, n, val: INTEGER; - - Code, Data, Bss: RECORD address, size: INTEGER END; - - ram, rom: INTEGER; - - reloc: RELOC; - -BEGIN - IdxWords.src := NOWORD; - IdxWords.dst := NOWORD; - - ram := options.ram; - rom := options.rom; - - IF ODD(ram) THEN DEC(ram) END; - IF ODD(rom) THEN DEC(rom) END; - - ram := MIN(MAX(ram, minRAM), maxRAM); - rom := MIN(MAX(rom, minROM), maxROM); - - IF IL.codes.bss > ram - StkReserve - RTL.VarSize THEN - ERRORS.Error(204) - END; - - Labels := CHL.CreateIntList(); - FOR i := 1 TO IL.codes.lcount DO - CHL.PushInt(Labels, 0) - END; - - CodeList := LISTS.create(NIL); - RelList := LISTS.create(NIL); - REG.Init(R, Push, Pop, mov, xchg, {R4, R5, R6, R7}); - - prolog; - translate(chkSTK IN options.checking); - epilog; - - TypesSize := CHL.Length(IL.codes.types) * 2; - Data.size := CHL.Length(IL.codes.data); - IF ODD(Data.size) THEN - CHL.PushByte(IL.codes.data, 0); - INC(Data.size) - END; - Code.size := Fixup(0, IntVectorSize + TypesSize + Data.size); - Code.address := 10000H - (IntVectorSize + TypesSize + Data.size + Code.size); - IF Code.address < 10000H - rom THEN - ERRORS.Error(203) - END; - Code.size := Fixup(Code.address, IntVectorSize + TypesSize + Data.size); - Data.address := Code.address + Code.size; - TextSize := Code.size + Data.size; - - IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN - ERRORS.Error(203) - END; - - stack := RTL.ram + ram; - Bss.size := IL.codes.bss + IL.codes.bss MOD 2; - DEC(stack, Bss.size); - Bss.address := stack; - DEC(stack, RTL.VarSize); - heap := RTL.ram; - ASSERT(stack - heap >= StkReserve); - adr := Code.address + 2; - PutWord(stack, adr); - adr := Code.address + 6; - PutWord(heap, adr); - - reloc := RelList.first(RELOC); - WHILE reloc # NIL DO - adr := reloc.WordPtr.offset * 2; - val := reloc.WordPtr.val; - CASE reloc.section OF - |RCODE: PutWord(LabelOffs(val) * 2, adr) - |RDATA: PutWord(val + Data.address, adr) - |RBSS: PutWord((val + Bss.address) MOD 65536, adr) - END; - reloc := reloc.next(RELOC) - END; - - adr := Data.address; - - FOR i := 0 TO Data.size - 1 DO - mem[adr] := CHL.GetByte(IL.codes.data, i); - INC(adr) - END; - - FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO - PutWord(CHL.GetInt(IL.codes.types, i), adr) - END; - - FOR i := 0 TO 15 DO - PutWord((33 - i) * i, adr); - END; - - FOR n := 0 TO 15 DO - bits := ORD({0 .. n}); - FOR i := 0 TO 15 - n DO - PutWord(bits, adr); - bits := LSL(bits, 1) - END - END; - - PutWord(4130H, adr); (* RET *) - PutWord(stack, adr); - PutWord(0001H, adr); (* bsl signature (adr 0FFBEH) *) - - FOR i := 0 TO LEN(IV) - 1 DO - PutWord(LabelOffs(IV[i]) * 2, adr) - END; - - INC(TextSize, IntVectorSize + TypesSize + Code.address MOD 16); - INC(Bss.size, StkReserve + RTL.VarSize); - - WR.Create(outname); - HEX.Data(mem, Code.address - Code.address MOD 16, TextSize); - HEX.End; - WR.Close; - - C.Dashes; - C.String(" rom: "); C.Int(TextSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(TextSize * 100 DIV rom); C.StringLn("%)"); - C.Ln; - C.String(" ram: "); C.Int(Bss.size); C.String(" of "); C.Int(ram); C.String(" ("); C.Int(Bss.size * 100 DIV ram); C.StringLn("%)") -END CodeGen; - - -END MSP430. \ No newline at end of file diff --git a/programs/develop/oberon07/source/MSP430RTL.ob07 b/programs/develop/oberon07/source/MSP430RTL.ob07 deleted file mode 100644 index 4ddfe5ac2..000000000 --- a/programs/develop/oberon07/source/MSP430RTL.ob07 +++ /dev/null @@ -1,671 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2021, Anton Krotov - All rights reserved. -*) - -MODULE MSP430RTL; - - -CONST - - _mul* = 0; - _divmod* = 1; - _lsl* = 2; - _asr* = 3; - _ror* = 4; - _lsr* = 5; - _in* = 6; - _in2* = 7; - _set1* = 8; - _incl* = 9; - _excl* = 10; - _move* = 11; - _set* = 12; - _arrcpy* = 13; - _rot* = 14; - _strcmp* = 15; - _error* = 16; - _is* = 17; - _guard* = 18; - _guardrec* = 19; - _length* = 20; - _new* = 21; - - - HP* = 15; - - LenIV* = 32; - - iv = 10000H - LenIV * 2; - bsl = iv - 2; - sp = bsl - 2; - empty_proc* = sp - 2; - bits = empty_proc - 272; - bits_offs = bits - 32; - DataSize* = iv - bits_offs; - types = bits_offs - 2; - - IntVectorSize* = LenIV * 2 + DataSize; - - VarSize* = 4; - - StkReserve* = 40; - - trap = 2; - - -TYPE - - EMITPROC = PROCEDURE (n: INTEGER); - - -VAR - - ram*: INTEGER; - - rtl*: ARRAY 22 OF - RECORD - label*: INTEGER; - used: BOOLEAN - END; - - Label, Word, Call: EMITPROC; - - -PROCEDURE Gen*; - - - PROCEDURE Word1 (word: INTEGER); - BEGIN - Word(word) - END Word1; - - - PROCEDURE Word2 (word1, word2: INTEGER); - BEGIN - Word1(word1); - Word1(word2) - END Word2; - - - PROCEDURE Word3 (word1, word2, word3: INTEGER); - BEGIN - Word1(word1); - Word1(word2); - Word1(word3) - END Word3; - - -BEGIN - (* _lsl (n, x: INTEGER): INTEGER *) - IF rtl[_lsl].used THEN - Label(rtl[_lsl].label); - Word2(4115H, 2); (* MOV 2(SP), R5; R5 <- n *) - Word2(4114H, 4); (* MOV 4(SP), R4; R4 <- x *) - Word2(0F035H, 15); (* AND #15, R5 *) - Word1(2400H + 3); (* JZ L1 *) - (* L2: *) - Word1(5404H); (* ADD R4, R4 *) - Word1(8315H); (* SUB #1, R5 *) - Word1(2000H + 400H - 3); (* JNZ L2 *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _asr (n, x: INTEGER): INTEGER *) - IF rtl[_asr].used THEN - Label(rtl[_asr].label); - Word2(4115H, 2); (* MOV 2(SP), R5; R5 <- n *) - Word2(4114H, 4); (* MOV 4(SP), R4; R4 <- x *) - Word2(0F035H, 15); (* AND #15, R5 *) - Word1(2400H + 3); (* JZ L1 *) - (* L2: *) - Word1(1104H); (* RRA R4 *) - Word1(8315H); (* SUB #1, R5 *) - Word1(2000H + 400H - 3); (* JNZ L2 *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _ror (n, x: INTEGER): INTEGER *) - IF rtl[_ror].used THEN - Label(rtl[_ror].label); - Word2(4115H, 2); (* MOV 2(SP), R5; R5 <- n *) - Word2(4114H, 4); (* MOV 4(SP), R4; R4 <- x *) - Word2(0F035H, 15); (* AND #15, R5 *) - Word1(2400H + 5); (* JZ L1 *) - Word1(4406H); (* MOV R4, R6 *) - (* L2: *) - Word1(1006H); (* RRC R6 *) - Word1(1004H); (* RRC R4 *) - Word1(8315H); (* SUB #1, R5 *) - Word1(2000H + 400H - 4); (* JNZ L2 *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _lsr (n, x: INTEGER): INTEGER *) - IF rtl[_lsr].used THEN - Label(rtl[_lsr].label); - Word2(4115H, 2); (* MOV 2(SP), R5; R5 <- n *) - Word2(4114H, 4); (* MOV 4(SP), R4; R4 <- x *) - Word2(0F035H, 15); (* AND #15, R5 *) - Word1(2400H + 4); (* JZ L1 *) - (* L2: *) - Word1(0C312H); (* BIC #1, SR *) - Word1(1004H); (* RRC R4 *) - Word1(8315H); (* SUB #1, R5 *) - Word1(2000H + 400H - 4); (* JNZ L2 *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _set (b, a: INTEGER): SET *) - IF rtl[_set].used THEN - Label(rtl[_set].label); - Word2(4114H, 2); (* MOV 2(SP), R4; R4 <- b *) - Word2(4115H, 4); (* MOV 4(SP), R5; R5 <- a *) - Word1(9504H); (* CMP R5, R4 *) - Word1(3800H + 24); (* JL L1 *) - Word2(9035H, 16); (* CMP #16, R5 *) - Word1(3400H + 21); (* JGE L1 *) - Word1(9304H); (* CMP #0, R4 *) - Word1(3800H + 19); (* JL L1 *) - Word2(9034H, 16); (* CMP #16, R4 *) - Word1(3800H + 2); (* JL L2 *) - Word2(4034H, 15); (* MOV #15, R4 *) - (* L2: *) - Word1(9305H); (* CMP #0, R5 *) - Word1(3400H + 1); (* JGE L3 *) - Word1(4305H); (* MOV #0, R5 *) - (* L3: *) - Word1(8504H); (* SUB R5, R4 *) - Word1(5404H); (* ADD R4, R4 *) - Word2(5034H, bits_offs); (* ADD bits_offs, R4 *) - Word1(4424H); (* MOV @R4, R4 *) - Word1(5505H); (* ADD R5, R5 *) - Word1(5405H); (* ADD R4, R5 *) - Word2(5035H, bits); (* ADD bits, R5 *) - Word1(4524H); (* MOV @R5, R4 *) - Word1(4130H); (* RET *) - (* L1: *) - Word1(4304H); (* MOV #0, R4 *) - Word1(4130H) (* RET *) - END; - - (* _set1 (a: INTEGER): SET *) - IF rtl[_set1].used THEN - Label(rtl[_set1].label); - Word2(4114H, 2); (* MOV 2(SP), R4; R4 <- a *) - Word2(0B034H, 0FFF0H); (* BIT #0FFF0H, R4 *) - Word1(2000H + 5); (* JNZ L1 *) - Word1(5404H); (* ADD R4, R4 *) - Word2(5034H, bits); (* ADD bits, R4 *) - Word1(4424H); (* MOV @R4, R4 *) - Word1(4130H); (* RET *) - (* L1: *) - Word1(4304H); (* MOV #0, R4 *) - Word1(4130H) (* RET *) - END; - - (* _in2 (i, s: INTEGER): BOOLEAN *) - IF rtl[_in2].used THEN - Label(rtl[_in2].label); - Word2(4114H, 2); (* MOV 2(SP), R4; R4 <- i *) - Word1(5404H); (* ADD R4, R4 *) - Word2(5034H, bits); (* ADD bits, R4 *) - Word1(4424H); (* MOV @R4, R4 *) - Word2(0F114H, 4); (* AND 4(SP), R4 *) - Word1(2400H + 1); (* JZ L1 *) - Word1(4314H); (* MOV #1, R4 *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _in (s, i: INTEGER): BOOLEAN *) - IF rtl[_in].used THEN - Label(rtl[_in].label); - Word2(4114H, 4); (* MOV 4(SP), R4; R4 <- i *) - Word2(0B034H, 0FFF0H); (* BIT #0FFF0H, R4 *) - Word1(2000H + 9); (* JNZ L2 *) - Word1(5404H); (* ADD R4, R4 *) - Word2(5034H, bits); (* ADD bits, R4 *) - Word1(4424H); (* MOV @R4, R4 *) - Word2(0F114H, 2); (* AND 2(SP), R4 *) - Word1(2400H + 3); (* JZ L1 *) - Word1(4314H); (* MOV #1, R4 *) - Word1(4130H); (* RET *) - (* L2: *) - Word1(4304H); (* MOV #0, R4 *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _incl (VAR s: SET; i: INTEGER) *) - IF rtl[_incl].used THEN - Label(rtl[_incl].label); - Word2(4114H, 4); (* MOV 4(SP), R4; R4 <- i *) - Word2(0B034H, 0FFF0H); (* BIT #0FFF0H, R4 *) - Word1(2000H + 8); (* JNZ L1 *) - Word1(5404H); (* ADD R4, R4 *) - Word2(5034H, bits); (* ADD bits, R4 *) - Word1(4424H); (* MOV @R4, R4 *) - Word2(4115H, 2); (* MOV 2(SP), R5; R5 <- @s *) - Word2(0D485H, 0); (* BIS R4, 0(R5) *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _excl (VAR s: SET; i: INTEGER) *) - IF rtl[_excl].used THEN - Label(rtl[_excl].label); - Word2(4114H, 4); (* MOV 4(SP), R4; R4 <- i *) - Word2(0B034H, 0FFF0H); (* BIT #0FFF0H, R4 *) - Word1(2000H + 8); (* JNZ L1 *) - Word1(5404H); (* ADD R4, R4 *) - Word2(5034H, bits); (* ADD bits, R4 *) - Word1(4424H); (* MOV @R4, R4 *) - Word2(4115H, 2); (* MOV 2(SP), R5; R5 <- @s *) - Word2(0C485H, 0); (* BIC R4, 0(R5) *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _rot (len, adr: INTEGER) *) - IF rtl[_rot].used THEN - Label(rtl[_rot].label); - Word2(4114H, 2); (* MOV 2(SP), R4; R4 <- len *) - Word2(4115H, 4); (* MOV 4(SP), R5; R5 <- adr *) - Word1(8314H); (* SUB #1, R4 *) - Word1(5404H); (* ADD R4, R4 *) - Word1(1225H); (* PUSH @R5 *) - Word1(4406H); (* MOV R4, R6 *) - (* L1: *) - Word3(4595H, 2, 0); (* MOV 2(R5), 0(R5) *) - Word1(5325H); (* ADD #2, R5 *) - Word1(8326H); (* SUB #2, R6 *) - Word1(2000H + 400H - 6); (* JNZ L1 *) - Word2(41B5H, 0); (* MOV @SP+, 0(R5) *) - Word1(4130H) (* RET *) - END; - - (* _divmod (b, a: INTEGER): INTEGER (* res -> R4, mod -> R5 *) *) - IF rtl[_divmod].used THEN - Label(rtl[_divmod].label); - Word2(4115H, 4); (* MOV 4(SP), R5; R5 <- a *) - Word1(4304H); (* MOV #0, R4 *) - (* L1: *) - Word2(4116H, 2); (* MOV 2(SP), R6; R6 <- b *) - Word1(9605H); (* CMP R6, R5 *) - Word1(3800H + 17); (* JL L3 *) - Word1(4327H); (* MOV #2, R7 *) - Word1(5606H); (* ADD R6, R6 *) - (* L4: *) - Word1(9306H); (* CMP #0, R6 *) - Word1(2400H + 6); (* JZ L2 *) - Word1(3800H + 5); (* JL L2 *) - Word1(9605H); (* CMP R6, R5 *) - Word1(3800H + 3); (* JL L2 *) - Word1(5606H); (* ADD R6, R6 *) - Word1(5707H); (* ADD R7, R7 *) - Word1(3C00H + 400H - 8); (* JMP L4 *) - (* L2: *) - Word1(0C312H); (* BIC #1, SR *) - Word1(1006H); (* RRC R6 *) - Word1(0C312H); (* BIC #1, SR *) - Word1(1007H); (* RRC R7 *) - Word1(8605H); (* SUB R6, R5 *) - Word1(5704H); (* ADD R7, R4 *) - Word1(3C00H + 400H - 21); (* JMP L1 *) - (* L3: *) - (*----------- (a < 0) --------------*) - (* L1: *) - Word1(9305H); (* CMP #0, R5 *) - Word1(3400H + 23); (* JGE L3 *) - Word2(4116H, 2); (* MOV 2(SP), R6; R6 <- b *) - Word1(4327H); (* MOV #2, R7 *) - Word1(5606H); (* ADD R6, R6 *) - Word1(0E335H); (* XOR #-1, R5 *) - Word1(5315H); (* ADD #1, R5 *) - (* L4: *) - Word1(9306H); (* CMP #0, R6 *) - Word1(2400H + 6); (* JZ L2 *) - Word1(3800H + 5); (* JL L2 *) - Word1(9605H); (* CMP R6, R5 *) - Word1(3800H + 3); (* JL L2 *) - Word1(5606H); (* ADD R6, R6 *) - Word1(5707H); (* ADD R7, R7 *) - Word1(3C00H + 400H - 8); (* JMP L4 *) - (* L2: *) - Word1(0E335H); (* XOR #-1, R5 *) - Word1(5315H); (* ADD #1, R5 *) - Word1(0C312H); (* BIC #1, SR *) - Word1(1006H); (* RRC R6 *) - Word1(0C312H); (* BIC #1, SR *) - Word1(1007H); (* RRC R7 *) - Word1(5605H); (* ADD R6, R5 *) - Word1(8704H); (* SUB R7, R4 *) - Word1(3C00H + 400H - 25); (* JMP L1 *) - (* L3: *) - Word1(4130H) (* RET *) - END; - - (* _mul (a, b: INTEGER): INTEGER *) - IF rtl[_mul].used THEN - Label(rtl[_mul].label); - Word2(4115H, 2); (* MOV 2(SP), R5; R5 <- a *) - Word2(4116H, 4); (* MOV 4(SP), R6; R6 <- b *) - Word1(4304H); (* MOV #0, R4; res := 0 *) - Word1(9306H); (* CMP #0, R6 *) - Word1(2400H + 7); (* JZ L1 *) - (* L2: *) - Word1(0B316H); (* BIT #1, R6 *) - Word1(2400H + 1); (* JZ L3 *) - Word1(5504H); (* ADD R5, R4 *) - (* L3: *) - Word1(5505H); (* ADD R5, R5 *) - Word1(0C312H); (* BIC #1, SR *) - Word1(1006H); (* RRC R6 *) - Word1(2000H + 400H - 7); (* JNZ L2 *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _error (modNum, modName, err, line: INTEGER) *) - IF rtl[_error].used THEN - Label(rtl[_error].label); - Word1(5321H); (* ADD #2, SP *) - Word1(4134H); (* POP R4; R4 <- modNum *) - Word1(4135H); (* POP R5; R5 <- modName *) - Word1(4136H); (* POP R6; R6 <- err *) - Word1(4137H); (* POP R7; R7 <- line *) - Word2(4211H, sp); (* MOV sp(SR), SP *) - Word1(1207H); (* PUSH R7 *) - Word1(1206H); (* PUSH R6 *) - Word1(1205H); (* PUSH R5 *) - Word1(1204H); (* PUSH R4 *) - Word2(4214H, sp); (* MOV sp(SR), R4 *) - Word2(1294H, trap); (* CALL trap(R4) *) - Word2(04032H, 0F0H) (* MOV CPUOFF+OSCOFF+SCG0+SCG1, SR *) - END; - - (* _new (t, size: INTEGER; VAR ptr: INTEGER) *) - IF rtl[_new].used THEN - Label(rtl[_new].label); - Word1(1202H); (* PUSH SR *) - Word1(4302H); (* MOV #0, SR *) - Word1(4303H); (* NOP *) - Word1(4104H); (* MOV SP, R4 *) - Word2(8034H, StkReserve); (* SUB #StkReserve, R4 *) - Word1(4005H + 100H * HP); (* MOV HP, R5 *) - Word2(5115H, 6); (* ADD 6(SP), R5 *) - Word1(9504H); (* CMP R5, R4 *) - Word2(4114H, 8); (* MOV 8(SP), R4 *) - Word1(3800H + 12); (* JL L1 *) - Word3(4190H + HP, 4, 0); (* MOV 4(SP), 0(HP) *) - Word1(5320H + HP); (* ADD #2, HP *) - Word2(4084H + 100H * HP, 0); (* MOV HP, 0(R4) *) - (* L3 *) - Word2(4380H + HP, 0); (* MOV #0, 0(HP) *) - Word1(5320H + HP); (* ADD #2, HP *) - Word1(9500H + HP); (* CMP R5, HP *) - Word1(3800H + 400H - 5); (* JL L3 *) - Word1(3C00H + 2); (* JMP L2 *) - (* L1 *) - Word2(4384H, 0); (* MOV #0, 0(R4) *) - (* L2 *) - Word1(1300H) (* RETI *) - END; - - (* _guardrec (t0, t1: INTEGER): INTEGER *) - IF rtl[_guardrec].used THEN - Label(rtl[_guardrec].label); - Word2(4114H, 2); (* MOV 2(SP), R4; R4 <- t0 *) - Word2(4115H, 4); (* MOV 4(SP), R5; R5 <- t1 *) - Word2(4036H, types); (* MOV #types, R6 *) - (* L3: *) - Word1(9305H); (* CMP #0, R5 *) - Word1(2400H + 8); (* JZ L1 *) - Word1(9405H); (* CMP R4, R5 *) - Word1(2400H + 10); (* JZ L2 *) - Word1(5505H); (* ADD R5, R5 *) - Word1(0E335H); (* XOR #-1, R5 *) - Word1(5315H); (* ADD #1, R5 *) - Word1(5605H); (* ADD R6, R5 *) - Word1(4525H); (* MOV @R5, R5 *) - Word1(3C00H + 400H - 10); (* JMP L3 *) - (* L1: *) - Word1(9405H); (* CMP R4, R5 *) - Word1(2400H + 2); (* JZ L2 *) - Word1(4304H); (* MOV #0, R4 *) - Word1(4130H); (* RET *) - (* L2: *) - Word1(4314H); (* MOV #1, R4 *) - Word1(4130H) (* RET *) - END; - - (* _is (t, p: INTEGER): INTEGER *) - IF rtl[_is].used THEN - Label(rtl[_is].label); - Word2(4114H, 4); (* MOV 4(SP), R4; R4 <- p *) - Word2(4115H, 2); (* MOV 2(SP), R5; R5 <- t *) - Word1(9304H); (* TST R4 *) - Word1(2400H + 2); (* JZ L *) - Word2(4414H, -2); (* MOV -2(R4), R4 *) - (* L: *) - Word1(1204H); (* PUSH R4 *) - Word1(1205H); (* PUSH R5 *) - Call(rtl[_guardrec].label); (* CALL _guardrec *) - Word1(5221H); (* ADD #4, SP *) - Word1(4130H) (* RET *) - END; - - (* _guard (t, p: INTEGER): INTEGER *) - IF rtl[_guard].used THEN - Label(rtl[_guard].label); - Word2(4115H, 4); (* MOV 4(SP), R5; R5 <- p *) - Word1(4314H); (* MOV #1, R4 *) - Word1(4525H); (* MOV @R5, R5 *) - Word1(9305H); (* TST R5 *) - Word1(2400H + 9); (* JZ L *) - Word2(4515H, -2); (* MOV -2(R5), R5 *) - Word2(4114H, 2); (* MOV 2(SP), R4; R4 <- t *) - Word1(1205H); (* PUSH R5 *) - Word1(1204H); (* PUSH R4 *) - Call(rtl[_guardrec].label); (* CALL _guardrec *) - Word1(5221H); (* ADD #4, SP *) - (* L: *) - Word1(4130H) (* RET *) - END; - - (* _move (bytes, dest, source: INTEGER) *) - IF rtl[_move].used THEN - Label(rtl[_move].label); - Word2(4116H, 2); (* MOV 2(SP), R6; R6 <- bytes *) - Word2(4117H, 4); (* MOV 4(SP), R7; R7 <- dest *) - Word2(4115H, 6); (* MOV 6(SP), R5; R5 <- source *) - Word1(9306H); (* CMP #0, R6 *) - Word1(3800H + 6); (* JL L1 *) - Word1(2400H + 5); (* JZ L1 *) - (* L2: *) - Word2(45F7H, 0); (* MOV.B @R5+, 0(R7) *) - Word1(5317H); (* ADD #1, R7 *) - Word1(8316H); (* SUB #1, R6 *) - Word1(2000H + 400H - 5); (* JNZ L2 *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _arrcpy (base_size, len_dst, dst, len_src, src: INTEGER) *) - IF rtl[_arrcpy].used THEN - Label(rtl[_arrcpy].label); - Word3(9191H, 8, 4); (* CMP 8(SP), 4(SP) *) - Word1(3800H + 18); (* JL L1 *) - Word2(1211H, 12); (* PUSH 12(SP) *) - Word2(1211H, 10); (* PUSH 10(SP) *) - Word2(1211H, 14); (* PUSH 14(SP) *) - Word2(1211H, 10); (* PUSH 10(SP) *) - Call(rtl[_mul].label); (* CALL _mul *) - Word1(5221H); (* ADD #4, SP *) - Word1(1204H); (* PUSH R4 *) - Call(rtl[_move].label); (* CALL _move *) - Word2(5031H, 6); (* ADD #6, SP *) - Word1(4314H); (* MOV #1, R4 *) - Word1(4130H); (* RET *) - (* L1 *) - Word1(4304H); (* MOV #0, R4 *) - Word1(4130H) (* RET *) - END; - - (* _length (len, str: INTEGER): INTEGER *) - IF rtl[_length].used THEN - Label(rtl[_length].label); - Word2(4116H, 2); (* MOV 2(SP), R6; R6 <- len *) - Word2(4117H, 4); (* MOV 4(SP), R7; R7 <- str *) - Word1(4304H); (* MOV #0, R4; res := 0 *) - (* L2: *) - Word1(4775H); (* MOV.B @R7+, R5 *) - Word1(9305H); (* CMP #0, R5 *) - Word1(2400H + 3); (* JZ L1 *) - Word1(5314H); (* ADD #1, R4 *) - Word1(8316H); (* SUB #1, R6 *) - Word1(2000H + 400H - 6); (* JNZ L2 *) - (* L1: *) - Word1(4130H) (* RET *) - END; - - (* _strcmp (op, len2, str2, len1, str1: INTEGER): BOOLEAN *) - IF rtl[_strcmp].used THEN - Label(rtl[_strcmp].label); - Word2(4116H, 4); (* MOV 4(SP), R6; R6 <- len2 *) - Word2(4117H, 8); (* MOV 8(SP), R7; R7 <- len1 *) - Word1(9607H); (* CMP R6, R7 *) - Word1(3400H + 1); (* JGE L5 *) - Word1(4706H); (* MOV R7, R6 *) - (* L5: *) - Word1(1206H); (* PUSH R6 *) - Word2(4116H, 12); (* MOV 12(SP), R6; R6 <- str1 *) - Word2(4117H, 8); (* MOV 8(SP), R7; R7 <- str2 *) - (* L3: *) - Word2(9381H, 0); (* CMP #0, 0(SP) *) - Word1(2400H + 11); (* JZ L1 *) - Word1(4674H); (* MOV.B @R6+, R4 *) - Word1(4775H); (* MOV.B @R7+, R5 *) - Word2(8391H, 0); (* SUB #1, 0(SP) *) - Word1(9405H); (* CMP R4, R5 *) - Word1(2400H + 2); (* JZ L2 *) - Word1(8504H); (* SUB R5, R4 *) - Word1(3C00H + 5); (* JMP L4 *) - (* L2: *) - Word1(9304H); (* CMP #0, R4 *) - Word1(2000H + 400H - 13); (* JNZ L3 *) - Word1(3C00H + 2); (* JMP L4 *) - (* L1: *) - Word2(4034H, 8000H); (* MOV #8000H, R4 *) - (* L4: *) - Word1(5321H); (* ADD #2, SP *) - - Word2(9034H, 8000H); (* CMP #8000H, R4 *) - Word1(2000H + 18); (* JNZ L6 *) - Word2(4116H, 4); (* MOV 4(SP), R6; R6 <- len2 *) - Word2(4117H, 8); (* MOV 8(SP), R7; R7 <- len1 *) - Word1(9607H); (* CMP R6, R7 *) - Word1(2400H + 11); (* JZ L7 *) - Word1(3800H + 4); (* JL L8 *) - Word2(5116H, 10); (* ADD 10(SP), R6 *) - Word1(4664H); (* MOV.B @R6, R4 *) - Word1(3C00H + 7); (* JMP L6 *) - (* L8: *) - Word2(5117H, 6); (* ADD 6(SP), R7 *) - Word1(4764H); (* MOV.B @R7, R4 *) - Word1(0E334H); (* XOR #-1, R4 *) - Word1(5314H); (* ADD #1, R4 *) - Word1(3C00H + 1); (* JMP L6 *) - (* L7: *) - Word1(4304H); (* MOV #0, R4 *) - (* L6: *) - - Word2(5110H, 2); (* ADD 2(SP), PC; PC <- PC + op *) - - Word1(9304H); (* CMP #0, R4 *) - Word1(4314H); (* MOV #1, R4 *) - Word1(2400H + 1); (* JZ L *) - Word1(4304H); (* MOV #0, R4 *) - (* L *) - Word1(4130H); (* RET *) - Word1(4303H); (* NOP *) - - Word1(9304H); (* CMP #0, R4 *) - Word1(4314H); (* MOV #1, R4 *) - Word1(2000H + 1); (* JNZ L *) - Word1(4304H); (* MOV #0, R4 *) - (* L *) - Word1(4130H); (* RET *) - Word1(4303H); (* NOP *) - - Word1(9304H); (* CMP #0, R4 *) - Word1(4314H); (* MOV #1, R4 *) - Word1(3800H + 1); (* JL L *) - Word1(4304H); (* MOV #0, R4 *) - (* L *) - Word1(4130H); (* RET *) - Word1(4303H); (* NOP *) - - Word1(9304H); (* CMP #0, R4 *) - Word1(4314H); (* MOV #1, R4 *) - Word1(3800H + 2); (* JL L *) - Word1(2400H + 1); (* JZ L *) - Word1(4304H); (* MOV #0, R4 *) - (* L *) - Word1(4130H); (* RET *) - - Word1(9304H); (* CMP #0, R4 *) - Word1(4304H); (* MOV #0, R4 *) - Word1(3800H + 2); (* JL L *) - Word1(2400H + 1); (* JZ L *) - Word1(4314H); (* MOV #1, R4 *) - (* L *) - Word1(4130H); (* RET *) - - Word1(9304H); (* CMP #0, R4 *) - Word1(4314H); (* MOV #1, R4 *) - Word1(3400H + 1); (* JGE L *) - Word1(4304H); (* MOV #0, R4 *) - (* L *) - Word1(4130H) (* RET *) - END - -END Gen; - - -PROCEDURE Set* (idx, label: INTEGER); -BEGIN - rtl[idx].label := label; - rtl[idx].used := FALSE -END Set; - - -PROCEDURE Used* (idx: INTEGER); -BEGIN - rtl[idx].used := TRUE; - IF (idx = _guard) OR (idx = _is) THEN - rtl[_guardrec].used := TRUE - ELSIF idx = _arrcpy THEN - rtl[_move].used := TRUE; - rtl[_mul].used := TRUE - END -END Used; - - -PROCEDURE Init* (pLabel, pWord, pCall: EMITPROC); -BEGIN - Label := pLabel; - Word := pWord; - Call := pCall; - ram := 200H; -END Init; - - -END MSP430RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/source/PARS.ob07 b/programs/develop/oberon07/source/PARS.ob07 deleted file mode 100644 index 17d1ab30e..000000000 --- a/programs/develop/oberon07/source/PARS.ob07 +++ /dev/null @@ -1,1397 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2022, Anton Krotov - All rights reserved. -*) - -MODULE PARS; - -IMPORT PROG, SCAN, ARITH, STRINGS, ERRORS, LISTS, IL, CONSOLE, PATHS, UTILS, - C := COLLECTIONS, TARGETS, THUMB, MSP430; - - -CONST - - eCONST* = 1; eTYPE* = 2; eVAR* = 3; eEXPR* = 4; - eVREC* = 5; ePROC* = 6; eVPAR* = 7; ePARAM* = 8; - eSTPROC* = 9; eSTFUNC* = 10; eSYSFUNC* = 11; eSYSPROC* = 12; - eIMP* = 13; - - -TYPE - - PATH* = PATHS.PATH; - - PARSER* = POINTER TO rPARSER; - - POSITION* = RECORD (SCAN.POSITION) - - parser*: PARSER - - END; - - EXPR* = RECORD - - obj*: INTEGER; - _type*: PROG._TYPE; - value*: ARITH.VALUE; - stproc*: INTEGER; - readOnly*: BOOLEAN; - ident*: PROG.IDENT - - END; - - STATPROC = PROCEDURE (parser: PARSER); - EXPRPROC = PROCEDURE (parser: PARSER; VAR e: EXPR); - RETPROC = PROCEDURE (parser: PARSER; e: EXPR; t: PROG._TYPE; pos: POSITION): BOOLEAN; - - rPARSER = RECORD (C.ITEM) - - fname*: PATH; - path: PATH; - lib_path: PATH; - ext: PATH; - modname: PATH; - scanner: SCAN.SCANNER; - lex*: SCAN.LEX; - sym*: INTEGER; - unit*: PROG.UNIT; - constexp*: BOOLEAN; - main*: BOOLEAN; - - open*: PROCEDURE (parser: PARSER; modname, FileExt: ARRAY OF CHAR): BOOLEAN; - parse*: PROCEDURE (parser: PARSER); - StatSeq*: STATPROC; - expression*: EXPRPROC; - designator*: EXPRPROC; - chkreturn: RETPROC; - - create*: PROCEDURE (path, lib_path: PATH; StatSeq: STATPROC; expression, designator: EXPRPROC; chkreturn: RETPROC): PARSER - - END; - - -VAR - - parsers: C.COLLECTION; - - lines*, modules: INTEGER; - - -PROCEDURE destroy* (VAR parser: PARSER); -BEGIN - IF parser.scanner # NIL THEN - SCAN.close(parser.scanner) - END; - - C.push(parsers, parser); - parser := NIL -END destroy; - - -PROCEDURE getpos (parser: PARSER; VAR pos: POSITION); -BEGIN - pos.line := parser.lex.pos.line; - pos.col := parser.lex.pos.col; - pos.parser := parser -END getpos; - - -PROCEDURE error* (pos: POSITION; errno: INTEGER); -BEGIN - ERRORS.ErrorMsg(pos.parser.fname, pos.line, pos.col, errno) -END error; - - -PROCEDURE check* (condition: BOOLEAN; pos: POSITION; errno: INTEGER); -BEGIN - IF ~condition THEN - error(pos, errno) - END -END check; - - -PROCEDURE check1* (condition: BOOLEAN; parser: PARSER; errno: INTEGER); -VAR - pos: POSITION; - -BEGIN - IF ~condition THEN - getpos(parser, pos); - error(pos, errno) - END -END check1; - - -PROCEDURE Next* (parser: PARSER); -VAR - errno: INTEGER; - -BEGIN - SCAN.Next(parser.scanner, parser.lex); - errno := parser.lex.error; - IF errno = 0 THEN - IF (TARGETS.RealSize = 0) & (parser.lex.sym = SCAN.lxFLOAT) THEN - errno := -SCAN.lxERROR13 - ELSIF (TARGETS.BitDepth = 16) & (parser.lex.sym = SCAN.lxCHAR) & (parser.lex.value.typ = ARITH.tWCHAR) THEN - errno := -SCAN.lxERROR10 - END - END; - - IF errno # 0 THEN - check1(FALSE, parser, errno) - END; - parser.sym := parser.lex.sym -END Next; - - -PROCEDURE NextPos (parser: PARSER; VAR pos: POSITION); -BEGIN - Next(parser); - getpos(parser, pos) -END NextPos; - - -PROCEDURE checklex* (parser: PARSER; sym: INTEGER); -VAR - err: INTEGER; - -BEGIN - - IF parser.sym # sym THEN - - CASE sym OF - |SCAN.lxCOMMA: err := 65 - |SCAN.lxRROUND: err := 33 - |SCAN.lxPOINT: err := 26 - |SCAN.lxIDENT: err := 22 - |SCAN.lxRSQUARE: err := 71 - |SCAN.lxRCURLY: err := 35 - |SCAN.lxUNDEF: err := 34 - |SCAN.lxTHEN: err := 88 - |SCAN.lxEND: err := 27 - |SCAN.lxDO: err := 89 - |SCAN.lxUNTIL: err := 90 - |SCAN.lxCOLON: err := 53 - |SCAN.lxOF: err := 67 - |SCAN.lxASSIGN: err := 96 - |SCAN.lxTO: err := 57 - |SCAN.lxLROUND: err := 64 - |SCAN.lxEQ: err := 32 - |SCAN.lxSEMI: err := 24 - |SCAN.lxRETURN: err := 38 - |SCAN.lxMODULE: err := 21 - END; - - check1(FALSE, parser, err) - END -END checklex; - - -PROCEDURE ExpectSym* (parser: PARSER; sym: INTEGER); -BEGIN - Next(parser); - checklex(parser, sym) -END ExpectSym; - - -PROCEDURE ImportList (parser: PARSER); -VAR - fname, path, ext, _name: PATH; - name: SCAN.IDENT; - parser2: PARSER; - pos: POSITION; - alias, _in: BOOLEAN; - unit: PROG.UNIT; - ident: PROG.IDENT; - -BEGIN - alias := FALSE; - - REPEAT - - ExpectSym(parser, SCAN.lxIDENT); - name := parser.lex.ident; - - getpos(parser, pos); - - IF ~alias THEN - ident := PROG.addIdent(parser.unit, name, PROG.idMODULE); - check(ident # NIL, pos, 30) - END; - - Next(parser); - - path := parser.path; - fname := ""; - ext := UTILS.FILE_EXT; - COPY(name.s, _name); - _in := FALSE; - - IF parser.sym = SCAN.lxIN THEN - _in := TRUE; - Next(parser); - IF parser.sym = SCAN.lxSTRING THEN - STRINGS.trim(parser.lex.string.s, fname) - ELSIF parser.sym = SCAN.lxCHAR THEN - fname[0] := CHR(ARITH.Int(parser.lex.value)); - fname[1] := 0X - ELSE - check1(FALSE, parser, 117) - END; - STRINGS.replace(fname, "/", UTILS.slash); - STRINGS.replace(fname, "\", UTILS.slash); - PATHS.DelSlashes(fname); - PATHS.split(fname, path, _name, ext); - IF PATHS.isRelative(path) THEN - PATHS.RelPath(parser.path, path, fname); - STRINGS.append(fname, _name); - STRINGS.append(fname, ext); - PATHS.split(fname, path, _name, ext) - END; - Next(parser) - END; - - IF (parser.sym = SCAN.lxCOMMA) OR (parser.sym = SCAN.lxSEMI) THEN - alias := FALSE; - IF (fname = "") & ((_name = "SYSTEM") OR PROG.LowerCase & (_name = "system")) THEN - unit := PROG.program.sysunit - ELSE - IF fname # "" THEN - unit := PROG.getUnit(fname) - ELSE - fname := path; - STRINGS.append(fname, _name); - STRINGS.append(fname, UTILS.FILE_EXT); - unit := PROG.getUnit(fname); - IF unit = NIL THEN - fname := parser.lib_path; - STRINGS.append(fname, _name); - STRINGS.append(fname, UTILS.FILE_EXT); - unit := PROG.getUnit(fname) - END - END - END; - - IF unit # NIL THEN - check(unit.closed, pos, 31) - ELSE - parser2 := parser.create(path, parser.lib_path, - parser.StatSeq, parser.expression, parser.designator, parser.chkreturn); - - IF ~parser2.open(parser2, _name, ext) THEN - IF (path # parser.lib_path) & ~_in THEN - destroy(parser2); - parser2 := parser.create(parser.lib_path, parser.lib_path, - parser.StatSeq, parser.expression, parser.designator, parser.chkreturn); - check(parser2.open(parser2, _name, ext), pos, 29) - ELSE - error(pos, 29) - END - END; - - parser2.parse(parser2); - unit := parser2.unit; - unit.fname := parser2.fname; - destroy(parser2) - END; - IF unit = PROG.program.sysunit THEN - parser.unit.sysimport := TRUE - END; - ident.unit := unit - - ELSIF parser.sym = SCAN.lxASSIGN THEN - alias := TRUE - - ELSE - check1(FALSE, parser, 28) - END - - UNTIL parser.sym = SCAN.lxSEMI; - - Next(parser) - -END ImportList; - - -PROCEDURE QIdent (parser: PARSER; forward: BOOLEAN): PROG.IDENT; -VAR - ident: PROG.IDENT; - unit: PROG.UNIT; - -BEGIN - ASSERT(parser.sym = SCAN.lxIDENT); - - ident := PROG.getIdent(parser.unit, parser.lex.ident, FALSE); - - IF ~forward THEN - check1(ident # NIL, parser, 48) - END; - - IF (ident # NIL) & (ident.typ = PROG.idMODULE) THEN - unit := ident.unit; - ExpectSym(parser, SCAN.lxPOINT); - ExpectSym(parser, SCAN.lxIDENT); - ident := PROG.getIdent(unit, parser.lex.ident, FALSE); - check1((ident # NIL) & ident.export, parser, 48) - END - - RETURN ident -END QIdent; - - -PROCEDURE strcmp* (VAR v: ARITH.VALUE; v2: ARITH.VALUE; operator: INTEGER); -VAR - str: SCAN.TEXTSTR; - string1, string2: SCAN.STRING; - bool: BOOLEAN; - -BEGIN - - IF v.typ = ARITH.tCHAR THEN - ASSERT(v2.typ = ARITH.tSTRING); - ARITH.charToStr(v, str); - string1 := SCAN.enterStr(str); - string2 := v2.string(SCAN.STRING) - END; - - IF v2.typ = ARITH.tCHAR THEN - ASSERT(v.typ = ARITH.tSTRING); - ARITH.charToStr(v2, str); - string2 := SCAN.enterStr(str); - string1 := v.string(SCAN.STRING) - END; - - IF v.typ = v2.typ THEN - string1 := v.string(SCAN.STRING); - string2 := v2.string(SCAN.STRING) - END; - - CASE operator OF - |SCAN.lxEQ: bool := string1.s = string2.s - |SCAN.lxNE: bool := string1.s # string2.s - |SCAN.lxLT: bool := string1.s < string2.s - |SCAN.lxGT: bool := string1.s > string2.s - |SCAN.lxLE: bool := string1.s <= string2.s - |SCAN.lxGE: bool := string1.s >= string2.s - END; - - ARITH.setbool(v, bool) -END strcmp; - - -PROCEDURE ConstExpression* (parser: PARSER; VAR v: ARITH.VALUE); -VAR - e: EXPR; - pos: POSITION; - -BEGIN - getpos(parser, pos); - parser.constexp := TRUE; - parser.expression(parser, e); - parser.constexp := FALSE; - check(e.obj = eCONST, pos, 62); - v := e.value -END ConstExpression; - - -PROCEDURE FieldList (parser: PARSER; rec: PROG._TYPE); -VAR - name: SCAN.IDENT; - export: BOOLEAN; - pos: POSITION; - -BEGIN - ASSERT(parser.sym = SCAN.lxIDENT); - - WHILE parser.sym = SCAN.lxIDENT DO - - getpos(parser, pos); - - name := parser.lex.ident; - - Next(parser); - - export := parser.sym = SCAN.lxMUL; - - IF export THEN - check1(parser.unit.scopeLvl = 0, parser, 61); - Next(parser) - END; - - check(PROG.addField(rec, name, export), pos, 30); - - IF parser.sym = SCAN.lxCOMMA THEN - ExpectSym(parser, SCAN.lxIDENT) - ELSE - checklex(parser, SCAN.lxCOLON) - END - - END - -END FieldList; - - -PROCEDURE FormalParameters (parser: PARSER; _type: PROG._TYPE); -VAR - ident: PROG.IDENT; - - - PROCEDURE FPSection (parser: PARSER; _type: PROG._TYPE); - VAR - ident: PROG.IDENT; - exit: BOOLEAN; - vPar: BOOLEAN; - dim: INTEGER; - t0, t1: PROG._TYPE; - pos: POSITION; - - BEGIN - vPar := parser.sym = SCAN.lxVAR; - IF vPar THEN - Next(parser) - END; - - checklex(parser, SCAN.lxIDENT); - exit := FALSE; - - WHILE (parser.sym = SCAN.lxIDENT) & ~exit DO - check1(PROG.addParam(_type, parser.lex.ident, vPar), parser, 30); - Next(parser); - IF parser.sym = SCAN.lxCOMMA THEN - ExpectSym(parser, SCAN.lxIDENT) - ELSIF parser.sym = SCAN.lxCOLON THEN - Next(parser); - getpos(parser, pos); - dim := 0; - WHILE parser.sym = SCAN.lxARRAY DO - INC(dim); - check1(dim <= PROG.MAXARRDIM, parser, 84); - ExpectSym(parser, SCAN.lxOF); - Next(parser) - END; - checklex(parser, SCAN.lxIDENT); - ident := QIdent(parser, FALSE); - check1(ident.typ = PROG.idTYPE, parser, 68); - - t0 := ident._type; - t1 := t0; - - WHILE dim > 0 DO - t1 := PROG.enterType(PROG.tARRAY, -1, 0, parser.unit); - t1.base := t0; - t0 := t1; - DEC(dim) - END; - IF _type.call IN {PROG.fastcall, PROG._fastcall} THEN - check(t1.typ # PROG.tREAL, pos, 126) - END; - PROG.setParams(_type, t1); - Next(parser); - exit := TRUE - ELSE - checklex(parser, SCAN.lxCOLON) - END - END - - END FPSection; - - -BEGIN - IF parser.sym = SCAN.lxLROUND THEN - - Next(parser); - - IF (parser.sym = SCAN.lxVAR) OR (parser.sym = SCAN.lxIDENT) THEN - FPSection(parser, _type); - WHILE parser.sym = SCAN.lxSEMI DO - Next(parser); - FPSection(parser, _type) - END - END; - - checklex(parser, SCAN.lxRROUND); - Next(parser); - - IF parser.sym = SCAN.lxCOLON THEN - ExpectSym(parser, SCAN.lxIDENT); - ident := QIdent(parser, FALSE); - check1(ident.typ = PROG.idTYPE, parser, 68); - check1(~(ident._type.typ IN {PROG.tRECORD, PROG.tARRAY}), parser, 69); - check1( ~(ODD(_type.call) & (ident._type.typ = PROG.tREAL)), parser, 113); - _type.base := ident._type; - Next(parser) - ELSE - _type.base := NIL - END - - END -END FormalParameters; - - -PROCEDURE sysflag (parser: PARSER; proc: BOOLEAN): INTEGER; -VAR - res, sf: INTEGER; - -BEGIN - checklex(parser, SCAN.lxIDENT); - IF parser.lex.ident.s = "stdcall" THEN - sf := PROG.sf_stdcall - ELSIF parser.lex.ident.s = "cdecl" THEN - sf := PROG.sf_cdecl - ELSIF parser.lex.ident.s = "ccall" THEN - sf := PROG.sf_ccall - ELSIF parser.lex.ident.s = "win64" THEN - sf := PROG.sf_win64 - ELSIF parser.lex.ident.s = "systemv" THEN - sf := PROG.sf_systemv - ELSIF parser.lex.ident.s = "windows" THEN - sf := PROG.sf_windows - ELSIF parser.lex.ident.s = "linux" THEN - sf := PROG.sf_linux - ELSIF parser.lex.ident.s = "code" THEN - sf := PROG.sf_code - ELSIF parser.lex.ident.s = "oberon" THEN - sf := PROG.sf_oberon - ELSIF parser.lex.ident.s = "fastcall" THEN - sf := PROG.sf_fastcall - ELSIF parser.lex.ident.s = "noalign" THEN - sf := PROG.sf_noalign - ELSE - check1(FALSE, parser, 124) - END; - - check1(sf IN PROG.program.sysflags, parser, 125); - - IF proc THEN - check1(sf IN PROG.proc_flags, parser, 123) - ELSE - check1(sf IN PROG.rec_flags, parser, 123) - END; - - CASE sf OF - |PROG.sf_stdcall: - res := PROG.stdcall - |PROG.sf_cdecl: - res := PROG.cdecl - |PROG.sf_ccall: - IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32, TARGETS.osKOS} THEN - res := PROG.ccall - ELSIF TARGETS.OS = TARGETS.osWIN64 THEN - res := PROG.win64 - ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN - res := PROG.systemv - END - |PROG.sf_win64: - res := PROG.win64 - |PROG.sf_systemv: - res := PROG.systemv - |PROG.sf_code: - res := PROG.code - |PROG.sf_fastcall: - res := PROG.fastcall - |PROG.sf_oberon: - IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32, TARGETS.osKOS} THEN - res := PROG.default32 - ELSIF TARGETS.OS IN {TARGETS.osWIN64, TARGETS.osLINUX64} THEN - res := PROG.default64 - END - |PROG.sf_windows: - IF TARGETS.OS = TARGETS.osWIN32 THEN - res := PROG.stdcall - ELSIF TARGETS.OS = TARGETS.osWIN64 THEN - res := PROG.win64 - END - |PROG.sf_linux: - IF TARGETS.OS = TARGETS.osLINUX32 THEN - res := PROG.ccall - ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN - res := PROG.systemv - END - |PROG.sf_noalign: - res := PROG.noalign - END - - RETURN res -END sysflag; - - -PROCEDURE procflag (parser: PARSER; VAR _import: IL.IMPORT_PROC; isProc: BOOLEAN): INTEGER; -VAR - call: INTEGER; - dll, proc: SCAN.TEXTSTR; - pos: POSITION; - - - PROCEDURE getStr (parser: PARSER; VAR name: SCAN.TEXTSTR); - VAR - pos: POSITION; - str: ARITH.VALUE; - - BEGIN - getpos(parser, pos); - ConstExpression(parser, str); - IF str.typ = ARITH.tSTRING THEN - name := str.string(SCAN.STRING).s - ELSIF str.typ = ARITH.tCHAR THEN - ARITH.charToStr(str, name) - ELSE - check(FALSE, pos, 117) - END - END getStr; - - -BEGIN - _import := NIL; - - IF parser.sym = SCAN.lxLSQUARE THEN - getpos(parser, pos); - check1(parser.unit.sysimport, parser, 54); - Next(parser); - call := sysflag(parser, TRUE); - Next(parser); - IF parser.sym = SCAN.lxMINUS THEN - Next(parser); - INC(call) - END; - - IF isProc & (parser.sym = SCAN.lxCOMMA) THEN - Next(parser); - getStr(parser, dll); - STRINGS.UpCase(dll); - checklex(parser, SCAN.lxCOMMA); - Next(parser); - getStr(parser, proc); - _import := IL.AddImp(dll, proc) - END; - - checklex(parser, SCAN.lxRSQUARE); - Next(parser) - ELSE - CASE TARGETS.BitDepth OF - |16: call := PROG.default16 - |32: IF TARGETS.CPU = TARGETS.cpuX86 THEN - call := PROG.default32 - ELSE - call := PROG.cdecl - END - |64: IF TARGETS.CPU = TARGETS.cpuAMD64 THEN - call := PROG.default64 - ELSE - call := PROG.cdecl - END - END - END; - - IF _import # NIL THEN - check(TARGETS.Import, pos, 70) - END - - RETURN call -END procflag; - - -PROCEDURE _type (parser: PARSER; VAR t: PROG._TYPE; flags: SET); -CONST - comma = 0; - closed = 1; - forward = 2; - -VAR - arrLen: ARITH.VALUE; - typeSize: ARITH.VALUE; - ident: PROG.IDENT; - unit: PROG.UNIT; - pos, pos2: POSITION; - fieldType: PROG._TYPE; - baseIdent: SCAN.IDENT; - a, b: INTEGER; - RecFlag: INTEGER; - _import: IL.IMPORT_PROC; - -BEGIN - unit := parser.unit; - t := NIL; - - IF parser.sym = SCAN.lxIDENT THEN - ident := QIdent(parser, forward IN flags); - - IF ident # NIL THEN - check1(ident.typ = PROG.idTYPE, parser, 49); - t := ident._type; - check1(t # NIL, parser, 50); - IF closed IN flags THEN - check1(t.closed, parser, 50) - END - END; - - Next(parser) - - ELSIF (parser.sym = SCAN.lxARRAY) OR ((parser.sym = SCAN.lxCOMMA) & (comma IN flags)) THEN - - IF parser.sym = SCAN.lxARRAY THEN - getpos(parser, pos2) - END; - NextPos(parser, pos); - - ConstExpression(parser, arrLen); - - check(arrLen.typ = ARITH.tINTEGER, pos, 43); - check(ARITH.check(arrLen), pos, 39); - check(ARITH.getInt(arrLen) > 0, pos, 51); - - t := PROG.enterType(PROG.tARRAY, -1, ARITH.getInt(arrLen), unit); - - IF parser.sym = SCAN.lxCOMMA THEN - _type(parser, t.base, {comma, closed}) - ELSIF parser.sym = SCAN.lxOF THEN - Next(parser); - _type(parser, t.base, {closed}) - ELSE - check1(FALSE, parser, 47) - END; - - t.align := t.base.align; - - a := t.length; - b := t.base.size; - check(ARITH.mulInt(a, b), pos2, 104); - check(ARITH.setInt(typeSize, a), pos2, 104); - t.size := a; - - t.closed := TRUE - - ELSIF parser.sym = SCAN.lxRECORD THEN - getpos(parser, pos2); - Next(parser); - - t := PROG.enterType(PROG.tRECORD, 0, 0, unit); - t.align := 1; - - IF parser.sym = SCAN.lxLSQUARE THEN - check1(parser.unit.sysimport, parser, 54); - Next(parser); - RecFlag := sysflag(parser, FALSE); - t.noalign := RecFlag = PROG.noalign; - ExpectSym(parser, SCAN.lxRSQUARE); - Next(parser) - END; - - IF parser.sym = SCAN.lxLROUND THEN - check1(~t.noalign, parser, 111); - ExpectSym(parser, SCAN.lxIDENT); - getpos(parser, pos); - - _type(parser, t.base, {closed}); - - check(t.base.typ IN {PROG.tRECORD, PROG.tPOINTER}, pos, 52); - - IF t.base.typ = PROG.tPOINTER THEN - t.base := t.base.base; - check(t.base # NIL, pos, 55) - END; - - check(~t.base.noalign, pos, 112); - - checklex(parser, SCAN.lxRROUND); - Next(parser); - - t.size := t.base.size; - IF t.base.align > t.align THEN - t.align := t.base.align - END - ELSE - t.base := PROG.program.stTypes.tANYREC - END; - - WHILE parser.sym = SCAN.lxIDENT DO - FieldList(parser, t); - - ASSERT(parser.sym = SCAN.lxCOLON); - Next(parser); - - _type(parser, fieldType, {closed}); - check(PROG.setFields(t, fieldType), pos2, 104); - - IF (fieldType.align > t.align) & ~t.noalign THEN - t.align := fieldType.align - END; - - IF parser.sym = SCAN.lxSEMI THEN - ExpectSym(parser, SCAN.lxIDENT) - ELSE - checklex(parser, SCAN.lxEND) - END - END; - - t.closed := TRUE; - - IL.AddRec(t.base.num); - - IF ~t.noalign THEN - check(UTILS.Align(t.size, t.align), pos2, 104); - check(ARITH.setInt(typeSize, t.size), pos2, 104) - END; - - checklex(parser, SCAN.lxEND); - Next(parser) - - ELSIF parser.sym = SCAN.lxPOINTER THEN - ExpectSym(parser, SCAN.lxTO); - Next(parser); - - t := PROG.enterType(PROG.tPOINTER, TARGETS.AdrSize, 0, unit); - t.align := TARGETS.AdrSize; - - getpos(parser, pos); - - IF parser.sym = SCAN.lxIDENT THEN - baseIdent := parser.lex.ident - END; - - _type(parser, t.base, {forward}); - - IF t.base # NIL THEN - check(t.base.typ = PROG.tRECORD, pos, 58) - ELSE - PROG.frwPtr(unit, t, baseIdent, pos) - END - - ELSIF parser.sym = SCAN.lxPROCEDURE THEN - NextPos(parser, pos); - t := PROG.enterType(PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit); - t.align := TARGETS.AdrSize; - t.call := procflag(parser, _import, FALSE); - FormalParameters(parser, t) - ELSE - check1(FALSE, parser, 49) - END - -END _type; - - -PROCEDURE IdentDef (parser: PARSER; typ: INTEGER; VAR name: SCAN.IDENT): PROG.IDENT; -VAR - ident: PROG.IDENT; - pos: POSITION; - -BEGIN - ASSERT(parser.sym = SCAN.lxIDENT); - - name := parser.lex.ident; - getpos(parser, pos); - ident := PROG.addIdent(parser.unit, name, typ); - check(ident # NIL, pos, 30); - ident.pos := pos; - Next(parser); - - IF parser.sym = SCAN.lxMUL THEN - check1(ident.global, parser, 61); - ident.export := TRUE; - Next(parser) - END - - RETURN ident -END IdentDef; - - -PROCEDURE ConstTypeDeclaration (parser: PARSER; _const: BOOLEAN); -VAR - ident: PROG.IDENT; - name: SCAN.IDENT; - pos: POSITION; - -BEGIN - IF _const THEN - ident := IdentDef(parser, PROG.idNONE, name) - ELSE - ident := IdentDef(parser, PROG.idTYPE, name) - END; - - checklex(parser, SCAN.lxEQ); - NextPos(parser, pos); - - IF _const THEN - ConstExpression(parser, ident.value); - IF ident.value.typ = ARITH.tINTEGER THEN - check(ARITH.check(ident.value), pos, 39) - ELSIF ident.value.typ = ARITH.tREAL THEN - check(ARITH.check(ident.value), pos, 40) - END; - ident.typ := PROG.idCONST; - ident._type := PROG.getType(ident.value.typ) - ELSE - _type(parser, ident._type, {}) - END; - - checklex(parser, SCAN.lxSEMI); - Next(parser) - -END ConstTypeDeclaration; - - -PROCEDURE VarDeclaration (parser: PARSER); -VAR - ident: PROG.IDENT; - name: SCAN.IDENT; - t: PROG._TYPE; - -BEGIN - - REPEAT - ident := IdentDef(parser, PROG.idVAR, name); - - IF parser.sym = SCAN.lxCOMMA THEN - ExpectSym(parser, SCAN.lxIDENT) - ELSIF parser.sym = SCAN.lxCOLON THEN - Next(parser); - _type(parser, t, {}); - PROG.setVarsType(parser.unit, t); - checklex(parser, SCAN.lxSEMI); - Next(parser) - ELSE - checklex(parser, SCAN.lxCOLON) - END - - UNTIL parser.sym # SCAN.lxIDENT - -END VarDeclaration; - - -PROCEDURE DeclarationSequence (parser: PARSER): BOOLEAN; -VAR - ptr: PROG.FRWPTR; - endmod: BOOLEAN; - pos: POSITION; - - - PROCEDURE ProcDeclaration (parser: PARSER): BOOLEAN; - VAR - proc: PROG.IDENT; - endname, - name: SCAN.IDENT; - param: PROG.PARAM; - unit: PROG.UNIT; - ident: PROG.IDENT; - e: EXPR; - pos, pos1, - pos2: POSITION; - label: INTEGER; - enter: IL.COMMAND; - call: INTEGER; - t: PROG._TYPE; - _import: IL.IMPORT_PROC; - endmod, b: BOOLEAN; - fparams: SET; - int, flt: INTEGER; - comma: BOOLEAN; - code, iv: ARITH.VALUE; - codeProc, - handler: BOOLEAN; - line: INTEGER; - - BEGIN - endmod := FALSE; - handler := FALSE; - - unit := parser.unit; - - call := procflag(parser, _import, TRUE); - - getpos(parser, pos); - pos1 := pos; - checklex(parser, SCAN.lxIDENT); - line := pos.line; - - IF _import # NIL THEN - proc := IdentDef(parser, PROG.idIMP, name); - proc._import := _import; - IF _import.name = "" THEN - COPY(name.s, _import.name) - END; - PROG.program.procs.last(PROG.PROC)._import := _import - ELSE - proc := IdentDef(parser, PROG.idPROC, name) - END; - - check(PROG.openScope(unit, proc.proc), pos, 116); - - proc._type := PROG.enterType(PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit); - t := proc._type; - t.align := TARGETS.AdrSize; - t.call := call; - - FormalParameters(parser, t); - - IF parser.sym = SCAN.lxLSQUARE THEN - getpos(parser, pos2); - check((TARGETS.CPU = TARGETS.cpuTHUMB) & (TARGETS.OS = TARGETS.osNONE), pos2, 24); - Next(parser); - getpos(parser, pos2); - ConstExpression(parser, iv); - check(iv.typ = ARITH.tINTEGER, pos2, 43); - check((0 <= ARITH.Int(iv)) & (ARITH.Int(iv) <= THUMB.maxIVT), pos2, 46); - check(THUMB.SetIV(ARITH.Int(iv)), pos2, 121); - checklex(parser, SCAN.lxRSQUARE); - Next(parser); - handler := TRUE - END; - - codeProc := call IN {PROG.code, PROG._code}; - - IF call IN {PROG.systemv, PROG._systemv} THEN - check(t.parSize <= PROG.MAXSYSVPARAM, pos, 120) - END; - - param := t.params.first(PROG.PARAM); - WHILE param # NIL DO - ident := PROG.addIdent(unit, param.name, PROG.idPARAM); - ASSERT(ident # NIL); - ident._type := param._type; - ident.offset := param.offset; - IF param.vPar THEN - ident.typ := PROG.idVPAR - END; - param := param.next(PROG.PARAM) - END; - - IF _import = NIL THEN - label := IL.NewLabel(); - proc.proc.label := label; - proc.proc.used := handler; - IF handler THEN - IL.AddCmd2(IL.opHANDLER, label, ARITH.Int(iv)) - END - END; - - IF codeProc THEN - enter := IL.EnterC(label); - comma := FALSE; - WHILE (parser.sym # SCAN.lxSEMI) OR comma DO - getpos(parser, pos2); - ConstExpression(parser, code); - check(code.typ = ARITH.tINTEGER, pos2, 43); - IF TARGETS.WordSize > TARGETS.InstrSize THEN - CASE TARGETS.InstrSize OF - |1: check(ARITH.range(code, 0, 255), pos, 42) - |2: check(ARITH.range(code, 0, 65535), pos, 110) - END - END; - IL.AddCmd(IL.opCODE, ARITH.getInt(code)); - comma := parser.sym = SCAN.lxCOMMA; - IF comma THEN - Next(parser) - ELSE - checklex(parser, SCAN.lxSEMI) - END - END - END; - - checklex(parser, SCAN.lxSEMI); - Next(parser); - - IF _import = NIL THEN - - IF parser.main & proc.export & TARGETS.Dll THEN - IF TARGETS.target = TARGETS.KolibriOSDLL THEN - check((proc.name.s # "lib_init") & (proc.name.s # "version"), pos, 114) - END; - IL.AddExp(label, proc.name.s); - proc.proc.used := TRUE - END; - - IF ~codeProc THEN - b := DeclarationSequence(parser) - END; - - PROG.ResetLocSize; - IF call IN {PROG._win64, PROG.win64} THEN - fparams := PROG.getFloatParamsPos(proc._type, 3, int, flt); - enter := IL.Enter(label, LSL(ORD(fparams), 5) + MIN(proc._type.parSize, 4)) - ELSIF call IN {PROG._systemv, PROG.systemv} THEN - fparams := PROG.getFloatParamsPos(proc._type, PROG.MAXSYSVPARAM - 1, int, flt); - enter := IL.Enter(label, -(LSL(ORD(fparams), 5) + proc._type.parSize)) - ELSIF codeProc THEN - - ELSIF call IN {PROG.fastcall, PROG._fastcall} THEN - enter := IL.Enter(label, proc._type.parSize) - ELSE - enter := IL.Enter(label, 0) - END; - proc.proc.enter := enter; - - IF ~codeProc & (parser.sym = SCAN.lxBEGIN) THEN - Next(parser); - parser.StatSeq(parser) - END; - - IF ~codeProc & (t.base # NIL) THEN - checklex(parser, SCAN.lxRETURN); - NextPos(parser, pos); - parser.expression(parser, e); - check(parser.chkreturn(parser, e, t.base, pos), pos, 87) - END; - - IF ~codeProc THEN - proc.proc.leave := IL.Leave(t.base # NIL, (t.base # NIL) & (t.base.typ = PROG.tREAL), PROG.program.locsize, - t.parSize * ORD((t.call IN PROG.callee_clean_up) OR (t.call IN {PROG.systemv, PROG._systemv}))); - enter.param2 := PROG.program.locsize; - checklex(parser, SCAN.lxEND) - ELSE - proc.proc.leave := IL.LeaveC() - END; - - IF (TARGETS.CPU = TARGETS.cpuMSP430) & ~codeProc THEN - check(MSP430.CheckProcDataSize(enter.param2 + proc._type.parSize, PROG.program.options.ram), pos1, 63); - enter.param2 := enter.param2 * 65536 + line; - enter.param3 := IL.codes.errlabels[10] - END - END; - - IF parser.sym = SCAN.lxEND THEN - Next(parser); - IF parser.sym = SCAN.lxIDENT THEN - getpos(parser, pos); - endname := parser.lex.ident; - IF ~codeProc & (_import = NIL) THEN - check(PROG.IdEq(endname, name), pos, 60); - ExpectSym(parser, SCAN.lxSEMI); - Next(parser) - ELSE - IF PROG.IdEq(endname, parser.unit.name) THEN - ExpectSym(parser, SCAN.lxPOINT); - Next(parser); - endmod := TRUE - ELSIF PROG.IdEq(endname, name) THEN - ExpectSym(parser, SCAN.lxSEMI); - Next(parser) - ELSE - error(pos, 60) - END - END - ELSIF parser.sym = SCAN.lxSEMI THEN - Next(parser) - ELSE - checklex(parser, SCAN.lxIDENT) - END - END; - - PROG.closeScope(unit); - - RETURN endmod - END ProcDeclaration; - - -BEGIN - IF parser.sym = SCAN.lxCONST THEN - Next(parser); - WHILE parser.sym = SCAN.lxIDENT DO - ConstTypeDeclaration(parser, TRUE) - END - END; - - IF parser.sym = SCAN.lxTYPE THEN - Next(parser); - WHILE parser.sym = SCAN.lxIDENT DO - ConstTypeDeclaration(parser, FALSE) - END - END; - - ptr := PROG.linkPtr(parser.unit); - IF ptr # NIL THEN - pos.line := ptr.pos.line; - pos.col := ptr.pos.col; - pos.parser := parser; - IF ptr.notRecord THEN - error(pos, 58) - ELSE - error(pos, 48) - END - END; - - IF parser.sym = SCAN.lxVAR THEN - Next(parser); - IF parser.sym = SCAN.lxIDENT THEN - VarDeclaration(parser) - END - END; - - endmod := FALSE; - WHILE ~endmod & (parser.sym = SCAN.lxPROCEDURE) DO - Next(parser); - endmod := ProcDeclaration(parser) - END - - RETURN endmod -END DeclarationSequence; - - -PROCEDURE parse (parser: PARSER); -VAR - unit: PROG.UNIT; - label: INTEGER; - name: INTEGER; - endmod: BOOLEAN; - errlabel: INTEGER; - errno: INTEGER; - ident: PROG.IDENT; - -BEGIN - ASSERT(parser # NIL); - ASSERT(parser.scanner # NIL); - - ExpectSym(parser, SCAN.lxMODULE); - ExpectSym(parser, SCAN.lxIDENT); - - IF ~parser.main THEN - check1(parser.lex.ident.s = parser.modname, parser, 23) - END; - - unit := PROG.newUnit(parser.lex.ident); - unit.fname := parser.fname; - parser.unit := unit; - - ExpectSym(parser, SCAN.lxSEMI); - - Next(parser); - IF parser.sym = SCAN.lxIMPORT THEN - ImportList(parser) - END; - - INC(modules); - - CONSOLE.String("compiling "); - CONSOLE.String("("); CONSOLE.Int(modules); CONSOLE.String(") "); - CONSOLE.String(unit.name.s); - IF unit.sysimport THEN - CONSOLE.String(" (SYSTEM)") - END; - CONSOLE.Ln; - - IF PROG.program.options.uses THEN - ident := unit.idents.first(PROG.IDENT); - WHILE ident # NIL DO - IF (ident.typ = PROG.idMODULE) & (ident.unit # PROG.program.sysunit) THEN - CONSOLE.String(" "); CONSOLE.String(ident.unit.fname); CONSOLE.Ln - END; - ident := ident.next(PROG.IDENT) - END; - CONSOLE.Ln - END; - - IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN - IL.fname(parser.fname) - END; - - label := IL.NewLabel(); - IL.Jmp(IL.opJMP, label); - - name := IL.putstr(unit.name.s); - - errlabel := IL.NewLabel(); - IL.SetLabel(errlabel); - IL.StrAdr(name); - IL.Param1; - IL.AddCmd(IL.opPUSHC, modules); - IL.AddCmd0(IL.opERR); - - FOR errno := 1 TO LEN(IL.codes.errlabels) - 1 DO - IL.SetErrLabel(errno); - IL.AddCmd(IL.opPUSHC, errno); - IL.Jmp(IL.opJMP, errlabel) - END; - - endmod := DeclarationSequence(parser); - - IL.SetLabel(label); - - IF ~endmod THEN - - IF parser.sym = SCAN.lxBEGIN THEN - Next(parser); - parser.StatSeq(parser) - END; - - checklex(parser, SCAN.lxEND); - - ExpectSym(parser, SCAN.lxIDENT); - check1(parser.lex.ident.s = unit.name.s, parser, 25); - ExpectSym(parser, SCAN.lxPOINT) - END; - - INC(lines, parser.lex.pos.line); - PROG.closeUnit(unit) -END parse; - - -PROCEDURE open (parser: PARSER; modname, FileExt: ARRAY OF CHAR): BOOLEAN; -BEGIN - ASSERT(parser # NIL); - - STRINGS.append(parser.fname, modname); - STRINGS.append(parser.fname, FileExt); - STRINGS.append(parser.modname, modname); - - parser.scanner := SCAN.open(parser.fname) - - RETURN parser.scanner # NIL -END open; - - -PROCEDURE NewParser (): PARSER; -VAR - pars: PARSER; - citem: C.ITEM; - -BEGIN - citem := C.pop(parsers); - IF citem = NIL THEN - NEW(pars) - ELSE - pars := citem(PARSER) - END - - RETURN pars -END NewParser; - - -PROCEDURE create* (path, lib_path: PATH; StatSeq: STATPROC; expression, designator: EXPRPROC; chkreturn: RETPROC): PARSER; -VAR - parser: PARSER; - -BEGIN - parser := NewParser(); - - parser.path := path; - parser.lib_path := lib_path; - parser.ext := UTILS.FILE_EXT; - parser.fname := path; - parser.modname := ""; - parser.scanner := NIL; - parser.unit := NIL; - parser.constexp := FALSE; - parser.main := FALSE; - - parser.open := open; - parser.parse := parse; - parser.StatSeq := StatSeq; - parser.expression := expression; - parser.designator := designator; - parser.chkreturn := chkreturn; - parser.create := create - - RETURN parser -END create; - - -PROCEDURE init* (options: PROG.OPTIONS); -BEGIN - PROG.create(options); - parsers := C.create(); - lines := 0; - modules := 0 -END init; - - -END PARS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/PATHS.ob07 b/programs/develop/oberon07/source/PATHS.ob07 deleted file mode 100644 index f75c64a00..000000000 --- a/programs/develop/oberon07/source/PATHS.ob07 +++ /dev/null @@ -1,151 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE PATHS; - -IMPORT STRINGS, UTILS; - - -CONST - - slash = UTILS.slash; - - PATHLEN = 2048; - - -TYPE - - PATH* = ARRAY PATHLEN OF CHAR; - - -PROCEDURE split* (fname: ARRAY OF CHAR; VAR path, name, ext: ARRAY OF CHAR); -VAR - pos1, pos2, len: INTEGER; - -BEGIN - len := LENGTH(fname); - pos1 := len - 1; - pos2 := pos1; - STRINGS.search(fname, pos1, slash, FALSE); - STRINGS.search(fname, pos2, ".", FALSE); - - path := fname; - path[pos1 + 1] := 0X; - - IF (pos2 = -1) OR (pos2 < pos1) THEN - pos2 := len - END; - - INC(pos1); - - STRINGS.copy(fname, name, pos1, 0, pos2 - pos1); - name[pos2 - pos1] := 0X; - STRINGS.copy(fname, ext, pos2, 0, len - pos2); - ext[len - pos2] := 0X -END split; - - -PROCEDURE RelPath* (absolute, relative: ARRAY OF CHAR; VAR res: ARRAY OF CHAR); -VAR - i, j: INTEGER; - error: BOOLEAN; - -BEGIN - COPY(absolute, res); - i := LENGTH(res) - 1; - WHILE (i >= 0) & (res[i] # slash) DO - DEC(i) - END; - - INC(i); - res[i] := 0X; - - error := FALSE; - j := 0; - WHILE (relative[j] = ".") & (relative[j + 1] = slash) DO - INC(j, 2) - ELSIF relative[j] = slash DO - INC(j) - END; - - WHILE ~error & (relative[j] # 0X) DO - IF (relative[j] = ".") & (relative[j + 1] = ".") & (relative[j + 2] = slash) & (i > 0) & (res[i - 1] = slash) THEN - DEC(i, 2); - WHILE (i >= 0) & (res[i] # slash) DO - DEC(i) - END; - IF i < 0 THEN - error := TRUE - ELSE - INC(i); - INC(j, 3) - END - ELSE - res[i] := relative[j]; - INC(i); - INC(j) - END - END; - - IF error THEN - COPY(relative, res) - ELSE - res[i] := 0X - END - -END RelPath; - - -PROCEDURE DelSlashes* (VAR path: ARRAY OF CHAR); -VAR - i, j, k: INTEGER; - c: CHAR; - -BEGIN - i := 0; - j := 0; - k := 0; - REPEAT - c := path[j]; - INC(j); - IF c = slash THEN - INC(k) - ELSE - k := 0 - END; - IF k <= 1 THEN - path[i] := c; - INC(i) - END - UNTIL c = 0X; - - i := 0; - j := 0; - REPEAT - c := path[j]; - INC(j); - path[i] := c; - INC(i); - IF (c = slash) & (path[j] = ".") & (path[j + 1] = slash) THEN - INC(j, 2) - END - UNTIL c = 0X -END DelSlashes; - - -PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; - RETURN UTILS.isRelative(path) -END isRelative; - - -PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); -BEGIN - UTILS.GetCurrentDirectory(path) -END GetCurrentDirectory; - - -END PATHS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/PE32.ob07 b/programs/develop/oberon07/source/PE32.ob07 deleted file mode 100644 index 30a4ed3b9..000000000 --- a/programs/develop/oberon07/source/PE32.ob07 +++ /dev/null @@ -1,695 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE PE32; - -IMPORT BIN, LISTS, UTILS, WR := WRITER, CHL := CHUNKLISTS; - - -CONST - - SIZE_OF_DWORD = 4; - SIZE_OF_WORD = 2; - - SIZE_OF_IMAGE_EXPORT_DIRECTORY = 40; - - IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; - - IMAGE_SIZEOF_SHORT_NAME = 8; - - SIZE_OF_IMAGE_FILE_HEADER* = 20; - - SIZE_OF_IMAGE_SECTION_HEADER* = 40; - - (* SectionHeader.Characteristics *) - - SHC_text = 060000020H; - SHC_data = 040000040H; - SHC_bss = 0C0000080H; - - SectionAlignment = 1000H; - FileAlignment = 200H; - - -TYPE - - WORD = WCHAR; - DWORD = INTEGER; - - NAME* = ARRAY IMAGE_SIZEOF_SHORT_NAME OF CHAR; - - - IMAGE_DATA_DIRECTORY = RECORD - - VirtualAddress: DWORD; - Size: DWORD - - END; - - - IMAGE_OPTIONAL_HEADER = RECORD - - Magic: WORD; - MajorLinkerVersion: BYTE; - MinorLinkerVersion: BYTE; - SizeOfCode: DWORD; - SizeOfInitializedData: DWORD; - SizeOfUninitializedData: DWORD; - AddressOfEntryPoint: DWORD; - BaseOfCode: DWORD; - BaseOfData: DWORD; - ImageBase: DWORD; - SectionAlignment: DWORD; - FileAlignment: DWORD; - MajorOperatingSystemVersion: WORD; - MinorOperatingSystemVersion: WORD; - MajorImageVersion: WORD; - MinorImageVersion: WORD; - MajorSubsystemVersion: WORD; - MinorSubsystemVersion: WORD; - Win32VersionValue: DWORD; - SizeOfImage: DWORD; - SizeOfHeaders: DWORD; - CheckSum: DWORD; - Subsystem: WORD; - DllCharacteristics: WORD; - SizeOfStackReserve: DWORD; - SizeOfStackCommit: DWORD; - SizeOfHeapReserve: DWORD; - SizeOfHeapCommit: DWORD; - LoaderFlags: DWORD; - NumberOfRvaAndSizes: DWORD; - - DataDirectory: ARRAY IMAGE_NUMBEROF_DIRECTORY_ENTRIES OF IMAGE_DATA_DIRECTORY - - END; - - - IMAGE_FILE_HEADER* = RECORD - - Machine*: WORD; - NumberOfSections*: WORD; - TimeDateStamp*: DWORD; - PointerToSymbolTable*: DWORD; - NumberOfSymbols*: DWORD; - SizeOfOptionalHeader*: WORD; - Characteristics*: WORD - - END; - - - IMAGE_SECTION_HEADER* = RECORD - - Name*: NAME; - - VirtualSize*, - VirtualAddress*, - SizeOfRawData*, - PointerToRawData*, - PointerToRelocations*, - PointerToLinenumbers*: DWORD; - - NumberOfRelocations*, - NumberOfLinenumbers*: WORD; - - Characteristics*: DWORD - - END; - - - IMAGE_EXPORT_DIRECTORY = RECORD - - Characteristics: DWORD; - TimeDateStamp: DWORD; - MajorVersion: WORD; - MinorVersion: WORD; - Name, - Base, - NumberOfFunctions, - NumberOfNames, - AddressOfFunctions, - AddressOfNames, - AddressOfNameOrdinals: DWORD - - END; - - - VIRTUAL_ADDR* = RECORD - - Code*, Data*, Bss*, Import*: INTEGER - - END; - - -VAR - - Signature: ARRAY 4 OF BYTE; - FileHeader: IMAGE_FILE_HEADER; - OptionalHeader: IMAGE_OPTIONAL_HEADER; - - msdos: ARRAY 128 OF BYTE; - SectionHeaders: ARRAY 16 OF IMAGE_SECTION_HEADER; - libcnt: INTEGER; - SizeOfWord: INTEGER; - - -PROCEDURE Export (program: BIN.PROGRAM; name: INTEGER; VAR ExportDir: IMAGE_EXPORT_DIRECTORY): INTEGER; -BEGIN - - ExportDir.Characteristics := 0; - ExportDir.TimeDateStamp := FileHeader.TimeDateStamp; - ExportDir.MajorVersion := 0X; - ExportDir.MinorVersion := 0X; - ExportDir.Name := name; - ExportDir.Base := 0; - ExportDir.NumberOfFunctions := LISTS.count(program.exp_list); - ExportDir.NumberOfNames := ExportDir.NumberOfFunctions; - ExportDir.AddressOfFunctions := SIZE_OF_IMAGE_EXPORT_DIRECTORY; - ExportDir.AddressOfNames := ExportDir.AddressOfFunctions + ExportDir.NumberOfFunctions * SIZE_OF_DWORD; - ExportDir.AddressOfNameOrdinals := ExportDir.AddressOfNames + ExportDir.NumberOfFunctions * SIZE_OF_DWORD - - RETURN SIZE_OF_IMAGE_EXPORT_DIRECTORY + ExportDir.NumberOfFunctions * (2 * SIZE_OF_DWORD + SIZE_OF_WORD) -END Export; - - -PROCEDURE GetProcCount (lib: BIN.IMPRT): INTEGER; -VAR - imp: BIN.IMPRT; - res: INTEGER; - -BEGIN - res := 0; - imp := lib.next(BIN.IMPRT); - WHILE (imp # NIL) & (imp.label # 0) DO - INC(res); - imp := imp.next(BIN.IMPRT) - END - - RETURN res -END GetProcCount; - - -PROCEDURE GetImportSize (imp_list: LISTS.LIST): INTEGER; -VAR - imp: BIN.IMPRT; - proccnt: INTEGER; - procoffs: INTEGER; - OriginalCurrentThunk, - CurrentThunk: INTEGER; - -BEGIN - libcnt := 0; - proccnt := 0; - imp := imp_list.first(BIN.IMPRT); - WHILE imp # NIL DO - IF imp.label = 0 THEN - INC(libcnt) - ELSE - INC(proccnt) - END; - imp := imp.next(BIN.IMPRT) - END; - - procoffs := 0; - - imp := imp_list.first(BIN.IMPRT); - WHILE imp # NIL DO - IF imp.label = 0 THEN - imp.OriginalFirstThunk := procoffs; - imp.FirstThunk := procoffs + (GetProcCount(imp) + 1); - OriginalCurrentThunk := imp.OriginalFirstThunk; - CurrentThunk := imp.FirstThunk; - INC(procoffs, (GetProcCount(imp) + 1) * 2) - ELSE - imp.OriginalFirstThunk := OriginalCurrentThunk; - imp.FirstThunk := CurrentThunk; - INC(OriginalCurrentThunk); - INC(CurrentThunk) - END; - imp := imp.next(BIN.IMPRT) - END - - RETURN (libcnt + 1) * 5 * SIZE_OF_DWORD + (proccnt + libcnt) * 2 * SizeOfWord -END GetImportSize; - - -PROCEDURE fixup* (program: BIN.PROGRAM; Address: VIRTUAL_ADDR; amd64: BOOLEAN); -VAR - reloc: BIN.RELOC; - iproc: BIN.IMPRT; - code: CHL.BYTELIST; - L, delta, delta0, AdrImp, offset: INTEGER; - -BEGIN - AdrImp := Address.Import + (libcnt + 1) * 5 * SIZE_OF_DWORD; - code := program.code; - reloc := program.rel_list.first(BIN.RELOC); - delta0 := 3 - 7 * ORD(amd64) - Address.Code; - - WHILE reloc # NIL DO - - offset := reloc.offset; - L := BIN.get32le(code, offset); - delta := delta0 - offset; - - CASE reloc.opcode OF - |BIN.PICDATA: - INC(delta, L + Address.Data) - - |BIN.PICCODE: - INC(delta, BIN.GetLabel(program, L) + Address.Code) - - |BIN.PICBSS: - INC(delta, L + Address.Bss) - - |BIN.PICIMP: - iproc := BIN.GetIProc(program, L); - INC(delta, iproc.FirstThunk * SizeOfWord + AdrImp) - END; - BIN.put32le(code, offset, delta); - - reloc := reloc.next(BIN.RELOC) - END -END fixup; - - -PROCEDURE WriteWord (w: WORD); -BEGIN - WR.Write16LE(ORD(w)) -END WriteWord; - - -PROCEDURE WriteName* (name: NAME); -VAR - i, nameLen: INTEGER; - -BEGIN - nameLen := LENGTH(name); - - FOR i := 0 TO nameLen - 1 DO - WR.WriteByte(ORD(name[i])) - END; - - i := LEN(name) - nameLen; - WHILE i > 0 DO - WR.WriteByte(0); - DEC(i) - END - -END WriteName; - - -PROCEDURE WriteSectionHeader* (h: IMAGE_SECTION_HEADER); -VAR - i, nameLen: INTEGER; - -BEGIN - nameLen := LENGTH(h.Name); - - FOR i := 0 TO nameLen - 1 DO - WR.WriteByte(ORD(h.Name[i])) - END; - - i := LEN(h.Name) - nameLen; - WHILE i > 0 DO - WR.WriteByte(0); - DEC(i) - END; - - WR.Write32LE(h.VirtualSize); - WR.Write32LE(h.VirtualAddress); - WR.Write32LE(h.SizeOfRawData); - WR.Write32LE(h.PointerToRawData); - WR.Write32LE(h.PointerToRelocations); - WR.Write32LE(h.PointerToLinenumbers); - - WriteWord(h.NumberOfRelocations); - WriteWord(h.NumberOfLinenumbers); - - WR.Write32LE(h.Characteristics) -END WriteSectionHeader; - - -PROCEDURE WriteFileHeader* (h: IMAGE_FILE_HEADER); -BEGIN - WriteWord(h.Machine); - WriteWord(h.NumberOfSections); - - WR.Write32LE(h.TimeDateStamp); - WR.Write32LE(h.PointerToSymbolTable); - WR.Write32LE(h.NumberOfSymbols); - - WriteWord(h.SizeOfOptionalHeader); - WriteWord(h.Characteristics) -END WriteFileHeader; - - -PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; console, dll, amd64: BOOLEAN); -VAR - i, n, temp: INTEGER; - - Size: RECORD - - Code, Data, Bss, Import, Reloc, Export: INTEGER - - END; - - BaseAddress: INTEGER; - - Address: VIRTUAL_ADDR; - - _import: BIN.IMPRT; - ImportTable: CHL.INTLIST; - - ExportDir: IMAGE_EXPORT_DIRECTORY; - export: BIN.EXPRT; - - - PROCEDURE WriteExportDir (e: IMAGE_EXPORT_DIRECTORY); - BEGIN - WR.Write32LE(e.Characteristics); - WR.Write32LE(e.TimeDateStamp); - - WriteWord(e.MajorVersion); - WriteWord(e.MinorVersion); - - WR.Write32LE(e.Name); - WR.Write32LE(e.Base); - WR.Write32LE(e.NumberOfFunctions); - WR.Write32LE(e.NumberOfNames); - WR.Write32LE(e.AddressOfFunctions); - WR.Write32LE(e.AddressOfNames); - WR.Write32LE(e.AddressOfNameOrdinals) - END WriteExportDir; - - - PROCEDURE WriteOptHeader (h: IMAGE_OPTIONAL_HEADER; amd64: BOOLEAN); - VAR - i: INTEGER; - - BEGIN - WriteWord(h.Magic); - - WR.WriteByte(h.MajorLinkerVersion); - WR.WriteByte(h.MinorLinkerVersion); - - WR.Write32LE(h.SizeOfCode); - WR.Write32LE(h.SizeOfInitializedData); - WR.Write32LE(h.SizeOfUninitializedData); - WR.Write32LE(h.AddressOfEntryPoint); - WR.Write32LE(h.BaseOfCode); - - IF amd64 THEN - WR.Write64LE(h.ImageBase) - ELSE - WR.Write32LE(h.BaseOfData); - WR.Write32LE(h.ImageBase) - END; - - WR.Write32LE(h.SectionAlignment); - WR.Write32LE(h.FileAlignment); - - WriteWord(h.MajorOperatingSystemVersion); - WriteWord(h.MinorOperatingSystemVersion); - WriteWord(h.MajorImageVersion); - WriteWord(h.MinorImageVersion); - WriteWord(h.MajorSubsystemVersion); - WriteWord(h.MinorSubsystemVersion); - - WR.Write32LE(h.Win32VersionValue); - WR.Write32LE(h.SizeOfImage); - WR.Write32LE(h.SizeOfHeaders); - WR.Write32LE(h.CheckSum); - - WriteWord(h.Subsystem); - WriteWord(h.DllCharacteristics); - - IF amd64 THEN - WR.Write64LE(h.SizeOfStackReserve); - WR.Write64LE(h.SizeOfStackCommit); - WR.Write64LE(h.SizeOfHeapReserve); - WR.Write64LE(h.SizeOfHeapCommit) - ELSE - WR.Write32LE(h.SizeOfStackReserve); - WR.Write32LE(h.SizeOfStackCommit); - WR.Write32LE(h.SizeOfHeapReserve); - WR.Write32LE(h.SizeOfHeapCommit) - END; - - WR.Write32LE(h.LoaderFlags); - WR.Write32LE(h.NumberOfRvaAndSizes); - - FOR i := 0 TO LEN(h.DataDirectory) - 1 DO - WR.Write32LE(h.DataDirectory[i].VirtualAddress); - WR.Write32LE(h.DataDirectory[i].Size) - END - - END WriteOptHeader; - - - PROCEDURE InitSection (VAR section: IMAGE_SECTION_HEADER; Name: NAME; VirtualSize: INTEGER; Characteristics: DWORD); - BEGIN - section.Name := Name; - section.VirtualSize := VirtualSize; - section.SizeOfRawData := WR.align(VirtualSize, FileAlignment); - section.PointerToRelocations := 0; - section.PointerToLinenumbers := 0; - section.NumberOfRelocations := 0X; - section.NumberOfLinenumbers := 0X; - section.Characteristics := Characteristics - END InitSection; - - -BEGIN - SizeOfWord := SIZE_OF_DWORD * (ORD(amd64) + 1); - - Size.Code := CHL.Length(program.code); - Size.Data := CHL.Length(program.data); - Size.Bss := program.bss; - - IF dll THEN - BaseAddress := 10000000H - ELSE - BaseAddress := 400000H - END; - - Signature[0] := 50H; - Signature[1] := 45H; - Signature[2] := 0; - Signature[3] := 0; - - IF amd64 THEN - FileHeader.Machine := 08664X - ELSE - FileHeader.Machine := 014CX - END; - - FileHeader.NumberOfSections := WCHR(4 + ORD(dll)); - - FileHeader.TimeDateStamp := UTILS.UnixTime(); - FileHeader.PointerToSymbolTable := 0H; - FileHeader.NumberOfSymbols := 0H; - FileHeader.SizeOfOptionalHeader := WCHR(0E0H + 10H * ORD(amd64)); - FileHeader.Characteristics := WCHR(010EH + (20H - 100H) * ORD(amd64) + 2000H * ORD(dll)); - - OptionalHeader.Magic := WCHR(010BH + 100H * ORD(amd64)); - OptionalHeader.MajorLinkerVersion := UTILS.vMajor; - OptionalHeader.MinorLinkerVersion := UTILS.vMinor; - OptionalHeader.SizeOfCode := WR.align(Size.Code, FileAlignment); - OptionalHeader.SizeOfInitializedData := 0; - OptionalHeader.SizeOfUninitializedData := 0; - OptionalHeader.AddressOfEntryPoint := SectionAlignment; - OptionalHeader.BaseOfCode := SectionAlignment; - OptionalHeader.BaseOfData := OptionalHeader.BaseOfCode + WR.align(Size.Code, SectionAlignment); - OptionalHeader.ImageBase := BaseAddress; - OptionalHeader.SectionAlignment := SectionAlignment; - OptionalHeader.FileAlignment := FileAlignment; - OptionalHeader.MajorOperatingSystemVersion := 1X; - OptionalHeader.MinorOperatingSystemVersion := 0X; - OptionalHeader.MajorImageVersion := 0X; - OptionalHeader.MinorImageVersion := 0X; - OptionalHeader.MajorSubsystemVersion := 4X; - OptionalHeader.MinorSubsystemVersion := 0X; - OptionalHeader.Win32VersionValue := 0H; - OptionalHeader.SizeOfImage := SectionAlignment; - OptionalHeader.SizeOfHeaders := 400H; - OptionalHeader.CheckSum := 0; - OptionalHeader.Subsystem := WCHR((2 + ORD(console)) * ORD(~dll)); - OptionalHeader.DllCharacteristics := 0040X; - OptionalHeader.SizeOfStackReserve := 100000H; - OptionalHeader.SizeOfStackCommit := 10000H; - OptionalHeader.SizeOfHeapReserve := 100000H; - OptionalHeader.SizeOfHeapCommit := 10000H; - OptionalHeader.LoaderFlags := 0; - OptionalHeader.NumberOfRvaAndSizes := IMAGE_NUMBEROF_DIRECTORY_ENTRIES; - - FOR i := 0 TO IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 DO - OptionalHeader.DataDirectory[i].VirtualAddress := 0; - OptionalHeader.DataDirectory[i].Size := 0 - END; - - InitSection(SectionHeaders[0], ".text", Size.Code, SHC_text); - SectionHeaders[0].VirtualAddress := SectionAlignment; - SectionHeaders[0].PointerToRawData := OptionalHeader.SizeOfHeaders; - - InitSection(SectionHeaders[1], ".data", Size.Data, SHC_data); - SectionHeaders[1].VirtualAddress := WR.align(SectionHeaders[0].VirtualAddress + SectionHeaders[0].VirtualSize, SectionAlignment); - SectionHeaders[1].PointerToRawData := SectionHeaders[0].PointerToRawData + SectionHeaders[0].SizeOfRawData; - - InitSection(SectionHeaders[2], ".bss", Size.Bss, SHC_bss); - SectionHeaders[2].VirtualAddress := WR.align(SectionHeaders[1].VirtualAddress + SectionHeaders[1].VirtualSize, SectionAlignment); - SectionHeaders[2].PointerToRawData := SectionHeaders[1].PointerToRawData + SectionHeaders[1].SizeOfRawData; - SectionHeaders[2].SizeOfRawData := 0; - - Size.Import := GetImportSize(program.imp_list); - - InitSection(SectionHeaders[3], ".idata", Size.Import + CHL.Length(program._import), SHC_data); - SectionHeaders[3].VirtualAddress := WR.align(SectionHeaders[2].VirtualAddress + SectionHeaders[2].VirtualSize, SectionAlignment); - SectionHeaders[3].PointerToRawData := SectionHeaders[2].PointerToRawData + SectionHeaders[2].SizeOfRawData; - - Address.Code := SectionHeaders[0].VirtualAddress + OptionalHeader.ImageBase; - Address.Data := SectionHeaders[1].VirtualAddress + OptionalHeader.ImageBase; - Address.Bss := SectionHeaders[2].VirtualAddress + OptionalHeader.ImageBase; - Address.Import := SectionHeaders[3].VirtualAddress + OptionalHeader.ImageBase; - - fixup(program, Address, amd64); - - IF dll THEN - Size.Export := Export(program, SectionHeaders[1].VirtualAddress + program.modname, ExportDir); - - InitSection(SectionHeaders[4], ".edata", Size.Export + CHL.Length(program.export), SHC_data); - SectionHeaders[4].VirtualAddress := WR.align(SectionHeaders[3].VirtualAddress + SectionHeaders[3].VirtualSize, SectionAlignment); - SectionHeaders[4].PointerToRawData := SectionHeaders[3].PointerToRawData + SectionHeaders[3].SizeOfRawData; - - OptionalHeader.DataDirectory[0].VirtualAddress := SectionHeaders[4].VirtualAddress; - OptionalHeader.DataDirectory[0].Size := SectionHeaders[4].VirtualSize - END; - - OptionalHeader.DataDirectory[1].VirtualAddress := SectionHeaders[3].VirtualAddress; - OptionalHeader.DataDirectory[1].Size := SectionHeaders[3].VirtualSize; - - FOR i := 1 TO ORD(FileHeader.NumberOfSections) - 1 DO - INC(OptionalHeader.SizeOfInitializedData, SectionHeaders[i].SizeOfRawData) - END; - - OptionalHeader.SizeOfUninitializedData := WR.align(SectionHeaders[2].VirtualSize, FileAlignment); - - FOR i := 0 TO ORD(FileHeader.NumberOfSections) - 1 DO - INC(OptionalHeader.SizeOfImage, WR.align(SectionHeaders[i].VirtualSize, SectionAlignment)) - END; - - n := 0; - BIN.InitArray(msdos, n, "4D5A80000100000004001000FFFF000040010000000000004000000000000000"); - BIN.InitArray(msdos, n, "0000000000000000000000000000000000000000000000000000000080000000"); - BIN.InitArray(msdos, n, "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F"); - BIN.InitArray(msdos, n, "742062652072756E20696E20444F53206D6F64652E0D0A240000000000000000"); - - WR.Create(FileName); - - WR.Write(msdos, LEN(msdos)); - - WR.Write(Signature, LEN(Signature)); - WriteFileHeader(FileHeader); - WriteOptHeader(OptionalHeader, amd64); - - FOR i := 0 TO ORD(FileHeader.NumberOfSections) - 1 DO - WriteSectionHeader(SectionHeaders[i]) - END; - - WR.Padding(FileAlignment); - - CHL.WriteToFile(program.code); - WR.Padding(FileAlignment); - - CHL.WriteToFile(program.data); - WR.Padding(FileAlignment); - - n := (libcnt + 1) * 5; - ImportTable := CHL.CreateIntList(); - - FOR i := 0 TO (Size.Import - n * SIZE_OF_DWORD) DIV SizeOfWord + n - 1 DO - CHL.PushInt(ImportTable, 0) - END; - - i := 0; - _import := program.imp_list.first(BIN.IMPRT); - WHILE _import # NIL DO - IF _import.label = 0 THEN - CHL.SetInt(ImportTable, i + 0, _import.OriginalFirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); - CHL.SetInt(ImportTable, i + 1, 0); - CHL.SetInt(ImportTable, i + 2, 0); - CHL.SetInt(ImportTable, i + 3, _import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress); - CHL.SetInt(ImportTable, i + 4, _import.FirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); - INC(i, 5) - END; - _import := _import.next(BIN.IMPRT) - END; - - CHL.SetInt(ImportTable, i + 0, 0); - CHL.SetInt(ImportTable, i + 1, 0); - CHL.SetInt(ImportTable, i + 2, 0); - CHL.SetInt(ImportTable, i + 3, 0); - CHL.SetInt(ImportTable, i + 4, 0); - - _import := program.imp_list.first(BIN.IMPRT); - WHILE _import # NIL DO - IF _import.label # 0 THEN - temp := _import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress - 2; - CHL.SetInt(ImportTable, _import.OriginalFirstThunk + n, temp); - CHL.SetInt(ImportTable, _import.FirstThunk + n, temp) - END; - _import := _import.next(BIN.IMPRT) - END; - - FOR i := 0 TO n - 1 DO - WR.Write32LE(CHL.GetInt(ImportTable, i)) - END; - - FOR i := n TO CHL.Length(ImportTable) - 1 DO - IF amd64 THEN - WR.Write64LE(CHL.GetInt(ImportTable, i)) - ELSE - WR.Write32LE(CHL.GetInt(ImportTable, i)) - END - END; - - CHL.WriteToFile(program._import); - WR.Padding(FileAlignment); - - IF dll THEN - - INC(ExportDir.AddressOfFunctions, SectionHeaders[4].VirtualAddress); - INC(ExportDir.AddressOfNames, SectionHeaders[4].VirtualAddress); - INC(ExportDir.AddressOfNameOrdinals, SectionHeaders[4].VirtualAddress); - - WriteExportDir(ExportDir); - - export := program.exp_list.first(BIN.EXPRT); - WHILE export # NIL DO - WR.Write32LE(export.label + SectionHeaders[0].VirtualAddress); - export := export.next(BIN.EXPRT) - END; - - export := program.exp_list.first(BIN.EXPRT); - WHILE export # NIL DO - WR.Write32LE(export.nameoffs + Size.Export + SectionHeaders[4].VirtualAddress); - export := export.next(BIN.EXPRT) - END; - - FOR i := 0 TO ExportDir.NumberOfFunctions - 1 DO - WriteWord(WCHR(i)) - END; - - CHL.WriteToFile(program.export); - WR.Padding(FileAlignment) - END; - - WR.Close -END write; - - -END PE32. \ No newline at end of file diff --git a/programs/develop/oberon07/source/PROG.ob07 b/programs/develop/oberon07/source/PROG.ob07 deleted file mode 100644 index c1bfd4577..000000000 --- a/programs/develop/oberon07/source/PROG.ob07 +++ /dev/null @@ -1,1283 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2023, Anton Krotov - All rights reserved. -*) - -MODULE PROG; - -IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, IL, UTILS, TARGETS, STRINGS, PATHS; - - -CONST - - MAXARRDIM* = 5; - MAXSCOPE = 16; - MAXSYSVPARAM* = 26; - - idNONE* = 0; idGUARD = 1; idMODULE* = 2; idCONST* = 3; - idTYPE* = 4; idSTFUNC* = 5; idSTPROC* = 6; idVAR* = 7; - idPROC* = 8; idVPAR* = 9; idPARAM* = 10; idSYSFUNC* = 11; - idSYSPROC* = 12; idIMP* = 13; - - tINTEGER* = 1; tBYTE* = 2; tCHAR* = 3; tSET* = 4; - tBOOLEAN* = 5; tREAL* = 6; tARRAY* = 7; tRECORD* = 8; - tPOINTER* = 9; tPROCEDURE* = 10; tSTRING* = 11; tNIL* = 12; - tCARD32* = 13; tANYREC* = 14; tWCHAR* = 15; tNONE* = 16; - - BASICTYPES* = {tINTEGER, tBYTE, tCHAR, tSET, tBOOLEAN, tREAL, tCARD32, tWCHAR}; - - stABS* = 1; stASR* = 2; stCHR* = 3; stFLOOR* = 4; - stFLT* = 5; stLEN* = 6; stLSL* = 7; stODD* = 8; - stORD* = 9; stROR* = 10; stASSERT* = 11; stDEC* = 12; - stEXCL* = 13; stINC* = 14; stINCL* = 15; stNEW* = 16; - stPACK* = 17; stUNPK* = 18; sysADR* = 19; sysSIZE* = 20; - sysGET* = 21; sysPUT* = 22; - - stDISPOSE* = 23; stLSR* = 24; stBITS* = 25; sysCODE* = 26; - sysMOVE* = 27; stLENGTH* = 28; stMIN* = 29; stMAX* = 30; - sysSADR* = 31; sysTYPEID* = 32; sysCOPY* = 33; sysINF* = 34; - sysPUT8* = 35; sysPUT16* = 36; stCOPY* = 37; stWCHR* = 38; - sysWSADR* = 39; sysPUT32* = 40; (*sysNOP* = 41; sysEINT* = 42; - sysDINT* = 43;*)sysGET8* = 44; sysGET16* = 45; sysGET32* = 46; - sysVAL* = 47; - - default32* = 2; _default32* = default32 + 1; - stdcall* = 4; _stdcall* = stdcall + 1; - cdecl* = 6; _cdecl* = cdecl + 1; - ccall* = 8; _ccall* = ccall + 1; - win64* = 10; _win64* = win64 + 1; - default64* = 12; _default64* = default64 + 1; - systemv* = 14; _systemv* = systemv + 1; - default16* = 16; _default16* = default16 + 1; - code* = 18; _code* = code + 1; - fastcall* = 20; _fastcall* = fastcall + 1; - - noalign* = 22; - - callee_clean_up* = {default32, _default32, stdcall, _stdcall, default64, _default64, fastcall, _fastcall}; - - sf_stdcall* = 0; sf_oberon* = 1; sf_cdecl* = 2; sf_ccall* = 3; - sf_win64* = 4; sf_systemv* = 5; sf_windows* = 6; sf_linux* = 7; - sf_code* = 8; sf_fastcall* = 9; - sf_noalign* = 10; - - proc_flags* = {sf_stdcall, sf_cdecl, sf_ccall, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code, sf_oberon, sf_fastcall}; - rec_flags* = {sf_noalign}; - - STACK_FRAME = 2; - - -TYPE - - OPTIONS* = RECORD - - version*, stack*, ram*, rom*, tab*: INTEGER; - pic*, lower*, uses*: BOOLEAN; - checking*: SET - - END; - - IDENT* = POINTER TO rIDENT; - - UNIT* = POINTER TO rUNIT; - - _TYPE* = POINTER TO rTYPE; - - FRWPTR* = POINTER TO RECORD (LISTS.ITEM) - - _type: _TYPE; - baseIdent: SCAN.IDENT; - linked: BOOLEAN; - - pos*: SCAN.POSITION; - notRecord*: BOOLEAN - - END; - - PROC* = POINTER TO RECORD (LISTS.ITEM) - - label*: INTEGER; - used*: BOOLEAN; - processed*: BOOLEAN; - _import*: LISTS.ITEM; - using*: LISTS.LIST; - enter*, - leave*: LISTS.ITEM - - END; - - USED_PROC = POINTER TO RECORD (LISTS.ITEM) - - proc: PROC - - END; - - rUNIT = RECORD (LISTS.ITEM) - - fname*: PATHS.PATH; - name*: SCAN.IDENT; - idents*: LISTS.LIST; - frwPointers: LISTS.LIST; - gscope: IDENT; - closed*: BOOLEAN; - scopeLvl*: INTEGER; - sysimport*: BOOLEAN; - scopes*: ARRAY MAXSCOPE OF PROC - - END; - - FIELD* = POINTER TO rFIELD; - - PARAM* = POINTER TO rPARAM; - - rTYPE = RECORD (LISTS.ITEM) - - typ*: INTEGER; - size*: INTEGER; - parSize*: INTEGER; - length*: INTEGER; - align*: INTEGER; - base*: _TYPE; - fields*: LISTS.LIST; - params*: LISTS.LIST; - unit*: UNIT; - closed*: BOOLEAN; - num*: INTEGER; - call*: INTEGER; - _import*: BOOLEAN; - noalign*: BOOLEAN - - END; - - rFIELD = RECORD (LISTS.ITEM) - - _type*: _TYPE; - name*: SCAN.IDENT; - export*: BOOLEAN; - offset*: INTEGER - - END; - - rPARAM = RECORD (LISTS.ITEM) - - name*: SCAN.IDENT; - _type*: _TYPE; - vPar*: BOOLEAN; - offset*: INTEGER - - END; - - rIDENT = RECORD (LISTS.ITEM) - - name*: SCAN.IDENT; - typ*: INTEGER; - export*: BOOLEAN; - _import*: LISTS.ITEM; - unit*: UNIT; - value*: ARITH.VALUE; - _type*: _TYPE; - stproc*: INTEGER; - global*: BOOLEAN; - scopeLvl*: INTEGER; - offset*: INTEGER; - proc*: PROC; - pos*: SCAN.POSITION - - END; - - PROGRAM = RECORD - - recCount: INTEGER; - units*: LISTS.LIST; - types*: LISTS.LIST; - sysunit*: UNIT; - rtl*: UNIT; - bss*: INTEGER; - locsize*: INTEGER; - - procs*: LISTS.LIST; - - sysflags*: SET; - options*: OPTIONS; - - stTypes*: RECORD - - tINTEGER*, tBYTE*, tCHAR*, tWCHAR*, tSET*, tBOOLEAN*, tREAL*, - tSTRING*, tNIL*, tCARD32*, tANYREC*, tNONE*: _TYPE - - END - - END; - - DELIMPORT = PROCEDURE (_import: LISTS.ITEM); - - -VAR - - LowerCase*: BOOLEAN; - idents: C.COLLECTION; - program*: PROGRAM; - - -PROCEDURE NewIdent (): IDENT; -VAR - ident: IDENT; - citem: C.ITEM; - -BEGIN - citem := C.pop(idents); - IF citem = NIL THEN - NEW(ident) - ELSE - ident := citem(IDENT) - END - - RETURN ident -END NewIdent; - - -PROCEDURE getOffset* (varIdent: IDENT): INTEGER; -VAR - size, glob_align: INTEGER; - -BEGIN - IF varIdent.offset = -1 THEN - size := varIdent._type.size; - IF varIdent.global THEN - IF TARGETS.WinLin THEN - glob_align := 16 - ELSE - glob_align := varIdent._type.align - END; - IF UTILS.Align(program.bss, glob_align) THEN - IF UTILS.maxint - program.bss >= size THEN - varIdent.offset := program.bss; - INC(program.bss, size) - END - END - ELSE - IF UTILS.Align(size, TARGETS.WordSize) THEN - size := size DIV TARGETS.WordSize; - IF UTILS.maxint - program.locsize >= size THEN - INC(program.locsize, size); - varIdent.offset := program.locsize - END - END - END; - - IF varIdent.offset = -1 THEN - ERRORS.Error(204) - END - END - - RETURN varIdent.offset -END getOffset; - - -PROCEDURE closeUnit* (unit: UNIT); -VAR - ident, prev: IDENT; - offset: INTEGER; - -BEGIN - ident := unit.idents.last(IDENT); - WHILE (ident # NIL) & (ident.typ # idGUARD) DO - IF (ident.typ = idVAR) & (ident.offset = -1) THEN - ERRORS.HintMsg(ident.name.s, ident.pos.line, ident.pos.col, 0); - IF ident.export THEN - offset := getOffset(ident) - END - END; - ident := ident.prev(IDENT) - END; - - ident := unit.idents.last(IDENT); - WHILE ident # NIL DO - prev := ident.prev(IDENT); - IF ~ident.export THEN - LISTS.delete(unit.idents, ident); - C.push(idents, ident) - END; - ident := prev - END; - - unit.closed := TRUE -END closeUnit; - - -PROCEDURE IdEq* (a, b: SCAN.IDENT): BOOLEAN; - RETURN (a.hash = b.hash) & (a.s = b.s) -END IdEq; - - -PROCEDURE unique (unit: UNIT; ident: SCAN.IDENT): BOOLEAN; -VAR - item: IDENT; - -BEGIN - item := unit.idents.last(IDENT); - WHILE (item.typ # idGUARD) & ~IdEq(item.name, ident) DO - item := item.prev(IDENT) - END - - RETURN item.typ = idGUARD -END unique; - - -PROCEDURE addIdent* (unit: UNIT; ident: SCAN.IDENT; typ: INTEGER): IDENT; -VAR - item: IDENT; - res: BOOLEAN; - proc: PROC; - -BEGIN - ASSERT(unit # NIL); - - res := unique(unit, ident); - - IF res THEN - item := NewIdent(); - - item.name := ident; - item.typ := typ; - item.unit := NIL; - item.export := FALSE; - item._import := NIL; - item._type := NIL; - item.value.typ := 0; - item.stproc := 0; - - item.global := unit.scopeLvl = 0; - item.scopeLvl := unit.scopeLvl; - item.offset := -1; - - IF item.typ IN {idPROC, idIMP} THEN - NEW(proc); - proc._import := NIL; - proc.label := 0; - proc.used := FALSE; - proc.processed := FALSE; - proc.using := LISTS.create(NIL); - LISTS.push(program.procs, proc); - item.proc := proc - END; - - LISTS.push(unit.idents, item) - ELSE - item := NIL - END - - RETURN item -END addIdent; - - -PROCEDURE UseProc* (unit: UNIT; call_proc: PROC); -VAR - procs: LISTS.LIST; - cur: LISTS.ITEM; - proc: USED_PROC; - -BEGIN - IF unit.scopeLvl = 0 THEN - call_proc.used := TRUE - ELSE - procs := unit.scopes[unit.scopeLvl].using; - - cur := procs.first; - WHILE (cur # NIL) & (cur(USED_PROC).proc # call_proc) DO - cur := cur.next - END; - - IF cur = NIL THEN - NEW(proc); - proc.proc := call_proc; - LISTS.push(procs, proc) - END - END -END UseProc; - - -PROCEDURE setVarsType* (unit: UNIT; _type: _TYPE); -VAR - item: IDENT; - -BEGIN - ASSERT(_type # NIL); - - item := unit.idents.last(IDENT); - WHILE (item # NIL) & (item.typ = idVAR) & (item._type = NIL) DO - item._type := _type; - item := item.prev(IDENT) - END -END setVarsType; - - -PROCEDURE getIdent* (unit: UNIT; ident: SCAN.IDENT; currentScope: BOOLEAN): IDENT; -VAR - item: IDENT; - -BEGIN - item := unit.idents.last(IDENT); - - IF item # NIL THEN - - IF currentScope THEN - WHILE (item.typ # idGUARD) & ~IdEq(item.name, ident) DO - item := item.prev(IDENT) - END; - IF item.typ = idGUARD THEN - item := NIL - END - ELSE - WHILE (item # NIL) & ~IdEq(item.name, ident) DO - item := item.prev(IDENT) - END - END - - END - - RETURN item -END getIdent; - - -PROCEDURE openScope* (unit: UNIT; proc: PROC): BOOLEAN; -VAR - item: IDENT; - res: BOOLEAN; - -BEGIN - INC(unit.scopeLvl); - - res := unit.scopeLvl < MAXSCOPE; - - IF res THEN - - unit.scopes[unit.scopeLvl] := proc; - - NEW(item); - item := NewIdent(); - - item.name.s := ""; - item.name.hash := 0; - item.typ := idGUARD; - - LISTS.push(unit.idents, item) - END - - RETURN res -END openScope; - - -PROCEDURE closeScope* (unit: UNIT); -VAR - item: IDENT; - del: IDENT; - -BEGIN - item := unit.idents.last(IDENT); - - WHILE (item # NIL) & (item.typ # idGUARD) DO - del := item; - item := item.prev(IDENT); - IF (del.typ = idVAR) & (del.offset = -1) THEN - ERRORS.HintMsg(del.name.s, del.pos.line, del.pos.col, 0) - END; - LISTS.delete(unit.idents, del); - C.push(idents, del) - END; - - IF (item # NIL) & (item.typ = idGUARD) THEN - LISTS.delete(unit.idents, item); - C.push(idents, item) - END; - - DEC(unit.scopeLvl) -END closeScope; - - -PROCEDURE frwPtr* (unit: UNIT; _type: _TYPE; baseIdent: SCAN.IDENT; pos: SCAN.POSITION); -VAR - newptr: FRWPTR; - -BEGIN - ASSERT(unit # NIL); - ASSERT(_type # NIL); - - NEW(newptr); - - newptr._type := _type; - newptr.baseIdent := baseIdent; - newptr.pos := pos; - newptr.linked := FALSE; - newptr.notRecord := FALSE; - - LISTS.push(unit.frwPointers, newptr) -END frwPtr; - - -PROCEDURE linkPtr* (unit: UNIT): FRWPTR; -VAR - item: FRWPTR; - ident: IDENT; - res: FRWPTR; - -BEGIN - res := NIL; - item := unit.frwPointers.last(FRWPTR); - - WHILE (item # NIL) & ~item.linked & (res = NIL) DO - ident := getIdent(unit, item.baseIdent, TRUE); - - IF (ident # NIL) THEN - IF (ident.typ = idTYPE) & (ident._type.typ = tRECORD) THEN - item._type.base := ident._type; - item.linked := TRUE - ELSE - item.notRecord := TRUE; - res := item - END - ELSE - item.notRecord := FALSE; - res := item - END; - - item := item.prev(FRWPTR) - END - - RETURN res -END linkPtr; - - -PROCEDURE isTypeEq* (t1, t2: _TYPE): BOOLEAN; -VAR - res: BOOLEAN; - param1, param2: LISTS.ITEM; - -BEGIN - IF t1 = t2 THEN - res := TRUE - ELSIF (t1 = NIL) OR (t2 = NIL) THEN - res := FALSE - ELSIF (t1.typ = tPROCEDURE) & (t2.typ = tPROCEDURE) THEN - - param1 := t1.params.first; - param2 := t2.params.first; - - res := ((t1.call = t2.call) OR (t1.call IN {code, _code}) OR (t2.call IN {code, _code})) & ((param1 # NIL) = (param2 # NIL)); - - WHILE res & (param1 # NIL) & (param2 # NIL) DO - res := (param1(PARAM).vPar = param2(PARAM).vPar) & isTypeEq(param1(PARAM)._type, param2(PARAM)._type); - param1 := param1.next; - param2 := param2.next; - res := res & ((param1 # NIL) = (param2 # NIL)) - END; - - res := res & isTypeEq(t1.base, t2.base) - - ELSIF (t1.typ = tARRAY) & (t2.typ = tARRAY) THEN - res := (t1.length = 0) & (t2.length = 0) & isTypeEq(t1.base, t2.base) - ELSE - res := FALSE - END - - RETURN res -END isTypeEq; - - -PROCEDURE isBaseOf* (t0, t1: _TYPE): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - res := (t0.typ = t1.typ) & (t0.typ IN {tPOINTER, tRECORD}); - - IF res & (t0.typ = tPOINTER) THEN - t0 := t0.base; - t1 := t1.base - END; - - IF res THEN - WHILE (t1 # NIL) & (t1 # t0) DO - t1 := t1.base - END; - res := t1 # NIL - END - - RETURN res -END isBaseOf; - - -PROCEDURE isOpenArray* (t: _TYPE): BOOLEAN; - RETURN (t.typ = tARRAY) & (t.length = 0) -END isOpenArray; - - -PROCEDURE arrcomp* (src, dst: _TYPE): BOOLEAN; - RETURN (dst.typ = tARRAY) & isOpenArray(src) & - ~isOpenArray(src.base) & ~isOpenArray(dst.base) & - isTypeEq(src.base, dst.base) -END arrcomp; - - -PROCEDURE getUnit* (name: PATHS.PATH): UNIT; -VAR - item: UNIT; - -BEGIN - item := program.units.first(UNIT); - - WHILE (item # NIL) & (item.fname # name) DO - item := item.next(UNIT) - END; - - IF (item = NIL) & ((name = "SYSTEM") OR LowerCase & (name = "system")) THEN - item := program.sysunit - END - - RETURN item -END getUnit; - - -PROCEDURE enterStTypes (unit: UNIT); - - - PROCEDURE enter (unit: UNIT; nameStr: SCAN.IDSTR; _type: _TYPE); - VAR - ident: IDENT; - upper: SCAN.IDSTR; - name: SCAN.IDENT; - - BEGIN - IF LowerCase THEN - SCAN.setIdent(name, nameStr); - ident := addIdent(unit, name, idTYPE); - ident._type := _type - END; - upper := nameStr; - STRINGS.UpCase(upper); - SCAN.setIdent(name, upper); - ident := addIdent(unit, name, idTYPE); - ident._type := _type - END enter; - - -BEGIN - enter(unit, "integer", program.stTypes.tINTEGER); - enter(unit, "byte", program.stTypes.tBYTE); - enter(unit, "char", program.stTypes.tCHAR); - enter(unit, "set", program.stTypes.tSET); - enter(unit, "boolean", program.stTypes.tBOOLEAN); - - IF TARGETS.RealSize # 0 THEN - enter(unit, "real", program.stTypes.tREAL) - END; - - IF TARGETS.BitDepth >= 32 THEN - enter(unit, "wchar", program.stTypes.tWCHAR) - END -END enterStTypes; - - -PROCEDURE enterStProcs (unit: UNIT); - - - PROCEDURE Enter (unit: UNIT; nameStr: SCAN.IDSTR; nfunc, tfunc: INTEGER); - VAR - ident: IDENT; - upper: SCAN.IDSTR; - name: SCAN.IDENT; - - BEGIN - IF LowerCase THEN - SCAN.setIdent(name, nameStr); - ident := addIdent(unit, name, tfunc); - ident.stproc := nfunc; - ident._type := program.stTypes.tNONE - END; - upper := nameStr; - STRINGS.UpCase(upper); - SCAN.setIdent(name, upper); - ident := addIdent(unit, name, tfunc); - ident.stproc := nfunc; - ident._type := program.stTypes.tNONE - END Enter; - - -BEGIN - Enter(unit, "assert", stASSERT, idSTPROC); - Enter(unit, "dec", stDEC, idSTPROC); - Enter(unit, "excl", stEXCL, idSTPROC); - Enter(unit, "inc", stINC, idSTPROC); - Enter(unit, "incl", stINCL, idSTPROC); - Enter(unit, "new", stNEW, idSTPROC); - Enter(unit, "copy", stCOPY, idSTPROC); - - Enter(unit, "abs", stABS, idSTFUNC); - Enter(unit, "asr", stASR, idSTFUNC); - Enter(unit, "chr", stCHR, idSTFUNC); - Enter(unit, "len", stLEN, idSTFUNC); - Enter(unit, "lsl", stLSL, idSTFUNC); - Enter(unit, "odd", stODD, idSTFUNC); - Enter(unit, "ord", stORD, idSTFUNC); - Enter(unit, "ror", stROR, idSTFUNC); - Enter(unit, "bits", stBITS, idSTFUNC); - Enter(unit, "lsr", stLSR, idSTFUNC); - Enter(unit, "length", stLENGTH, idSTFUNC); - Enter(unit, "min", stMIN, idSTFUNC); - Enter(unit, "max", stMAX, idSTFUNC); - - IF TARGETS.RealSize # 0 THEN - Enter(unit, "pack", stPACK, idSTPROC); - Enter(unit, "unpk", stUNPK, idSTPROC); - Enter(unit, "floor", stFLOOR, idSTFUNC); - Enter(unit, "flt", stFLT, idSTFUNC) - END; - - IF TARGETS.BitDepth >= 32 THEN - Enter(unit, "wchr", stWCHR, idSTFUNC) - END; - - IF TARGETS.Dispose THEN - Enter(unit, "dispose", stDISPOSE, idSTPROC) - END - -END enterStProcs; - - -PROCEDURE newUnit* (name: SCAN.IDENT): UNIT; -VAR - unit: UNIT; - -BEGIN - NEW(unit); - - unit.name := name; - unit.closed := FALSE; - unit.idents := LISTS.create(NIL); - unit.frwPointers := LISTS.create(NIL); - - ASSERT(openScope(unit, NIL)); - - enterStTypes(unit); - enterStProcs(unit); - - ASSERT(openScope(unit, NIL)); - - unit.gscope := unit.idents.last(IDENT); - - LISTS.push(program.units, unit); - - unit.scopeLvl := 0; - unit.scopes[0] := NIL; - - unit.sysimport := FALSE; - - IF unit.name.s = UTILS.RTL_NAME THEN - program.rtl := unit - END - - RETURN unit -END newUnit; - - -PROCEDURE getField* (self: _TYPE; name: SCAN.IDENT; unit: UNIT): FIELD; -VAR - field: FIELD; - -BEGIN - ASSERT(self # NIL); - ASSERT(unit # NIL); - - field := NIL; - WHILE (self # NIL) & (field = NIL) DO - - field := self.fields.first(FIELD); - - WHILE (field # NIL) & ~IdEq(field.name, name) DO - field := field.next(FIELD) - END; - - IF field = NIL THEN - self := self.base - END - - END; - - IF (field # NIL) & (self.unit # unit) & ~field.export THEN - field := NIL - END - - RETURN field -END getField; - - -PROCEDURE addField* (self: _TYPE; name: SCAN.IDENT; export: BOOLEAN): BOOLEAN; -VAR - field: FIELD; - res: BOOLEAN; - -BEGIN - res := getField(self, name, self.unit) = NIL; - - IF res THEN - NEW(field); - - field.name := name; - field.export := export; - field._type := NIL; - field.offset := self.size; - - LISTS.push(self.fields, field) - END - - RETURN res -END addField; - - -PROCEDURE setFields* (self: _TYPE; _type: _TYPE): BOOLEAN; -VAR - item: FIELD; - res: BOOLEAN; - -BEGIN - ASSERT(_type # NIL); - - item := self.fields.first(FIELD); - - WHILE (item # NIL) & (item._type # NIL) DO - item := item.next(FIELD) - END; - - res := TRUE; - - WHILE res & (item # NIL) & (item._type = NIL) DO - item._type := _type; - IF ~self.noalign THEN - res := UTILS.Align(self.size, _type.align) - ELSE - res := TRUE - END; - item.offset := self.size; - res := res & (UTILS.maxint - self.size >= _type.size); - IF res THEN - INC(self.size, _type.size) - END; - item := item.next(FIELD) - END - - RETURN res -END setFields; - - -PROCEDURE getParam* (self: _TYPE; name: SCAN.IDENT): PARAM; -VAR - item: PARAM; - -BEGIN - item := self.params.first(PARAM); - - WHILE (item # NIL) & ~IdEq(item.name, name) DO - item := item.next(PARAM) - END - - RETURN item -END getParam; - - -PROCEDURE addParam* (self: _TYPE; name: SCAN.IDENT; vPar: BOOLEAN): BOOLEAN; -VAR - param: PARAM; - res: BOOLEAN; - -BEGIN - res := getParam(self, name) = NIL; - - IF res THEN - NEW(param); - - param.name := name; - param._type := NIL; - param.vPar := vPar; - - LISTS.push(self.params, param) - END - - RETURN res -END addParam; - - -PROCEDURE Dim* (t: _TYPE): INTEGER; -VAR - res: INTEGER; - -BEGIN - res := 0; - WHILE isOpenArray(t) DO - t := t.base; - INC(res) - END - RETURN res -END Dim; - - -PROCEDURE OpenBase* (t: _TYPE): _TYPE; -BEGIN - WHILE isOpenArray(t) DO t := t.base END - RETURN t -END OpenBase; - - -PROCEDURE getFloatParamsPos* (self: _TYPE; maxoffs: INTEGER; VAR int, flt: INTEGER): SET; -VAR - res: SET; - param: PARAM; - -BEGIN - res := {}; - int := 0; - flt := 0; - param := self.params.first(PARAM); - WHILE (param # NIL) & (param.offset <= maxoffs + STACK_FRAME) DO - IF ~param.vPar & (param._type.typ = tREAL) THEN - INCL(res, param.offset - STACK_FRAME); - INC(flt) - END; - param := param.next(PARAM) - END; - - int := self.parSize - flt - - RETURN res -END getFloatParamsPos; - - -PROCEDURE setParams* (self: _TYPE; _type: _TYPE); -VAR - item: LISTS.ITEM; - param: PARAM; - word, size: INTEGER; - -BEGIN - ASSERT(_type # NIL); - - word := UTILS.target.bit_depth DIV 8; - - item := self.params.first; - - WHILE (item # NIL) & (item(PARAM)._type # NIL) DO - item := item.next - END; - - WHILE (item # NIL) & (item(PARAM)._type = NIL) DO - param := item(PARAM); - param._type := _type; - IF param.vPar THEN - IF _type.typ = tRECORD THEN - size := 2 - ELSIF isOpenArray(_type) THEN - size := Dim(_type) + 1 - ELSE - size := 1 - END; - param.offset := self.parSize + ORD(_type.typ = tRECORD) + Dim(_type) + STACK_FRAME; - INC(self.parSize, size) - ELSE - IF _type.typ IN {tRECORD, tARRAY} THEN - IF isOpenArray(_type) THEN - size := Dim(_type) + 1 - ELSE - size := 1 - END - ELSE - size := _type.size; - ASSERT(UTILS.Align(size, word)); - size := size DIV word - END; - param.offset := self.parSize + Dim(_type) + STACK_FRAME; - INC(self.parSize, size) - END; - - item := item.next - END - -END setParams; - - -PROCEDURE enterType* (typ, size, length: INTEGER; unit: UNIT): _TYPE; -VAR - t: _TYPE; - -BEGIN - NEW(t); - - t.typ := typ; - t.size := size; - t.length := length; - t.align := 0; - t.base := NIL; - t.fields := LISTS.create(NIL); - t.params := LISTS.create(NIL); - t.unit := unit; - t.num := 0; - - CASE TARGETS.BitDepth OF - |16: t.call := default16 - |32: t.call := default32 - |64: t.call := default64 - END; - - t._import := FALSE; - t.noalign := FALSE; - t.parSize := 0; - - IF typ IN {tARRAY, tRECORD} THEN - t.closed := FALSE; - IF typ = tRECORD THEN - INC(program.recCount); - t.num := program.recCount - END - ELSE - t.closed := TRUE - END; - - LISTS.push(program.types, t) - - RETURN t -END enterType; - - -PROCEDURE getType* (typ: INTEGER): _TYPE; -VAR - res: _TYPE; - -BEGIN - - CASE typ OF - |ARITH.tINTEGER: res := program.stTypes.tINTEGER - |ARITH.tREAL: res := program.stTypes.tREAL - |ARITH.tSET: res := program.stTypes.tSET - |ARITH.tBOOLEAN: res := program.stTypes.tBOOLEAN - |ARITH.tCHAR: res := program.stTypes.tCHAR - |ARITH.tWCHAR: res := program.stTypes.tWCHAR - |ARITH.tSTRING: res := program.stTypes.tSTRING - END - - RETURN res -END getType; - - -PROCEDURE createSysUnit; -VAR - ident: IDENT; - unit: UNIT; - name: SCAN.IDENT; - - - PROCEDURE EnterProc (sys: UNIT; nameStr: SCAN.IDSTR; idtyp, proc: INTEGER); - VAR - ident: IDENT; - upper: SCAN.IDSTR; - name: SCAN.IDENT; - - BEGIN - IF LowerCase THEN - SCAN.setIdent(name, nameStr); - ident := addIdent(sys, name, idtyp); - ident.stproc := proc; - ident._type := program.stTypes.tNONE; - ident.export := TRUE - END; - upper := nameStr; - STRINGS.UpCase(upper); - SCAN.setIdent(name, upper); - ident := addIdent(sys, name, idtyp); - ident.stproc := proc; - ident._type := program.stTypes.tNONE; - ident.export := TRUE - END EnterProc; - - -BEGIN - SCAN.setIdent(name, "$SYSTEM"); - unit := newUnit(name); - unit.fname := "SYSTEM"; - - EnterProc(unit, "adr", idSYSFUNC, sysADR); - EnterProc(unit, "size", idSYSFUNC, sysSIZE); - EnterProc(unit, "sadr", idSYSFUNC, sysSADR); - EnterProc(unit, "typeid", idSYSFUNC, sysTYPEID); - - EnterProc(unit, "get", idSYSPROC, sysGET); - EnterProc(unit, "get8", idSYSPROC, sysGET8); - EnterProc(unit, "put", idSYSPROC, sysPUT); - EnterProc(unit, "put8", idSYSPROC, sysPUT8); - EnterProc(unit, "code", idSYSPROC, sysCODE); - EnterProc(unit, "move", idSYSPROC, sysMOVE); - EnterProc(unit, "val", idSYSPROC, sysVAL); - (* - IF program.target.sys = mConst.Target_iMSP430 THEN - EnterProc(unit, "nop", idSYSPROC, sysNOP); - EnterProc(unit, "eint", idSYSPROC, sysEINT); - EnterProc(unit, "dint", idSYSPROC, sysDINT) - END; - *) - IF TARGETS.RealSize # 0 THEN - EnterProc(unit, "inf", idSYSFUNC, sysINF); - END; - - IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN - EnterProc(unit, "copy", idSYSPROC, sysCOPY) - END; - - IF TARGETS.BitDepth >= 32 THEN - EnterProc(unit, "wsadr", idSYSFUNC, sysWSADR); - EnterProc(unit, "put16", idSYSPROC, sysPUT16); - EnterProc(unit, "put32", idSYSPROC, sysPUT32); - EnterProc(unit, "get16", idSYSPROC, sysGET16); - EnterProc(unit, "get32", idSYSPROC, sysGET32); - - IF LowerCase THEN - SCAN.setIdent(name, "card32"); - ident := addIdent(unit, name, idTYPE); - ident._type := program.stTypes.tCARD32; - ident.export := TRUE - END; - SCAN.setIdent(name, "CARD32"); - ident := addIdent(unit, name, idTYPE); - ident._type := program.stTypes.tCARD32; - ident.export := TRUE; - END; - - closeUnit(unit); - - program.sysunit := unit -END createSysUnit; - - -PROCEDURE DelUnused* (DelImport: DELIMPORT); -VAR - proc: PROC; - flag: BOOLEAN; - - - PROCEDURE process (proc: PROC); - VAR - used_proc: LISTS.ITEM; - - BEGIN - proc.processed := TRUE; - - used_proc := proc.using.first; - WHILE used_proc # NIL DO - used_proc(USED_PROC).proc.used := TRUE; - used_proc := used_proc.next - END - - END process; - - -BEGIN - - REPEAT - flag := FALSE; - proc := program.procs.first(PROC); - - WHILE proc # NIL DO - IF proc.used & ~proc.processed THEN - process(proc); - flag := TRUE - END; - proc := proc.next(PROC) - END - - UNTIL ~flag; - - proc := program.procs.first(PROC); - - WHILE proc # NIL DO - IF ~proc.used THEN - IF proc._import = NIL THEN - IL.delete2(proc.enter, proc.leave) - ELSE - DelImport(proc._import) - END - END; - proc := proc.next(PROC) - END - -END DelUnused; - - -PROCEDURE ResetLocSize*; -BEGIN - program.locsize := 0 -END ResetLocSize; - - -PROCEDURE create* (options: OPTIONS); -BEGIN - LowerCase := options.lower; - SCAN.init(options.lower); - idents := C.create(); - - UTILS.SetBitDepth(TARGETS.BitDepth, TARGETS.RealSize = 8); - - program.options := options; - - CASE TARGETS.OS OF - |TARGETS.osWIN32: program.sysflags := {sf_oberon, sf_windows, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign} - |TARGETS.osLINUX32: program.sysflags := {sf_oberon, sf_linux, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign} - |TARGETS.osKOS: program.sysflags := {sf_oberon, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign} - |TARGETS.osWIN64: program.sysflags := {sf_oberon, sf_windows, sf_win64, sf_systemv, sf_ccall, sf_noalign} - |TARGETS.osLINUX64: program.sysflags := {sf_oberon, sf_linux, sf_win64, sf_systemv, sf_ccall, sf_noalign} - |TARGETS.osNONE: program.sysflags := {sf_code} - END; - - program.recCount := -1; - program.bss := 0; - - program.units := LISTS.create(NIL); - program.types := LISTS.create(NIL); - program.procs := LISTS.create(NIL); - - program.stTypes.tINTEGER := enterType(tINTEGER, TARGETS.WordSize, 0, NIL); - program.stTypes.tBYTE := enterType(tBYTE, 1, 0, NIL); - program.stTypes.tCHAR := enterType(tCHAR, 1, 0, NIL); - program.stTypes.tSET := enterType(tSET, TARGETS.WordSize, 0, NIL); - program.stTypes.tBOOLEAN := enterType(tBOOLEAN, 1, 0, NIL); - - program.stTypes.tINTEGER.align := TARGETS.WordSize; - program.stTypes.tBYTE.align := 1; - program.stTypes.tCHAR.align := 1; - program.stTypes.tSET.align := TARGETS.WordSize; - program.stTypes.tBOOLEAN.align := 1; - - IF TARGETS.BitDepth >= 32 THEN - program.stTypes.tWCHAR := enterType(tWCHAR, 2, 0, NIL); - program.stTypes.tCARD32 := enterType(tCARD32, 4, 0, NIL); - program.stTypes.tWCHAR.align := 2; - program.stTypes.tCARD32.align := 4 - END; - - IF TARGETS.RealSize # 0 THEN - program.stTypes.tREAL := enterType(tREAL, TARGETS.RealSize, 0, NIL); - IF TARGETS.OS = TARGETS.osLINUX32 THEN - program.stTypes.tREAL.align := 4 - ELSE - program.stTypes.tREAL.align := TARGETS.RealSize - END - END; - - program.stTypes.tSTRING := enterType(tSTRING, TARGETS.WordSize, 0, NIL); - program.stTypes.tNIL := enterType(tNIL, TARGETS.WordSize, 0, NIL); - program.stTypes.tNONE := enterType(tNONE, 0, 0, NIL); - program.stTypes.tANYREC := enterType(tRECORD, 0, 0, NIL); - program.stTypes.tANYREC.closed := TRUE; - - createSysUnit -END create; - - -END PROG. \ No newline at end of file diff --git a/programs/develop/oberon07/source/REG.ob07 b/programs/develop/oberon07/source/REG.ob07 deleted file mode 100644 index 06aab4fe1..000000000 --- a/programs/develop/oberon07/source/REG.ob07 +++ /dev/null @@ -1,286 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE REG; - - -CONST - - N = 16; - - R0* = 0; R1* = 1; R2* = 2; R3* = 3; - R4* = 4; R5* = 5; R6* = 6; R7* = 7; - R8* = 8; R9* = 9; R10* = 10; R11* = 11; - R12* = 12; R13* = 13; R14* = 14; R15* = 15; - - -TYPE - - OP1 = PROCEDURE (arg: INTEGER); - OP2 = PROCEDURE (arg1, arg2: INTEGER); - - REGS* = RECORD - - regs*: SET; - stk*: ARRAY N OF INTEGER; - top*: INTEGER; - pushed*: INTEGER; - - push, pop: OP1; - mov, xch: OP2 - - END; - - -PROCEDURE push (VAR R: REGS); -VAR - i, reg: INTEGER; - -BEGIN - reg := R.stk[0]; - INCL(R.regs, reg); - R.push(reg); - FOR i := 0 TO R.top - 1 DO - R.stk[i] := R.stk[i + 1] - END; - DEC(R.top); - INC(R.pushed) -END push; - - -PROCEDURE pop (VAR R: REGS; reg: INTEGER); -VAR - i: INTEGER; - -BEGIN - FOR i := R.top + 1 TO 1 BY -1 DO - R.stk[i] := R.stk[i - 1] - END; - R.stk[0] := reg; - EXCL(R.regs, reg); - R.pop(reg); - INC(R.top); - DEC(R.pushed) -END pop; - - -PROCEDURE InStk (R: REGS; reg: INTEGER): INTEGER; -VAR - i: INTEGER; - -BEGIN - i := R.top; - WHILE (i >= 0) & (R.stk[i] # reg) DO - DEC(i) - END - - RETURN i -END InStk; - - -PROCEDURE GetFreeReg (R: REGS): INTEGER; -VAR - i: INTEGER; - -BEGIN - i := 0; - WHILE (i < N) & ~(i IN R.regs) DO - INC(i) - END; - - IF i = N THEN - i := -1 - END - - RETURN i -END GetFreeReg; - - -PROCEDURE Put (VAR R: REGS; reg: INTEGER); -BEGIN - EXCL(R.regs, reg); - INC(R.top); - R.stk[R.top] := reg -END Put; - - -PROCEDURE PopAnyReg (VAR R: REGS): INTEGER; -VAR - reg: INTEGER; - -BEGIN - reg := GetFreeReg(R); - ASSERT(reg # -1); - ASSERT(R.top < LEN(R.stk) - 1); - ASSERT(R.pushed > 0); - pop(R, reg) - - RETURN reg -END PopAnyReg; - - -PROCEDURE GetAnyReg* (VAR R: REGS): INTEGER; -VAR - reg: INTEGER; - -BEGIN - reg := GetFreeReg(R); - IF reg = -1 THEN - ASSERT(R.top >= 0); - reg := R.stk[0]; - push(R) - END; - - Put(R, reg) - - RETURN reg -END GetAnyReg; - - -PROCEDURE GetReg* (VAR R: REGS; reg: INTEGER): BOOLEAN; -VAR - free: INTEGER; - res: BOOLEAN; - - - PROCEDURE exch (VAR R: REGS; reg1, reg2: INTEGER); - VAR - n1, n2: INTEGER; - - BEGIN - n1 := InStk(R, reg1); - n2 := InStk(R, reg2); - R.stk[n1] := reg2; - R.stk[n2] := reg1; - R.xch(reg1, reg2) - END exch; - - -BEGIN - IF reg IN R.regs THEN - Put(R, reg); - res := TRUE - ELSE - res := InStk(R, reg) # -1; - IF res THEN - free := GetFreeReg(R); - IF free # -1 THEN - Put(R, free); - exch(R, reg, free) - ELSE - push(R); - free := GetFreeReg(R); - ASSERT(free # -1); - Put(R, free); - IF free # reg THEN - exch(R, reg, free) - END - END - END - END - - RETURN res -END GetReg; - - -PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN; -VAR - n1, n2: INTEGER; - res: BOOLEAN; - -BEGIN - res := TRUE; - - IF reg1 # reg2 THEN - n1 := InStk(R, reg1); - n2 := InStk(R, reg2); - - IF (n1 # -1) & (n2 # -1) THEN - R.stk[n1] := reg2; - R.stk[n2] := reg1; - R.xch(reg2, reg1) - ELSIF (n1 # -1) & (reg2 IN R.regs) THEN - R.stk[n1] := reg2; - INCL(R.regs, reg1); - EXCL(R.regs, reg2); - R.mov(reg2, reg1) - ELSIF (n2 # -1) & (reg1 IN R.regs) THEN - R.stk[n2] := reg1; - EXCL(R.regs, reg1); - INCL(R.regs, reg2); - R.mov(reg1, reg2) - ELSE - res := FALSE - END - END - - RETURN res -END Exchange; - - -PROCEDURE Drop* (VAR R: REGS); -BEGIN - INCL(R.regs, R.stk[R.top]); - DEC(R.top) -END Drop; - - -PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER); -BEGIN - IF R.top > 0 THEN - reg1 := R.stk[R.top - 1]; - reg2 := R.stk[R.top] - ELSIF R.top = 0 THEN - reg1 := PopAnyReg(R); - reg2 := R.stk[1] - ELSE (* R.top = -1 *) - reg2 := PopAnyReg(R); - reg1 := PopAnyReg(R) - END -END BinOp; - - -PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER); -BEGIN - IF R.top >= 0 THEN - reg := R.stk[R.top] - ELSE - reg := PopAnyReg(R) - END -END UnOp; - - -PROCEDURE PushAll* (VAR R: REGS); -BEGIN - WHILE R.top >= 0 DO - push(R) - END -END PushAll; - - -PROCEDURE PushAll_1* (VAR R: REGS); -BEGIN - WHILE R.top >= 1 DO - push(R) - END -END PushAll_1; - - -PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; regs: SET); -BEGIN - R.regs := regs; - R.pushed := 0; - R.top := -1; - - R.push := push; - R.pop := pop; - R.mov := mov; - R.xch := xch; -END Init; - - -END REG. \ No newline at end of file diff --git a/programs/develop/oberon07/source/RVMxI.ob07 b/programs/develop/oberon07/source/RVMxI.ob07 deleted file mode 100644 index 53bb5a86b..000000000 --- a/programs/develop/oberon07/source/RVMxI.ob07 +++ /dev/null @@ -1,1415 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020-2022, Anton Krotov - All rights reserved. -*) - -MODULE RVMxI; - -IMPORT - - PROG, WR := WRITER, IL, CHL := CHUNKLISTS, REG, UTILS, STRINGS, ERRORS, TARGETS; - - -CONST - - LTypes = 0; - LStrings = 1; - LGlobal = 2; - LHeap = 3; - LStack = 4; - - numGPRs = 3; - - R0 = 0; R1 = 1; - BP = 3; SP = 4; - - ACC = R0; - - GPRs = {0 .. 2} + {5 .. numGPRs + 1}; - - opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opNOP = 5; - opXCHG = 6; opLDB = 7; opLDH = 8; opLDW = 9; opPUSH = 10; opPUSHC = 11; - opPOP = 12; opLABEL = 13; opLEA = 14; opLLA = 15; - opLDD = 16; (* 17, 18 *) - opJMP = 19; opCALL = 20; opCALLI = 21; - - opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32; - opSTB = 34; opSTH = 36; opSTW = 38; opSTD = 40; (* 42, 44 *) - opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54; - opLSL = 56; opROR = 58; (* 60, 62 *) opCMP = 64; - - opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33; - opSTBC = 35; opSTHC = 37; opSTWC = 39; opSTDC = 41; (* 43, 45 *) - opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55; - opLSLC = 57; opRORC = 59; (* 61, 63 *) opCMPC = 65; - - opBIT = 66; opSYSCALL = 67; opJBT = 68; opADDRC = 69; - - opJEQ = 70; opJNE = 71; opJLT = 72; opJGE = 73; opJGT = 74; opJLE = 75; - opSEQ = 76; opSNE = 77; opSLT = 78; opSGE = 79; opSGT = 80; opSLE = 81; - - -VAR - - R: REG.REGS; count, szWord: INTEGER; - - ldr, str: PROCEDURE (r1, r2: INTEGER); - - -PROCEDURE OutByte (n: BYTE); -BEGIN - WR.WriteByte(n); - INC(count) -END OutByte; - - -PROCEDURE OutInt (n: INTEGER); -BEGIN - IF szWord = 8 THEN - WR.Write64LE(n); - INC(count, 8) - ELSE (* szWord = 4 *) - WR.Write32LE(n); - INC(count, 4) - END -END OutInt; - - -PROCEDURE Emit (op, par1, par2: INTEGER); -BEGIN - OutInt(op); - OutInt(par1); - OutInt(par2) -END Emit; - - -PROCEDURE drop; -BEGIN - REG.Drop(R) -END drop; - - -PROCEDURE GetAnyReg (): INTEGER; - RETURN REG.GetAnyReg(R) -END GetAnyReg; - - -PROCEDURE GetAcc; -BEGIN - ASSERT(REG.GetReg(R, ACC)) -END GetAcc; - - -PROCEDURE UnOp (VAR r: INTEGER); -BEGIN - REG.UnOp(R, r) -END UnOp; - - -PROCEDURE BinOp (VAR r1, r2: INTEGER); -BEGIN - REG.BinOp(R, r1, r2) -END BinOp; - - -PROCEDURE PushAll (NumberOfParameters: INTEGER); -BEGIN - REG.PushAll(R); - DEC(R.pushed, NumberOfParameters) -END PushAll; - - -PROCEDURE push (r: INTEGER); -BEGIN - Emit(opPUSH, r, 0) -END push; - - -PROCEDURE pop (r: INTEGER); -BEGIN - Emit(opPOP, r, 0) -END pop; - - -PROCEDURE mov (r1, r2: INTEGER); -BEGIN - Emit(opMOV, r1, r2) -END mov; - - -PROCEDURE xchg (r1, r2: INTEGER); -BEGIN - Emit(opXCHG, r1, r2) -END xchg; - - -PROCEDURE addrc (r, c: INTEGER); -BEGIN - Emit(opADDC, r, c) -END addrc; - - -PROCEDURE subrc (r, c: INTEGER); -BEGIN - Emit(opSUBC, r, c) -END subrc; - - -PROCEDURE movrc (r, c: INTEGER); -BEGIN - Emit(opMOVC, r, c) -END movrc; - - -PROCEDURE pushc (c: INTEGER); -BEGIN - Emit(opPUSHC, c, 0) -END pushc; - - -PROCEDURE add (r1, r2: INTEGER); -BEGIN - Emit(opADD, r1, r2) -END add; - - -PROCEDURE sub (r1, r2: INTEGER); -BEGIN - Emit(opSUB, r1, r2) -END sub; - - -PROCEDURE ldr64 (r1, r2: INTEGER); -BEGIN - Emit(opLDD, r2 * 256 + r1, 0) -END ldr64; - - -PROCEDURE ldr32 (r1, r2: INTEGER); -BEGIN - Emit(opLDW, r2 * 256 + r1, 0) -END ldr32; - - -PROCEDURE ldr16 (r1, r2: INTEGER); -BEGIN - Emit(opLDH, r2 * 256 + r1, 0) -END ldr16; - - -PROCEDURE ldr8 (r1, r2: INTEGER); -BEGIN - Emit(opLDB, r2 * 256 + r1, 0) -END ldr8; - - -PROCEDURE str64 (r1, r2: INTEGER); -BEGIN - Emit(opSTD, r1 * 256 + r2, 0) -END str64; - - -PROCEDURE str32 (r1, r2: INTEGER); -BEGIN - Emit(opSTW, r1 * 256 + r2, 0) -END str32; - - -PROCEDURE str16 (r1, r2: INTEGER); -BEGIN - Emit(opSTH, r1 * 256 + r2, 0) -END str16; - - -PROCEDURE str8 (r1, r2: INTEGER); -BEGIN - Emit(opSTB, r1 * 256 + r2, 0) -END str8; - - -PROCEDURE GlobalAdr (r, offset: INTEGER); -BEGIN - Emit(opLEA, r + 256 * LGlobal, offset) -END GlobalAdr; - - -PROCEDURE StrAdr (r, offset: INTEGER); -BEGIN - Emit(opLEA, r + 256 * LStrings, offset) -END StrAdr; - - -PROCEDURE ProcAdr (r, label: INTEGER); -BEGIN - Emit(opLLA, r, label) -END ProcAdr; - - -PROCEDURE jnz (r, label: INTEGER); -BEGIN - Emit(opCMPC, r, 0); - Emit(opJNE, label, 0) -END jnz; - - -PROCEDURE CallRTL (proc, par: INTEGER); -BEGIN - Emit(opCALL, IL.codes.rtl[proc], 0); - addrc(SP, par * szWord) -END CallRTL; - - -PROCEDURE jcc (cc: INTEGER): INTEGER; -BEGIN - CASE cc OF - |IL.opEQ, IL.opEQC: cc := opJEQ - |IL.opNE, IL.opNEC: cc := opJNE - |IL.opLT, IL.opLTC: cc := opJLT - |IL.opLE, IL.opLEC: cc := opJLE - |IL.opGT, IL.opGTC: cc := opJGT - |IL.opGE, IL.opGEC: cc := opJGE - END - RETURN cc -END jcc; - - -PROCEDURE shift1 (op, param: INTEGER); -VAR - r1, r2: INTEGER; - -BEGIN - r2 := GetAnyReg(); - Emit(opMOVC, r2, param); - BinOp(r1, r2); - Emit(op, r2, r1); - mov(r1, r2); - drop -END shift1; - - -PROCEDURE shift (op: INTEGER); -VAR - r1, r2: INTEGER; - -BEGIN - BinOp(r1, r2); - Emit(op, r1, r2); - drop -END shift; - - -PROCEDURE translate (szWord: INTEGER); -VAR - cmd, next: IL.COMMAND; - - opcode, param1, param2, r1, r2, r3, - a, b, label, opLD, opST, opSTC: INTEGER; - -BEGIN - IF szWord = 8 THEN - opLD := opLDD; - opST := opSTD; - opSTC := opSTDC - ELSE - opLD := opLDW; - opST := opSTW; - opSTC := opSTWC - END; - - cmd := IL.codes.commands.first(IL.COMMAND); - - WHILE cmd # NIL DO - - param1 := cmd.param1; - param2 := cmd.param2; - opcode := cmd.opcode; - - CASE opcode OF - - |IL.opJMP: - Emit(opJMP, param1, 0) - - |IL.opLABEL: - Emit(opLABEL, param1, 0) - - |IL.opCALL: - Emit(opCALL, param1, 0) - - |IL.opCALLP: - UnOp(r1); - Emit(opCALLI, r1, 0); - drop; - ASSERT(R.top = -1) - - |IL.opPUSHC: - pushc(param2) - - |IL.opCLEANUP: - IF param2 # 0 THEN - addrc(SP, param2 * szWord) - END - - |IL.opNOP, IL.opAND, IL.opOR: - - |IL.opSADR: - StrAdr(GetAnyReg(), param2) - - |IL.opGADR: - GlobalAdr(GetAnyReg(), param2) - - |IL.opLADR: - param2 := param2 * szWord; - next := cmd.next(IL.COMMAND); - IF ((next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVEF)) & (szWord = 8) OR (next.opcode = IL.opSAVE64) THEN - UnOp(r1); - Emit(opSTD, BP * 256 + r1, param2); - drop; - cmd := next - ELSIF ((next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVEF)) & (szWord = 4) OR (next.opcode = IL.opSAVE32) THEN - UnOp(r1); - Emit(opSTW, BP * 256 + r1, param2); - drop; - cmd := next - ELSIF next.opcode = IL.opSAVE16 THEN - UnOp(r1); - Emit(opSTH, BP * 256 + r1, param2); - drop; - cmd := next - ELSIF next.opcode = IL.opSAVE8 THEN - UnOp(r1); - Emit(opSTB, BP * 256 + r1, param2); - drop; - cmd := next - ELSE - Emit(opADDRC, BP * 256 + GetAnyReg(), param2) - END - - |IL.opPARAM: - IF param2 = 1 THEN - UnOp(r1); - push(r1); - drop - ELSE - ASSERT(R.top + 1 <= param2); - PushAll(param2) - END - - |IL.opONERR: - pushc(param2); - Emit(opJMP, param1, 0) - - |IL.opPRECALL: - PushAll(0) - - |IL.opRES, IL.opRESF: - ASSERT(R.top = -1); - GetAcc - - |IL.opENTER: - ASSERT(R.top = -1); - Emit(opLABEL, param1, 0); - Emit(opENTER, param2, 0) - - |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: - IF opcode # IL.opLEAVE THEN - UnOp(r1); - IF r1 # ACC THEN - mov(ACC, r1) - END; - drop - END; - - ASSERT(R.top = -1); - - IF param1 > 0 THEN - mov(SP, BP) - END; - - pop(BP); - - Emit(opRET, 0, 0) - - |IL.opLEAVEC: - Emit(opRET, 0, 0) - - |IL.opCONST: - next := cmd.next(IL.COMMAND); - IF (next.opcode = IL.opPARAM) & (next.param2 = 1) THEN - pushc(param2); - cmd := next - ELSE - movrc(GetAnyReg(), param2) - END - - |IL.opDROP: - UnOp(r1); - drop - - |IL.opSAVEC: - UnOp(r1); - Emit(opSTC, r1, param2); - drop - - |IL.opSAVE8C: - UnOp(r1); - Emit(opSTBC, r1, param2 MOD 256); - drop - - |IL.opSAVE16C: - UnOp(r1); - Emit(opSTHC, r1, param2 MOD 65536); - drop - - |IL.opSAVE, IL.opSAVEF: - BinOp(r2, r1); - str(r1, r2); - drop; - drop - - |IL.opSAVE32: - BinOp(r2, r1); - str32(r1, r2); - drop; - drop - - |IL.opSAVE64: - BinOp(r2, r1); - str64(r1, r2); - drop; - drop - - |IL.opSAVEFI: - BinOp(r2, r1); - str(r2, r1); - drop; - drop - - |IL.opSAVE8: - BinOp(r2, r1); - str8(r1, r2); - drop; - drop - - |IL.opSAVE16: - BinOp(r2, r1); - str16(r1, r2); - drop; - drop - - |IL.opGLOAD32: - r1 := GetAnyReg(); - GlobalAdr(r1, param2); - ldr32(r1, r1) - - |IL.opGLOAD64: - r1 := GetAnyReg(); - GlobalAdr(r1, param2); - ldr64(r1, r1) - - |IL.opVADR: - Emit(opLD, BP * 256 + GetAnyReg(), param2 * szWord) - - |IL.opLLOAD32: - Emit(opLDW, BP * 256 + GetAnyReg(), param2 * szWord) - - |IL.opLLOAD64: - Emit(opLDD, BP * 256 + GetAnyReg(), param2 * szWord) - - |IL.opVLOAD32: - r1 := GetAnyReg(); - Emit(opLD, BP * 256 + r1, param2 * szWord); - ldr32(r1, r1) - - |IL.opVLOAD64: - r1 := GetAnyReg(); - Emit(opLDD, BP * 256 + r1, param2 * szWord); - ldr64(r1, r1) - - |IL.opGLOAD16: - r1 := GetAnyReg(); - GlobalAdr(r1, param2); - ldr16(r1, r1) - - |IL.opLLOAD16: - Emit(opLDH, BP * 256 + GetAnyReg(), param2 * szWord) - - |IL.opVLOAD16: - r1 := GetAnyReg(); - Emit(opLD, BP * 256 + r1, param2 * szWord); - ldr16(r1, r1) - - |IL.opGLOAD8: - r1 := GetAnyReg(); - GlobalAdr(r1, param2); - ldr8(r1, r1) - - |IL.opLLOAD8: - Emit(opLDB, BP * 256 + GetAnyReg(), param2 * szWord) - - |IL.opVLOAD8: - r1 := GetAnyReg(); - Emit(opLD, BP * 256 + r1, param2 * szWord); - ldr8(r1, r1) - - |IL.opLOAD8: - UnOp(r1); - ldr8(r1, r1) - - |IL.opLOAD16: - UnOp(r1); - ldr16(r1, r1) - - |IL.opLOAD32: - UnOp(r1); - ldr32(r1, r1) - - |IL.opLOAD64: - UnOp(r1); - ldr64(r1, r1) - - |IL.opLOADF: - UnOp(r1); - ldr(r1, r1) - - |IL.opUMINUS: - UnOp(r1); - Emit(opNEG, r1, 0) - - |IL.opADD: - BinOp(r1, r2); - add(r1, r2); - drop - - |IL.opSUB: - BinOp(r1, r2); - sub(r1, r2); - drop - - |IL.opADDC: - UnOp(r1); - next := cmd.next(IL.COMMAND); - CASE next.opcode OF - |IL.opLOADF: - Emit(opLD, r1 * 256 + r1, param2); - cmd := next - |IL.opLOAD64: - Emit(opLDD, r1 * 256 + r1, param2); - cmd := next - |IL.opLOAD32: - Emit(opLDW, r1 * 256 + r1, param2); - cmd := next - |IL.opLOAD16: - Emit(opLDH, r1 * 256 + r1, param2); - cmd := next - |IL.opLOAD8: - Emit(opLDB, r1 * 256 + r1, param2); - cmd := next - ELSE - addrc(r1, param2) - END - - |IL.opSUBR: - UnOp(r1); - subrc(r1, param2) - - |IL.opSUBL: - UnOp(r1); - subrc(r1, param2); - Emit(opNEG, r1, 0) - - |IL.opMULC: - UnOp(r1); - Emit(opMULC, r1, param2) - - |IL.opMUL: - BinOp(r1, r2); - Emit(opMUL, r1, r2); - drop - - |IL.opDIV: - BinOp(r1, r2); - Emit(opDIV, r1, r2); - drop - - |IL.opMOD: - BinOp(r1, r2); - Emit(opMOD, r1, r2); - drop - - |IL.opDIVR: - UnOp(r1); - Emit(opDIVC, r1, param2) - - |IL.opMODR: - UnOp(r1); - Emit(opMODC, r1, param2) - - |IL.opDIVL: - UnOp(r1); - r2 := GetAnyReg(); - movrc(r2, param2); - Emit(opDIV, r2, r1); - mov(r1, r2); - drop - - |IL.opMODL: - UnOp(r1); - r2 := GetAnyReg(); - movrc(r2, param2); - Emit(opMOD, r2, r1); - mov(r1, r2); - drop - - |IL.opEQ .. IL.opGE, IL.opEQC .. IL.opGEC: - IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN - BinOp(r1, r2); - Emit(opCMP, r1, r2); - drop - ELSE - UnOp(r1); - Emit(opCMPC, r1, param2) - END; - next := cmd.next(IL.COMMAND); - IF next.opcode = IL.opJZ THEN - Emit(ORD(BITS(jcc(opcode)) / {0}), next.param1, 0); - cmd := next; - drop - ELSIF next.opcode = IL.opJNZ THEN - Emit(jcc(opcode), next.param1, 0); - cmd := next; - drop - ELSE - Emit(jcc(opcode) + 6, r1, 0) - END - - |IL.opJNZ1: - UnOp(r1); - jnz(r1, param1) - - |IL.opJG: - UnOp(r1); - Emit(opCMPC, r1, 0); - Emit(opJGT, param1, 0) - - |IL.opJNZ: - UnOp(r1); - jnz(r1, param1); - drop - - |IL.opJZ: - UnOp(r1); - Emit(opCMPC, r1, 0); - Emit(opJEQ, param1, 0); - drop - - |IL.opMULS: - BinOp(r1, r2); - Emit(opAND, r1, r2); - drop - - |IL.opMULSC: - UnOp(r1); - Emit(opANDC, r1, param2) - - |IL.opDIVS: - BinOp(r1, r2); - Emit(opXOR, r1, r2); - drop - - |IL.opDIVSC: - UnOp(r1); - Emit(opXORC, r1, param2) - - |IL.opADDS: - BinOp(r1, r2); - Emit(opOR, r1, r2); - drop - - |IL.opSUBS: - BinOp(r1, r2); - Emit(opNOT, r2, 0); - Emit(opAND, r1, r2); - drop - - |IL.opADDSC: - UnOp(r1); - Emit(opORC, r1, param2) - - |IL.opSUBSL: - UnOp(r1); - Emit(opNOT, r1, 0); - Emit(opANDC, r1, param2) - - |IL.opSUBSR: - UnOp(r1); - Emit(opANDC, r1, ORD(-BITS(param2))) - - |IL.opUMINS: - UnOp(r1); - Emit(opNOT, r1, 0) - - |IL.opASR: - shift(opASR) - - |IL.opLSL: - shift(opLSL) - - |IL.opROR: - shift(opROR) - - |IL.opLSR: - shift(opLSR) - - |IL.opASR1: - shift1(opASR, param2) - - |IL.opLSL1: - shift1(opLSL, param2) - - |IL.opROR1: - shift1(opROR, param2) - - |IL.opLSR1: - shift1(opLSR, param2) - - |IL.opASR2: - UnOp(r1); - Emit(opASRC, r1, param2 MOD (szWord * 8)) - - |IL.opLSL2: - UnOp(r1); - Emit(opLSLC, r1, param2 MOD (szWord * 8)) - - |IL.opROR2: - UnOp(r1); - Emit(opRORC, r1, param2 MOD (szWord * 8)) - - |IL.opLSR2: - UnOp(r1); - Emit(opLSRC, r1, param2 MOD (szWord * 8)) - - |IL.opABS: - UnOp(r1); - Emit(opCMPC, r1, 0); - label := IL.NewLabel(); - Emit(opJGE, label, 0); - Emit(opNEG, r1, 0); - Emit(opLABEL, label, 0) - - |IL.opLEN: - UnOp(r1); - drop; - EXCL(R.regs, r1); - - WHILE param2 > 0 DO - UnOp(r2); - drop; - DEC(param2) - END; - - INCL(R.regs, r1); - ASSERT(REG.GetReg(R, r1)) - - |IL.opSWITCH: - UnOp(r1); - IF param2 = 0 THEN - r2 := ACC - ELSE - r2 := R1 - END; - IF r1 # r2 THEN - ASSERT(REG.GetReg(R, r2)); - ASSERT(REG.Exchange(R, r1, r2)); - drop - END; - drop - - |IL.opENDSW: - - |IL.opCASEL: - Emit(opCMPC, ACC, param1); - Emit(opJLT, param2, 0) - - |IL.opCASER: - Emit(opCMPC, ACC, param1); - Emit(opJGT, param2, 0) - - |IL.opCASELR: - Emit(opCMPC, ACC, param1); - IF param2 = cmd.param3 THEN - Emit(opJNE, param2, 0) - ELSE - Emit(opJLT, param2, 0); - Emit(opJGT, cmd.param3, 0) - END - - |IL.opSBOOL: - BinOp(r2, r1); - Emit(opCMPC, r2, 0); - Emit(opSNE, r2, 0); - str8(r1, r2); - drop; - drop - - |IL.opSBOOLC: - UnOp(r1); - Emit(opSTBC, r1, ORD(param2 # 0)); - drop - - |IL.opINCC: - UnOp(r1); - r2 := GetAnyReg(); - ldr(r2, r1); - addrc(r2, param2); - str(r1, r2); - drop; - drop - - |IL.opINCCB, IL.opDECCB: - IF opcode = IL.opDECCB THEN - param2 := -param2 - END; - UnOp(r1); - r2 := GetAnyReg(); - ldr8(r2, r1); - addrc(r2, param2); - str8(r1, r2); - drop; - drop - - |IL.opINCB, IL.opDECB: - BinOp(r2, r1); - r3 := GetAnyReg(); - ldr8(r3, r1); - IF opcode = IL.opINCB THEN - add(r3, r2) - ELSE - sub(r3, r2) - END; - str8(r1, r3); - drop; - drop; - drop - - |IL.opINC, IL.opDEC: - BinOp(r2, r1); - r3 := GetAnyReg(); - ldr(r3, r1); - IF opcode = IL.opINC THEN - add(r3, r2) - ELSE - sub(r3, r2) - END; - str(r1, r3); - drop; - drop; - drop - - |IL.opINCL, IL.opEXCL: - BinOp(r2, r1); - Emit(opBIT, r2, r2); - r3 := GetAnyReg(); - ldr(r3, r1); - IF opcode = IL.opINCL THEN - Emit(opOR, r3, r2) - ELSE - Emit(opNOT, r2, 0); - Emit(opAND, r3, r2) - END; - str(r1, r3); - drop; - drop; - drop - - |IL.opINCLC, IL.opEXCLC: - UnOp(r1); - r2 := GetAnyReg(); - ldr(r2, r1); - IF opcode = IL.opINCLC THEN - Emit(opORC, r2, ORD({param2})) - ELSE - Emit(opANDC, r2, ORD(-{param2})) - END; - str(r1, r2); - drop; - drop - - |IL.opEQB, IL.opNEB: - BinOp(r1, r2); - Emit(opCMPC, r1, 0); - Emit(opSNE, r1, 0); - Emit(opCMPC, r2, 0); - Emit(opSNE, r2, 0); - Emit(opCMP, r1, r2); - IF opcode = IL.opEQB THEN - Emit(opSEQ, r1, 0) - ELSE - Emit(opSNE, r1, 0) - END; - drop - - |IL.opCHKIDX: - UnOp(r1); - Emit(opCMPC, r1, param2); - Emit(opJBT, param1, 0) - - |IL.opCHKIDX2: - BinOp(r1, r2); - IF param2 # -1 THEN - Emit(opCMP, r2, r1); - Emit(opJBT, param1, 0) - END; - INCL(R.regs, r1); - DEC(R.top); - R.stk[R.top] := r2 - - |IL.opEQP, IL.opNEP: - ProcAdr(GetAnyReg(), param1); - BinOp(r1, r2); - Emit(opCMP, r1, r2); - IF opcode = IL.opEQP THEN - Emit(opSEQ, r1, 0) - ELSE - Emit(opSNE, r1, 0) - END; - drop - - |IL.opSAVEP: - UnOp(r1); - r2 := GetAnyReg(); - ProcAdr(r2, param2); - str(r1, r2); - drop; - drop - - |IL.opPUSHP: - ProcAdr(GetAnyReg(), param2) - - |IL.opPUSHT: - UnOp(r1); - Emit(opLD, r1 * 256 + GetAnyReg(), -szWord) - - |IL.opGET, IL.opGETC: - IF opcode = IL.opGET THEN - BinOp(r1, r2) - ELSIF opcode = IL.opGETC THEN - UnOp(r2); - r1 := GetAnyReg(); - movrc(r1, param1) - END; - drop; - drop; - - CASE param2 OF - |1: ldr8(r1, r1); str8(r2, r1) - |2: ldr16(r1, r1); str16(r2, r1) - |4: ldr32(r1, r1); str32(r2, r1) - |8: ldr64(r1, r1); str64(r2, r1) - END - - |IL.opNOT: - UnOp(r1); - Emit(opCMPC, r1, 0); - Emit(opSEQ, r1, 0) - - |IL.opORD: - UnOp(r1); - Emit(opCMPC, r1, 0); - Emit(opSNE, r1, 0) - - |IL.opMIN, IL.opMAX: - BinOp(r1, r2); - Emit(opCMP, r1, r2); - label := IL.NewLabel(); - IF opcode = IL.opMIN THEN - Emit(opJLE, label, 0) - ELSE - Emit(opJGE, label, 0) - END; - Emit(opMOV, r1, r2); - Emit(opLABEL, label, 0); - drop - - |IL.opMINC, IL.opMAXC: - UnOp(r1); - Emit(opCMPC, r1, param2); - label := IL.NewLabel(); - IF opcode = IL.opMINC THEN - Emit(opJLE, label, 0) - ELSE - Emit(opJGE, label, 0) - END; - Emit(opMOVC, r1, param2); - Emit(opLABEL, label, 0) - - |IL.opIN: - BinOp(r1, r2); - Emit(opBIT, r1, r1); - Emit(opAND, r1, r2); - Emit(opCMPC, r1, 0); - Emit(opSNE, r1, 0); - drop - - |IL.opINL: - UnOp(r1); - Emit(opANDC, r1, ORD({param2})); - Emit(opCMPC, r1, 0); - Emit(opSNE, r1, 0) - - |IL.opINR: - UnOp(r1); - Emit(opBIT, r1, r1); - Emit(opANDC, r1, param2); - Emit(opCMPC, r1, 0); - Emit(opSNE, r1, 0) - - |IL.opERR: - CallRTL(IL._error, 4) - - |IL.opEQS .. IL.opGES: - PushAll(4); - pushc(opcode - IL.opEQS); - CallRTL(IL._strcmp, 5); - GetAcc - - |IL.opEQSW .. IL.opGESW: - PushAll(4); - pushc(opcode - IL.opEQSW); - CallRTL(IL._strcmpw, 5); - GetAcc - - |IL.opCOPY: - PushAll(2); - pushc(param2); - CallRTL(IL._move, 3) - - |IL.opMOVE: - PushAll(3); - CallRTL(IL._move, 3) - - |IL.opCOPYA: - PushAll(4); - pushc(param2); - CallRTL(IL._arrcpy, 5); - GetAcc - - |IL.opCOPYS: - PushAll(4); - pushc(param2); - CallRTL(IL._strcpy, 5) - - |IL.opROT: - PushAll(0); - mov(ACC, SP); - push(ACC); - pushc(param2); - CallRTL(IL._rot, 2) - - |IL.opLENGTH: - PushAll(2); - CallRTL(IL._length, 2); - GetAcc - - |IL.opLENGTHW: - PushAll(2); - CallRTL(IL._lengthw, 2); - GetAcc - - |IL.opSAVES: - UnOp(r2); - REG.PushAll_1(R); - r1 := GetAnyReg(); - StrAdr(r1, param2); - push(r1); - drop; - push(r2); - drop; - pushc(param1); - CallRTL(IL._move, 3) - - |IL.opRSET: - PushAll(2); - CallRTL(IL._set, 2); - GetAcc - - |IL.opRSETR: - PushAll(1); - pushc(param2); - CallRTL(IL._set, 2); - GetAcc - - |IL.opRSETL: - UnOp(r1); - REG.PushAll_1(R); - pushc(param2); - push(r1); - drop; - CallRTL(IL._set, 2); - GetAcc - - |IL.opRSET1: - PushAll(1); - CallRTL(IL._set1, 1); - GetAcc - - |IL.opNEW: - PushAll(1); - INC(param2, szWord); - ASSERT(UTILS.Align(param2, szWord)); - pushc(param2); - pushc(param1); - CallRTL(IL._new, 3) - - |IL.opTYPEGP: - UnOp(r1); - PushAll(0); - push(r1); - pushc(param2); - CallRTL(IL._guard, 2); - GetAcc - - |IL.opIS: - PushAll(1); - pushc(param2); - CallRTL(IL._is, 2); - GetAcc - - |IL.opISREC: - PushAll(2); - pushc(param2); - CallRTL(IL._guardrec, 3); - GetAcc - - |IL.opTYPEGR: - PushAll(1); - pushc(param2); - CallRTL(IL._guardrec, 2); - GetAcc - - |IL.opTYPEGD: - UnOp(r1); - PushAll(0); - subrc(r1, szWord); - ldr(r1, r1); - push(r1); - pushc(param2); - CallRTL(IL._guardrec, 2); - GetAcc - - |IL.opCASET: - push(R1); - push(R1); - pushc(param2); - CallRTL(IL._guardrec, 2); - pop(R1); - jnz(ACC, param1) - - |IL.opCONSTF: - IF szWord = 8 THEN - movrc(GetAnyReg(), UTILS.splitf(cmd.float, a, b)) - ELSE (* szWord = 4 *) - movrc(GetAnyReg(), UTILS.d2s(cmd.float)) - END - - |IL.opMULF: - PushAll(2); - CallRTL(IL._fmul, 2); - GetAcc - - |IL.opDIVF: - PushAll(2); - CallRTL(IL._fdiv, 2); - GetAcc - - |IL.opDIVFI: - PushAll(2); - CallRTL(IL._fdivi, 2); - GetAcc - - |IL.opADDF: - PushAll(2); - CallRTL(IL._fadd, 2); - GetAcc - - |IL.opSUBFI: - PushAll(2); - CallRTL(IL._fsubi, 2); - GetAcc - - |IL.opSUBF: - PushAll(2); - CallRTL(IL._fsub, 2); - GetAcc - - |IL.opEQF..IL.opGEF: - PushAll(2); - pushc(opcode - IL.opEQF); - CallRTL(IL._fcmp, 3); - GetAcc - - |IL.opFLOOR: - PushAll(1); - CallRTL(IL._floor, 1); - GetAcc - - |IL.opFLT: - PushAll(1); - CallRTL(IL._flt, 1); - GetAcc - - |IL.opUMINF: - UnOp(r1); - Emit(opRORC, r1, -1); - Emit(opXORC, r1, 1); - Emit(opRORC, r1, 1) - - |IL.opFABS: - UnOp(r1); - Emit(opLSLC, r1, 1); - Emit(opLSRC, r1, 1) - - |IL.opINF: - r1 := GetAnyReg(); - Emit(opMOVC, r1, 1); - Emit(opRORC, r1, 1); - Emit(opASRC, r1, 7 + 3 * ORD(szWord = 8)); - Emit(opLSRC, r1, 1) - - |IL.opPUSHF: - UnOp(r1); - push(r1); - drop - - |IL.opPACK: - PushAll(2); - CallRTL(IL._pack, 2) - - |IL.opPACKC: - PushAll(1); - pushc(param2); - CallRTL(IL._pack, 2) - - |IL.opUNPK: - PushAll(2); - CallRTL(IL._unpk, 2) - - |IL.opCODE: - OutInt(param2) - - |IL.opLADR_SAVE: - UnOp(r1); - Emit(opST, BP * 256 + r1, param2 * szWord); - drop - - |IL.opLADR_INCC: - r1 := GetAnyReg(); - Emit(opLD, BP * 256 + r1, param1 * szWord); - Emit(opADDC, r1, param2); - Emit(opST, BP * 256 + r1, param1 * szWord); - drop - - END; - - cmd := cmd.next(IL.COMMAND) - END; - - ASSERT(R.pushed = 0); - ASSERT(R.top = -1) -END translate; - - -PROCEDURE prolog; -BEGIN - Emit(opLEA, SP + LStack * 256, 0); - Emit(opLEA, ACC + LTypes * 256, 0); - push(ACC); - Emit(opLEA, ACC + LHeap * 256, 0); - push(ACC); - pushc(CHL.Length(IL.codes.types)); - CallRTL(IL._init, 3) -END prolog; - - -PROCEDURE epilog (ram, szWord: INTEGER); -VAR - tcount, dcount, i, offTypes, offStrings, - szData, szGlobal, szHeapStack: INTEGER; - -BEGIN - Emit(opSTOP, 0, 0); - - offTypes := count; - - tcount := CHL.Length(IL.codes.types); - FOR i := 0 TO tcount - 1 DO - OutInt(CHL.GetInt(IL.codes.types, i)) - END; - - offStrings := count; - dcount := CHL.Length(IL.codes.data); - FOR i := 0 TO dcount - 1 DO - OutByte(CHL.GetByte(IL.codes.data, i)) - END; - - IF dcount MOD szWord # 0 THEN - i := szWord - dcount MOD szWord; - WHILE i > 0 DO - OutByte(0); - DEC(i) - END - END; - - szData := count - offTypes; - szGlobal := (IL.codes.bss DIV szWord + 1) * szWord; - szHeapStack := ram - szData - szGlobal; - - OutInt(offTypes); - OutInt(offStrings); - OutInt(szGlobal DIV szWord); - OutInt(szHeapStack DIV szWord); - FOR i := 1 TO 8 DO - OutInt(0) - END -END epilog; - - -PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); -CONST - minRAM = 32*1024; - maxRAM = 256*1024; - -VAR - szData, szRAM: INTEGER; - -BEGIN - szWord := TARGETS.WordSize; - IF szWord = 8 THEN - ldr := ldr64; - str := str64 - ELSE - ldr := ldr32; - str := str32 - END; - szData := (CHL.Length(IL.codes.types) + CHL.Length(IL.codes.data) DIV szWord + IL.codes.bss DIV szWord + 2) * szWord; - szRAM := MIN(MAX(options.ram, minRAM), maxRAM) * 1024; - - IF szRAM - szData < 1024*1024 THEN - ERRORS.Error(208) - END; - - count := 0; - WR.Create(outname); - - REG.Init(R, push, pop, mov, xchg, GPRs); - - prolog; - translate(szWord); - epilog(szRAM, szWord); - - WR.Close -END CodeGen; - - -END RVMxI. \ No newline at end of file diff --git a/programs/develop/oberon07/source/SCAN.ob07 b/programs/develop/oberon07/source/SCAN.ob07 deleted file mode 100644 index f32cf45f4..000000000 --- a/programs/develop/oberon07/source/SCAN.ob07 +++ /dev/null @@ -1,783 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE SCAN; - -IMPORT TXT := TEXTDRV, ARITH, S := STRINGS, ERRORS, LISTS; - - -CONST - - NUMLEN = 256; - IDLEN = 256; - TEXTLEN = 512; - - lxUNDEF* = 0; lxIDENT* = 1; lxINTEGER* = 2; lxHEX* = 3; - lxCHAR* = 4; lxFLOAT* = 5; lxSTRING* = 6; lxCOMMENT* = 7; - lxEOF* = 8; - - lxPLUS* = 21; lxMINUS* = 22; lxMUL* = 23; lxSLASH* = 24; - lxNOT* = 25; lxAND* = 26; lxPOINT* = 27; lxCOMMA* = 28; - lxSEMI* = 29; lxBAR* = 30; lxLROUND* = 31; lxLSQUARE* = 32; - lxLCURLY* = 33; lxCARET* = 34; lxEQ* = 35; lxNE* = 36; - lxLT* = 37; lxGT* = 38; lxCOLON* = 39; lxRROUND* = 40; - lxRSQUARE* = 41; lxRCURLY* = 42; lxLE* = 43; lxGE* = 44; - lxASSIGN* = 45; lxRANGE* = 46; - - lxKW = 51; - - lxARRAY* = 51; lxBEGIN* = 52; lxBY* = 53; lxCASE* = 54; - lxCONST* = 55; lxDIV* = 56; lxDO* = 57; lxELSE* = 58; - lxELSIF* = 59; lxEND* = 60; lxFALSE* = 61; lxFOR* = 62; - lxIF* = 63; lxIMPORT* = 64; lxIN* = 65; lxIS* = 66; - lxMOD* = 67; lxMODULE* = 68; lxNIL* = 69; lxOF* = 70; - lxOR* = 71; lxPOINTER* = 72; lxPROCEDURE* = 73; lxRECORD* = 74; - lxREPEAT* = 75; lxRETURN* = 76; lxTHEN* = 77; lxTO* = 78; - lxTRUE* = 79; lxTYPE* = 80; lxUNTIL* = 81; lxVAR* = 82; - lxWHILE* = 83; - - lxERROR01* = -1; lxERROR02* = -2; lxERROR03* = -3; lxERROR04* = -4; - lxERROR05* = -5; (*lxERROR06* = -6;*) lxERROR07* = -7; lxERROR08* = -8; - lxERROR09* = -9; lxERROR10* = -10; lxERROR11* = -11; lxERROR12* = -12; - lxERROR13* = -13; - - -TYPE - - TEXTSTR* = ARRAY TEXTLEN OF CHAR; - IDSTR* = ARRAY IDLEN OF CHAR; - - DEF = POINTER TO RECORD (LISTS.ITEM) - - ident: IDSTR - - END; - - STRING* = POINTER TO RECORD (LISTS.ITEM) - - s*: TEXTSTR; - offset*, offsetW*, hash: INTEGER - - END; - - IDENT* = RECORD - - s*: IDSTR; - hash*: INTEGER - - END; - - POSITION* = RECORD - - line*, col*: INTEGER - - END; - - LEX* = RECORD - - sym*: INTEGER; - pos*: POSITION; - ident*: IDENT; - string*: STRING; - value*: ARITH.VALUE; - error*: INTEGER - - END; - - SCANNER* = TXT.TEXT; - - KEYWORD = ARRAY 10 OF CHAR; - - -VAR - - delimiters: ARRAY 256 OF BOOLEAN; - - upto, LowerCase, _if: BOOLEAN; - - strings, def: LISTS.LIST; - - KW: ARRAY 33 OF RECORD upper, lower: KEYWORD; uhash, lhash: INTEGER END; - - -PROCEDURE enterKW (s: KEYWORD; idx: INTEGER); -BEGIN - KW[idx].lower := s; - KW[idx].upper := s; - S.UpCase(KW[idx].upper); - KW[idx].uhash := S.HashStr(KW[idx].upper); - KW[idx].lhash := S.HashStr(KW[idx].lower); -END enterKW; - - -PROCEDURE checkKW (ident: IDENT): INTEGER; -VAR - i, res: INTEGER; - -BEGIN - res := lxIDENT; - i := 0; - WHILE i < LEN(KW) DO - IF (KW[i].uhash = ident.hash) & (KW[i].upper = ident.s) - OR LowerCase & (KW[i].lhash = ident.hash) & (KW[i].lower = ident.s) THEN - res := i + lxKW; - i := LEN(KW) - END; - INC(i) - END - - RETURN res -END checkKW; - - -PROCEDURE enterStr* (s: TEXTSTR): STRING; -VAR - str, res: STRING; - hash: INTEGER; - -BEGIN - hash := S.HashStr(s); - str := strings.first(STRING); - res := NIL; - WHILE str # NIL DO - IF (str.hash = hash) & (str.s = s) THEN - res := str; - str := NIL - ELSE - str := str.next(STRING) - END - END; - IF res = NIL THEN - NEW(res); - res.s := s; - res.offset := -1; - res.offsetW := -1; - res.hash := hash; - LISTS.push(strings, res) - END - - RETURN res -END enterStr; - - -PROCEDURE nextc (text: TXT.TEXT): CHAR; -BEGIN - TXT.next(text) - RETURN text.peak -END nextc; - - -PROCEDURE setIdent* (VAR ident: IDENT; s: IDSTR); -BEGIN - ident.s := s; - ident.hash := S.HashStr(s) -END setIdent; - - -PROCEDURE ident (text: TXT.TEXT; VAR lex: LEX); -VAR - c: CHAR; - i: INTEGER; - -BEGIN - c := text.peak; - ASSERT(S.letter(c)); - - i := 0; - WHILE (i < IDLEN - 1) & (S.letter(c) OR S.digit(c)) DO - lex.ident.s[i] := c; - INC(i); - c := nextc(text) - END; - - lex.ident.s[i] := 0X; - lex.ident.hash := S.HashStr(lex.ident.s); - lex.sym := checkKW(lex.ident); - - IF S.letter(c) OR S.digit(c) THEN - ERRORS.WarningMsg(lex.pos.line, lex.pos.col, 2); - WHILE S.letter(c) OR S.digit(c) DO - c := nextc(text) - END - END -END ident; - - -PROCEDURE number (text: TXT.TEXT; VAR lex: LEX); -TYPE - NUMSTR = ARRAY NUMLEN OF CHAR; - -VAR - c: CHAR; - hex: BOOLEAN; - error, sym, i: INTEGER; - num: NUMSTR; - - - PROCEDURE push (VAR num: NUMSTR; VAR i: INTEGER; c: CHAR); - BEGIN - IF i < NUMLEN - 1 THEN - num[i] := c; - INC(i) - END - END push; - - -BEGIN - c := text.peak; - ASSERT(S.digit(c)); - - i := 0; - - error := 0; - - sym := lxINTEGER; - hex := FALSE; - - WHILE S.digit(c) DO - push(num, i, c); - c := nextc(text) - END; - - WHILE S.hexdigit(c) OR LowerCase & ("a" <= c) & (c <= "f") DO - S.cap(c); - push(num, i, c); - c := nextc(text); - hex := TRUE - END; - - IF (c = "H") OR LowerCase & (c = "h") THEN - push(num, i, c); - TXT.next(text); - sym := lxHEX - - ELSIF (c = "X") OR LowerCase & (c = "x") THEN - push(num, i, c); - TXT.next(text); - sym := lxCHAR - - ELSIF c = "." THEN - - IF hex THEN - sym := lxERROR01 - ELSE - - c := nextc(text); - - IF c # "." THEN - push(num, i, "."); - sym := lxFLOAT - ELSE - sym := lxINTEGER; - text.peak := 7FX; - upto := TRUE - END; - - WHILE S.digit(c) DO - push(num, i, c); - c := nextc(text) - END; - - IF (c = "E") OR LowerCase & (c = "e") THEN - - push(num, i, c); - c := nextc(text); - IF (c = "+") OR (c = "-") THEN - push(num, i, c); - c := nextc(text) - END; - - IF S.digit(c) THEN - WHILE S.digit(c) DO - push(num, i, c); - c := nextc(text) - END - ELSE - sym := lxERROR02 - END - - END - - END - - ELSIF hex THEN - sym := lxERROR01 - - END; - - IF (i = NUMLEN - 1) & (sym >= 0) THEN - sym := lxERROR07 - END; - - num[i] := 0X; - - IF sym = lxINTEGER THEN - ARITH.iconv(num, lex.value, error) - ELSIF (sym = lxHEX) OR (sym = lxCHAR) THEN - ARITH.hconv(num, lex.value, error) - ELSIF sym = lxFLOAT THEN - ARITH.fconv(num, lex.value, error) - END; - - CASE error OF - |0: - |1: sym := lxERROR08 - |2: sym := lxERROR09 - |3: sym := lxERROR10 - |4: sym := lxERROR11 - |5: sym := lxERROR12 - END; - - lex.sym := sym -END number; - - -PROCEDURE string (text: TXT.TEXT; VAR lex: LEX; quot: CHAR); -VAR - c: CHAR; - i: INTEGER; - str: TEXTSTR; - -BEGIN - c := nextc(text); - - i := 0; - WHILE (i < LEN(str) - 1) & (c # quot) & (c # 0X) & ~text.eol & ~text.eof DO - str[i] := c; - c := nextc(text); - INC(i) - END; - - str[i] := 0X; - - IF (i = LEN(str) - 1) & (c # quot) & (c # 0X) & ~text.eol & ~text.eof THEN - lex.sym := lxERROR05 - END; - - IF c = quot THEN - TXT.next(text); - IF i # 1 THEN - lex.sym := lxSTRING - ELSE - lex.sym := lxCHAR; - ARITH.setChar(lex.value, ORD(str[0])) - END - ELSIF lex.sym # lxERROR05 THEN - lex.sym := lxERROR03 - END; - - IF lex.sym = lxSTRING THEN - lex.string := enterStr(str); - lex.value.typ := ARITH.tSTRING; - lex.value.string := lex.string - END - -END string; - - -PROCEDURE comment (text: TXT.TEXT); -VAR - c: CHAR; - cond, depth: INTEGER; - -BEGIN - cond := 0; - depth := 1; - - REPEAT - - c := text.peak; - TXT.next(text); - - IF c = "*" THEN - IF cond = 1 THEN - cond := 0; - INC(depth) - ELSE - cond := 2 - END - ELSIF c = ")" THEN - IF cond = 2 THEN - DEC(depth) - END; - cond := 0 - ELSIF c = "(" THEN - cond := 1 - ELSE - cond := 0 - END - - UNTIL (depth = 0) OR text.eof - -END comment; - - -PROCEDURE delimiter (text: TXT.TEXT; c: CHAR): INTEGER; -VAR - sym: INTEGER; - c0: CHAR; - -BEGIN - c0 := c; - c := nextc(text); - - CASE c0 OF - |"+": - sym := lxPLUS - - |"-": - sym := lxMINUS - - |"*": - sym := lxMUL - - |"/": - sym := lxSLASH; - - IF c = "/" THEN - sym := lxCOMMENT; - REPEAT - TXT.next(text) - UNTIL text.eol OR text.eof - END - - |"~": - sym := lxNOT - - |"&": - sym := lxAND - - |".": - sym := lxPOINT; - - IF c = "." THEN - sym := lxRANGE; - TXT.next(text) - END - - |",": - sym := lxCOMMA - - |";": - sym := lxSEMI - - |"|": - sym := lxBAR - - |"(": - sym := lxLROUND; - - IF c = "*" THEN - sym := lxCOMMENT; - TXT.next(text); - comment(text) - END - - |"[": - sym := lxLSQUARE - - |"{": - sym := lxLCURLY - - |"^": - sym := lxCARET - - |"=": - sym := lxEQ - - |"#": - sym := lxNE - - |"<": - sym := lxLT; - - IF c = "=" THEN - sym := lxLE; - TXT.next(text) - END - - |">": - sym := lxGT; - - IF c = "=" THEN - sym := lxGE; - TXT.next(text) - END - - |":": - sym := lxCOLON; - - IF c = "=" THEN - sym := lxASSIGN; - TXT.next(text) - END - - |")": - sym := lxRROUND - - |"]": - sym := lxRSQUARE - - |"}": - sym := lxRCURLY - - END - - RETURN sym -END delimiter; - - -PROCEDURE Next* (text: SCANNER; VAR lex: LEX); -VAR - c: CHAR; - - - PROCEDURE check (cond: BOOLEAN; text: SCANNER; lex: LEX; errno: INTEGER); - BEGIN - IF ~cond THEN - ERRORS.ErrorMsg(text.fname, lex.pos.line, lex.pos.col, errno) - END - END check; - - - PROCEDURE IsDef (str: ARRAY OF CHAR): BOOLEAN; - VAR - cur: DEF; - - BEGIN - cur := def.first(DEF); - WHILE (cur # NIL) & (cur.ident # str) DO - cur := cur.next(DEF) - END - - RETURN cur # NIL - END IsDef; - - - PROCEDURE Skip (text: SCANNER); - VAR - i: INTEGER; - - BEGIN - i := 0; - WHILE (i <= text.ifc) & ~text._skip[i] DO - INC(i) - END; - text.skip := i <= text.ifc - END Skip; - - - PROCEDURE prep_if (text: SCANNER; VAR lex: LEX); - VAR - skip: BOOLEAN; - - BEGIN - INC(text.ifc); - text._elsif[text.ifc] := lex.sym = lxELSIF; - IF lex.sym = lxIF THEN - INC(text.elsec); - text._else[text.elsec] := FALSE - END; - _if := TRUE; - skip := TRUE; - text.skip := FALSE; - - Next(text, lex); - check(lex.sym = lxLROUND, text, lex, 64); - - Next(text, lex); - check(lex.sym = lxIDENT, text, lex, 22); - - REPEAT - IF IsDef(lex.ident.s) THEN - skip := FALSE - END; - - Next(text, lex); - IF lex.sym = lxBAR THEN - Next(text, lex); - check(lex.sym = lxIDENT, text, lex, 22) - ELSE - check(lex.sym = lxRROUND, text, lex, 33) - END - UNTIL lex.sym = lxRROUND; - - _if := FALSE; - text._skip[text.ifc] := skip; - Skip(text); - Next(text, lex) - END prep_if; - - - PROCEDURE prep_end (text: SCANNER; VAR lex: LEX); - BEGIN - check(text.ifc > 0, text, lex, 118); - IF lex.sym = lxEND THEN - WHILE text._elsif[text.ifc] DO - DEC(text.ifc) - END; - DEC(text.ifc); - DEC(text.elsec) - ELSIF (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN - check(~text._else[text.elsec], text, lex, 118); - text._skip[text.ifc] := ~text._skip[text.ifc]; - text._else[text.elsec] := lex.sym = lxELSE - END; - Skip(text); - IF lex.sym = lxELSIF THEN - prep_if(text, lex) - ELSE - Next(text, lex) - END - END prep_end; - - -BEGIN - - REPEAT - c := text.peak; - - WHILE S.space(c) DO - c := nextc(text) - END; - - lex.pos.line := text.line; - lex.pos.col := text.col; - - IF S.letter(c) THEN - ident(text, lex) - ELSIF S.digit(c) THEN - number(text, lex) - ELSIF (c = '"') OR (c = "'") THEN - string(text, lex, c) - ELSIF delimiters[ORD(c)] THEN - lex.sym := delimiter(text, c) - ELSIF c = "$" THEN - IF S.letter(nextc(text)) THEN - ident(text, lex); - IF lex.sym = lxIF THEN - IF ~_if THEN - prep_if(text, lex) - END - ELSIF (lex.sym = lxEND) OR (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN - IF ~_if THEN - prep_end(text, lex) - END - ELSE - check(FALSE, text, lex, 119) - END - ELSE - check(FALSE, text, lex, 119) - END - ELSIF c = 0X THEN - lex.sym := lxEOF; - text.skip := FALSE; - IF text.eof THEN - INC(lex.pos.col) - END - ELSIF (c = 7FX) & upto THEN - upto := FALSE; - lex.sym := lxRANGE; - DEC(lex.pos.col); - TXT.next(text) - ELSE - TXT.next(text); - lex.sym := lxERROR04 - END; - - IF lex.sym < 0 THEN - lex.error := -lex.sym - ELSE - lex.error := 0 - END - - UNTIL (lex.sym # lxCOMMENT) & ~text.skip - -END Next; - - -PROCEDURE open* (name: ARRAY OF CHAR): SCANNER; - RETURN TXT.open(name) -END open; - - -PROCEDURE close* (VAR scanner: SCANNER); -BEGIN - TXT.close(scanner) -END close; - - -PROCEDURE init* (lower: BOOLEAN); -VAR - i: INTEGER; - delim: ARRAY 23 OF CHAR; - -BEGIN - upto := FALSE; - LowerCase := lower; - - FOR i := 0 TO 255 DO - delimiters[i] := FALSE - END; - - delim := "+-*/~&.,;|([{^=#<>:)]}"; - - FOR i := 0 TO LEN(delim) - 2 DO - delimiters[ORD(delim[i])] := TRUE - END; - - enterKW("array", 0); - enterKW("begin", 1); - enterKW("by", 2); - enterKW("case", 3); - enterKW("const", 4); - enterKW("div", 5); - enterKW("do", 6); - enterKW("else", 7); - enterKW("elsif", 8); - enterKW("end", 9); - enterKW("false", 10); - enterKW("for", 11); - enterKW("if", 12); - enterKW("import", 13); - enterKW("in", 14); - enterKW("is", 15); - enterKW("mod", 16); - enterKW("module", 17); - enterKW("nil", 18); - enterKW("of", 19); - enterKW("or", 20); - enterKW("pointer", 21); - enterKW("procedure", 22); - enterKW("record", 23); - enterKW("repeat", 24); - enterKW("return", 25); - enterKW("then", 26); - enterKW("to", 27); - enterKW("true", 28); - enterKW("type", 29); - enterKW("until", 30); - enterKW("var", 31); - enterKW("while", 32) -END init; - - -PROCEDURE NewDef* (str: ARRAY OF CHAR); -VAR - item: DEF; - -BEGIN - NEW(item); - COPY(str, item.ident); - LISTS.push(def, item) -END NewDef; - - -BEGIN - def := LISTS.create(NIL); - strings := LISTS.create(NIL) -END SCAN. \ No newline at end of file diff --git a/programs/develop/oberon07/source/STATEMENTS.ob07 b/programs/develop/oberon07/source/STATEMENTS.ob07 deleted file mode 100644 index d7b1d3b67..000000000 --- a/programs/develop/oberon07/source/STATEMENTS.ob07 +++ /dev/null @@ -1,3444 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2023, Anton Krotov - All rights reserved. -*) - -MODULE STATEMENTS; - -IMPORT - - PARS, PROG, SCAN, ARITH, STRINGS, LISTS, IL, X86, AMD64, MSP430, THUMB, RVMxI, - ERRORS, UTILS, AVL := AVLTREES, CONSOLE, C := COLLECTIONS, TARGETS; - - -CONST - - eCONST = PARS.eCONST; eTYPE = PARS.eTYPE; eVAR = PARS.eVAR; - eEXPR = PARS.eEXPR; eVREC = PARS.eVREC; ePROC = PARS.ePROC; - eVPAR = PARS.eVPAR; ePARAM = PARS.ePARAM; eSTPROC = PARS.eSTPROC; - eSTFUNC = PARS.eSTFUNC; eSYSFUNC = PARS.eSYSFUNC; eSYSPROC = PARS.eSYSPROC; - eIMP = PARS.eIMP; - - errASSERT = 1; errPTR = 2; errDIV = 3; errPROC = 4; - errGUARD = 5; errIDX = 6; errCASE = 7; errCOPY = 8; - errCHR = 9; errWCHR = 10; errBYTE = 11; - - chkIDX* = 0; chkGUARD* = 1; chkPTR* = 2; chkCHR* = 3; chkWCHR* = 4; chkBYTE* = 5; - chkSTK* = MSP430.chkSTK; (* 6 *) - - chkALL* = {chkIDX, chkGUARD, chkPTR, chkCHR, chkWCHR, chkBYTE, chkSTK}; - - -TYPE - - isXXX = PROCEDURE (e: PARS.EXPR): BOOLEAN; - - RANGE = RECORD - - a, b: INTEGER - - END; - - CASE_LABEL = POINTER TO rCASE_LABEL; - - rCASE_LABEL = RECORD (AVL.DATA) - - range: RANGE; - - variant, self: INTEGER; - - _type: PROG._TYPE; - - prev: CASE_LABEL - - END; - - CASE_VARIANT = POINTER TO RECORD (LISTS.ITEM) - - label: INTEGER; - cmd: IL.COMMAND; - processed: BOOLEAN - - END; - - -VAR - - Options: PROG.OPTIONS; - - begcall, endcall: IL.COMMAND; - - CaseLabels, CaseVar: C.COLLECTION; - - CaseVariants: LISTS.LIST; - - CPU: INTEGER; - - tINTEGER, tBYTE, tCHAR, tWCHAR, tSET, tBOOLEAN, tREAL: PROG._TYPE; - - -PROCEDURE isExpr (e: PARS.EXPR): BOOLEAN; - RETURN e.obj IN {eCONST, eVAR, eEXPR, eVPAR, ePARAM, eVREC} -END isExpr; - - -PROCEDURE isVar (e: PARS.EXPR): BOOLEAN; - RETURN e.obj IN {eVAR, eVPAR, ePARAM, eVREC} -END isVar; - - -PROCEDURE isBoolean (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type = tBOOLEAN) -END isBoolean; - - -PROCEDURE isInteger (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type = tINTEGER) -END isInteger; - - -PROCEDURE isByte (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type = tBYTE) -END isByte; - - -PROCEDURE isInt (e: PARS.EXPR): BOOLEAN; - RETURN isByte(e) OR isInteger(e) -END isInt; - - -PROCEDURE isReal (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type = tREAL) -END isReal; - - -PROCEDURE isSet (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type = tSET) -END isSet; - - -PROCEDURE isString (e: PARS.EXPR): BOOLEAN; - RETURN (e.obj = eCONST) & (e._type.typ IN {PROG.tSTRING, PROG.tCHAR}) -END isString; - - -PROCEDURE isStringW (e: PARS.EXPR): BOOLEAN; - RETURN (e.obj = eCONST) & (e._type.typ IN {PROG.tSTRING, PROG.tCHAR, PROG.tWCHAR}) -END isStringW; - - -PROCEDURE isChar (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type = tCHAR) -END isChar; - - -PROCEDURE isCharW (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type = tWCHAR) -END isCharW; - - -PROCEDURE isPtr (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type.typ = PROG.tPOINTER) -END isPtr; - - -PROCEDURE isRec (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type.typ = PROG.tRECORD) -END isRec; - - -PROCEDURE isRecPtr (e: PARS.EXPR): BOOLEAN; - RETURN isRec(e) OR isPtr(e) -END isRecPtr; - - -PROCEDURE isArr (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type.typ = PROG.tARRAY) -END isArr; - - -PROCEDURE isProc (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e._type.typ = PROG.tPROCEDURE) OR (e.obj IN {ePROC, eIMP}) -END isProc; - - -PROCEDURE isNil (e: PARS.EXPR): BOOLEAN; - RETURN e._type.typ = PROG.tNIL -END isNil; - - -PROCEDURE isCharArray (e: PARS.EXPR): BOOLEAN; - RETURN isArr(e) & (e._type.base = tCHAR) -END isCharArray; - - -PROCEDURE isCharArrayW (e: PARS.EXPR): BOOLEAN; - RETURN isArr(e) & (e._type.base = tWCHAR) -END isCharArrayW; - - -PROCEDURE isCharArrayX (e: PARS.EXPR): BOOLEAN; - RETURN isCharArray(e) OR isCharArrayW(e) -END isCharArrayX; - - -PROCEDURE getpos (parser: PARS.PARSER; VAR pos: PARS.POSITION); -BEGIN - pos.line := parser.lex.pos.line; - pos.col := parser.lex.pos.col; - pos.parser := parser -END getpos; - - -PROCEDURE NextPos (parser: PARS.PARSER; VAR pos: PARS.POSITION); -BEGIN - PARS.Next(parser); - getpos(parser, pos) -END NextPos; - - -PROCEDURE strlen (e: PARS.EXPR): INTEGER; -VAR - res: INTEGER; - -BEGIN - ASSERT(isString(e)); - IF e._type = tCHAR THEN - res := 1 - ELSE - res := LENGTH(e.value.string(SCAN.STRING).s) - END - RETURN res -END strlen; - - -PROCEDURE _length (s: ARRAY OF CHAR): INTEGER; -VAR - i, res: INTEGER; - -BEGIN - i := 0; - res := 0; - WHILE (i < LEN(s)) & (s[i] # 0X) DO - IF (s[i] <= CHR(127)) OR (s[i] >= CHR(192)) THEN - INC(res) - END; - INC(i) - END - - RETURN res -END _length; - - -PROCEDURE utf8strlen (e: PARS.EXPR): INTEGER; -VAR - res: INTEGER; - -BEGIN - ASSERT(isStringW(e)); - IF e._type.typ IN {PROG.tCHAR, PROG.tWCHAR} THEN - res := 1 - ELSE - res := _length(e.value.string(SCAN.STRING).s) - END - RETURN res -END utf8strlen; - - -PROCEDURE StrToWChar (s: ARRAY OF CHAR): INTEGER; -VAR - res: ARRAY 2 OF WCHAR; - -BEGIN - ASSERT(STRINGS.Utf8To16(s, res) = 1) - RETURN ORD(res[0]) -END StrToWChar; - - -PROCEDURE isStringW1 (e: PARS.EXPR): BOOLEAN; - RETURN isString(e) & (utf8strlen(e) = 1) & (strlen(e) > 1) -END isStringW1; - - -PROCEDURE assigncomp (e: PARS.EXPR; t: PROG._TYPE): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - IF isExpr(e) OR (e.obj IN {ePROC, eIMP}) THEN - - IF t = e._type THEN - res := TRUE - ELSIF isInt(e) & (t.typ IN {PROG.tBYTE, PROG.tINTEGER}) THEN - IF (e.obj = eCONST) & (t = tBYTE) THEN - res := ARITH.range(e.value, 0, 255) - ELSE - res := TRUE - END - ELSIF - (e.obj = eCONST) & isChar(e) & (t = tWCHAR) - OR isStringW1(e) & (t = tWCHAR) - OR PROG.isBaseOf(t, e._type) - OR ~PROG.isOpenArray(t) & ~PROG.isOpenArray(e._type) & PROG.isTypeEq(t, e._type) - OR isNil(e) & (t.typ IN {PROG.tPOINTER, PROG.tPROCEDURE}) - OR PROG.arrcomp(e._type, t) - OR isString(e) & (t.typ = PROG.tARRAY) & (t.base = tCHAR) & (t.length > strlen(e)) - OR isStringW(e) & (t.typ = PROG.tARRAY) & (t.base = tWCHAR) & (t.length > utf8strlen(e)) - THEN - res := TRUE - ELSE - res := FALSE - END - ELSE - res := FALSE - END - - RETURN res -END assigncomp; - - -PROCEDURE String (e: PARS.EXPR): INTEGER; -VAR - offset: INTEGER; - string: SCAN.STRING; - -BEGIN - IF strlen(e) # 1 THEN - string := e.value.string(SCAN.STRING); - IF string.offset = -1 THEN - string.offset := IL.putstr(string.s); - END; - offset := string.offset - ELSE - offset := IL.putstr1(ARITH.Int(e.value)) - END - - RETURN offset -END String; - - -PROCEDURE StringW (e: PARS.EXPR): INTEGER; -VAR - offset: INTEGER; - string: SCAN.STRING; - -BEGIN - IF utf8strlen(e) # 1 THEN - string := e.value.string(SCAN.STRING); - IF string.offsetW = -1 THEN - string.offsetW := IL.putstrW(string.s); - END; - offset := string.offsetW - ELSE - IF e._type.typ IN {PROG.tWCHAR, PROG.tCHAR} THEN - offset := IL.putstrW1(ARITH.Int(e.value)) - ELSE (* e._type.typ = PROG.tSTRING *) - string := e.value.string(SCAN.STRING); - IF string.offsetW = -1 THEN - string.offsetW := IL.putstrW(string.s); - END; - offset := string.offsetW - END - END - - RETURN offset -END StringW; - - -PROCEDURE CheckRange (range, line, errno: INTEGER); -VAR - label: INTEGER; - -BEGIN - label := IL.NewLabel(); - IL.AddCmd2(IL.opCHKIDX, label, range); - IL.OnError(line, errno); - IL.SetLabel(label) -END CheckRange; - - -PROCEDURE Float (parser: PARS.PARSER; e: PARS.EXPR); -VAR - pos: PARS.POSITION; - -BEGIN - getpos(parser, pos); - IL.Float(ARITH.Float(e.value), pos.line, pos.col) -END Float; - - -PROCEDURE assign (parser: PARS.PARSER; e: PARS.EXPR; VarType: PROG._TYPE; line: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - label: INTEGER; - -BEGIN - IF isExpr(e) OR (e.obj IN {ePROC, eIMP}) THEN - res := TRUE; - IF PROG.arrcomp(e._type, VarType) THEN - - IF ~PROG.isOpenArray(VarType) THEN - IL.Const(VarType.length) - END; - IL.AddCmd(IL.opCOPYA, VarType.base.size); - label := IL.NewLabel(); - IL.Jmp(IL.opJNZ, label); - IL.OnError(line, errCOPY); - IL.SetLabel(label) - - ELSIF isInt(e) & (VarType.typ IN {PROG.tBYTE, PROG.tINTEGER}) THEN - IF VarType = tINTEGER THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) - ELSE - IL.AddCmd0(IL.opSAVE) - END - ELSE - IF e.obj = eCONST THEN - res := ARITH.range(e.value, 0, 255); - IF res THEN - IL.AddCmd(IL.opSAVE8C, ARITH.Int(e.value)) - END - ELSE - IL.AddCmd0(IL.opSAVE8) - END - END - ELSIF isSet(e) & (VarType = tSET) THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) - ELSE - IL.AddCmd0(IL.opSAVE) - END - ELSIF isBoolean(e) & (VarType = tBOOLEAN) THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opSBOOLC, ARITH.Int(e.value)) - ELSE - IL.AddCmd0(IL.opSBOOL) - END - ELSIF isReal(e) & (VarType = tREAL) THEN - IF e.obj = eCONST THEN - Float(parser, e) - END; - IL.savef(e.obj = eCONST) - ELSIF isChar(e) & (VarType = tCHAR) THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opSAVE8C, ARITH.Int(e.value)) - ELSE - IL.AddCmd0(IL.opSAVE8) - END - ELSIF (e.obj = eCONST) & isChar(e) & (VarType = tWCHAR) THEN - IL.AddCmd(IL.opSAVE16C, ARITH.Int(e.value)) - ELSIF isStringW1(e) & (VarType = tWCHAR) THEN - IL.AddCmd(IL.opSAVE16C, StrToWChar(e.value.string(SCAN.STRING).s)) - ELSIF isCharW(e) & (VarType = tWCHAR) THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opSAVE16C, ARITH.Int(e.value)) - ELSE - IL.AddCmd0(IL.opSAVE16) - END - ELSIF PROG.isBaseOf(VarType, e._type) THEN - IF VarType.typ = PROG.tPOINTER THEN - IL.AddCmd0(IL.opSAVE) - ELSE - IL.AddCmd(IL.opCOPY, VarType.size) - END - ELSIF (e._type.typ = PROG.tCARD32) & (VarType.typ = PROG.tCARD32) THEN - IL.AddCmd0(IL.opSAVE32) - ELSIF ~PROG.isOpenArray(VarType) & ~PROG.isOpenArray(e._type) & PROG.isTypeEq(VarType, e._type) THEN - IF e.obj = ePROC THEN - IL.AssignProc(e.ident.proc.label) - ELSIF e.obj = eIMP THEN - IL.AssignImpProc(e.ident._import) - ELSE - IF VarType.typ = PROG.tPROCEDURE THEN - IL.AddCmd0(IL.opSAVE) - ELSE - IL.AddCmd(IL.opCOPY, VarType.size) - END - END - ELSIF isNil(e) & (VarType.typ IN {PROG.tPOINTER, PROG.tPROCEDURE}) THEN - IL.AddCmd(IL.opSAVEC, 0) - ELSIF isString(e) & ((VarType.typ = PROG.tARRAY) & (VarType.base = tCHAR) & (VarType.length > strlen(e))) THEN - IL.saves(String(e), strlen(e) + 1) - ELSIF isStringW(e) & ((VarType.typ = PROG.tARRAY) & (VarType.base = tWCHAR) & (VarType.length > utf8strlen(e))) THEN - IL.saves(StringW(e), (utf8strlen(e) + 1) * 2) - ELSE - res := FALSE - END - ELSE - res := FALSE - END - RETURN res -END assign; - - -PROCEDURE LoadConst (e: PARS.EXPR); -BEGIN - IL.Const(ARITH.Int(e.value)) -END LoadConst; - - -PROCEDURE paramcomp (parser: PARS.PARSER; pos: PARS.POSITION; e: PARS.EXPR; p: PROG.PARAM); -VAR - stroffs: INTEGER; - - PROCEDURE arrcomp (e: PARS.EXPR; p: PROG.PARAM): BOOLEAN; - VAR - t1, t2: PROG._TYPE; - - BEGIN - t1 := p._type; - t2 := e._type; - WHILE (t2.typ = PROG.tARRAY) & PROG.isOpenArray(t1) DO - t1 := t1.base; - t2 := t2.base - END - - RETURN PROG.isTypeEq(t1, t2) - END arrcomp; - - - PROCEDURE ArrLen (t: PROG._TYPE; n: INTEGER): INTEGER; - VAR - res: INTEGER; - - BEGIN - REPEAT - res := t.length; - t := t.base; - DEC(n) - UNTIL (n < 0) OR (t.typ # PROG.tARRAY); - ASSERT(n < 0) - RETURN res - END ArrLen; - - - PROCEDURE OpenArray (t, t2: PROG._TYPE); - VAR - n, d1, d2: INTEGER; - - BEGIN - IF t.length # 0 THEN - IL.Param1; - n := PROG.Dim(t2) - 1; - WHILE n >= 0 DO - IL.Const(ArrLen(t, n)); - IL.Param1; - DEC(n) - END - ELSE - d1 := PROG.Dim(t); - d2 := PROG.Dim(t2); - IF d1 # d2 THEN - n := d2 - d1; - WHILE d2 > d1 DO - IL.Const(ArrLen(t, d2 - 1)); - DEC(d2) - END; - d2 := PROG.Dim(t2); - WHILE n > 0 DO - IL.AddCmd(IL.opROT, d2); - DEC(n) - END - END; - IL.AddCmd(IL.opPARAM, PROG.Dim(t2) + 1) - END - END OpenArray; - - -BEGIN - IF p.vPar THEN - - PARS.check(isVar(e), pos, 93); - IF p._type.typ = PROG.tRECORD THEN - PARS.check(PROG.isBaseOf(p._type, e._type), pos, 66); - IF e.obj = eVREC THEN - IF e.ident # NIL THEN - IL.AddCmd(IL.opVADR, e.ident.offset - 1) - ELSE - IL.AddCmd0(IL.opPUSHT) - END - ELSE - IL.Const(e._type.num) - END; - IL.AddCmd(IL.opPARAM, 2) - ELSIF PROG.isOpenArray(p._type) THEN - PARS.check(arrcomp(e, p), pos, 66); - OpenArray(e._type, p._type) - ELSE - PARS.check(PROG.isTypeEq(e._type, p._type), pos, 66); - IL.Param1 - END; - PARS.check(~e.readOnly, pos, 94) - - ELSE - PARS.check(isExpr(e) OR isProc(e), pos, 66); - IF PROG.isOpenArray(p._type) THEN - IF e._type.typ = PROG.tARRAY THEN - PARS.check(arrcomp(e, p), pos, 66); - OpenArray(e._type, p._type) - ELSIF isString(e) & (p._type.typ = PROG.tARRAY) & (p._type.base = tCHAR) THEN - IL.StrAdr(String(e)); - IL.Param1; - IL.Const(strlen(e) + 1); - IL.Param1 - ELSIF isStringW(e) & (p._type.typ = PROG.tARRAY) & (p._type.base = tWCHAR) THEN - IL.StrAdr(StringW(e)); - IL.Param1; - IL.Const(utf8strlen(e) + 1); - IL.Param1 - ELSE - PARS.error(pos, 66) - END - ELSE - PARS.check(~PROG.isOpenArray(e._type), pos, 66); - PARS.check(assigncomp(e, p._type), pos, 66); - IF e.obj = eCONST THEN - IF e._type = tREAL THEN - Float(parser, e); - IL.AddCmd0(IL.opPUSHF) - ELSIF e._type.typ = PROG.tNIL THEN - IL.Const(0); - IL.Param1 - ELSIF isStringW1(e) & (p._type = tWCHAR) THEN - IL.Const(StrToWChar(e.value.string(SCAN.STRING).s)); - IL.Param1 - ELSIF (e._type.typ = PROG.tSTRING) OR - (e._type.typ IN {PROG.tCHAR, PROG.tWCHAR}) & (p._type.typ = PROG.tARRAY) & (p._type.base.typ IN {PROG.tCHAR, PROG.tWCHAR}) THEN - IF p._type.base = tCHAR THEN - stroffs := String(e); - IL.StrAdr(stroffs); - IF (CPU = TARGETS.cpuMSP430) & (p._type.size - strlen(e) - 1 > MSP430.IntVectorSize) THEN - ERRORS.WarningMsg(pos.line, pos.col, 0) - END - ELSE (* WCHAR *) - stroffs := StringW(e); - IL.StrAdr(stroffs) - END; - IL.set_dmin(stroffs + p._type.size); - IL.Param1 - ELSE - LoadConst(e); - IL.Param1 - END - ELSIF e.obj = ePROC THEN - PARS.check(e.ident.global, pos, 85); - IL.PushProc(e.ident.proc.label); - IL.Param1 - ELSIF e.obj = eIMP THEN - IL.PushImpProc(e.ident._import); - IL.Param1 - ELSIF isExpr(e) & (e._type = tREAL) THEN - IL.AddCmd0(IL.opPUSHF) - ELSE - IF (p._type = tBYTE) & (e._type = tINTEGER) & (chkBYTE IN Options.checking) THEN - CheckRange(256, pos.line, errBYTE) - END; - IL.Param1 - END - END - - END -END paramcomp; - - -PROCEDURE PExpression (parser: PARS.PARSER; VAR e: PARS.EXPR); -BEGIN - parser.expression(parser, e) -END PExpression; - - -PROCEDURE stProc (parser: PARS.PARSER; VAR e: PARS.EXPR); -VAR - e1, e2: PARS.EXPR; - pos: PARS.POSITION; - proc, - label, - size, - n, i: INTEGER; - code: ARITH.VALUE; - wchar, - comma: BOOLEAN; - cmd1, - cmd2: IL.COMMAND; - - - PROCEDURE varparam (parser: PARS.PARSER; pos: PARS.POSITION; isfunc: isXXX; readOnly: BOOLEAN; VAR e: PARS.EXPR); - BEGIN - parser.designator(parser, e); - PARS.check(isVar(e), pos, 93); - PARS.check(isfunc(e), pos, 66); - IF readOnly THEN - PARS.check(~e.readOnly, pos, 94) - END - END varparam; - - - PROCEDURE shift_minmax (proc: INTEGER): CHAR; - VAR - res: CHAR; - - BEGIN - CASE proc OF - |PROG.stASR: res := "A" - |PROG.stLSL: res := "L" - |PROG.stROR: res := "O" - |PROG.stLSR: res := "R" - |PROG.stMIN: res := "m" - |PROG.stMAX: res := "x" - END - RETURN res - END shift_minmax; - - -BEGIN - ASSERT(e.obj IN {eSTPROC, eSTFUNC, eSYSPROC, eSYSFUNC}); - proc := e.stproc; - -(* IF (proc # PROG.sysNOP) & (proc # PROG.sysEINT) & (proc # PROG.sysDINT) THEN *) - PARS.checklex(parser, SCAN.lxLROUND); - PARS.Next(parser); -(* END; *) - - getpos(parser, pos); - - IF e.obj IN {eSTPROC, eSYSPROC} THEN - - CASE proc OF - |PROG.stASSERT: - PExpression(parser, e); - PARS.check(isBoolean(e), pos, 66); - IF e.obj = eCONST THEN - IF ~ARITH.getBool(e.value) THEN - IL.OnError(pos.line, errASSERT) - END - ELSE - label := IL.NewLabel(); - IL.not; - IL.AndOrOpt(label); - IL.OnError(pos.line, errASSERT); - IL.SetLabel(label) - END - - |PROG.stINC, PROG.stDEC: - IL.pushBegEnd(begcall, endcall); - varparam(parser, pos, isInt, TRUE, e); - IF e._type = tINTEGER THEN - IF parser.sym = SCAN.lxCOMMA THEN - NextPos(parser, pos); - IL.setlast(begcall); - PExpression(parser, e2); - IL.setlast(endcall.prev(IL.COMMAND)); - PARS.check(isInt(e2), pos, 66); - IF e2.obj = eCONST THEN - IL.AddCmd(IL.opINCC, ARITH.Int(e2.value) * (ORD(proc = PROG.stINC) * 2 - 1)) - ELSE - IL.AddCmd0(IL.opINC + ORD(proc = PROG.stDEC)) - END - ELSE - IL.AddCmd(IL.opINCC, ORD(proc = PROG.stINC) * 2 - 1) - END - ELSE (* e._type = tBYTE *) - IF parser.sym = SCAN.lxCOMMA THEN - NextPos(parser, pos); - IL.setlast(begcall); - PExpression(parser, e2); - IL.setlast(endcall.prev(IL.COMMAND)); - PARS.check(isInt(e2), pos, 66); - IF e2.obj = eCONST THEN - IL.AddCmd(IL.opINCCB + ORD(proc = PROG.stDEC), ARITH.Int(e2.value)) - ELSE - IL.AddCmd0(IL.opINCB + ORD(proc = PROG.stDEC)) - END - ELSE - IL.AddCmd(IL.opINCCB + ORD(proc = PROG.stDEC), 1) - END - END; - IL.popBegEnd(begcall, endcall) - - |PROG.stINCL, PROG.stEXCL: - IL.pushBegEnd(begcall, endcall); - varparam(parser, pos, isSet, TRUE, e); - PARS.checklex(parser, SCAN.lxCOMMA); - NextPos(parser, pos); - IL.setlast(begcall); - PExpression(parser, e2); - IL.setlast(endcall.prev(IL.COMMAND)); - PARS.check(isInt(e2), pos, 66); - IF e2.obj = eCONST THEN - PARS.check(ARITH.range(e2.value, 0, UTILS.target.maxSet), pos, 56); - IL.AddCmd(IL.opINCLC + ORD(proc = PROG.stEXCL), ARITH.Int(e2.value)) - ELSE - IL.AddCmd0(IL.opINCL + ORD(proc = PROG.stEXCL)) - END; - IL.popBegEnd(begcall, endcall) - - |PROG.stNEW: - varparam(parser, pos, isPtr, TRUE, e); - IF CPU = TARGETS.cpuMSP430 THEN - PARS.check(e._type.base.size + 16 < Options.ram, pos, 63) - END; - IL.New(e._type.base.size, e._type.base.num) - - |PROG.stDISPOSE: - varparam(parser, pos, isPtr, TRUE, e); - IL.AddCmd0(IL.opDISP) - - |PROG.stPACK: - varparam(parser, pos, isReal, TRUE, e); - PARS.checklex(parser, SCAN.lxCOMMA); - NextPos(parser, pos); - PExpression(parser, e2); - PARS.check(isInt(e2), pos, 66); - IF e2.obj = eCONST THEN - IL.AddCmd(IL.opPACKC, ARITH.Int(e2.value)) - ELSE - IL.AddCmd0(IL.opPACK) - END - - |PROG.stUNPK: - varparam(parser, pos, isReal, TRUE, e); - PARS.checklex(parser, SCAN.lxCOMMA); - NextPos(parser, pos); - varparam(parser, pos, isInteger, TRUE, e2); - IL.AddCmd0(IL.opUNPK) - - |PROG.stCOPY: - IL.pushBegEnd(begcall, endcall); - PExpression(parser, e); - IF isString(e) OR isCharArray(e) THEN - wchar := FALSE - ELSIF isStringW(e) OR isCharArrayW(e) THEN - wchar := TRUE - ELSE - PARS.error(pos, 66) - END; - - IF isCharArrayX(e) & ~PROG.isOpenArray(e._type) THEN - IL.Const(e._type.length) - END; - - PARS.checklex(parser, SCAN.lxCOMMA); - NextPos(parser, pos); - IL.setlast(begcall); - - IF wchar THEN - varparam(parser, pos, isCharArrayW, TRUE, e1) - ELSE - IF e.obj = eCONST THEN - varparam(parser, pos, isCharArrayX, TRUE, e1) - ELSE - varparam(parser, pos, isCharArray, TRUE, e1) - END; - - wchar := e1._type.base = tWCHAR - END; - - IF ~PROG.isOpenArray(e1._type) THEN - IL.Const(e1._type.length) - END; - - IL.setlast(endcall.prev(IL.COMMAND)); - - IF e.obj = eCONST THEN - IF wchar THEN - IL.StrAdr(StringW(e)); - IL.Const(utf8strlen(e) + 1) - ELSE - IL.StrAdr(String(e)); - IL.Const(strlen(e) + 1) - END - END; - IL.AddCmd(IL.opCOPYS, e1._type.base.size); - IL.popBegEnd(begcall, endcall) - - |PROG.sysGET, PROG.sysGET8, PROG.sysGET16, PROG.sysGET32: - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - PARS.checklex(parser, SCAN.lxCOMMA); - NextPos(parser, pos); - parser.designator(parser, e2); - PARS.check(isVar(e2), pos, 93); - IF proc = PROG.sysGET THEN - PARS.check(e2._type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66) - ELSE - PARS.check(e2._type.typ IN {PROG.tINTEGER, PROG.tBYTE, PROG.tCHAR, PROG.tSET, PROG.tWCHAR, PROG.tCARD32}, pos, 66) - END; - - CASE proc OF - |PROG.sysGET: size := e2._type.size - |PROG.sysGET8: size := 1 - |PROG.sysGET16: size := 2 - |PROG.sysGET32: size := 4 - END; - - PARS.check(size <= e2._type.size, pos, 66); - - IF e.obj = eCONST THEN - IL.AddCmd2(IL.opGETC, ARITH.Int(e.value), size) - ELSE - IL.AddCmd(IL.opGET, size) - END - - |PROG.sysPUT, PROG.sysPUT8, PROG.sysPUT16, PROG.sysPUT32: - IL.pushBegEnd(begcall, endcall); - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - IF e.obj = eCONST THEN - LoadConst(e) - END; - PARS.checklex(parser, SCAN.lxCOMMA); - NextPos(parser, pos); - IL.setlast(begcall); - PExpression(parser, e2); - PARS.check(isExpr(e2), pos, 66); - - IF proc = PROG.sysPUT THEN - PARS.check(e2._type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66); - IF e2.obj = eCONST THEN - IF e2._type = tREAL THEN - Float(parser, e2); - IL.setlast(endcall.prev(IL.COMMAND)); - IL.savef(FALSE) - ELSE - LoadConst(e2); - IL.setlast(endcall.prev(IL.COMMAND)); - IL.SysPut(e2._type.size) - END - ELSE - IL.setlast(endcall.prev(IL.COMMAND)); - IF e2._type = tREAL THEN - IL.savef(FALSE) - ELSIF e2._type = tBYTE THEN - IL.SysPut(tINTEGER.size) - ELSE - IL.SysPut(e2._type.size) - END - END - - ELSIF (proc = PROG.sysPUT8) OR (proc = PROG.sysPUT16) OR (proc = PROG.sysPUT32) THEN - PARS.check(e2._type.typ IN {PROG.tINTEGER, PROG.tBYTE, PROG.tCHAR, PROG.tSET, PROG.tWCHAR, PROG.tCARD32}, pos, 66); - IF e2.obj = eCONST THEN - LoadConst(e2) - END; - IL.setlast(endcall.prev(IL.COMMAND)); - CASE proc OF - |PROG.sysPUT8: size := 1 - |PROG.sysPUT16: size := 2 - |PROG.sysPUT32: size := 4 - END; - IL.SysPut(size) - - END; - IL.popBegEnd(begcall, endcall) - - |PROG.sysMOVE: - FOR i := 1 TO 2 DO - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - IF e.obj = eCONST THEN - LoadConst(e) - END; - PARS.checklex(parser, SCAN.lxCOMMA); - NextPos(parser, pos) - END; - - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - IF e.obj = eCONST THEN - IL.AddCmd(IL.opCOPY, ARITH.Int(e.value)) - ELSE - IL.AddCmd0(IL.opMOVE) - END - - |PROG.sysCOPY: - FOR i := 1 TO 2 DO - parser.designator(parser, e); - PARS.check(isVar(e), pos, 93); - n := PROG.Dim(e._type); - WHILE n > 0 DO - IL.drop; - DEC(n) - END; - PARS.checklex(parser, SCAN.lxCOMMA); - NextPos(parser, pos) - END; - - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - IF e.obj = eCONST THEN - IL.AddCmd(IL.opCOPY, ARITH.Int(e.value)) - ELSE - IL.AddCmd0(IL.opMOVE) - END - - |PROG.sysCODE: - REPEAT - getpos(parser, pos); - PARS.ConstExpression(parser, code); - PARS.check(code.typ = ARITH.tINTEGER, pos, 43); - IF TARGETS.WordSize > TARGETS.InstrSize THEN - CASE TARGETS.InstrSize OF - |1: PARS.check(ARITH.range(code, 0, 255), pos, 42) - |2: PARS.check(ARITH.range(code, 0, 65535), pos, 110) - END - END; - IL.AddCmd(IL.opCODE, ARITH.getInt(code)); - comma := parser.sym = SCAN.lxCOMMA; - IF comma THEN - PARS.Next(parser) - ELSE - PARS.checklex(parser, SCAN.lxRROUND) - END - UNTIL (parser.sym = SCAN.lxRROUND) & ~comma - (* - |PROG.sysNOP, PROG.sysDINT, PROG.sysEINT: - IF parser.sym = SCAN.lxLROUND THEN - PARS.Next(parser); - PARS.checklex(parser, SCAN.lxRROUND); - PARS.Next(parser) - END; - ASSERT(CPU = cpuMSP430); - CASE proc OF - |PROG.sysNOP: IL.AddCmd(IL.opCODE, 4303H) - |PROG.sysDINT: IL.AddCmd(IL.opCODE, 0C232H); IL.AddCmd(IL.opCODE, 4303H) - |PROG.sysEINT: IL.AddCmd(IL.opCODE, 0D232H) - END - *) - END; - - e.obj := eEXPR; - e._type := NIL - - ELSIF e.obj IN {eSTFUNC, eSYSFUNC} THEN - - CASE e.stproc OF - |PROG.stABS: - PExpression(parser, e); - PARS.check(isInt(e) OR isReal(e), pos, 66); - IF e.obj = eCONST THEN - PARS.check(ARITH.abs(e.value), pos, 39) - ELSE - IL.abs(isReal(e)) - END - - |PROG.stASR, PROG.stLSL, PROG.stROR, PROG.stLSR, PROG.stMIN, PROG.stMAX: - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - PARS.checklex(parser, SCAN.lxCOMMA); - NextPos(parser, pos); - PExpression(parser, e2); - PARS.check(isInt(e2), pos, 66); - e._type := tINTEGER; - IF (e.obj = eCONST) & (e2.obj = eCONST) THEN - ASSERT(ARITH.opInt(e.value, e2.value, shift_minmax(proc))) - ELSE - IF e.obj = eCONST THEN - IL.shift_minmax1(shift_minmax(proc), ARITH.Int(e.value)) - ELSIF e2.obj = eCONST THEN - IL.shift_minmax2(shift_minmax(proc), ARITH.Int(e2.value)) - ELSE - IL.shift_minmax(shift_minmax(proc)) - END; - e.obj := eEXPR - END - - |PROG.stCHR: - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - e._type := tCHAR; - IF e.obj = eCONST THEN - ARITH.setChar(e.value, ARITH.getInt(e.value)); - PARS.check(ARITH.check(e.value), pos, 107) - ELSE - IF chkCHR IN Options.checking THEN - CheckRange(256, pos.line, errCHR) - ELSE - IL.AddCmd(IL.opMODR, 256) - END - END - - |PROG.stWCHR: - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - e._type := tWCHAR; - IF e.obj = eCONST THEN - ARITH.setWChar(e.value, ARITH.getInt(e.value)); - PARS.check(ARITH.check(e.value), pos, 101) - ELSE - IF chkWCHR IN Options.checking THEN - CheckRange(65536, pos.line, errWCHR) - ELSE - IL.AddCmd(IL.opMODR, 65536) - END - END - - |PROG.stFLOOR: - PExpression(parser, e); - PARS.check(isReal(e), pos, 66); - e._type := tINTEGER; - IF e.obj = eCONST THEN - PARS.check(ARITH.floor(e.value), pos, 39) - ELSE - IL.AddCmd0(IL.opFLOOR) - END - - |PROG.stFLT: - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - e._type := tREAL; - IF e.obj = eCONST THEN - ARITH.flt(e.value) - ELSE - IL.AddCmd2(IL.opFLT, pos.line, pos.col) - END - - |PROG.stLEN: - cmd1 := IL.getlast(); - varparam(parser, pos, isArr, FALSE, e); - IF e._type.length > 0 THEN - cmd2 := IL.getlast(); - IL.delete2(cmd1.next, cmd2); - IL.setlast(cmd1); - ASSERT(ARITH.setInt(e.value, e._type.length)); - e.obj := eCONST - ELSE - IL.len(PROG.Dim(e._type)) - END; - e._type := tINTEGER - - |PROG.stLENGTH: - PExpression(parser, e); - IF isCharArray(e) THEN - IF e._type.length > 0 THEN - IL.Const(e._type.length) - END; - IL.AddCmd0(IL.opLENGTH) - ELSIF isCharArrayW(e) THEN - IF e._type.length > 0 THEN - IL.Const(e._type.length) - END; - IL.AddCmd0(IL.opLENGTHW) - ELSE - PARS.error(pos, 66); - END; - e._type := tINTEGER - - |PROG.stODD: - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - e._type := tBOOLEAN; - IF e.obj = eCONST THEN - ARITH.odd(e.value) - ELSE - IL.AddCmd(IL.opMODR, 2) - END - - |PROG.stORD: - cmd1 := IL.getlast(); - PExpression(parser, e); - PARS.check(isChar(e) OR isBoolean(e) OR isSet(e) OR isCharW(e) OR isStringW1(e), pos, 66); - IF e.obj = eCONST THEN - IF isStringW1(e) THEN - ASSERT(ARITH.setInt(e.value, StrToWChar(e.value.string(SCAN.STRING).s))) - ELSE - ARITH.ord(e.value) - END - ELSE - IF isBoolean(e) THEN - cmd2 := IL.getlast(); - IL.setlast(cmd1); - IL.AddCmd(IL.opPRECALL, 0); - IL.AddCmd0(IL.opRES); - IL.drop; - IL.setlast(cmd2); - IL._ord - END - END; - e._type := tINTEGER - - |PROG.stBITS: - PExpression(parser, e); - PARS.check(isInt(e), pos, 66); - IF e.obj = eCONST THEN - ARITH.bits(e.value) - END; - e._type := tSET - - |PROG.sysADR: - parser.designator(parser, e); - IF isVar(e) THEN - n := PROG.Dim(e._type); - WHILE n > 0 DO - IL.drop; - DEC(n) - END - ELSIF e.obj = ePROC THEN - IL.PushProc(e.ident.proc.label) - ELSIF e.obj = eIMP THEN - IL.PushImpProc(e.ident._import) - ELSE - PARS.error(pos, 108) - END; - e._type := tINTEGER - - |PROG.sysSADR: - PExpression(parser, e); - PARS.check(isString(e), pos, 66); - IL.StrAdr(String(e)); - e._type := tINTEGER; - e.obj := eEXPR - - |PROG.sysWSADR: - PExpression(parser, e); - PARS.check(isStringW(e), pos, 66); - IL.StrAdr(StringW(e)); - e._type := tINTEGER; - e.obj := eEXPR - - |PROG.sysTYPEID: - PExpression(parser, e); - PARS.check(e.obj = eTYPE, pos, 68); - IF e._type.typ = PROG.tRECORD THEN - ASSERT(ARITH.setInt(e.value, e._type.num)) - ELSIF e._type.typ = PROG.tPOINTER THEN - ASSERT(ARITH.setInt(e.value, e._type.base.num)) - ELSE - PARS.error(pos, 52) - END; - e.obj := eCONST; - e._type := tINTEGER - - |PROG.sysINF: - IL.AddCmd2(IL.opINF, pos.line, pos.col); - e.obj := eEXPR; - e._type := tREAL - - |PROG.sysSIZE: - PExpression(parser, e); - PARS.check(e.obj = eTYPE, pos, 68); - ASSERT(ARITH.setInt(e.value, e._type.size)); - e.obj := eCONST; - e._type := tINTEGER - - END - - END; - -(* IF (proc # PROG.sysNOP) & (proc # PROG.sysEINT) & (proc # PROG.sysDINT) THEN *) - PARS.checklex(parser, SCAN.lxRROUND); - PARS.Next(parser); -(* END; *) - - IF e.obj # eCONST THEN - e.obj := eEXPR - END - -END stProc; - - -PROCEDURE ActualParameters (parser: PARS.PARSER; VAR e: PARS.EXPR); -VAR - proc: PROG._TYPE; - param: LISTS.ITEM; - e1: PARS.EXPR; - pos: PARS.POSITION; - -BEGIN - ASSERT(parser.sym = SCAN.lxLROUND); - - IF (e.obj IN {ePROC, eIMP}) OR isExpr(e) THEN - proc := e._type; - PARS.check1(proc.typ = PROG.tPROCEDURE, parser, 86); - PARS.Next(parser); - - param := proc.params.first; - WHILE param # NIL DO - getpos(parser, pos); - - IL.setlast(begcall); - - IF param(PROG.PARAM).vPar THEN - parser.designator(parser, e1) - ELSE - PExpression(parser, e1) - END; - paramcomp(parser, pos, e1, param(PROG.PARAM)); - param := param.next; - IF param # NIL THEN - PARS.checklex(parser, SCAN.lxCOMMA); - PARS.Next(parser) - END - END; - - PARS.checklex(parser, SCAN.lxRROUND); - PARS.Next(parser); - - e.obj := eEXPR; - e._type := proc.base - - ELSIF e.obj IN {eSTPROC, eSTFUNC, eSYSPROC, eSYSFUNC} THEN - stProc(parser, e) - ELSE - PARS.check1(FALSE, parser, 86) - END - -END ActualParameters; - - -PROCEDURE qualident (parser: PARS.PARSER; VAR e: PARS.EXPR); -VAR - ident: PROG.IDENT; - imp: BOOLEAN; - pos: PARS.POSITION; - -BEGIN - PARS.checklex(parser, SCAN.lxIDENT); - getpos(parser, pos); - imp := FALSE; - ident := PROG.getIdent(parser.unit, parser.lex.ident, FALSE); - PARS.check1(ident # NIL, parser, 48); - IF ident.typ = PROG.idMODULE THEN - PARS.ExpectSym(parser, SCAN.lxPOINT); - PARS.ExpectSym(parser, SCAN.lxIDENT); - ident := PROG.getIdent(ident.unit, parser.lex.ident, FALSE); - PARS.check1((ident # NIL) & ident.export, parser, 48); - imp := TRUE - END; - PARS.Next(parser); - - e.readOnly := FALSE; - e.ident := ident; - - CASE ident.typ OF - |PROG.idCONST: - e.obj := eCONST; - e._type := ident._type; - e.value := ident.value - |PROG.idTYPE: - e.obj := eTYPE; - e._type := ident._type - |PROG.idVAR: - e.obj := eVAR; - e._type := ident._type; - e.readOnly := imp - |PROG.idPROC: - e.obj := ePROC; - e._type := ident._type - |PROG.idIMP: - e.obj := eIMP; - e._type := ident._type - |PROG.idVPAR: - e._type := ident._type; - IF e._type.typ = PROG.tRECORD THEN - e.obj := eVREC - ELSE - e.obj := eVPAR - END - |PROG.idPARAM: - e.obj := ePARAM; - e._type := ident._type; - e.readOnly := (e._type.typ IN {PROG.tRECORD, PROG.tARRAY}) - |PROG.idSTPROC: - e.obj := eSTPROC; - e._type := ident._type; - e.stproc := ident.stproc - |PROG.idSTFUNC: - e.obj := eSTFUNC; - e._type := ident._type; - e.stproc := ident.stproc - |PROG.idSYSPROC: - e.obj := eSYSPROC; - e._type := ident._type; - e.stproc := ident.stproc - |PROG.idSYSFUNC: - PARS.check(~parser.constexp, pos, 109); - e.obj := eSYSFUNC; - e._type := ident._type; - e.stproc := ident.stproc - |PROG.idNONE: - PARS.error(pos, 115) - END; - - IF isVar(e) THEN - PARS.check(e.ident.global OR (e.ident.scopeLvl = parser.unit.scopeLvl), pos, 105) - END - -END qualident; - - -PROCEDURE deref (pos: PARS.POSITION; e: PARS.EXPR; load: BOOLEAN; error: INTEGER); -VAR - label: INTEGER; - -BEGIN - IF load THEN - IL.load(e._type.size) - END; - - IF chkPTR IN Options.checking THEN - label := IL.NewLabel(); - IL.Jmp(IL.opJNZ1, label); - IL.OnError(pos.line, error); - IL.SetLabel(label) - END -END deref; - - -PROCEDURE designator (parser: PARS.PARSER; VAR e: PARS.EXPR); -VAR - field: PROG.FIELD; - pos: PARS.POSITION; - t, idx: PARS.EXPR; - sysVal: BOOLEAN; - n: INTEGER; - - - PROCEDURE LoadAdr (e: PARS.EXPR); - VAR - offset: INTEGER; - - PROCEDURE OpenArray (e: PARS.EXPR); - VAR - offset, n: INTEGER; - BEGIN - offset := e.ident.offset; - n := PROG.Dim(e._type); - WHILE n >= 0 DO - IL.AddCmd(IL.opVADR, offset); - DEC(offset); - DEC(n) - END - END OpenArray; - - - BEGIN - IF e.obj = eVAR THEN - offset := PROG.getOffset(e.ident); - IF e.ident.global THEN - IL.AddCmd(IL.opGADR, offset) - ELSE - IL.AddCmd(IL.opLADR, -offset) - END - ELSIF e.obj = ePARAM THEN - IF (e._type.typ = PROG.tRECORD) OR ((e._type.typ = PROG.tARRAY) & (e._type.length > 0)) THEN - IL.AddCmd(IL.opVADR, e.ident.offset) - ELSIF PROG.isOpenArray(e._type) THEN - OpenArray(e) - ELSE - IL.AddCmd(IL.opLADR, e.ident.offset) - END - ELSIF e.obj IN {eVPAR, eVREC} THEN - IF PROG.isOpenArray(e._type) THEN - OpenArray(e) - ELSE - IL.AddCmd(IL.opVADR, e.ident.offset) - END - END - END LoadAdr; - - - PROCEDURE OpenIdx (parser: PARS.PARSER; pos: PARS.POSITION; e: PARS.EXPR); - VAR - label, offset, n, k: INTEGER; - _type: PROG._TYPE; - - BEGIN - IF chkIDX IN Options.checking THEN - label := IL.NewLabel(); - IL.AddCmd2(IL.opCHKIDX2, label, 0); - IL.OnError(pos.line, errIDX); - IL.SetLabel(label) - ELSE - IL.AddCmd(IL.opCHKIDX2, -1) - END; - - _type := PROG.OpenBase(e._type); - IF _type.size # 1 THEN - IL.AddCmd(IL.opMULC, _type.size) - END; - n := PROG.Dim(e._type) - 1; - k := n; - WHILE n > 0 DO - IL.AddCmd0(IL.opMUL); - DEC(n) - END; - IL.AddCmd0(IL.opADD); - offset := e.ident.offset - 1; - n := k; - WHILE n > 0 DO - IL.AddCmd(IL.opVADR, offset); - DEC(offset); - DEC(n) - END - END OpenIdx; - - -BEGIN - qualident(parser, e); - sysVal := (e.obj = eSYSPROC) & (e.stproc = PROG.sysVAL); - IF sysVal THEN - PARS.checklex(parser, SCAN.lxLROUND); - PARS.Next(parser); - getpos(parser, pos); - designator(parser, e); - PARS.check(isVar(e), pos, 93); - IF PROG.isOpenArray(e._type) THEN - n := PROG.Dim(e._type); - WHILE n > 0 DO - IL.drop; - DEC(n) - END - END; - PARS.checklex(parser, SCAN.lxCOMMA); - PARS.Next(parser); - getpos(parser, pos); - qualident(parser, t); - PARS.check(t.obj = eTYPE, pos, 79); - e._type := t._type; - PARS.checklex(parser, SCAN.lxRROUND); - PARS.Next(parser) - END; - - IF e.obj IN {ePROC, eIMP} THEN - PROG.UseProc(parser.unit, e.ident.proc) - END; - - IF isVar(e) & ~sysVal THEN - LoadAdr(e) - END; - - WHILE parser.sym = SCAN.lxPOINT DO - getpos(parser, pos); - PARS.check1(isExpr(e) & (e._type.typ IN {PROG.tRECORD, PROG.tPOINTER}), parser, 73); - IF e._type.typ = PROG.tPOINTER THEN - deref(pos, e, TRUE, errPTR) - END; - PARS.ExpectSym(parser, SCAN.lxIDENT); - IF e._type.typ = PROG.tPOINTER THEN - e._type := e._type.base; - e.readOnly := FALSE - END; - field := PROG.getField(e._type, parser.lex.ident, parser.unit); - PARS.check1(field # NIL, parser, 74); - e._type := field._type; - IF e.obj = eVREC THEN - e.obj := eVPAR - END; - IF field.offset # 0 THEN - IL.AddCmd(IL.opADDC, field.offset) - END; - PARS.Next(parser); - e.ident := NIL - - ELSIF parser.sym = SCAN.lxLSQUARE DO - - REPEAT - - PARS.check1(isArr(e), parser, 75); - NextPos(parser, pos); - PExpression(parser, idx); - PARS.check(isInt(idx), pos, 76); - - IF idx.obj = eCONST THEN - IF e._type.length > 0 THEN - PARS.check(ARITH.range(idx.value, 0, e._type.length - 1), pos, 83); - IF ARITH.Int(idx.value) > 0 THEN - IL.AddCmd(IL.opADDC, ARITH.Int(idx.value) * e._type.base.size) - END - ELSE - PARS.check(ARITH.range(idx.value, 0, UTILS.target.maxInt), pos, 83); - LoadConst(idx); - OpenIdx(parser, pos, e) - END - ELSE - IF e._type.length > 0 THEN - IF chkIDX IN Options.checking THEN - CheckRange(e._type.length, pos.line, errIDX) - END; - IF e._type.base.size # 1 THEN - IL.AddCmd(IL.opMULC, e._type.base.size) - END; - IL.AddCmd0(IL.opADD) - ELSE - OpenIdx(parser, pos, e) - END - END; - - e._type := e._type.base - - UNTIL parser.sym # SCAN.lxCOMMA; - - PARS.checklex(parser, SCAN.lxRSQUARE); - PARS.Next(parser); - IF ~(isArr(e) & (e._type.length = 0) & (parser.sym = SCAN.lxLSQUARE)) THEN - e.ident := NIL - END - - ELSIF parser.sym = SCAN.lxCARET DO - getpos(parser, pos); - PARS.check1(isPtr(e), parser, 77); - deref(pos, e, TRUE, errPTR); - e._type := e._type.base; - e.readOnly := FALSE; - PARS.Next(parser); - e.ident := NIL; - e.obj := eVREC - - ELSIF (parser.sym = SCAN.lxLROUND) & isExpr(e) & (e._type.typ IN {PROG.tRECORD, PROG.tPOINTER}) DO - - IF e._type.typ = PROG.tRECORD THEN - PARS.check1(e.obj = eVREC, parser, 78) - END; - NextPos(parser, pos); - qualident(parser, t); - PARS.check(t.obj = eTYPE, pos, 79); - - IF e._type.typ = PROG.tRECORD THEN - PARS.check(t._type.typ = PROG.tRECORD, pos, 80); - IF chkGUARD IN Options.checking THEN - IF e.ident = NIL THEN - IL.TypeGuard(IL.opTYPEGD, t._type.num, pos.line, errGUARD) - ELSE - IL.AddCmd(IL.opVADR, e.ident.offset - 1); - IL.TypeGuard(IL.opTYPEGR, t._type.num, pos.line, errGUARD) - END - END; - ELSE - PARS.check(t._type.typ = PROG.tPOINTER, pos, 81); - IF chkGUARD IN Options.checking THEN - IL.TypeGuard(IL.opTYPEGP, t._type.base.num, pos.line, errGUARD) - END - END; - - PARS.check(PROG.isBaseOf(e._type, t._type), pos, 82); - - e._type := t._type; - - PARS.checklex(parser, SCAN.lxRROUND); - PARS.Next(parser) - - END - -END designator; - - -PROCEDURE ProcCall (e: PARS.EXPR; procType: PROG._TYPE; isfloat: BOOLEAN; parser: PARS.PARSER; pos: PARS.POSITION; CallStat: BOOLEAN); -VAR - cconv, - parSize, - callconv, - fparSize, - int, flt, - stk_par: INTEGER; - -BEGIN - cconv := procType.call; - parSize := procType.parSize; - - IF cconv IN {PROG._win64, PROG.win64} THEN - callconv := IL.call_win64; - fparSize := LSL(ORD(PROG.getFloatParamsPos(procType, 3, int, flt)), 5) + MIN(parSize, 4) - ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN - callconv := IL.call_sysv; - fparSize := LSL(ORD(PROG.getFloatParamsPos(procType, PROG.MAXSYSVPARAM - 1, int, flt)), 5) + parSize; - stk_par := MAX(0, int - 6) + MAX(0, flt - 8) - ELSIF cconv IN {PROG.fastcall, PROG._fastcall} THEN - IF parSize = 0 THEN - callconv := IL.call_stack - ELSIF parSize = 1 THEN - callconv := IL.call_fast1 - ELSIF parSize >= 2 THEN - callconv := IL.call_fast2 - END; - fparSize := 0 - ELSE - callconv := IL.call_stack; - fparSize := 0 - END; - IL.setlast(begcall); - IL.AddCmd(IL.opPRECALL, ORD(isfloat)); - - IF cconv IN {PROG._ccall, PROG.ccall} THEN - IL.AddCmd(IL.opALIGN16, parSize) - ELSIF cconv IN {PROG._win64, PROG.win64} THEN - IL.AddCmd(IL.opWIN64ALIGN16, parSize) - ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN - IL.AddCmd(IL.opSYSVALIGN16, parSize + stk_par) - END; - IL.setlast(endcall.prev(IL.COMMAND)); - - IF e.obj = eIMP THEN - IL.CallImp(e.ident._import, callconv, fparSize) - ELSIF e.obj = ePROC THEN - IL.Call(e.ident.proc.label, callconv, fparSize) - ELSIF isExpr(e) THEN - deref(pos, e, CallStat, errPROC); - IL.CallP(callconv, fparSize) - END; - - IF cconv IN {PROG._ccall, PROG.ccall} THEN - IL.AddCmd(IL.opCLEANUP, parSize); - IL.AddCmd0(IL.opPOPSP) - ELSIF cconv IN {PROG._win64, PROG.win64} THEN - IL.AddCmd(IL.opCLEANUP, MAX(parSize + parSize MOD 2, 4) + 1); - IL.AddCmd0(IL.opPOPSP) - ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN - IL.AddCmd(IL.opCLEANUP, parSize + stk_par); - IL.AddCmd0(IL.opPOPSP) - ELSIF cconv IN {PROG._cdecl, PROG.cdecl, PROG.default16, PROG.code, PROG._code} THEN - IL.AddCmd(IL.opCLEANUP, parSize) - END; - - IF CallStat THEN - IL.AddCmd0(IL.opRES); - IL.drop - ELSE - IF isfloat THEN - IL.AddCmd2(IL.opRESF, pos.line, pos.col) - ELSE - IL.AddCmd0(IL.opRES) - END - END -END ProcCall; - - -PROCEDURE expression (parser: PARS.PARSER; VAR e: PARS.EXPR); -VAR - pos, pos0, pos1: PARS.POSITION; - e1: PARS.EXPR; - op, cmp, error: INTEGER; - constant, eq: BOOLEAN; - - - PROCEDURE relation (sym: INTEGER): BOOLEAN; - RETURN (sym = SCAN.lxEQ) OR (sym = SCAN.lxNE) OR - (sym = SCAN.lxLT) OR (sym = SCAN.lxLE) OR - (sym = SCAN.lxGT) OR (sym = SCAN.lxGE) OR - (sym = SCAN.lxIN) OR (sym = SCAN.lxIS) - END relation; - - - PROCEDURE AddOperator (sym: INTEGER): BOOLEAN; - RETURN (sym = SCAN.lxPLUS) OR (sym = SCAN.lxMINUS) OR - (sym = SCAN.lxOR) - END AddOperator; - - - PROCEDURE MulOperator (sym: INTEGER): BOOLEAN; - RETURN (sym = SCAN.lxMUL) OR (sym = SCAN.lxSLASH) OR - (sym = SCAN.lxDIV) OR (sym = SCAN.lxMOD) OR - (sym = SCAN.lxAND) - END MulOperator; - - - PROCEDURE element (parser: PARS.PARSER; VAR e: PARS.EXPR); - VAR - e1, e2: PARS.EXPR; - pos: PARS.POSITION; - range: BOOLEAN; - - BEGIN - range := FALSE; - getpos(parser, pos); - expression(parser, e1); - PARS.check(isInt(e1), pos, 76); - - IF e1.obj = eCONST THEN - PARS.check(ARITH.range(e1.value, 0, UTILS.target.maxSet), pos, 44) - END; - - range := parser.sym = SCAN.lxRANGE; - - IF range THEN - NextPos(parser, pos); - expression(parser, e2); - PARS.check(isInt(e2), pos, 76); - - IF e2.obj = eCONST THEN - PARS.check(ARITH.range(e2.value, 0, UTILS.target.maxSet), pos, 44) - END - ELSE - IF e1.obj = eCONST THEN - e2 := e1 - END - END; - - e._type := tSET; - - IF (e1.obj = eCONST) & (e2.obj = eCONST) THEN - ARITH.constrSet(e.value, e1.value, e2.value); - e.obj := eCONST - ELSE - IF range THEN - IF e1.obj = eCONST THEN - IL.AddCmd(IL.opRSETL, ARITH.Int(e1.value)) - ELSIF e2.obj = eCONST THEN - IL.AddCmd(IL.opRSETR, ARITH.Int(e2.value)) - ELSE - IL.AddCmd0(IL.opRSET) - END - ELSE - IL.AddCmd0(IL.opRSET1) - END; - e.obj := eEXPR - END - - END element; - - - PROCEDURE set (parser: PARS.PARSER; VAR e: PARS.EXPR); - VAR - e1: PARS.EXPR; - - BEGIN - ASSERT(parser.sym = SCAN.lxLCURLY); - - e.obj := eCONST; - e._type := tSET; - ARITH.emptySet(e.value); - - PARS.Next(parser); - IF parser.sym # SCAN.lxRCURLY THEN - element(parser, e1); - - IF e1.obj = eCONST THEN - ARITH.opSet(e.value, e1.value, "+") - ELSE - e.obj := eEXPR - END; - - WHILE parser.sym = SCAN.lxCOMMA DO - PARS.Next(parser); - element(parser, e1); - IF (e.obj = eCONST) & (e1.obj = eCONST) THEN - ARITH.opSet(e.value, e1.value, "+") - ELSE - IF e.obj = eCONST THEN - IL.AddCmd(IL.opADDSC, ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opADDSC, ARITH.Int(e1.value)) - ELSE - IL.AddCmd0(IL.opADDS) - END; - e.obj := eEXPR - END - END; - PARS.checklex(parser, SCAN.lxRCURLY) - END; - PARS.Next(parser); - END set; - - - PROCEDURE factor (parser: PARS.PARSER; VAR e: PARS.EXPR); - VAR - sym: INTEGER; - pos: PARS.POSITION; - e1: PARS.EXPR; - isfloat: BOOLEAN; - - - PROCEDURE LoadVar (e: PARS.EXPR; parser: PARS.PARSER; pos: PARS.POSITION); - BEGIN - IF ~(e._type.typ IN {PROG.tRECORD, PROG.tARRAY}) THEN - IF e._type = tREAL THEN - IL.AddCmd2(IL.opLOADF, pos.line, pos.col) - ELSE - IL.load(e._type.size) - END - END - END LoadVar; - - - BEGIN - sym := parser.sym; - - IF (sym = SCAN.lxINTEGER) OR (sym = SCAN.lxHEX) OR (sym = SCAN.lxFLOAT) OR (sym = SCAN.lxCHAR) OR (sym = SCAN.lxSTRING) THEN - e.obj := eCONST; - e.value := parser.lex.value; - e._type := PROG.getType(e.value.typ); - PARS.Next(parser) - - ELSIF sym = SCAN.lxNIL THEN - e.obj := eCONST; - e._type := PROG.program.stTypes.tNIL; - PARS.Next(parser) - - ELSIF (sym = SCAN.lxTRUE) OR (sym = SCAN.lxFALSE) THEN - e.obj := eCONST; - ARITH.setbool(e.value, sym = SCAN.lxTRUE); - e._type := tBOOLEAN; - PARS.Next(parser) - - ELSIF sym = SCAN.lxLCURLY THEN - set(parser, e) - - ELSIF sym = SCAN.lxIDENT THEN - getpos(parser, pos); - - IL.pushBegEnd(begcall, endcall); - - designator(parser, e); - IF isVar(e) THEN - LoadVar(e, parser, pos) - END; - IF parser.sym = SCAN.lxLROUND THEN - e1 := e; - ActualParameters(parser, e); - PARS.check(e._type # NIL, pos, 59); - isfloat := e._type = tREAL; - IF e1.obj IN {ePROC, eIMP} THEN - ProcCall(e1, e1.ident._type, isfloat, parser, pos, FALSE) - ELSIF isExpr(e1) THEN - ProcCall(e1, e1._type, isfloat, parser, pos, FALSE) - END - END; - IL.popBegEnd(begcall, endcall) - - ELSIF sym = SCAN.lxLROUND THEN - PARS.Next(parser); - expression(parser, e); - PARS.checklex(parser, SCAN.lxRROUND); - PARS.Next(parser); - IF isExpr(e) & (e.obj # eCONST) THEN - e.obj := eEXPR - END - - ELSIF sym = SCAN.lxNOT THEN - NextPos(parser, pos); - factor(parser, e); - PARS.check(isBoolean(e), pos, 72); - IF e.obj # eCONST THEN - IL.not; - e.obj := eEXPR - ELSE - ASSERT(ARITH.neg(e.value)) - END - - ELSE - PARS.check1(FALSE, parser, 34) - END - END factor; - - - PROCEDURE term (parser: PARS.PARSER; VAR e: PARS.EXPR); - VAR - pos: PARS.POSITION; - e1: PARS.EXPR; - op, label, label1: INTEGER; - - BEGIN - factor(parser, e); - label := -1; - - WHILE MulOperator(parser.sym) DO - op := parser.sym; - getpos(parser, pos); - PARS.Next(parser); - - IF op = SCAN.lxAND THEN - IF ~parser.constexp THEN - - IF label = -1 THEN - label := IL.NewLabel() - END; - - IF (e.obj = eCONST) & isBoolean(e) THEN - IL.Const(ORD(ARITH.getBool(e.value))) - END; - IL.Jmp(IL.opJZ, label) - END - END; - - factor(parser, e1); - - CASE op OF - |SCAN.lxMUL: - PARS.check(isInt(e) & isInt(e1) OR isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), pos, 37); - IF (e.obj = eCONST) & (e1.obj = eCONST) THEN - - CASE e.value.typ OF - |ARITH.tINTEGER: PARS.check(ARITH.opInt(e.value, e1.value, "*"), pos, 39) - |ARITH.tREAL: PARS.check(ARITH.opFloat(e.value, e1.value, "*"), pos, 40) - |ARITH.tSET: ARITH.opSet(e.value, e1.value, "*") - END - - ELSE - IF isInt(e) THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opMULC, ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opMULC, ARITH.Int(e1.value)) - ELSE - IL.AddCmd0(IL.opMUL) - END - ELSIF isReal(e) THEN - IF e.obj = eCONST THEN - Float(parser, e) - ELSIF e1.obj = eCONST THEN - Float(parser, e1) - END; - IL.AddCmd0(IL.opMULF) - ELSIF isSet(e) THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opMULSC, ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opMULSC, ARITH.Int(e1.value)) - ELSE - IL.AddCmd0(IL.opMULS) - END - END; - e.obj := eEXPR - END - - |SCAN.lxSLASH: - PARS.check(isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), pos, 37); - IF (e1.obj = eCONST) & isReal(e1) THEN - PARS.check(~ARITH.isZero(e1.value), pos, 45) - END; - IF (e.obj = eCONST) & (e1.obj = eCONST) THEN - - CASE e.value.typ OF - |ARITH.tREAL: PARS.check(ARITH.opFloat(e.value, e1.value, "/"), pos, 40) - |ARITH.tSET: ARITH.opSet(e.value, e1.value, "/") - END - - ELSE - IF isReal(e) THEN - IF e.obj = eCONST THEN - Float(parser, e); - IL.AddCmd0(IL.opDIVFI) - ELSIF e1.obj = eCONST THEN - Float(parser, e1); - IL.AddCmd0(IL.opDIVF) - ELSE - IL.AddCmd0(IL.opDIVF) - END - ELSIF isSet(e) THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opDIVSC, ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opDIVSC, ARITH.Int(e1.value)) - ELSE - IL.AddCmd0(IL.opDIVS) - END - END; - e.obj := eEXPR - END - - |SCAN.lxDIV, SCAN.lxMOD: - PARS.check(isInt(e) & isInt(e1), pos, 37); - IF e1.obj = eCONST THEN - PARS.check(ARITH.Int(e1.value) > 0, pos, 122) - END; - IF (e.obj = eCONST) & (e1.obj = eCONST) THEN - - IF op = SCAN.lxDIV THEN - PARS.check(ARITH.opInt(e.value, e1.value, "D"), pos, 39) - ELSE - ASSERT(ARITH.opInt(e.value, e1.value, "M")) - END - - ELSE - IF e1.obj # eCONST THEN - label1 := IL.NewLabel(); - IL.Jmp(IL.opJG, label1) - END; - IF e.obj = eCONST THEN - IL.OnError(pos.line, errDIV); - IL.SetLabel(label1); - IL.AddCmd(IL.opDIVL + ORD(op = SCAN.lxMOD), ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opDIVR + ORD(op = SCAN.lxMOD), ARITH.Int(e1.value)) - ELSE - IL.OnError(pos.line, errDIV); - IL.SetLabel(label1); - IL.AddCmd0(IL.opDIV + ORD(op = SCAN.lxMOD)) - END; - e.obj := eEXPR - END - - |SCAN.lxAND: - PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); - - IF (e.obj = eCONST) & (e1.obj = eCONST) & parser.constexp THEN - ARITH.opBoolean(e.value, e1.value, "&") - ELSE - e.obj := eEXPR; - IF e1.obj = eCONST THEN - IL.Const(ORD(ARITH.getBool(e1.value))) - END - END - - END - END; - - IF label # -1 THEN - label1 := IL.NewLabel(); - IL.Jmp(IL.opJNZ, label1); - IL.SetLabel(label); - IL.Const(0); - IL.drop; - label := IL.NewLabel(); - IL.Jmp(IL.opJMP, label); - IL.SetLabel(label1); - IL.Const(1); - IL.SetLabel(label); - IL.AddCmd0(IL.opAND) - END - END term; - - - PROCEDURE SimpleExpression (parser: PARS.PARSER; VAR e: PARS.EXPR); - VAR - pos: PARS.POSITION; - op: INTEGER; - e1: PARS.EXPR; - s, s1: SCAN.TEXTSTR; - - plus, minus: BOOLEAN; - - label, label1: INTEGER; - - BEGIN - plus := parser.sym = SCAN.lxPLUS; - minus := parser.sym = SCAN.lxMINUS; - - IF plus OR minus THEN - getpos(parser, pos); - PARS.Next(parser) - END; - - term(parser, e); - - IF plus OR minus THEN - PARS.check(isInt(e) OR isReal(e) OR isSet(e), pos, 36); - - IF minus & (e.obj = eCONST) THEN - PARS.check(ARITH.neg(e.value), pos, 39) - END; - - IF e.obj # eCONST THEN - IF minus THEN - IF isInt(e) THEN - IL.AddCmd0(IL.opUMINUS) - ELSIF isReal(e) THEN - IL.AddCmd0(IL.opUMINF) - ELSIF isSet(e) THEN - IL.AddCmd0(IL.opUMINS) - END - END; - e.obj := eEXPR - END - END; - - label := -1; - - WHILE AddOperator(parser.sym) DO - - op := parser.sym; - getpos(parser, pos); - PARS.Next(parser); - - IF op = SCAN.lxOR THEN - - IF ~parser.constexp THEN - - IF label = -1 THEN - label := IL.NewLabel() - END; - - IF (e.obj = eCONST) & isBoolean(e) THEN - IL.Const(ORD(ARITH.getBool(e.value))) - END; - IL.Jmp(IL.opJNZ, label) - END - - END; - - term(parser, e1); - - CASE op OF - |SCAN.lxPLUS, SCAN.lxMINUS: - - minus := op = SCAN.lxMINUS; - IF minus THEN - op := ORD("-") - ELSE - op := ORD("+") - END; - - PARS.check(isInt(e) & isInt(e1) OR isReal(e) & isReal(e1) OR isSet(e) & isSet(e1) OR isString(e) & isString(e1) & ~minus, pos, 37); - IF (e.obj = eCONST) & (e1.obj = eCONST) THEN - - CASE e.value.typ OF - |ARITH.tINTEGER: - PARS.check(ARITH.opInt(e.value, e1.value, CHR(op)), pos, 39) - - |ARITH.tREAL: - PARS.check(ARITH.opFloat(e.value, e1.value, CHR(op)), pos, 40) - - |ARITH.tSET: - ARITH.opSet(e.value, e1.value, CHR(op)) - - |ARITH.tCHAR, ARITH.tSTRING: - IF e.value.typ = ARITH.tCHAR THEN - ARITH.charToStr(e.value, s) - ELSE - s := e.value.string(SCAN.STRING).s - END; - IF e1.value.typ = ARITH.tCHAR THEN - ARITH.charToStr(e1.value, s1) - ELSE - s1 := e1.value.string(SCAN.STRING).s - END; - PARS.check(ARITH.concat(s, s1), pos, 5); - e.value.string := SCAN.enterStr(s); - e.value.typ := ARITH.tSTRING; - e._type := PROG.program.stTypes.tSTRING - END - - ELSE - IF isInt(e) THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opADDC - ORD(minus), ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opADDC + ORD(minus), ARITH.Int(e1.value)) - ELSE - IL.AddCmd0(IL.opADD + ORD(minus)) - END - ELSIF isReal(e) THEN - IF e.obj = eCONST THEN - Float(parser, e); - IL.AddCmd0(IL.opADDF - ORD(minus)) - ELSIF e1.obj = eCONST THEN - Float(parser, e1); - IL.AddCmd0(IL.opADDF + ORD(minus)) - ELSE - IL.AddCmd0(IL.opADDF + ORD(minus)) - END - ELSIF isSet(e) THEN - IF e.obj = eCONST THEN - IL.AddCmd(IL.opADDSC - ORD(minus), ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opADDSC + ORD(minus), ARITH.Int(e1.value)) - ELSE - IL.AddCmd0(IL.opADDS + ORD(minus)) - END - END; - e.obj := eEXPR - END - - |SCAN.lxOR: - PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); - - IF (e.obj = eCONST) & (e1.obj = eCONST) & parser.constexp THEN - ARITH.opBoolean(e.value, e1.value, "|") - ELSE - e.obj := eEXPR; - IF e1.obj = eCONST THEN - IL.Const(ORD(ARITH.getBool(e1.value))) - END - END - - END - END; - - IF label # -1 THEN - label1 := IL.NewLabel(); - IL.Jmp(IL.opJZ, label1); - IL.SetLabel(label); - IL.Const(1); - IL.drop; - label := IL.NewLabel(); - IL.Jmp(IL.opJMP, label); - IL.SetLabel(label1); - IL.Const(0); - IL.SetLabel(label); - IL.AddCmd0(IL.opOR) - END - - END SimpleExpression; - - - PROCEDURE cmpcode (op: INTEGER): INTEGER; - VAR - res: INTEGER; - - BEGIN - CASE op OF - |SCAN.lxEQ: res := ARITH.opEQ - |SCAN.lxNE: res := ARITH.opNE - |SCAN.lxLT: res := ARITH.opLT - |SCAN.lxLE: res := ARITH.opLE - |SCAN.lxGT: res := ARITH.opGT - |SCAN.lxGE: res := ARITH.opGE - |SCAN.lxIN: res := ARITH.opIN - |SCAN.lxIS: res := ARITH.opIS - END - - RETURN res - END cmpcode; - - - PROCEDURE invcmpcode (op: INTEGER): INTEGER; - VAR - res: INTEGER; - - BEGIN - CASE op OF - |SCAN.lxEQ: res := ARITH.opEQ - |SCAN.lxNE: res := ARITH.opNE - |SCAN.lxLT: res := ARITH.opGT - |SCAN.lxLE: res := ARITH.opGE - |SCAN.lxGT: res := ARITH.opLT - |SCAN.lxGE: res := ARITH.opLE - |SCAN.lxIN: res := ARITH.opIN - |SCAN.lxIS: res := ARITH.opIS - END - - RETURN res - END invcmpcode; - - - PROCEDURE BoolCmp (eq, val: BOOLEAN); - BEGIN - IF eq = val THEN - IL.AddCmd0(IL.opNEC) - ELSE - IL.AddCmd0(IL.opEQC) - END - END BoolCmp; - - - PROCEDURE strcmp (VAR e, e1: PARS.EXPR; op: INTEGER): BOOLEAN; - VAR - res: BOOLEAN; - cmp: INTEGER; - - BEGIN - res := TRUE; - cmp := cmpcode(op); - - IF isString(e) & isCharArray(e1) THEN - IL.StrAdr(String(e)); - IL.Const(strlen(e) + 1); - IL.AddCmd0(IL.opEQS + invcmpcode(op)) - - ELSIF (isString(e) OR isStringW(e)) & isCharArrayW(e1) THEN - IL.StrAdr(StringW(e)); - IL.Const(utf8strlen(e) + 1); - IL.AddCmd0(IL.opEQSW + invcmpcode(op)) - - ELSIF isCharArray(e) & isString(e1) THEN - IL.StrAdr(String(e1)); - IL.Const(strlen(e1) + 1); - IL.AddCmd0(IL.opEQS + cmp) - - ELSIF isCharArrayW(e) & (isString(e1) OR isStringW(e1)) THEN - IL.StrAdr(StringW(e1)); - IL.Const(utf8strlen(e1) + 1); - IL.AddCmd0(IL.opEQSW + cmp) - - ELSIF isCharArrayW(e) & isCharArrayW(e1) THEN - IL.AddCmd0(IL.opEQSW + cmp) - - ELSIF isCharArray(e) & isCharArray(e1) THEN - IL.AddCmd0(IL.opEQS + cmp) - - ELSIF isString(e) & isString(e1) THEN - PARS.strcmp(e.value, e1.value, op) - - ELSE - res := FALSE - - END - - RETURN res - END strcmp; - - -BEGIN - getpos(parser, pos0); - SimpleExpression(parser, e); - IF relation(parser.sym) THEN - IF (isCharArray(e) OR isCharArrayW(e)) & (e._type.length # 0) THEN - IL.Const(e._type.length) - END; - op := parser.sym; - getpos(parser, pos); - PARS.Next(parser); - - getpos(parser, pos1); - SimpleExpression(parser, e1); - - IF (isCharArray(e1) OR isCharArrayW(e1)) & (e1._type.length # 0) THEN - IL.Const(e1._type.length) - END; - - constant := (e.obj = eCONST) & (e1.obj = eCONST); - error := 0; - cmp := cmpcode(op); - - CASE op OF - |SCAN.lxEQ, SCAN.lxNE: - eq := op = SCAN.lxEQ; - IF isInt(e) & isInt(e1) OR isSet(e) & isSet(e1) OR isChar(e) & isChar(e1) OR isCharW(e) & isCharW(e1) OR - isCharW(e) & isChar(e1) & (e1.obj = eCONST) OR isCharW(e1) & isChar(e) & (e.obj = eCONST) OR - isCharW(e1) & (e1.obj = eCONST) & isChar(e) & (e.obj = eCONST) OR - isCharW(e) & (e.obj = eCONST) & isChar(e1) & (e1.obj = eCONST) OR - isPtr(e) & isPtr(e1) & (PROG.isBaseOf(e._type, e1._type) OR PROG.isBaseOf(e1._type, e._type)) THEN - IF constant THEN - ARITH.relation(e.value, e1.value, cmp, error) - ELSE - IF e.obj = eCONST THEN - IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e1.value)) - ELSE - IL.AddCmd0(IL.opEQ + cmp) - END - END - - ELSIF isStringW1(e) & isCharW(e1) THEN - IL.AddCmd(IL.opEQC + cmp, StrToWChar(e.value.string(SCAN.STRING).s)) - - ELSIF isStringW1(e1) & isCharW(e) THEN - IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.STRING).s)) - - ELSIF isBoolean(e) & isBoolean(e1) THEN - IF constant THEN - ARITH.relation(e.value, e1.value, cmp, error) - ELSE - IF e.obj = eCONST THEN - BoolCmp(eq, ARITH.Int(e.value) # 0) - ELSIF e1.obj = eCONST THEN - BoolCmp(eq, ARITH.Int(e1.value) # 0) - ELSE - IF eq THEN - IL.AddCmd0(IL.opEQB) - ELSE - IL.AddCmd0(IL.opNEB) - END - END - END - - ELSIF isReal(e) & isReal(e1) THEN - IF constant THEN - ARITH.relation(e.value, e1.value, cmp, error) - ELSE - IF e.obj = eCONST THEN - Float(parser, e) - ELSIF e1.obj = eCONST THEN - Float(parser, e1) - END; - IL.AddCmd0(IL.opEQF + cmp) - END - - ELSIF (isStringW(e) OR isCharArrayX(e)) & (isStringW(e1) OR isCharArrayX(e1)) THEN - IF ~strcmp(e, e1, op) THEN - PARS.error(pos, 37) - END - - ELSIF isPtr(e) & isNil(e1) OR isNil(e) & isPtr(e1) THEN - IL.AddCmd0(IL.opEQC + cmp) - - ELSIF isProc(e) & isNil(e1) THEN - IF e.obj IN {ePROC, eIMP} THEN - PARS.check(e.ident.global, pos0, 85); - constant := TRUE; - e.obj := eCONST; - ARITH.setbool(e.value, ~eq) - ELSE - IL.AddCmd0(IL.opEQC + cmp) - END - - ELSIF isNil(e) & isProc(e1) THEN - IF e1.obj IN {ePROC, eIMP} THEN - PARS.check(e1.ident.global, pos1, 85); - constant := TRUE; - e.obj := eCONST; - ARITH.setbool(e.value, ~eq) - ELSE - IL.AddCmd0(IL.opEQC + cmp) - END - - ELSIF isProc(e) & isProc(e1) & PROG.isTypeEq(e._type, e1._type) THEN - IF e.obj = ePROC THEN - PARS.check(e.ident.global, pos0, 85) - END; - IF e1.obj = ePROC THEN - PARS.check(e1.ident.global, pos1, 85) - END; - IF (e.obj IN {ePROC, eIMP}) & (e1.obj IN {ePROC, eIMP}) THEN - constant := TRUE; - e.obj := eCONST; - IF eq THEN - ARITH.setbool(e.value, e.ident = e1.ident) - ELSE - ARITH.setbool(e.value, e.ident # e1.ident) - END - ELSIF e.obj = ePROC THEN - IL.ProcCmp(e.ident.proc.label, eq) - ELSIF e1.obj = ePROC THEN - IL.ProcCmp(e1.ident.proc.label, eq) - ELSIF e.obj = eIMP THEN - IL.ProcImpCmp(e.ident._import, eq) - ELSIF e1.obj = eIMP THEN - IL.ProcImpCmp(e1.ident._import, eq) - ELSE - IL.AddCmd0(IL.opEQ + cmp) - END - - ELSIF isNil(e) & isNil(e1) THEN - constant := TRUE; - e.obj := eCONST; - ARITH.setbool(e.value, eq) - - ELSE - PARS.error(pos, 37) - END - - |SCAN.lxLT, SCAN.lxLE, SCAN.lxGT, SCAN.lxGE: - IF isInt(e) & isInt(e1) OR isChar(e) & isChar(e1) OR isCharW(e) & isCharW(e1) OR - isCharW(e) & isChar(e1) & (e1.obj = eCONST) OR isCharW(e1) & isChar(e) & (e.obj = eCONST) OR - isCharW(e1) & (e1.obj = eCONST) & isChar(e) & (e.obj = eCONST) OR - isCharW(e) & (e.obj = eCONST) & isChar(e1) & (e1.obj = eCONST) THEN - - IF constant THEN - ARITH.relation(e.value, e1.value, cmp, error) - ELSE - IF e.obj = eCONST THEN - IL.AddCmd(IL.opEQC + invcmpcode(op), ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e1.value)) - ELSE - IL.AddCmd0(IL.opEQ + cmp) - END - END - - ELSIF isStringW1(e) & isCharW(e1) THEN - IL.AddCmd(IL.opEQC + invcmpcode(op), StrToWChar(e.value.string(SCAN.STRING).s)) - - ELSIF isStringW1(e1) & isCharW(e) THEN - IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.STRING).s)) - - ELSIF isReal(e) & isReal(e1) THEN - IF constant THEN - ARITH.relation(e.value, e1.value, cmp, error) - ELSE - IF e.obj = eCONST THEN - Float(parser, e); - IL.AddCmd0(IL.opEQF + invcmpcode(op)) - ELSIF e1.obj = eCONST THEN - Float(parser, e1); - IL.AddCmd0(IL.opEQF + cmp) - ELSE - IL.AddCmd0(IL.opEQF + cmp) - END - END - - ELSIF (isStringW(e) OR isCharArrayX(e)) & (isStringW(e1) OR isCharArrayX(e1)) THEN - IF ~strcmp(e, e1, op) THEN - PARS.error(pos, 37) - END - - ELSE - PARS.error(pos, 37) - END - - |SCAN.lxIN: - PARS.check(isInt(e) & isSet(e1), pos, 37); - IF e.obj = eCONST THEN - PARS.check(ARITH.range(e.value, 0, UTILS.target.maxSet), pos0, 56) - END; - IF constant THEN - ARITH.relation(e.value, e1.value, ARITH.opIN, error) - ELSE - IF e.obj = eCONST THEN - IL.AddCmd(IL.opINL, ARITH.Int(e.value)) - ELSIF e1.obj = eCONST THEN - IL.AddCmd(IL.opINR, ARITH.Int(e1.value)) - ELSE - IL.AddCmd0(IL.opIN) - END - END - - |SCAN.lxIS: - PARS.check(isRecPtr(e), pos, 73); - PARS.check(e1.obj = eTYPE, pos1, 79); - - IF isRec(e) THEN - PARS.check(e.obj = eVREC, pos0, 78); - PARS.check(e1._type.typ = PROG.tRECORD, pos1, 80); - IF e.ident = NIL THEN - IL.TypeCheck(e1._type.num) - ELSE - IL.AddCmd(IL.opVADR, e.ident.offset - 1); - IL.TypeCheckRec(e1._type.num) - END - ELSE - PARS.check(e1._type.typ = PROG.tPOINTER, pos1, 81); - IL.TypeCheck(e1._type.base.num) - END; - - PARS.check(PROG.isBaseOf(e._type, e1._type), pos1, 82) - - END; - - ASSERT(error = 0); - - e._type := tBOOLEAN; - - IF ~constant THEN - e.obj := eEXPR - END - - END -END expression; - - -PROCEDURE ElementaryStatement (parser: PARS.PARSER); -VAR - e, e1: PARS.EXPR; - pos: PARS.POSITION; - line: INTEGER; - call: BOOLEAN; - -BEGIN - getpos(parser, pos); - - IL.pushBegEnd(begcall, endcall); - - designator(parser, e); - - IF parser.sym = SCAN.lxASSIGN THEN - line := parser.lex.pos.line; - PARS.check(isVar(e), pos, 93); - PARS.check(~e.readOnly, pos, 94); - - IL.setlast(begcall); - - NextPos(parser, pos); - expression(parser, e1); - IF (e._type.typ = PROG.tBYTE) & (e1.obj # eCONST) & (e1._type.typ = PROG.tINTEGER) & (chkBYTE IN Options.checking) THEN - CheckRange(256, pos.line, errBYTE) - END; - - IL.setlast(endcall.prev(IL.COMMAND)); - - PARS.check(assign(parser, e1, e._type, line), pos, 91); - IF e1.obj = ePROC THEN - PARS.check(e1.ident.global, pos, 85) - END; - call := FALSE - ELSIF parser.sym = SCAN.lxEQ THEN - PARS.check1(FALSE, parser, 96) - ELSIF parser.sym = SCAN.lxLROUND THEN - e1 := e; - ActualParameters(parser, e1); - PARS.check((e1._type = NIL) OR ODD(e._type.call), pos, 92); - call := TRUE - ELSE - IF e.obj IN {eSYSPROC, eSTPROC} THEN - stProc(parser, e); - call := FALSE - ELSE - PARS.check(isProc(e), pos, 86); - PARS.check((e._type.base = NIL) OR ODD(e._type.call), pos, 92); - PARS.check1(e._type.params.first = NIL, parser, 64); - call := TRUE - END - END; - - IF call THEN - IF e.obj IN {ePROC, eIMP} THEN - ProcCall(e, e.ident._type, FALSE, parser, pos, TRUE) - ELSIF isExpr(e) THEN - ProcCall(e, e._type, FALSE, parser, pos, TRUE) - END - END; - - IL.popBegEnd(begcall, endcall) -END ElementaryStatement; - - -PROCEDURE IfStatement (parser: PARS.PARSER; _if: BOOLEAN); -VAR - e: PARS.EXPR; - pos: PARS.POSITION; - - label, L: INTEGER; - -BEGIN - L := IL.NewLabel(); - - IF ~_if THEN - IL.AddCmd(IL.opNOP, IL.begin_loop); - IL.SetLabel(L) - END; - - REPEAT - NextPos(parser, pos); - - label := IL.NewLabel(); - - expression(parser, e); - PARS.check(isBoolean(e), pos, 72); - - IF e.obj = eCONST THEN - IF ~ARITH.getBool(e.value) THEN - IL.Jmp(IL.opJMP, label) - END - ELSE - IL.AndOrOpt(label) - END; - - IF _if THEN - PARS.checklex(parser, SCAN.lxTHEN) - ELSE - PARS.checklex(parser, SCAN.lxDO) - END; - - PARS.Next(parser); - parser.StatSeq(parser); - - IF ~_if OR (parser.sym # SCAN.lxEND) THEN - IL.Jmp(IL.opJMP, L) - END; - IL.SetLabel(label) - - UNTIL parser.sym # SCAN.lxELSIF; - - IF _if THEN - IF parser.sym = SCAN.lxELSE THEN - PARS.Next(parser); - parser.StatSeq(parser) - END; - IL.SetLabel(L) - ELSE - IL.AddCmd(IL.opNOP, IL.end_loop) - END; - - PARS.checklex(parser, SCAN.lxEND); - - PARS.Next(parser) -END IfStatement; - - -PROCEDURE RepeatStatement (parser: PARS.PARSER); -VAR - e: PARS.EXPR; - pos: PARS.POSITION; - label: INTEGER; - L: IL.COMMAND; - -BEGIN - IL.AddCmd(IL.opNOP, IL.begin_loop); - - label := IL.NewLabel(); - IL.SetLabel(label); - L := IL.getlast(); - - PARS.Next(parser); - parser.StatSeq(parser); - PARS.checklex(parser, SCAN.lxUNTIL); - NextPos(parser, pos); - expression(parser, e); - PARS.check(isBoolean(e), pos, 72); - - IF e.obj = eCONST THEN - IF ~ARITH.getBool(e.value) THEN - IL.Jmp(IL.opJMP, label) - END - ELSE - IL.AndOrOpt(label); - L.param1 := label - END; - - IL.AddCmd(IL.opNOP, IL.end_loop) -END RepeatStatement; - - -PROCEDURE LabelCmp (a, b: AVL.DATA): INTEGER; -VAR - La, Ra, Lb, Rb, res: INTEGER; - -BEGIN - La := a(CASE_LABEL).range.a; - Ra := a(CASE_LABEL).range.b; - Lb := b(CASE_LABEL).range.a; - Rb := b(CASE_LABEL).range.b; - IF (Ra < Lb) OR (La > Rb) THEN - res := ORD(La > Lb) - ORD(La < Lb) - ELSE - res := 0 - END - - RETURN res -END LabelCmp; - - -PROCEDURE DestroyLabel (VAR label: AVL.DATA); -BEGIN - C.push(CaseLabels, label); - label := NIL -END DestroyLabel; - - -PROCEDURE NewVariant (label: INTEGER; cmd: IL.COMMAND): CASE_VARIANT; -VAR - res: CASE_VARIANT; - citem: C.ITEM; - -BEGIN - citem := C.pop(CaseVar); - IF citem = NIL THEN - NEW(res) - ELSE - res := citem(CASE_VARIANT) - END; - - res.label := label; - res.cmd := cmd; - res.processed := FALSE - - RETURN res -END NewVariant; - - -PROCEDURE CaseStatement (parser: PARS.PARSER); -VAR - e: PARS.EXPR; - pos: PARS.POSITION; - - - PROCEDURE Label (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR _type: PROG._TYPE): INTEGER; - VAR - a: INTEGER; - label: PARS.EXPR; - pos: PARS.POSITION; - value: ARITH.VALUE; - - BEGIN - getpos(parser, pos); - _type := NIL; - - IF isChar(caseExpr) THEN - PARS.ConstExpression(parser, value); - PARS.check(value.typ = ARITH.tCHAR, pos, 99); - a := ARITH.getInt(value) - ELSIF isCharW(caseExpr) THEN - PARS.ConstExpression(parser, value); - IF (value.typ = ARITH.tSTRING) & (_length(value.string(SCAN.STRING).s) = 1) & (LENGTH(value.string(SCAN.STRING).s) > 1) THEN - ASSERT(ARITH.setInt(value, StrToWChar(value.string(SCAN.STRING).s))) - ELSE - PARS.check(value.typ IN {ARITH.tWCHAR, ARITH.tCHAR}, pos, 99) - END; - a := ARITH.getInt(value) - ELSIF isInt(caseExpr) THEN - PARS.ConstExpression(parser, value); - PARS.check(value.typ = ARITH.tINTEGER, pos, 99); - a := ARITH.getInt(value) - ELSIF isRecPtr(caseExpr) THEN - qualident(parser, label); - PARS.check(label.obj = eTYPE, pos, 79); - PARS.check(PROG.isBaseOf(caseExpr._type, label._type), pos, 99); - IF isRec(caseExpr) THEN - a := label._type.num - ELSE - a := label._type.base.num - END; - _type := label._type - END - - RETURN a - END Label; - - - PROCEDURE CheckType (node: AVL.NODE; _type: PROG._TYPE; parser: PARS.PARSER; pos: PARS.POSITION); - BEGIN - IF node # NIL THEN - PARS.check(~(PROG.isBaseOf(node.data(CASE_LABEL)._type, _type) OR PROG.isBaseOf(_type, node.data(CASE_LABEL)._type)), pos, 100); - CheckType(node.left, _type, parser, pos); - CheckType(node.right, _type, parser, pos) - END - END CheckType; - - - PROCEDURE LabelRange (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; variant: INTEGER): AVL.NODE; - VAR - label: CASE_LABEL; - citem: C.ITEM; - pos, pos1: PARS.POSITION; - node: AVL.NODE; - newnode: BOOLEAN; - range: RANGE; - - BEGIN - citem := C.pop(CaseLabels); - IF citem = NIL THEN - NEW(label) - ELSE - label := citem(CASE_LABEL) - END; - - label.variant := variant; - label.self := IL.NewLabel(); - - getpos(parser, pos1); - range.a := Label(parser, caseExpr, label._type); - - IF parser.sym = SCAN.lxRANGE THEN - PARS.check1(~isRecPtr(caseExpr), parser, 53); - NextPos(parser, pos); - range.b := Label(parser, caseExpr, label._type); - PARS.check(range.a <= range.b, pos, 103) - ELSE - range.b := range.a - END; - - label.range := range; - - IF isRecPtr(caseExpr) THEN - CheckType(tree, label._type, parser, pos1) - END; - tree := AVL.insert(tree, label, LabelCmp, newnode, node); - PARS.check(newnode, pos1, 100) - - RETURN node - - END LabelRange; - - - PROCEDURE CaseLabelList (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; variant: INTEGER): AVL.NODE; - VAR - exit: BOOLEAN; - res: AVL.NODE; - - BEGIN - exit := FALSE; - REPEAT - res := LabelRange(parser, caseExpr, tree, variant); - IF parser.sym = SCAN.lxCOMMA THEN - PARS.check1(~isRecPtr(caseExpr), parser, 53); - PARS.Next(parser) - ELSE - exit := TRUE - END - UNTIL exit - - RETURN res - END CaseLabelList; - - - PROCEDURE _case (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; _end: INTEGER); - VAR - sym: INTEGER; - t: PROG._TYPE; - variant: INTEGER; - node: AVL.NODE; - last: IL.COMMAND; - - BEGIN - sym := parser.sym; - IF sym # SCAN.lxBAR THEN - variant := IL.NewLabel(); - node := CaseLabelList(parser, caseExpr, tree, variant); - PARS.checklex(parser, SCAN.lxCOLON); - PARS.Next(parser); - IF isRecPtr(caseExpr) THEN - t := caseExpr._type; - caseExpr.ident._type := node.data(CASE_LABEL)._type - END; - - last := IL.getlast(); - IL.SetLabel(variant); - - IF ~isRecPtr(caseExpr) THEN - LISTS.push(CaseVariants, NewVariant(variant, last)) - END; - - parser.StatSeq(parser); - IL.Jmp(IL.opJMP, _end); - - IF isRecPtr(caseExpr) THEN - caseExpr.ident._type := t - END - END - END _case; - - - PROCEDURE Table (node: AVL.NODE; _else: INTEGER); - VAR - L, R: INTEGER; - range: RANGE; - left, right: AVL.NODE; - last: IL.COMMAND; - v: CASE_VARIANT; - - BEGIN - IF node # NIL THEN - - range := node.data(CASE_LABEL).range; - - left := node.left; - IF left # NIL THEN - L := left.data(CASE_LABEL).self - ELSE - L := _else - END; - - right := node.right; - IF right # NIL THEN - R := right.data(CASE_LABEL).self - ELSE - R := _else - END; - - last := IL.getlast(); - - v := CaseVariants.last(CASE_VARIANT); - WHILE (v # NIL) & (v.label # 0) & (v.label # node.data(CASE_LABEL).variant) DO - v := v.prev(CASE_VARIANT) - END; - - ASSERT((v # NIL) & (v.label # 0)); - IL.setlast(v.cmd); - - IL.SetLabel(node.data(CASE_LABEL).self); - IL._case(range.a, range.b, L, R); - IF v.processed THEN - IL.Jmp(IL.opJMP, node.data(CASE_LABEL).variant) - END; - v.processed := TRUE; - - IL.setlast(last); - - Table(left, _else); - Table(right, _else) - END - END Table; - - - PROCEDURE TableT (node: AVL.NODE); - BEGIN - IF node # NIL THEN - IL.AddCmd2(IL.opCASET, node.data(CASE_LABEL).variant, node.data(CASE_LABEL).range.a); - TableT(node.left); - TableT(node.right) - END - END TableT; - - - PROCEDURE ParseCase (parser: PARS.PARSER; e: PARS.EXPR; pos: PARS.POSITION); - VAR - table, _end, _else: INTEGER; - tree: AVL.NODE; - item: LISTS.ITEM; - - BEGIN - LISTS.push(CaseVariants, NewVariant(0, NIL)); - _end := IL.NewLabel(); - _else := IL.NewLabel(); - table := IL.NewLabel(); - IL.AddCmd(IL.opSWITCH, ORD(isRecPtr(e))); - IL.Jmp(IL.opJMP, table); - - tree := NIL; - - _case(parser, e, tree, _end); - WHILE parser.sym = SCAN.lxBAR DO - PARS.Next(parser); - _case(parser, e, tree, _end) - END; - - IL.SetLabel(_else); - IF parser.sym = SCAN.lxELSE THEN - PARS.Next(parser); - parser.StatSeq(parser); - IL.Jmp(IL.opJMP, _end) - ELSE - IL.OnError(pos.line, errCASE) - END; - - PARS.checklex(parser, SCAN.lxEND); - PARS.Next(parser); - - IF isRecPtr(e) THEN - IL.SetLabel(table); - TableT(tree); - IL.Jmp(IL.opJMP, _else) - ELSE - tree.data(CASE_LABEL).self := table; - Table(tree, _else) - END; - - AVL.destroy(tree, DestroyLabel); - IL.SetLabel(_end); - IL.AddCmd0(IL.opENDSW); - - REPEAT - item := LISTS.pop(CaseVariants); - C.push(CaseVar, item) - UNTIL item(CASE_VARIANT).cmd = NIL - - END ParseCase; - - -BEGIN - NextPos(parser, pos); - expression(parser, e); - PARS.check(isInt(e) OR isChar(e) OR isCharW(e) OR isPtr(e) OR isRec(e), pos, 95); - IF isRecPtr(e) THEN - PARS.check(isVar(e), pos, 93); - PARS.check(e.ident # NIL, pos, 106) - END; - IF isRec(e) THEN - PARS.check(e.obj = eVREC, pos, 78) - END; - - IF e.obj = eCONST THEN - LoadConst(e) - ELSIF isRec(e) THEN - IL.drop; - IL.AddCmd(IL.opLADR, e.ident.offset - 1); - IL.load(TARGETS.WordSize) - ELSIF isPtr(e) THEN - deref(pos, e, FALSE, errPTR); - IL.AddCmd(IL.opSUBR, TARGETS.WordSize); - IL.load(TARGETS.WordSize) - END; - - PARS.checklex(parser, SCAN.lxOF); - PARS.Next(parser); - ParseCase(parser, e, pos) -END CaseStatement; - - -PROCEDURE ForStatement (parser: PARS.PARSER); -VAR - e: PARS.EXPR; - pos, pos2: PARS.POSITION; - step: ARITH.VALUE; - st: INTEGER; - ident: PROG.IDENT; - offset: INTEGER; - L1, L2: INTEGER; - -BEGIN - IL.AddCmd(IL.opNOP, IL.begin_loop); - - L1 := IL.NewLabel(); - L2 := IL.NewLabel(); - - PARS.ExpectSym(parser, SCAN.lxIDENT); - ident := PROG.getIdent(parser.unit, parser.lex.ident, TRUE); - PARS.check1(ident # NIL, parser, 48); - PARS.check1(ident.typ = PROG.idVAR, parser, 93); - PARS.check1(ident._type = tINTEGER, parser, 97); - PARS.ExpectSym(parser, SCAN.lxASSIGN); - NextPos(parser, pos); - expression(parser, e); - PARS.check(isInt(e), pos, 76); - - offset := PROG.getOffset(ident); - - IF ident.global THEN - IL.AddCmd(IL.opGADR, offset) - ELSE - IL.AddCmd(IL.opLADR, -offset) - END; - - IF e.obj = eCONST THEN - IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) - ELSE - IL.AddCmd0(IL.opSAVE) - END; - - IL.SetLabel(L1); - - IF ident.global THEN - IL.AddCmd(IL.opGADR, offset) - ELSE - IL.AddCmd(IL.opLADR, -offset) - END; - IL.load(ident._type.size); - - PARS.checklex(parser, SCAN.lxTO); - NextPos(parser, pos2); - expression(parser, e); - PARS.check(isInt(e), pos2, 76); - - IF parser.sym = SCAN.lxBY THEN - NextPos(parser, pos); - PARS.ConstExpression(parser, step); - PARS.check(step.typ = ARITH.tINTEGER, pos, 76); - st := ARITH.getInt(step); - PARS.check(st # 0, pos, 98) - ELSE - st := 1 - END; - - IF e.obj = eCONST THEN - IF st > 0 THEN - IL.AddCmd(IL.opLEC, ARITH.Int(e.value)); - IF ARITH.Int(e.value) = UTILS.target.maxInt THEN - ERRORS.WarningMsg(pos2.line, pos2.col, 1) - END - ELSE - IL.AddCmd(IL.opGEC, ARITH.Int(e.value)); - IF ARITH.Int(e.value) = UTILS.target.minInt THEN - ERRORS.WarningMsg(pos2.line, pos2.col, 1) - END - END - ELSE - IF st > 0 THEN - IL.AddCmd0(IL.opLE) - ELSE - IL.AddCmd0(IL.opGE) - END - END; - - IL.Jmp(IL.opJZ, L2); - - PARS.checklex(parser, SCAN.lxDO); - PARS.Next(parser); - parser.StatSeq(parser); - - IF ident.global THEN - IL.AddCmd(IL.opGADR, offset) - ELSE - IL.AddCmd(IL.opLADR, -offset) - END; - - IL.AddCmd(IL.opINCC, st); - - IL.Jmp(IL.opJMP, L1); - - PARS.checklex(parser, SCAN.lxEND); - PARS.Next(parser); - - IL.SetLabel(L2); - - IL.AddCmd(IL.opNOP, IL.end_loop) -END ForStatement; - - -PROCEDURE statement (parser: PARS.PARSER); -VAR - sym: INTEGER; - -BEGIN - sym := parser.sym; - - IF sym = SCAN.lxIDENT THEN - ElementaryStatement(parser) - ELSIF sym = SCAN.lxIF THEN - IfStatement(parser, TRUE) - ELSIF sym = SCAN.lxWHILE THEN - IfStatement(parser, FALSE) - ELSIF sym = SCAN.lxREPEAT THEN - RepeatStatement(parser) - ELSIF sym = SCAN.lxCASE THEN - CaseStatement(parser) - ELSIF sym = SCAN.lxFOR THEN - ForStatement(parser) - END -END statement; - - -PROCEDURE StatSeq (parser: PARS.PARSER); -BEGIN - statement(parser); - WHILE parser.sym = SCAN.lxSEMI DO - PARS.Next(parser); - statement(parser) - END -END StatSeq; - - -PROCEDURE chkreturn (parser: PARS.PARSER; e: PARS.EXPR; t: PROG._TYPE; pos: PARS.POSITION): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - res := assigncomp(e, t); - IF res THEN - IF e.obj = eCONST THEN - IF e._type = tREAL THEN - Float(parser, e) - ELSIF e._type.typ = PROG.tNIL THEN - IL.Const(0) - ELSE - LoadConst(e) - END - ELSIF (e._type = tINTEGER) & (t = tBYTE) & (chkBYTE IN Options.checking) THEN - CheckRange(256, pos.line, errBYTE) - ELSIF e.obj = ePROC THEN - PARS.check(e.ident.global, pos, 85); - IL.PushProc(e.ident.proc.label) - ELSIF e.obj = eIMP THEN - IL.PushImpProc(e.ident._import) - END - END - - RETURN res -END chkreturn; - - -PROCEDURE setrtl; -VAR - rtl: PROG.UNIT; - - - PROCEDURE getproc (rtl: PROG.UNIT; name: SCAN.IDSTR; idx: INTEGER); - VAR - id: PROG.IDENT; - ident: SCAN.IDENT; - - BEGIN - SCAN.setIdent(ident, name); - id := PROG.getIdent(rtl, ident, FALSE); - - IF (id # NIL) & (id._import # NIL) THEN - IL.set_rtl(idx, -id._import(IL.IMPORT_PROC).label); - id.proc.used := TRUE - ELSIF (id # NIL) & (id.proc # NIL) THEN - IL.set_rtl(idx, id.proc.label); - id.proc.used := TRUE - ELSE - ERRORS.WrongRTL(name) - END - END getproc; - - -BEGIN - rtl := PROG.program.rtl; - ASSERT(rtl # NIL); - - getproc(rtl, "_strcmp", IL._strcmp); - getproc(rtl, "_length", IL._length); - getproc(rtl, "_arrcpy", IL._arrcpy); - getproc(rtl, "_is", IL._is); - getproc(rtl, "_guard", IL._guard); - getproc(rtl, "_guardrec", IL._guardrec); - getproc(rtl, "_new", IL._new); - getproc(rtl, "_rot", IL._rot); - getproc(rtl, "_strcpy", IL._strcpy); - getproc(rtl, "_move", IL._move); - getproc(rtl, "_set", IL._set); - getproc(rtl, "_set1", IL._set1); - getproc(rtl, "_lengthw", IL._lengthw); - getproc(rtl, "_strcmpw", IL._strcmpw); - getproc(rtl, "_init", IL._init); - - IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN - getproc(rtl, "_error", IL._error); - getproc(rtl, "_divmod", IL._divmod); - getproc(rtl, "_exit", IL._exit); - getproc(rtl, "_dispose", IL._dispose); - getproc(rtl, "_isrec", IL._isrec); - getproc(rtl, "_dllentry", IL._dllentry); - getproc(rtl, "_sofinit", IL._sofinit) - ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN - getproc(rtl, "_fmul", IL._fmul); - getproc(rtl, "_fdiv", IL._fdiv); - getproc(rtl, "_fdivi", IL._fdivi); - getproc(rtl, "_fadd", IL._fadd); - getproc(rtl, "_fsub", IL._fsub); - getproc(rtl, "_fsubi", IL._fsubi); - getproc(rtl, "_fcmp", IL._fcmp); - getproc(rtl, "_floor", IL._floor); - getproc(rtl, "_flt", IL._flt); - getproc(rtl, "_pack", IL._pack); - getproc(rtl, "_unpk", IL._unpk); - IF CPU IN {TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN - getproc(rtl, "_error", IL._error) - END - END - -END setrtl; - - -PROCEDURE compile* (path, lib_path, modname, outname: PARS.PATH; target: INTEGER; options: PROG.OPTIONS); -VAR - parser: PARS.PARSER; - ext: PARS.PATH; - -BEGIN - tINTEGER := PROG.program.stTypes.tINTEGER; - tBYTE := PROG.program.stTypes.tBYTE; - tCHAR := PROG.program.stTypes.tCHAR; - tSET := PROG.program.stTypes.tSET; - tBOOLEAN := PROG.program.stTypes.tBOOLEAN; - tWCHAR := PROG.program.stTypes.tWCHAR; - tREAL := PROG.program.stTypes.tREAL; - - Options := options; - CPU := TARGETS.CPU; - - ext := UTILS.FILE_EXT; - CaseLabels := C.create(); - CaseVar := C.create(); - - CaseVariants := LISTS.create(NIL); - LISTS.push(CaseVariants, NewVariant(0, NIL)); - - IL.init(CPU); - - IF TARGETS.RTL THEN - parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); - IF parser.open(parser, UTILS.RTL_NAME, UTILS.FILE_EXT) THEN - parser.parse(parser); - PARS.destroy(parser) - ELSE - PARS.destroy(parser); - parser := PARS.create(lib_path, lib_path, StatSeq, expression, designator, chkreturn); - IF parser.open(parser, UTILS.RTL_NAME, UTILS.FILE_EXT) THEN - parser.parse(parser); - PARS.destroy(parser) - ELSE - ERRORS.FileNotFound(lib_path, UTILS.RTL_NAME, UTILS.FILE_EXT) - END - END - END; - - parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); - parser.main := TRUE; - - IF parser.open(parser, modname, UTILS.FILE_EXT) THEN - parser.parse(parser) - ELSE - ERRORS.FileNotFound(path, modname, UTILS.FILE_EXT) - END; - - PARS.destroy(parser); - - IF PROG.program.bss > UTILS.MAX_GLOBAL_SIZE THEN - ERRORS.Error(204) - END; - - IF TARGETS.RTL THEN - setrtl - END; - - PROG.DelUnused(IL.DelImport); - - IL.set_bss(PROG.program.bss); - - CASE CPU OF - |TARGETS.cpuAMD64: AMD64.CodeGen(outname, target, options) - |TARGETS.cpuX86: X86.CodeGen(outname, target, options) - |TARGETS.cpuMSP430: MSP430.CodeGen(outname, target, options) - |TARGETS.cpuTHUMB: THUMB.CodeGen(outname, target, options) - |TARGETS.cpuRVM32I, - TARGETS.cpuRVM64I: RVMxI.CodeGen(outname, target, options) - END - -END compile; - - -END STATEMENTS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/STRINGS.ob07 b/programs/develop/oberon07/source/STRINGS.ob07 deleted file mode 100644 index 410944769..000000000 --- a/programs/develop/oberon07/source/STRINGS.ob07 +++ /dev/null @@ -1,342 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE STRINGS; - -IMPORT UTILS; - - -PROCEDURE copy* (src: ARRAY OF CHAR; VAR dst: ARRAY OF CHAR; spos, dpos, count: INTEGER); -BEGIN - WHILE count > 0 DO - dst[dpos] := src[spos]; - INC(spos); - INC(dpos); - DEC(count) - END -END copy; - - -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)); - - copy(s2, s1, 0, n1, n2); - s1[n1 + n2] := 0X -END append; - - -PROCEDURE IntToStr* (x: INTEGER; VAR str: ARRAY OF CHAR); -VAR - i, a: INTEGER; - -BEGIN - IF x = UTILS.minint THEN - IF UTILS.bit_depth = 32 THEN - COPY("-2147483648", str) - ELSIF UTILS.bit_depth = 64 THEN - COPY("-9223372036854775808", str) - END - - ELSE - i := 0; - IF x < 0 THEN - x := -x; - i := 1; - str[0] := "-" - END; - - 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 -END IntToStr; - - -PROCEDURE search* (s: ARRAY OF CHAR; VAR pos: INTEGER; c: CHAR; forward: BOOLEAN); -VAR - length: INTEGER; - -BEGIN - length := LENGTH(s); - - IF (0 <= pos) & (pos < length) THEN - IF forward THEN - WHILE (pos < length) & (s[pos] # c) DO - INC(pos) - END; - IF pos = length THEN - pos := -1 - END - ELSE - WHILE (pos >= 0) & (s[pos] # c) DO - DEC(pos) - END - END - ELSE - pos := -1 - END -END search; - - -PROCEDURE replace* (VAR s: ARRAY OF CHAR; find, repl: CHAR); -VAR - i, strlen: INTEGER; - -BEGIN - strlen := LENGTH(s) - 1; - FOR i := 0 TO strlen DO - IF s[i] = find THEN - s[i] := repl - END - END -END replace; - - -PROCEDURE trim* (source: ARRAY OF CHAR; VAR result: ARRAY OF CHAR); -VAR - LenS, start, _end, i, j: INTEGER; - -BEGIN - LenS := LENGTH(source) - 1; - j := 0; - IF LenS >= 0 THEN - start := 0; - WHILE (start <= LenS) & (source[start] <= 20X) DO - INC(start) - END; - - _end := LenS; - WHILE (_end >= 0) & (source[_end] <= 20X) DO - DEC(_end) - END; - - FOR i := start TO _end DO - result[j] := source[i]; - INC(j) - END - END; - result[j] := 0X -END trim; - - -PROCEDURE letter* (c: CHAR): BOOLEAN; - RETURN ("a" <= c) & (c <= "z") OR ("A" <= c) & (c <= "Z") OR (c = "_") -END letter; - - -PROCEDURE digit* (c: CHAR): BOOLEAN; - RETURN ("0" <= c) & (c <= "9") -END digit; - - -PROCEDURE hexdigit* (c: CHAR): BOOLEAN; - RETURN ("0" <= c) & (c <= "9") OR ("A" <= c) & (c <= "F") -END hexdigit; - - -PROCEDURE space* (c: CHAR): BOOLEAN; - RETURN (0X < c) & (c <= 20X) -END space; - - -PROCEDURE cap* (VAR c: CHAR); -BEGIN - IF ("a" <= c) & (c <= "z") THEN - c := CHR(ORD(c) - 32) - END -END cap; - - -PROCEDURE UpCase* (VAR str: ARRAY OF CHAR); -VAR - i: INTEGER; - -BEGIN - i := LENGTH(str) - 1; - WHILE i >= 0 DO - cap(str[i]); - DEC(i) - END -END UpCase; - - -PROCEDURE StrToInt* (str: ARRAY OF CHAR; VAR x: INTEGER): BOOLEAN; -VAR - i, k: INTEGER; - res: BOOLEAN; - -BEGIN - res := TRUE; - i := 0; - x := 0; - k := LENGTH(str); - WHILE i < k DO - IF digit(str[i]) THEN - x := x * 10 + ORD(str[i]) - ORD("0") - ELSE - i := k; - res := FALSE - END; - INC(i) - END - - RETURN res -END StrToInt; - - -PROCEDURE CheckVer (str: ARRAY OF CHAR): BOOLEAN; -VAR - i, k: INTEGER; - res: BOOLEAN; - -BEGIN - k := LENGTH(str); - res := k < LEN(str); - - IF res & digit(str[0]) THEN - i := 0; - WHILE (i < k) & digit(str[i]) DO - INC(i) - END; - IF (i < k) & (str[i] = ".") THEN - INC(i); - IF i < k THEN - WHILE (i < k) & digit(str[i]) DO - INC(i) - END - ELSE - res := FALSE - END - ELSE - res := FALSE - END; - - res := res & (i = k) - ELSE - res := FALSE - END - - RETURN res -END CheckVer; - - -PROCEDURE StrToVer* (str: ARRAY OF CHAR; VAR major, minor: INTEGER): BOOLEAN; -VAR - i: INTEGER; - res: BOOLEAN; - -BEGIN - res := CheckVer(str); - - IF res THEN - i := 0; - minor := 0; - major := 0; - WHILE digit(str[i]) DO - major := major * 10 + ORD(str[i]) - ORD("0"); - INC(i) - END; - INC(i); - WHILE digit(str[i]) DO - minor := minor * 10 + ORD(str[i]) - ORD("0"); - INC(i) - END - END - - RETURN res -END StrToVer; - - -PROCEDURE Utf8To16* (src: ARRAY OF CHAR; VAR dst: ARRAY OF WCHAR): INTEGER; -VAR - i, j, u, srclen, dstlen: INTEGER; - c: CHAR; - -BEGIN - srclen := LEN(src); - dstlen := LEN(dst); - i := 0; - j := 0; - WHILE (i < srclen) & (j < dstlen) & (src[i] # 0X) DO - c := src[i]; - CASE c OF - |00X..7FX: - u := ORD(c) - - |0C1X..0DFX: - u := (ORD(c) - 0C0H) * 64; - IF i + 1 < srclen THEN - INC(i); - INC(u, ORD(src[i]) MOD 64) - END - - |0E1X..0EFX: - u := (ORD(c) - 0E0H) * 4096; - IF i + 1 < srclen THEN - INC(i); - INC(u, (ORD(src[i]) MOD 64) * 64) - END; - IF i + 1 < srclen THEN - INC(i); - INC(u, ORD(src[i]) MOD 64) - END -(* - |0F1X..0F7X: - |0F9X..0FBX: - |0FDX: - *) - ELSE - END; - INC(i); - dst[j] := WCHR(u); - INC(j) - END; - IF j < dstlen THEN - dst[j] := WCHR(0) - END - - RETURN j -END Utf8To16; - - -PROCEDURE HashStr* (name: ARRAY OF CHAR): INTEGER; -VAR - i, h: INTEGER; - g: SET; - -BEGIN - h := 0; - i := 0; - WHILE name[i] # 0X DO - h := h * 16 + ORD(name[i]); - g := BITS(h) * {28..31}; - h := ORD(BITS(h) / BITS(LSR(ORD(g), 24)) - g); - INC(i) - END - - RETURN h -END HashStr; - - -END STRINGS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/TARGETS.ob07 b/programs/develop/oberon07/source/TARGETS.ob07 deleted file mode 100644 index d33aed7ca..000000000 --- a/programs/develop/oberon07/source/TARGETS.ob07 +++ /dev/null @@ -1,154 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2021, 2023, Anton Krotov - All rights reserved. -*) - -MODULE TARGETS; - -IMPORT UTILS; - - -CONST - - MSP430* = 0; - Win32C* = 1; - Win32GUI* = 2; - Win32DLL* = 3; - KolibriOS* = 4; - KolibriOSDLL* = 5; - Win64C* = 6; - Win64GUI* = 7; - Win64DLL* = 8; - Linux32* = 9; - Linux32SO* = 10; - Linux64* = 11; - Linux64SO* = 12; - STM32CM3* = 13; - RVM32I* = 14; - RVM64I* = 15; - - cpuX86* = 0; cpuAMD64* = 1; cpuMSP430* = 2; cpuTHUMB* = 3; - cpuRVM32I* = 4; cpuRVM64I* = 5; - - osNONE* = 0; osWIN32* = 1; osWIN64* = 2; - osLINUX32* = 3; osLINUX64* = 4; osKOS* = 5; - - noDISPOSE = {MSP430, STM32CM3, RVM32I, RVM64I}; - - noRTL = {MSP430}; - - libRVM32I = "RVMxI" + UTILS.slash + "32"; - libRVM64I = "RVMxI" + UTILS.slash + "64"; - - -TYPE - - STRING = ARRAY 32 OF CHAR; - - TARGET = RECORD - - target, CPU, OS, RealSize: INTEGER; - ComLinePar*, LibDir, FileExt: STRING - - END; - - -VAR - - Targets*: ARRAY 16 OF TARGET; - - CPUs: ARRAY 6 OF - RECORD - BitDepth, InstrSize: INTEGER; - LittleEndian: BOOLEAN - END; - - target*, CPU*, BitDepth*, OS*, RealSize*, WordSize*, AdrSize*, InstrSize*: INTEGER; - ComLinePar*, LibDir*, FileExt*: STRING; - Import*, Dispose*, RTL*, Dll*, LittleEndian*, WinLin*: BOOLEAN; - - -PROCEDURE Enter (idx, CPU, RealSize, OS: INTEGER; ComLinePar, LibDir, FileExt: STRING); -BEGIN - Targets[idx].target := idx; - Targets[idx].CPU := CPU; - Targets[idx].RealSize := RealSize; - Targets[idx].OS := OS; - Targets[idx].ComLinePar := ComLinePar; - Targets[idx].LibDir := LibDir; - Targets[idx].FileExt := FileExt; -END Enter; - - -PROCEDURE Select* (ComLineParam: ARRAY OF CHAR): BOOLEAN; -VAR - i: INTEGER; - res: BOOLEAN; - -BEGIN - i := 0; - WHILE (i < LEN(Targets)) & (Targets[i].ComLinePar # ComLineParam) DO - INC(i) - END; - - res := i < LEN(Targets); - IF res THEN - target := Targets[i].target; - CPU := Targets[i].CPU; - BitDepth := CPUs[CPU].BitDepth; - InstrSize := CPUs[CPU].InstrSize; - LittleEndian := CPUs[CPU].LittleEndian; - RealSize := Targets[i].RealSize; - OS := Targets[i].OS; - ComLinePar := Targets[i].ComLinePar; - LibDir := Targets[i].LibDir; - FileExt := Targets[i].FileExt; - - Import := OS IN {osWIN32, osWIN64, osKOS}; - Dispose := ~(target IN noDISPOSE); - RTL := ~(target IN noRTL); - Dll := target IN {Linux32SO, Linux64SO, Win32DLL, Win64DLL, KolibriOSDLL}; - WinLin := OS IN {osWIN32, osLINUX32, osWIN64, osLINUX64}; - WordSize := BitDepth DIV 8; - AdrSize := WordSize - END - - RETURN res -END Select; - - -PROCEDURE EnterCPU (cpu, BitDepth, InstrSize: INTEGER; LittleEndian: BOOLEAN); -BEGIN - CPUs[cpu].BitDepth := BitDepth; - CPUs[cpu].InstrSize := InstrSize; - CPUs[cpu].LittleEndian := LittleEndian -END EnterCPU; - - -BEGIN - EnterCPU(cpuX86, 32, 1, TRUE); - EnterCPU(cpuAMD64, 64, 1, TRUE); - EnterCPU(cpuMSP430, 16, 2, TRUE); - EnterCPU(cpuTHUMB, 32, 2, TRUE); - EnterCPU(cpuRVM32I, 32, 4, TRUE); - EnterCPU(cpuRVM64I, 64, 8, TRUE); - - Enter( MSP430, cpuMSP430, 0, osNONE, "msp430", "MSP430", ".hex"); - Enter( Win32C, cpuX86, 8, osWIN32, "win32con", "Windows", ".exe"); - Enter( Win32GUI, cpuX86, 8, osWIN32, "win32gui", "Windows", ".exe"); - Enter( Win32DLL, cpuX86, 8, osWIN32, "win32dll", "Windows", ".dll"); - Enter( KolibriOS, cpuX86, 8, osKOS, "kosexe", "KolibriOS", ""); - Enter( KolibriOSDLL, cpuX86, 8, osKOS, "kosdll", "KolibriOS", ".obj"); - Enter( Win64C, cpuAMD64, 8, osWIN64, "win64con", "Windows", ".exe"); - Enter( Win64GUI, cpuAMD64, 8, osWIN64, "win64gui", "Windows", ".exe"); - Enter( Win64DLL, cpuAMD64, 8, osWIN64, "win64dll", "Windows", ".dll"); - Enter( Linux32, cpuX86, 8, osLINUX32, "linux32exe", "Linux", ""); - Enter( Linux32SO, cpuX86, 8, osLINUX32, "linux32so", "Linux", ".so"); - Enter( Linux64, cpuAMD64, 8, osLINUX64, "linux64exe", "Linux", ""); - Enter( Linux64SO, cpuAMD64, 8, osLINUX64, "linux64so", "Linux", ".so"); - Enter( STM32CM3, cpuTHUMB, 4, osNONE, "stm32cm3", "STM32CM3", ".hex"); - Enter( RVM32I, cpuRVM32I, 4, osNONE, "rvm32i", libRVM32I, ".bin"); - Enter( RVM64I, cpuRVM64I, 8, osNONE, "rvm64i", libRVM64I, ".bin"); -END TARGETS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/TEXTDRV.ob07 b/programs/develop/oberon07/source/TEXTDRV.ob07 deleted file mode 100644 index b7c2f6d7c..000000000 --- a/programs/develop/oberon07/source/TEXTDRV.ob07 +++ /dev/null @@ -1,210 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE TEXTDRV; - -IMPORT FILES, C := COLLECTIONS; - - -CONST - - CR = 0DX; LF = 0AX; HT = 9X; - - CHUNK = 1024 * 256; - - defTabSize* = 4; - - -TYPE - - TEXT* = POINTER TO RECORD (C.ITEM) - - chunk: ARRAY CHUNK OF CHAR; - pos, size: INTEGER; - file: FILES.FILE; - utf8: BOOLEAN; - CR: BOOLEAN; - - line*, col*: INTEGER; - ifc*: INTEGER; - elsec*: INTEGER; - eof*: BOOLEAN; - eol*: BOOLEAN; - skip*: BOOLEAN; - peak*: CHAR; - _skip*, - _elsif*, - _else*: ARRAY 100 OF BOOLEAN; - fname*: ARRAY 2048 OF CHAR - - END; - - -VAR - - texts: C.COLLECTION; - TabSize: INTEGER; - - -PROCEDURE load (text: TEXT); -BEGIN - IF ~text.eof THEN - text.size := FILES.read(text.file, text.chunk, LEN(text.chunk)); - text.pos := 0; - IF text.size = 0 THEN - text.eof := TRUE; - text.chunk[0] := 0X - END; - text.peak := text.chunk[0] - END -END load; - - -PROCEDURE next* (text: TEXT); -VAR - c: CHAR; - -BEGIN - IF text.pos < text.size - 1 THEN - INC(text.pos); - text.peak := text.chunk[text.pos] - ELSE - load(text) - END; - - IF ~text.eof THEN - - c := text.peak; - - IF c = CR THEN - INC(text.line); - text.col := 0; - text.eol := TRUE; - text.CR := TRUE - ELSIF c = LF THEN - IF ~text.CR THEN - INC(text.line); - text.col := 0; - text.eol := TRUE - ELSE - text.eol := FALSE - END; - text.CR := FALSE - ELSIF c = HT THEN - text.col := text.col + TabSize - text.col MOD TabSize; - text.eol := FALSE; - text.CR := FALSE - ELSE - IF text.utf8 THEN - IF ORD(c) DIV 64 # 2 THEN - INC(text.col) - END - ELSE - INC(text.col) - END; - text.eol := FALSE; - text.CR := FALSE - END - - END - -END next; - - -PROCEDURE init (text: TEXT); -BEGIN - IF (text.pos = 0) & (text.size >= 3) THEN - IF (text.chunk[0] = 0EFX) & - (text.chunk[1] = 0BBX) & - (text.chunk[2] = 0BFX) THEN - text.pos := 3; - text.utf8 := TRUE - END - END; - - IF text.size = 0 THEN - text.chunk[0] := 0X; - text.size := 1; - text.eof := FALSE - END; - - text.line := 1; - text.col := 1; - - text.peak := text.chunk[text.pos] -END init; - - -PROCEDURE close* (VAR text: TEXT); -BEGIN - IF text # NIL THEN - IF text.file # NIL THEN - FILES.close(text.file) - END; - - C.push(texts, text); - text := NIL - END -END close; - - -PROCEDURE open* (name: ARRAY OF CHAR): TEXT; -VAR - text: TEXT; - citem: C.ITEM; - -BEGIN - citem := C.pop(texts); - IF citem = NIL THEN - NEW(text) - ELSE - text := citem(TEXT) - END; - - IF text # NIL THEN - text.chunk[0] := 0X; - text.pos := 0; - text.size := 0; - text.utf8 := FALSE; - text.CR := FALSE; - text.line := 1; - text.col := 1; - text.eof := FALSE; - text.eol := FALSE; - text.skip := FALSE; - text.ifc := 0; - text.elsec := 0; - text._skip[0] := FALSE; - text.peak := 0X; - text.file := FILES.open(name); - COPY(name, text.fname); - IF text.file # NIL THEN - load(text); - init(text) - ELSE - close(text) - END - END - - RETURN text -END open; - - -PROCEDURE setTabSize* (n: INTEGER); -BEGIN - IF (0 < n) & (n <= 64) THEN - TabSize := n - ELSE - TabSize := defTabSize - END -END setTabSize; - - -BEGIN - TabSize := defTabSize; - texts := C.create() -END TEXTDRV. \ No newline at end of file diff --git a/programs/develop/oberon07/source/THUMB.ob07 b/programs/develop/oberon07/source/THUMB.ob07 deleted file mode 100644 index 55c230dcf..000000000 --- a/programs/develop/oberon07/source/THUMB.ob07 +++ /dev/null @@ -1,2459 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2022, Anton Krotov - All rights reserved. -*) - -MODULE THUMB; - -IMPORT PROG, LISTS, CHL := CHUNKLISTS, BIN, REG, IL, C := CONSOLE, - UTILS, WR := WRITER, HEX, ERRORS, TARGETS; - - -CONST - - R0 = 0; R1 = 1; R2 = 2; R3 = 3; R4 = 4; - - SP = 13; LR = 14; PC = 15; - - ACC = R0; - - je = 0; jne = 1; jnb = 2; jb = 3; jge = 10; jl = 11; jg = 12; jle = 13; - - inf = 7F800000H; - - minROM* = 16; maxROM* = 65536; - minRAM* = 4; maxRAM* = 65536; - - maxIVT* = 1023; - - _THUMB2 = 0; _IT = 1; _SDIV = 2; _CBXZ = 3; - - CortexM0 = {}; - CortexM1 = {}; - CortexM3 = {_THUMB2, _IT, _SDIV, _CBXZ}; - CortexM23 = {_SDIV, _CBXZ}; - - -TYPE - - COMMAND = IL.COMMAND; - - ANYCODE = POINTER TO RECORD (LISTS.ITEM) - - offset: INTEGER - - END; - - CODE = POINTER TO RECORD (ANYCODE) - - code: INTEGER - - END; - - LABEL = POINTER TO RECORD (ANYCODE) - - label: INTEGER - - END; - - JUMP = POINTER TO RECORD (ANYCODE) - - label, diff, len, cond: INTEGER; - short: BOOLEAN - - END; - - JMP = POINTER TO RECORD (JUMP) - - END; - - JCC = POINTER TO RECORD (JUMP) - - END; - - CBXZ = POINTER TO RECORD (JUMP) - - reg: INTEGER - - END; - - CALL = POINTER TO RECORD (JUMP) - - END; - - RELOC = POINTER TO RECORD (ANYCODE) - - reg, rel, value: INTEGER - - END; - - RELOCCODE = ARRAY 7 OF INTEGER; - - MEM = RECORD - start, size, startReserve, endReserve: INTEGER - END; - - -VAR - - R: REG.REGS; - - tcount: INTEGER; - - CodeList: LISTS.LIST; - - program: BIN.PROGRAM; - - StkCount: INTEGER; - - Target: RECORD - flash, sram: MEM; - IVTLen, - MinStkSize: INTEGER; - InstrSet: SET; - isNXP: BOOLEAN - END; - - IVT: ARRAY maxIVT + 1 OF INTEGER; - - sdivProc, trap, genTrap, entry, emptyProc, int0, genInt: INTEGER; - - -PROCEDURE Code (code: INTEGER); -VAR - c: CODE; - -BEGIN - NEW(c); - c.code := code; - LISTS.push(CodeList, c) -END Code; - - -PROCEDURE Label (label: INTEGER); -VAR - L: LABEL; - -BEGIN - NEW(L); - L.label := label; - LISTS.push(CodeList, L) -END Label; - - -PROCEDURE jcc (cond, label: INTEGER); -VAR - j: JCC; - -BEGIN - NEW(j); - j.label := label; - j.cond := cond; - j.short := FALSE; - j.len := 3; - LISTS.push(CodeList, j) -END jcc; - - -PROCEDURE cbxz (cond, reg, label: INTEGER); -VAR - j: CBXZ; - -BEGIN - NEW(j); - j.label := label; - j.cond := cond; - j.reg := reg; - j.short := FALSE; - j.len := 4; - LISTS.push(CodeList, j) -END cbxz; - - -PROCEDURE jmp (label: INTEGER); -VAR - j: JMP; - -BEGIN - NEW(j); - j.label := label; - j.short := FALSE; - j.len := 2; - LISTS.push(CodeList, j) -END jmp; - - -PROCEDURE call (label: INTEGER); -VAR - c: CALL; - -BEGIN - NEW(c); - c.label := label; - c.short := FALSE; - c.len := 2; - LISTS.push(CodeList, c) -END call; - - -PROCEDURE reloc (reg, rel, value: INTEGER); -VAR - r: RELOC; - -BEGIN - NEW(r); - r.reg := reg; - r.rel := rel; - r.value := value; - LISTS.push(CodeList, r) -END reloc; - - -PROCEDURE NewLabel (): INTEGER; -BEGIN - BIN.NewLabel(program) - RETURN IL.NewLabel() -END NewLabel; - - -PROCEDURE range (x, n: INTEGER): BOOLEAN; - RETURN (0 <= x) & (x < LSL(1, n)) -END range; - - -PROCEDURE srange (x, n: INTEGER): BOOLEAN; - RETURN (-LSL(1, n - 1) <= x) & (x < LSL(1, n - 1)) -END srange; - - -PROCEDURE gen1 (op, imm, rs, rd: INTEGER); -BEGIN - ASSERT(op IN {0..2}); - ASSERT(range(imm, 5)); - ASSERT(range(rs, 3)); - ASSERT(range(rd, 3)); - Code(LSL(op, 11) + LSL(imm, 6) + LSL(rs, 3) + rd) -END gen1; - - -PROCEDURE gen2 (i, op: BOOLEAN; imm, rs, rd: INTEGER); -BEGIN - ASSERT(range(imm, 3)); - ASSERT(range(rs, 3)); - ASSERT(range(rd, 3)); - Code(1800H + LSL(ORD(i), 10) + LSL(ORD(op), 9) + LSL(imm, 6) + LSL(rs, 3) + rd) -END gen2; - - -PROCEDURE gen3 (op, rd, imm: INTEGER); -BEGIN - ASSERT(range(op, 2)); - ASSERT(range(rd, 3)); - ASSERT(range(imm, 8)); - Code(2000H + LSL(op, 11) + LSL(rd, 8) + imm) -END gen3; - - -PROCEDURE gen4 (op, rs, rd: INTEGER); -BEGIN - ASSERT(range(op, 4)); - ASSERT(range(rs, 3)); - ASSERT(range(rd, 3)); - Code(4000H + LSL(op, 6) + LSL(rs, 3) + rd) -END gen4; - - -PROCEDURE gen5 (op: INTEGER; h1, h2: BOOLEAN; rs, rd: INTEGER); -BEGIN - ASSERT(range(op, 2)); - ASSERT(range(rs, 3)); - ASSERT(range(rd, 3)); - Code(4400H + LSL(op, 8) + LSL(ORD(h1), 7) + LSL(ORD(h2), 6) + LSL(rs, 3) + rd) -END gen5; - - -PROCEDURE gen7 (l, b: BOOLEAN; ro, rb, rd: INTEGER); -BEGIN - ASSERT(range(ro, 3)); - ASSERT(range(rb, 3)); - ASSERT(range(rd, 3)); - Code(5000H + LSL(ORD(l), 11) + LSL(ORD(b), 10) + LSL(ro, 6) + LSL(rb, 3) + rd) -END gen7; - - -PROCEDURE gen8 (h, s: BOOLEAN; ro, rb, rd: INTEGER); -BEGIN - ASSERT(range(ro, 3)); - ASSERT(range(rb, 3)); - ASSERT(range(rd, 3)); - Code(5200H + LSL(ORD(h), 11) + LSL(ORD(s), 10) + LSL(ro, 6) + LSL(rb, 3) + rd) -END gen8; - - -PROCEDURE gen9 (b, l: BOOLEAN; imm, rb, rd: INTEGER); -BEGIN - ASSERT(range(imm, 5)); - ASSERT(range(rb, 3)); - ASSERT(range(rd, 3)); - Code(6000H + LSL(ORD(b), 12) + LSL(ORD(l), 11) + LSL(imm, 6) + LSL(rb, 3) + rd) -END gen9; - - -PROCEDURE gen10 (l: BOOLEAN; imm, rb, rd: INTEGER); -BEGIN - ASSERT(range(imm, 5)); - ASSERT(range(rb, 3)); - ASSERT(range(rd, 3)); - Code(8000H + LSL(ORD(l), 11) + LSL(imm, 6) + LSL(rb, 3) + rd) -END gen10; - - -PROCEDURE gen11 (l: BOOLEAN; rd, imm: INTEGER); -BEGIN - ASSERT(range(rd, 3)); - ASSERT(range(imm, 8)); - Code(9000H + LSL(ORD(l), 11) + LSL(rd, 8) + imm) -END gen11; - - -PROCEDURE gen12 (sp: BOOLEAN; rd, imm: INTEGER); -BEGIN - ASSERT(range(rd, 3)); - ASSERT(range(imm, 8)); - Code(0A000H + LSL(ORD(sp), 11) + LSL(rd, 8) + imm) -END gen12; - - -PROCEDURE gen14 (l, r: BOOLEAN; rlist: SET); -VAR - i, n: INTEGER; - -BEGIN - ASSERT(range(ORD(rlist), 8)); - - n := ORD(r); - FOR i := 0 TO 7 DO - IF i IN rlist THEN - INC(n) - END - END; - - IF l THEN - n := -n - END; - - INC(StkCount, n); - - Code(0B400H + LSL(ORD(l), 11) + LSL(ORD(r), 8) + ORD(rlist)) -END gen14; - - -PROCEDURE split16 (imm16: INTEGER; VAR imm4, imm1, imm3, imm8: INTEGER); -BEGIN - ASSERT(range(imm16, 16)); - imm8 := imm16 MOD 256; - imm4 := LSR(imm16, 12); - imm3 := LSR(imm16, 8) MOD 8; - imm1 := LSR(imm16, 11) MOD 2; -END split16; - - -PROCEDURE LslImm (r, imm5: INTEGER); -BEGIN - gen1(0, imm5, r, r) -END LslImm; - - -PROCEDURE LsrImm (r, imm5: INTEGER); -BEGIN - gen1(1, imm5, r, r) -END LsrImm; - - -PROCEDURE AsrImm (r, imm5: INTEGER); -BEGIN - gen1(2, imm5, r, r) -END AsrImm; - - -PROCEDURE AddReg (rd, rs, rn: INTEGER); -BEGIN - gen2(FALSE, FALSE, rn, rs, rd) -END AddReg; - - -PROCEDURE SubReg (rd, rs, rn: INTEGER); -BEGIN - gen2(FALSE, TRUE, rn, rs, rd) -END SubReg; - - -PROCEDURE AddImm8 (rd, imm8: INTEGER); -BEGIN - IF imm8 # 0 THEN - gen3(2, rd, imm8) - END -END AddImm8; - - -PROCEDURE SubImm8 (rd, imm8: INTEGER); -BEGIN - IF imm8 # 0 THEN - gen3(3, rd, imm8) - END -END SubImm8; - - -PROCEDURE AddSubImm12 (r, imm12: INTEGER; sub: BOOLEAN); -VAR - imm4, imm1, imm3, imm8: INTEGER; - -BEGIN - split16(imm12, imm4, imm1, imm3, imm8); - Code(0F200H + LSL(imm1, 10) + r + 0A0H * ORD(sub)); (* addw/subw r, r, imm12 *) - Code(LSL(imm3, 12) + LSL(r, 8) + imm8) -END AddSubImm12; - - -PROCEDURE MovImm8 (rd, imm8: INTEGER); -BEGIN - gen3(0, rd, imm8) -END MovImm8; - - -PROCEDURE CmpImm8 (rd, imm8: INTEGER); -BEGIN - gen3(1, rd, imm8) -END CmpImm8; - - -PROCEDURE Neg (r: INTEGER); -BEGIN - gen4(9, r, r) -END Neg; - - -PROCEDURE Mul (rd, rs: INTEGER); -BEGIN - gen4(13, rs, rd) -END Mul; - - -PROCEDURE Str32 (rs, rb: INTEGER); -BEGIN - gen9(FALSE, FALSE, 0, rb, rs) -END Str32; - - -PROCEDURE Ldr32 (rd, rb: INTEGER); -BEGIN - gen9(FALSE, TRUE, 0, rb, rd) -END Ldr32; - - -PROCEDURE Str16 (rs, rb: INTEGER); -BEGIN - gen10(FALSE, 0, rb, rs) -END Str16; - - -PROCEDURE Ldr16 (rd, rb: INTEGER); -BEGIN - gen10(TRUE, 0, rb, rd) -END Ldr16; - - -PROCEDURE Str8 (rs, rb: INTEGER); -BEGIN - gen9(TRUE, FALSE, 0, rb, rs) -END Str8; - - -PROCEDURE Ldr8 (rd, rb: INTEGER); -BEGIN - gen9(TRUE, TRUE, 0, rb, rd) -END Ldr8; - - -PROCEDURE Cmp (r1, r2: INTEGER); -BEGIN - gen4(10, r2, r1) -END Cmp; - - -PROCEDURE Tst (r: INTEGER); -BEGIN - gen3(1, r, 0) (* cmp r, 0 *) -END Tst; - - -PROCEDURE LdrSp (r, offset: INTEGER); -BEGIN - gen11(TRUE, r, offset) -END LdrSp; - - -PROCEDURE MovImm32 (r, imm32: INTEGER); -BEGIN - MovImm8(r, LSR(imm32, 24) MOD 256); - LslImm(r, 8); - AddImm8(r, LSR(imm32, 16) MOD 256); - LslImm(r, 8); - AddImm8(r, LSR(imm32, 8) MOD 256); - LslImm(r, 8); - AddImm8(r, imm32 MOD 256) -END MovImm32; - - -PROCEDURE low (x: INTEGER): INTEGER; - RETURN x MOD 65536 -END low; - - -PROCEDURE high (x: INTEGER): INTEGER; - RETURN (x DIV 65536) MOD 65536 -END high; - - -PROCEDURE movwt (r, imm16, t: INTEGER); -VAR - imm1, imm3, imm4, imm8: INTEGER; - -BEGIN - ASSERT(range(r, 3)); - ASSERT(range(imm16, 16)); - ASSERT(range(t, 1)); - split16(imm16, imm4, imm1, imm3, imm8); - Code(0F240H + imm1 * 1024 + t * 128 + imm4); - Code(imm3 * 4096 + r * 256 + imm8); -END movwt; - - -PROCEDURE inv0 (cond: INTEGER): INTEGER; - RETURN ORD(BITS(cond) / {0}) -END inv0; - - -PROCEDURE fixup (CodeAdr, DataAdr, BssAdr: INTEGER); -VAR - code: ANYCODE; - count: INTEGER; - shorted: BOOLEAN; - jump: JUMP; - - reloc, i, diff, len: INTEGER; - - RelocCode: RELOCCODE; - - - PROCEDURE genjcc (cond, offset: INTEGER): INTEGER; - BEGIN - ASSERT(range(cond, 4)); - ASSERT(srange(offset, 8)) - RETURN 0D000H + cond * 256 + offset MOD 256 - END genjcc; - - - PROCEDURE genjmp (offset: INTEGER): INTEGER; - BEGIN - ASSERT(srange(offset, 11)) - RETURN 0E000H + offset MOD 2048 - END genjmp; - - - PROCEDURE movwt (r, imm16, t: INTEGER; VAR code: RELOCCODE); - VAR - imm1, imm3, imm4, imm8: INTEGER; - - BEGIN - split16(imm16, imm4, imm1, imm3, imm8); - code[t * 2] := 0F240H + imm1 * 1024 + t * 128 + imm4; - code[t * 2 + 1] := imm3 * 4096 + r * 256 + imm8 - END movwt; - - - PROCEDURE genmovimm32 (r, value: INTEGER; VAR code: RELOCCODE); - BEGIN - IF _THUMB2 IN Target.InstrSet THEN - movwt(r, low(value), 0, code); - movwt(r, high(value), 1, code) - ELSE - code[0] := 2000H + r * 256 + UTILS.Byte(value, 3); (* movs r, imm8 *) - code[1] := 0200H + r * 9; (* lsls r, 8 *) - code[2] := 3000H + r * 256 + UTILS.Byte(value, 2); (* adds r, imm8 *) - code[3] := code[1]; (* lsls r, 8 *) - code[4] := 3000H + r * 256 + UTILS.Byte(value, 1); (* adds r, imm8 *) - code[5] := code[1]; (* lsls r, 8 *) - code[6] := 3000H + r * 256 + UTILS.Byte(value, 0) (* adds r, imm8 *) - END - END genmovimm32; - - - PROCEDURE PutCode (code: INTEGER); - BEGIN - BIN.PutCode16LE(program, code) - END PutCode; - - - PROCEDURE genlongjmp (offset: INTEGER); - BEGIN - ASSERT(srange(offset, 22)); - PutCode(0F000H + ASR(offset, 11) MOD 2048); - PutCode(0F800H + offset MOD 2048) - END genlongjmp; - - - PROCEDURE genbc (code: JUMP); - BEGIN - CASE code.len OF - |1: PutCode(genjcc(code.cond, code.diff)) - |2: PutCode(genjcc(inv0(code.cond), 0)); - PutCode(genjmp(code.diff)) - |3: PutCode(genjcc(inv0(code.cond), 1)); - genlongjmp(code.diff) - END - END genbc; - - - PROCEDURE SetIV (idx, label, CodeAdr: INTEGER); - VAR - l, h: LISTS.ITEM; - - BEGIN - l := CodeList.first; - h := l.next; - WHILE idx > 0 DO - l := h.next; - h := l.next; - DEC(idx) - END; - label := BIN.GetLabel(program, label) * 2 + CodeAdr + 1; - l(CODE).code := low(label); - h(CODE).code := high(label) - END SetIV; - - -BEGIN - - REPEAT - - shorted := FALSE; - count := 0; - - code := CodeList.first(ANYCODE); - WHILE code # NIL DO - code.offset := count; - - CASE code OF - |CODE: INC(count) - |LABEL: BIN.SetLabel(program, code.label, count) - |JUMP: INC(count, code.len); code.offset := count + ORD(code.short) - |RELOC: INC(count, 7 - ORD(_THUMB2 IN Target.InstrSet) * 3 + code.rel MOD 2) - END; - - code := code.next(ANYCODE) - END; - - code := CodeList.first(ANYCODE); - WHILE code # NIL DO - - IF code IS JUMP THEN - jump := code(JUMP); - jump.diff := BIN.GetLabel(program, jump.label) - jump.offset; - len := jump.len; - diff := jump.diff; - CASE jump OF - |JMP: - IF (len = 2) & srange(diff, 11) THEN - len := 1 - END - - |JCC: - CASE len OF - |1: - |2: IF srange(diff, 8) THEN DEC(len) END - |3: IF srange(diff, 11) THEN DEC(len) END - END - - |CBXZ: - CASE len OF - |1: - |2: IF range(diff, 6) THEN DEC(len) END - |3: IF srange(diff, 8) THEN DEC(len) END - |4: IF srange(diff, 11) THEN DEC(len) END - END - - |CALL: - - END; - IF len # jump.len THEN - jump.len := len; - jump.short := TRUE; - shorted := TRUE - END - END; - - code := code.next(ANYCODE) - END - - UNTIL ~shorted; - - FOR i := 1 TO Target.IVTLen - 1 DO - SetIV(i, IVT[i], CodeAdr) - END; - - code := CodeList.first(ANYCODE); - WHILE code # NIL DO - - CASE code OF - - |CODE: BIN.PutCode16LE(program, code.code) - - |LABEL: - - |JMP: - IF code.len = 1 THEN - PutCode(genjmp(code.diff)) - ELSE - genlongjmp(code.diff) - END - - |JCC: genbc(code) - - |CBXZ: - IF code.len > 1 THEN - PutCode(2800H + code.reg * 256); (* cmp code.reg, 0 *) - DEC(code.len); - genbc(code) - ELSE - (* cb(n)z code.reg, L *) - PutCode(0B100H + 800H * ORD(code.cond = jne) + 200H * (code.diff DIV 32) + (code.diff MOD 32) * 8 + code.reg) - END - - |CALL: genlongjmp(code.diff) - - |RELOC: - CASE code.rel OF - |BIN.RCODE, BIN.PICCODE: reloc := BIN.GetLabel(program, code.value) * 2 + CodeAdr - |BIN.RDATA, BIN.PICDATA: reloc := code.value + DataAdr - |BIN.RBSS, BIN.PICBSS: reloc := code.value + BssAdr - END; - IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN - DEC(reloc, CodeAdr + 2 * (code.offset - 3 * ORD(_THUMB2 IN Target.InstrSet) + 9)) - END; - genmovimm32(code.reg, reloc, RelocCode); - FOR i := 0 TO 6 - 3 * ORD(_THUMB2 IN Target.InstrSet) DO - PutCode(RelocCode[i]) - END; - IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN - PutCode(4478H + code.reg) (* add code.reg, pc *) - END - END; - - code := code.next(ANYCODE) - END - -END fixup; - - -PROCEDURE push (r: INTEGER); -BEGIN - gen14(FALSE, FALSE, {r}) -END push; - - -PROCEDURE pop (r: INTEGER); -BEGIN - gen14(TRUE, FALSE, {r}) -END pop; - - -PROCEDURE mov (r1, r2: INTEGER); -BEGIN - IF (r1 < 8) & (r2 < 8) THEN - gen1(0, 0, r2, r1) - ELSE - gen5(2, r1 >= 8, r2 >= 8, r2 MOD 8, r1 MOD 8) - END -END mov; - - -PROCEDURE xchg (r1, r2: INTEGER); -BEGIN - push(r1); - mov(r1, r2); - pop(r2) -END xchg; - - -PROCEDURE drop; -BEGIN - REG.Drop(R) -END drop; - - -PROCEDURE GetAnyReg (): INTEGER; - RETURN REG.GetAnyReg(R) -END GetAnyReg; - - -PROCEDURE UnOp (VAR r: INTEGER); -BEGIN - REG.UnOp(R, r) -END UnOp; - - -PROCEDURE BinOp (VAR r1, r2: INTEGER); -BEGIN - REG.BinOp(R, r1, r2) -END BinOp; - - -PROCEDURE PushAll (NumberOfParameters: INTEGER); -BEGIN - REG.PushAll(R); - DEC(R.pushed, NumberOfParameters) -END PushAll; - - -PROCEDURE cond (op: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - CASE op OF - |IL.opGT, IL.opGTC: res := jg - |IL.opGE, IL.opGEC: res := jge - |IL.opLT, IL.opLTC: res := jl - |IL.opLE, IL.opLEC: res := jle - |IL.opEQ, IL.opEQC: res := je - |IL.opNE, IL.opNEC: res := jne - END - - RETURN res -END cond; - - -PROCEDURE GetRegA; -BEGIN - ASSERT(REG.GetReg(R, ACC)) -END GetRegA; - - -PROCEDURE MovConst (r, c: INTEGER); -BEGIN - IF (0 <= c) & (c <= 255) THEN - MovImm8(r, c) - ELSIF (-255 <= c) & (c < 0) THEN - MovImm8(r, -c); - Neg(r) - ELSIF UTILS.Log2(c) >= 0 THEN - MovImm8(r, 1); - LslImm(r, UTILS.Log2(c)) - ELSIF c = UTILS.min32 THEN - MovImm8(r, 1); - LslImm(r, 31) - ELSE - IF _THUMB2 IN Target.InstrSet THEN - movwt(r, low(c), 0); - IF (c < 0) OR (c > 65535) THEN - movwt(r, high(c), 1) - END - ELSE - MovImm32(r, c) - END - END -END MovConst; - - -PROCEDURE CmpConst (r, c: INTEGER); -VAR - r2: INTEGER; - -BEGIN - IF (0 <= c) & (c <= 255) THEN - CmpImm8(r, c) - ELSE - r2 := GetAnyReg(); - ASSERT(r2 # r); - MovConst(r2, c); - Cmp(r, r2); - drop - END -END CmpConst; - - -PROCEDURE LocalOffset (offset: INTEGER): INTEGER; - RETURN offset + StkCount - ORD(offset > 0) -END LocalOffset; - - -PROCEDURE SetCC (cc, r: INTEGER); -VAR - L1, L2: INTEGER; - -BEGIN - IF _IT IN Target.InstrSet THEN - Code(0BF00H + cc * 16 + ((cc + 1) MOD 2) * 8 + 4); (* ite cc *) - MovConst(r, 1); - MovConst(r, 0) - ELSE - L1 := NewLabel(); - L2 := NewLabel(); - jcc(cc, L1); - MovConst(r, 0); - jmp(L2); - Label(L1); - MovConst(r, 1); - Label(L2) - END -END SetCC; - - -PROCEDURE PushConst (n: INTEGER); -VAR - r: INTEGER; - -BEGIN - r := GetAnyReg(); - MovConst(r, n); - push(r); - drop -END PushConst; - - -PROCEDURE AddConst (r, n: INTEGER); -VAR - r2: INTEGER; - -BEGIN - IF n # 0 THEN - IF (-255 <= n) & (n <= 255) THEN - IF n > 0 THEN - AddImm8(r, n) - ELSE - SubImm8(r, -n) - END - ELSIF (_THUMB2 IN Target.InstrSet) & (-4095 <= n) & (n <= 4095) THEN - AddSubImm12(r, ABS(n), n < 0) - ELSE - r2 := GetAnyReg(); - ASSERT(r2 # r); - IF n > 0 THEN - MovConst(r2, n); - AddReg(r, r, r2) - ELSE - MovConst(r2, -n); - SubReg(r, r, r2) - END; - drop - END - END -END AddConst; - - -PROCEDURE AddHH (r1, r2: INTEGER); -BEGIN - ASSERT((r1 >= 8) OR (r2 >= 8)); - gen5(0, r1 >= 8, r2 >= 8, r2 MOD 8, r1 MOD 8) -END AddHH; - - -PROCEDURE AddSP (n: INTEGER); -BEGIN - IF n > 0 THEN - IF n < 127 THEN - Code(0B000H + n) (* add sp, n*4 *) - ELSE - ASSERT(R2 IN R.regs); - MovConst(R2, n * 4); - AddHH(SP, R2) - END; - DEC(StkCount, n) - END -END AddSP; - - -PROCEDURE cbxz2 (c, r, label: INTEGER); -BEGIN - IF _CBXZ IN Target.InstrSet THEN - cbxz(c, r, label) - ELSE - Tst(r); - jcc(c, label) - END -END cbxz2; - - -PROCEDURE cbz (r, label: INTEGER); -BEGIN - cbxz2(je, r, label) -END cbz; - - -PROCEDURE cbnz (r, label: INTEGER); -BEGIN - cbxz2(jne, r, label) -END cbnz; - - -PROCEDURE Shift (op, r1, r2: INTEGER); -VAR - L: INTEGER; - -BEGIN - LslImm(r2, 27); - LsrImm(r2, 27); - L := NewLabel(); - cbz(r2, L); - CASE op OF - |IL.opLSL, IL.opLSL1: gen4(2, r2, r1) - |IL.opLSR, IL.opLSR1: gen4(3, r2, r1) - |IL.opASR, IL.opASR1: gen4(4, r2, r1) - |IL.opROR, IL.opROR1: gen4(7, r2, r1) - END; - Label(L) -END Shift; - - -PROCEDURE LocAdr (offs: INTEGER); -VAR - r1, n: INTEGER; - -BEGIN - r1 := GetAnyReg(); - n := LocalOffset(offs); - IF n <= 255 THEN - gen12(TRUE, r1, n) - ELSE - MovConst(r1, n * 4); - AddHH(r1, SP) - END -END LocAdr; - - -PROCEDURE CallRTL (proc, par: INTEGER); -BEGIN - call(IL.codes.rtl[proc]); - AddSP(par) -END CallRTL; - - -PROCEDURE divmod; -BEGIN - call(sdivProc); - AddSP(2) -END divmod; - - -PROCEDURE cpsid_i; -BEGIN - Code(0B672H) (* cpsid i *) -END cpsid_i; - - -PROCEDURE cpsie_i; -BEGIN - Code(0B662H) (* cpsie i *) -END cpsie_i; - - -PROCEDURE translate (pic, stroffs: INTEGER); -VAR - cmd, next: COMMAND; - opcode, param1, param2: INTEGER; - - r1, r2, r3: INTEGER; - - a, n, cc, L, L2: INTEGER; - -BEGIN - cmd := IL.codes.commands.first(COMMAND); - - WHILE cmd # NIL DO - - param1 := cmd.param1; - param2 := cmd.param2; - opcode := cmd.opcode; - - CASE opcode OF - - |IL.opJMP: - jmp(param1) - - |IL.opLABEL: - Label(param1) - - |IL.opHANDLER: - IF param2 = 0 THEN - int0 := param1 - ELSIF param2 = 1 THEN - trap := param1 - ELSE - IVT[param2] := param1 - END - - |IL.opCALL: - call(param1) - - |IL.opCALLP: - UnOp(r1); - AddImm8(r1, 1); (* Thumb mode *) - gen5(3, TRUE, FALSE, r1, 0); (* blx r1 *) - drop; - ASSERT(R.top = -1) - - |IL.opENTER: - ASSERT(R.top = -1); - - Label(param1); - - gen14(FALSE, TRUE, {}); (* push {lr} *) - - n := param2; - IF n >= 5 THEN - MovConst(ACC, 0); - MovConst(R2, n); - L := NewLabel(); - Label(L); - push(ACC); - SubImm8(R2, 1); - Tst(R2); - jcc(jne, L) - ELSIF n > 0 THEN - MovConst(ACC, 0); - WHILE n > 0 DO - push(ACC); - DEC(n) - END - END; - StkCount := param2 - - |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: - IF opcode # IL.opLEAVE THEN - UnOp(r1); - IF r1 # ACC THEN - mov(ACC, r1) - END; - drop - END; - - ASSERT(R.top = -1); - ASSERT(StkCount = param1); - - AddSP(param1); - gen14(TRUE, TRUE, {}) (* pop {pc} *) - - |IL.opLEAVEC: - gen5(3, FALSE, TRUE, 6, 0) (* bx lr *) - - |IL.opPRECALL: - PushAll(0) - - |IL.opPARAM: - IF param2 = 1 THEN - UnOp(r1); - push(r1); - drop - ELSE - ASSERT(R.top + 1 <= param2); - PushAll(param2) - END - - |IL.opCLEANUP: - AddSP(param2) - - |IL.opRES, IL.opRESF: - ASSERT(R.top = -1); - GetRegA - - |IL.opPUSHC: - PushConst(param2) - - |IL.opONERR: - cpsid_i; - MovConst(R0, param2); - push(R0); - DEC(StkCount); - jmp(param1) - - |IL.opERR: - call(genTrap) - - |IL.opNOP, IL.opAND, IL.opOR: - - |IL.opSADR: - reloc(GetAnyReg(), BIN.RDATA + pic, stroffs + param2) - - |IL.opGADR: - reloc(GetAnyReg(), BIN.RBSS + pic, param2) - - |IL.opLADR: - LocAdr(param2) - - |IL.opGLOAD32: - r1 := GetAnyReg(); - reloc(r1, BIN.RBSS + pic, param2); - Ldr32(r1, r1) - - |IL.opGLOAD16: - r1 := GetAnyReg(); - reloc(r1, BIN.RBSS + pic, param2); - Ldr16(r1, r1) - - |IL.opGLOAD8: - r1 := GetAnyReg(); - reloc(r1, BIN.RBSS + pic, param2); - Ldr8(r1, r1) - - |IL.opLADR_SAVE: - UnOp(r1); - n := LocalOffset(param2); - IF n <= 255 THEN - gen11(FALSE, r1, n) (* str r1, [sp, n*4] *) - ELSE - LocAdr(param2); - BinOp(r1, r2); - Str32(r1, r2); - drop - END; - drop - - |IL.opLADR_INCC: - n := LocalOffset(param1); - IF n <= 255 THEN - r1 := GetAnyReg(); - LdrSp(r1, n); - AddConst(r1, param2); - gen11(FALSE, r1, n) (* str r1, [sp, n*4] *) - ELSE - LocAdr(param1); - r1 := GetAnyReg(); - BinOp(r2, r1); - Ldr32(r1, r2); - AddConst(r1, param2); - BinOp(r2, r1); - Str32(r1, r2); - drop - END; - drop - - |IL.opLLOAD32, IL.opVADR, IL.opVLOAD32: - r1 := GetAnyReg(); - n := LocalOffset(param2); - IF n <= 255 THEN - LdrSp(r1, n) - ELSE - drop; - LocAdr(param2); - UnOp(r1); - Ldr32(r1, r1) - END; - IF opcode = IL.opVLOAD32 THEN - Ldr32(r1, r1) - END - - |IL.opLLOAD16: - LocAdr(param2); - UnOp(r1); - Ldr16(r1, r1) - - |IL.opLLOAD8: - LocAdr(param2); - UnOp(r1); - Ldr8(r1, r1) - - |IL.opLOAD32, IL.opLOADF: - UnOp(r1); - Ldr32(r1, r1) - - |IL.opLOAD16: - UnOp(r1); - Ldr16(r1, r1) - - |IL.opLOAD8: - UnOp(r1); - Ldr8(r1, r1) - - |IL.opVLOAD16: - LocAdr(param2); - UnOp(r1); - Ldr32(r1, r1); - Ldr16(r1, r1) - - |IL.opVLOAD8: - LocAdr(param2); - UnOp(r1); - Ldr32(r1, r1); - Ldr8(r1, r1) - - |IL.opSBOOL: - BinOp(r2, r1); - Tst(r2); - SetCC(jne, r2); - Str8(r2, r1); - drop; - drop - - |IL.opSBOOLC: - UnOp(r1); - r2 := GetAnyReg(); - MovConst(r2, ORD(param2 # 0)); - Str8(r2, r1); - drop; - drop - - |IL.opSAVEC: - UnOp(r1); - r2 := GetAnyReg(); - MovConst(r2, param2); - Str32(r2, r1); - drop; - drop - - |IL.opSAVE16C: - UnOp(r1); - r2 := GetAnyReg(); - MovConst(r2, low(param2)); - Str16(r2, r1); - drop; - drop - - |IL.opSAVE8C: - UnOp(r1); - r2 := GetAnyReg(); - MovConst(r2, param2 MOD 256); - Str8(r2, r1); - drop; - drop - - |IL.opSAVE, IL.opSAVE32, IL.opSAVEF: - BinOp(r2, r1); - Str32(r2, r1); - drop; - drop - - |IL.opSAVEFI: - BinOp(r2, r1); - Str32(r1, r2); - drop; - drop - - |IL.opSAVE16: - BinOp(r2, r1); - Str16(r2, r1); - drop; - drop - - |IL.opSAVE8: - BinOp(r2, r1); - Str8(r2, r1); - drop; - drop - - |IL.opSAVEP: - UnOp(r1); - r2 := GetAnyReg(); - reloc(r2, BIN.RCODE + pic, param2); - Str32(r2, r1); - drop; - drop - - |IL.opPUSHP: - reloc(GetAnyReg(), BIN.RCODE + pic, param2) - - |IL.opEQB, IL.opNEB: - BinOp(r1, r2); - drop; - - L := NewLabel(); - cbz(r1, L); - MovConst(r1, 1); - Label(L); - - L := NewLabel(); - cbz(r2, L); - MovConst(r2, 1); - Label(L); - - Cmp(r1, r2); - IF opcode = IL.opEQB THEN - SetCC(je, r1) - ELSE - SetCC(jne, r1) - END - - |IL.opDROP: - UnOp(r1); - drop - - |IL.opJNZ1: - UnOp(r1); - cbnz(r1, param1) - - |IL.opJG: - UnOp(r1); - Tst(r1); - jcc(jg, param1) - - |IL.opJNZ: - UnOp(r1); - cbnz(r1, param1); - drop - - |IL.opJZ: - UnOp(r1); - cbz(r1, param1); - drop - - |IL.opSWITCH: - UnOp(r1); - IF param2 = 0 THEN - r2 := ACC - ELSE - r2 := R2 - END; - IF r1 # r2 THEN - ASSERT(REG.GetReg(R, r2)); - ASSERT(REG.Exchange(R, r1, r2)); - drop - END; - drop - - |IL.opENDSW: - - |IL.opCASEL: - GetRegA; - CmpConst(ACC, param1); - jcc(jl, param2); - drop - - |IL.opCASER: - GetRegA; - CmpConst(ACC, param1); - jcc(jg, param2); - drop - - |IL.opCASELR: - GetRegA; - CmpConst(ACC, param1); - IF param2 = cmd.param3 THEN - jcc(jne, param2) - ELSE - jcc(jl, param2); - jcc(jg, cmd.param3) - END; - drop - - |IL.opCODE: - Code(param2) - - |IL.opEQ..IL.opGE, - IL.opEQC..IL.opGEC: - IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN - BinOp(r1, r2); - Cmp(r1, r2); - drop - ELSE - UnOp(r1); - CmpConst(r1, param2) - END; - - drop; - cc := cond(opcode); - next := cmd.next(COMMAND); - - IF next.opcode = IL.opJNZ THEN - jcc(cc, next.param1); - cmd := next - ELSIF next.opcode = IL.opJZ THEN - jcc(inv0(cc), next.param1); - cmd := next - ELSE - SetCC(cc, GetAnyReg()) - END - - |IL.opINCC: - UnOp(r1); - r2 := GetAnyReg(); - Ldr32(r2, r1); - AddConst(r2, param2); - Str32(r2, r1); - drop; - drop - - |IL.opINCCB, IL.opDECCB: - IF opcode = IL.opDECCB THEN - param2 := -param2 - END; - UnOp(r1); - r2 := GetAnyReg(); - Ldr8(r2, r1); - AddConst(r2, param2); - Str8(r2, r1); - drop; - drop - - |IL.opUMINUS: - UnOp(r1); - Neg(r1) - - |IL.opADD: - BinOp(r1, r2); - CASE cmd.next(COMMAND).opcode OF - |IL.opLOAD32, IL.opLOADF: - gen7(TRUE, FALSE, r2, r1, r1); (* ldr r1, [r1, r2] *) - cmd := cmd.next(COMMAND) - |IL.opLOAD8: - gen7(TRUE, TRUE, r2, r1, r1); (* ldrb r1, [r1, r2] *) - cmd := cmd.next(COMMAND) - |IL.opLOAD16: - gen8(TRUE, FALSE, r2, r1, r1); (* ldrh r1, [r1, r2] *) - cmd := cmd.next(COMMAND) - ELSE - AddReg(r1, r1, r2) - END; - drop - - |IL.opADDC: - UnOp(r1); - AddConst(r1, param2) - - |IL.opSUB: - BinOp(r1, r2); - SubReg(r1, r1, r2); - drop - - |IL.opSUBL, IL.opSUBR: - UnOp(r1); - AddConst(r1, -param2); - IF opcode = IL.opSUBL THEN - Neg(r1) - END - - |IL.opMUL: - BinOp(r1, r2); - Mul(r1, r2); - drop - - |IL.opMULC: - UnOp(r1); - - a := param2; - IF a > 1 THEN - n := UTILS.Log2(a) - ELSIF a < -1 THEN - n := UTILS.Log2(-a) - ELSE - n := -1 - END; - - IF a = 1 THEN - - ELSIF a = -1 THEN - Neg(r1) - ELSIF a = 0 THEN - MovConst(r1, 0) - ELSE - IF n > 0 THEN - IF a < 0 THEN - Neg(r1) - END; - LslImm(r1, n) - ELSE - r2 := GetAnyReg(); - MovConst(r2, a); - Mul(r1, r2); - drop - END - END - - |IL.opABS: - UnOp(r1); - Tst(r1); - L := NewLabel(); - jcc(jge, L); - Neg(r1); - Label(L) - - |IL.opNOT: - UnOp(r1); - Tst(r1); - SetCC(je, r1) - - |IL.opORD: - UnOp(r1); - Tst(r1); - SetCC(jne, r1) - - |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: - BinOp(r1, r2); - Shift(opcode, r1, r2); - drop - - |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: - MovConst(GetAnyReg(), param2); - BinOp(r2, r1); - Shift(opcode, r1, r2); - INCL(R.regs, r2); - DEC(R.top); - R.stk[R.top] := r1 - - |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: - n := param2 MOD 32; - IF n # 0 THEN - UnOp(r1); - CASE opcode OF - |IL.opASR2: AsrImm(r1, n) - |IL.opROR2: r2 := GetAnyReg(); MovConst(r2, n); Shift(IL.opROR, r1, r2); drop - |IL.opLSL2: LslImm(r1, n) - |IL.opLSR2: LsrImm(r1, n) - END - END - - |IL.opCHKIDX: - UnOp(r1); - CmpConst(r1, param2); - jcc(jb, param1) - - |IL.opCHKIDX2: - BinOp(r1, r2); - IF param2 # -1 THEN - Cmp(r2, r1); - jcc(jb, param1) - END; - INCL(R.regs, r1); - DEC(R.top); - R.stk[R.top] := r2 - - |IL.opLEN: - n := param2; - UnOp(r1); - drop; - EXCL(R.regs, r1); - - WHILE n > 0 DO - UnOp(r2); - drop; - DEC(n) - END; - - INCL(R.regs, r1); - ASSERT(REG.GetReg(R, r1)) - - |IL.opINF: - MovConst(GetAnyReg(), inf) - - |IL.opPUSHF: - UnOp(r1); - push(r1); - drop - - |IL.opCONST: - MovConst(GetAnyReg(), param2) - - |IL.opEQP, IL.opNEP: - reloc(GetAnyReg(), BIN.RCODE + pic, param1); - BinOp(r1, r2); - Cmp(r1, r2); - drop; - IF opcode = IL.opEQP THEN - SetCC(je, r1) - ELSE - SetCC(jne, r1) - END - - |IL.opPUSHT: - UnOp(r1); - r2 := GetAnyReg(); - mov(r2, r1); - SubImm8(r2, 4); - Ldr32(r2, r2) - - |IL.opGET, IL.opGETC: - IF opcode = IL.opGET THEN - BinOp(r1, r2) - ELSIF opcode = IL.opGETC THEN - UnOp(r2); - r1 := GetAnyReg(); - MovConst(r1, param1) - END; - drop; - drop; - - CASE param2 OF - |1: Ldr8(r1, r1); Str8(r1, r2) - |2: Ldr16(r1, r1); Str16(r1, r2) - |4: Ldr32(r1, r1); Str32(r1, r2) - END - - |IL.opINC, IL.opDEC: - BinOp(r2, r1); - r3 := GetAnyReg(); - Ldr32(r3, r1); - IF opcode = IL.opINC THEN - AddReg(r3, r3, r2) - ELSE - SubReg(r3, r3, r2) - END; - Str32(r3, r1); - drop; - drop; - drop - - |IL.opINCB, IL.opDECB: - BinOp(r2, r1); - r3 := GetAnyReg(); - Ldr8(r3, r1); - IF opcode = IL.opINCB THEN - AddReg(r3, r3, r2) - ELSE - SubReg(r3, r3, r2) - END; - Str8(r3, r1); - drop; - drop; - drop - - |IL.opMIN, IL.opMAX: - BinOp(r1, r2); - Cmp(r1, r2); - L := NewLabel(); - IF opcode = IL.opMIN THEN - cc := jle - ELSE - cc := jge - END; - jcc(cc, L); - mov(r1, r2); - Label(L); - drop - - |IL.opMINC, IL.opMAXC: - UnOp(r1); - CmpConst(r1, param2); - L := NewLabel(); - IF opcode = IL.opMINC THEN - cc := jle - ELSE - cc := jge - END; - jcc(cc, L); - MovConst(r1, param2); - Label(L) - - |IL.opMULS: - BinOp(r1, r2); - gen4(0, r2, r1); (* ands r1, r2 *) - drop - - |IL.opMULSC: - MovConst(GetAnyReg(), param2); - BinOp(r1, r2); - gen4(0, r2, r1); (* ands r1, r2 *) - drop - - |IL.opDIVS: - BinOp(r1, r2); - gen4(1, r2, r1); (* eors r1, r2 *) - drop - - |IL.opDIVSC: - MovConst(GetAnyReg(), param2); - BinOp(r1, r2); - gen4(1, r2, r1); (* eors r1, r2 *) - drop - - |IL.opADDS: - BinOp(r1, r2); - gen4(12, r2, r1); (* orrs r1, r2 *) - drop - - |IL.opSUBS: - BinOp(r1, r2); - gen4(14, r2, r1); (* bics r1, r2 *) - drop - - |IL.opADDSC: - MovConst(GetAnyReg(), param2); - BinOp(r1, r2); - gen4(12, r2, r1); (* orrs r1, r2 *) - drop - - |IL.opSUBSL: - MovConst(GetAnyReg(), param2); - BinOp(r1, r2); - gen4(14, r1, r2); (* bics r2, r1 *) - INCL(R.regs, r1); - DEC(R.top); - R.stk[R.top] := r2 - - |IL.opSUBSR: - MovConst(GetAnyReg(), param2); - BinOp(r1, r2); - gen4(14, r2, r1); (* bics r1, r2 *) - drop - - |IL.opUMINS: - UnOp(r1); - gen4(15, r1, r1) (* mvns r1, r1 *) - - |IL.opINCL, IL.opEXCL: - BinOp(r1, r2); - r3 := GetAnyReg(); - MovConst(r3, 1); - CmpConst(r1, 32); - L := NewLabel(); - jcc(jnb, L); - gen4(2, r1, r3); (* lsls r3, r1 *) - Ldr32(r1, r2); - IF opcode = IL.opINCL THEN - gen4(12, r3, r1) (* orrs r1, r3 *) - ELSE - gen4(14, r3, r1) (* bics r1, r3 *) - END; - Str32(r1, r2); - Label(L); - drop; - drop; - drop - - |IL.opINCLC, IL.opEXCLC: - UnOp(r2); - r1 := GetAnyReg(); - r3 := GetAnyReg(); - MovConst(r3, 1); - LslImm(r3, param2); - Ldr32(r1, r2); - IF opcode = IL.opINCLC THEN - gen4(12, r3, r1) (* orrs r1, r3 *) - ELSE - gen4(14, r3, r1) (* bics r1, r3 *) - END; - Str32(r1, r2); - drop; - drop; - drop - - |IL.opLENGTH: - PushAll(2); - CallRTL(IL._length, 2); - GetRegA - - |IL.opLENGTHW: - PushAll(2); - CallRTL(IL._lengthw, 2); - GetRegA - - |IL.opSAVES: - UnOp(r2); - REG.PushAll_1(R); - r1 := GetAnyReg(); - reloc(r1, BIN.RDATA + pic, stroffs + param2); - push(r1); - drop; - push(r2); - drop; - PushConst(param1); - CallRTL(IL._move, 3) - - |IL.opEQS .. IL.opGES: - PushAll(4); - PushConst(opcode - IL.opEQS); - CallRTL(IL._strcmp, 5); - GetRegA - - |IL.opEQSW .. IL.opGESW: - PushAll(4); - PushConst(opcode - IL.opEQSW); - CallRTL(IL._strcmpw, 5); - GetRegA - - |IL.opCOPY: - PushAll(2); - PushConst(param2); - CallRTL(IL._move, 3) - - |IL.opMOVE: - PushAll(3); - CallRTL(IL._move, 3) - - |IL.opCOPYA: - PushAll(4); - PushConst(param2); - CallRTL(IL._arrcpy, 5); - GetRegA - - |IL.opCOPYS: - PushAll(4); - PushConst(param2); - CallRTL(IL._strcpy, 5) - - |IL.opDIV: - PushAll(2); - divmod; - GetRegA - - |IL.opDIVL: - UnOp(r1); - REG.PushAll_1(R); - PushConst(param2); - push(r1); - drop; - divmod; - GetRegA - - |IL.opDIVR: - n := UTILS.Log2(param2); - IF n > 0 THEN - UnOp(r1); - AsrImm(r1, n) - ELSIF n < 0 THEN - PushAll(1); - PushConst(param2); - divmod; - GetRegA - END - - |IL.opMOD: - PushAll(2); - divmod; - mov(R0, R1); - GetRegA - - |IL.opMODR: - n := UTILS.Log2(param2); - IF n > 0 THEN - UnOp(r1); - IF n = 8 THEN - Code(0B2C0H + r1 * 9) (* uxtb r1, r1 *) - ELSIF n = 16 THEN - Code(0B280H + r1 * 9) (* uxth r1, r1 *) - ELSE - LslImm(r1, 32 - n); - LsrImm(r1, 32 - n) - END - ELSIF n < 0 THEN - PushAll(1); - PushConst(param2); - divmod; - mov(R0, R1); - GetRegA - ELSE - UnOp(r1); - MovConst(r1, 0) - END - - |IL.opMODL: - UnOp(r1); - REG.PushAll_1(R); - PushConst(param2); - push(r1); - drop; - divmod; - mov(R0, R1); - GetRegA - - |IL.opIN, IL.opINR: - IF opcode = IL.opINR THEN - r2 := GetAnyReg(); - MovConst(r2, param2) - END; - L := NewLabel(); - L2 := NewLabel(); - BinOp(r1, r2); - r3 := GetAnyReg(); - CmpConst(r1, 32); - jcc(jb, L); - MovConst(r1, 0); - jmp(L2); - Label(L); - MovConst(r3, 1); - Shift(IL.opLSL, r3, r1); - gen4(0, r3, r2); (* ands r2, r3 *) - SetCC(jne, r1); - Label(L2); - drop; - drop - - |IL.opINL: - UnOp(r1); - r2 := GetAnyReg(); - MovConst(r2, LSL(1, param2)); - gen4(0, r2, r1); (* ands r1, r2 *) - SetCC(jne, r1); - drop - - |IL.opRSET: - PushAll(2); - CallRTL(IL._set, 2); - GetRegA - - |IL.opRSETR: - PushAll(1); - PushConst(param2); - CallRTL(IL._set, 2); - GetRegA - - |IL.opRSETL: - UnOp(r1); - REG.PushAll_1(R); - PushConst(param2); - push(r1); - drop; - CallRTL(IL._set, 2); - GetRegA - - |IL.opRSET1: - PushAll(1); - CallRTL(IL._set1, 1); - GetRegA - - |IL.opCONSTF: - MovConst(GetAnyReg(), UTILS.d2s(cmd.float)) - - |IL.opMULF: - PushAll(2); - CallRTL(IL._fmul, 2); - GetRegA - - |IL.opDIVF: - PushAll(2); - CallRTL(IL._fdiv, 2); - GetRegA - - |IL.opDIVFI: - PushAll(2); - CallRTL(IL._fdivi, 2); - GetRegA - - |IL.opADDF: - PushAll(2); - CallRTL(IL._fadd, 2); - GetRegA - - |IL.opSUBFI: - PushAll(2); - CallRTL(IL._fsubi, 2); - GetRegA - - |IL.opSUBF: - PushAll(2); - CallRTL(IL._fsub, 2); - GetRegA - - |IL.opEQF..IL.opGEF: - PushAll(2); - PushConst(opcode - IL.opEQF); - CallRTL(IL._fcmp, 3); - GetRegA - - |IL.opFLOOR: - PushAll(1); - CallRTL(IL._floor, 1); - GetRegA - - |IL.opFLT: - PushAll(1); - CallRTL(IL._flt, 1); - GetRegA - - |IL.opUMINF: - UnOp(r1); - r2 := GetAnyReg(); - MovConst(r2, 1); - LslImm(r2, 31); - gen4(1, r2, r1); (* eors r1, r2 *) - drop - - |IL.opFABS: - UnOp(r1); - r2 := GetAnyReg(); - MovConst(r2, 1); - LslImm(r2, 31); - gen4(14, r2, r1); (* bics r1, r2 *) - drop - - |IL.opNEW: - cpsid_i; - PushAll(1); - n := param2 + 4; - ASSERT(UTILS.Align(n, 4)); - PushConst(n); - PushConst(param1); - CallRTL(IL._new, 3); - cpsie_i - - |IL.opTYPEGP: - UnOp(r1); - PushAll(0); - push(r1); - PushConst(param2); - CallRTL(IL._guard, 2); - GetRegA - - |IL.opIS: - PushAll(1); - PushConst(param2); - CallRTL(IL._is, 2); - GetRegA - - |IL.opISREC: - PushAll(2); - PushConst(param2); - CallRTL(IL._guardrec, 3); - GetRegA - - |IL.opTYPEGR: - PushAll(1); - PushConst(param2); - CallRTL(IL._guardrec, 2); - GetRegA - - |IL.opTYPEGD: - UnOp(r1); - PushAll(0); - SubImm8(r1, 4); - Ldr32(r1, r1); - push(r1); - PushConst(param2); - CallRTL(IL._guardrec, 2); - GetRegA - - |IL.opCASET: - push(R2); - push(R2); - PushConst(param2); - CallRTL(IL._guardrec, 2); - pop(R2); - cbnz(ACC, param1) - - |IL.opROT: - PushAll(0); - mov(R2, SP); - push(R2); - PushConst(param2); - CallRTL(IL._rot, 2) - - |IL.opPACK: - PushAll(2); - CallRTL(IL._pack, 2) - - |IL.opPACKC: - PushAll(1); - PushConst(param2); - CallRTL(IL._pack, 2) - - |IL.opUNPK: - PushAll(2); - CallRTL(IL._unpk, 2) - - END; - - cmd := cmd.next(COMMAND) - END; - - ASSERT(R.pushed = 0); - ASSERT(R.top = -1) -END translate; - - -PROCEDURE prolog (GlobSize, tcount, pic, sp, ivt_len: INTEGER); -VAR - r1, r2, i, dcount: INTEGER; - -BEGIN - entry := NewLabel(); - emptyProc := NewLabel(); - genInt := NewLabel(); - genTrap := NewLabel(); - sdivProc := NewLabel(); - - trap := emptyProc; - int0 := emptyProc; - - IVT[0] := sp; - IVT[1] := entry; - FOR i := 2 TO ivt_len - 1 DO - IVT[i] := genInt - END; - - FOR i := 0 TO ivt_len - 1 DO - Code(low(IVT[i])); - Code(high(IVT[i])) - END; - - Label(entry); - cpsie_i; - - r1 := GetAnyReg(); - r2 := GetAnyReg(); - reloc(r1, BIN.RDATA + pic, 0); - - FOR i := 0 TO tcount - 1 DO - MovConst(r2, CHL.GetInt(IL.codes.types, i)); - Str32(r2, r1); - AddImm8(r1, 4) - END; - - dcount := CHL.Length(IL.codes.data); - FOR i := 0 TO dcount - 1 BY 4 DO - MovConst(r2, BIN.get32le(IL.codes.data, i)); - Str32(r2, r1); - AddImm8(r1, 4) - END; - - drop; - drop; - - r1 := GetAnyReg(); - MovConst(r1, sp); - mov(SP, r1); - reloc(r1, BIN.RDATA + pic, 0); - push(r1); - reloc(r1, BIN.RBSS + pic, 0); - r2 := GetAnyReg(); - MovConst(r2, GlobSize); - AddReg(r1, r1, r2); - drop; - push(r1); - drop; - PushConst(tcount); - CallRTL(IL._init, 3) -END prolog; - - -PROCEDURE epilog; -VAR - L1, L2, L3, L4: INTEGER; - -BEGIN - (* L2: *) - Code(0E7FEH); (* b L2 *) - - Label(genInt); - Code(0F3EFH); Code(08005H); (* mrs r0, ipsr *) - gen14(FALSE, TRUE, {R0}); (* push {lr, r0} *) - call(int0); - gen14(TRUE, TRUE, {R0}); (* pop {pc, r0} *) - - Label(emptyProc); - Code(04770H); (* bx lr *) - - Label(genTrap); - call(trap); - call(entry); - - Label(sdivProc); - IF _SDIV IN Target.InstrSet THEN - Code(09800H); (* ldr r0, [sp] *) - Code(09901H); (* ldr r1, [sp, 4] *) - Code(0FB91H); (* sdiv r2, r1, r0 *) - Code(0F2F0H); - Code(00013H); (* movs r3, r2 *) - Code(04343H); (* muls r3, r0, r3 *) - Code(01AC9H); (* subs r1, r1, r3 *) - Code(0DA01H); (* bge L *) - Code(01809H); (* adds r1, r1, r0 *) - Code(03A01H); (* subs r2, 1 *) - (* L: *) - Code(00010H); (* movs r0, r2 *) - Code(04770H); (* bx lr *) - ELSE - (* a / b; a >= 0 *) - L1 := NewLabel(); - L2 := NewLabel(); - L3 := NewLabel(); - L4 := NewLabel(); - - LdrSp(R1, 1); - LdrSp(R2, 0); - MovConst(R0, 0); - push(R4); - - Label(L4); - Cmp(R1, R2); - jcc(jl, L1); - MovConst(R3, 2); - mov(R4, R2); - LslImm(R4, 1); - Label(L3); - Cmp(R1, R4); - jcc(jl, L2); - CmpConst(R4, 0); - jcc(jle, L2); - LslImm(R4, 1); - LslImm(R3, 1); - jmp(L3); - Label(L2); - LsrImm(R4, 1); - LsrImm(R3, 1); - SubReg(R1, R1, R4); - AddReg(R0, R0, R3); - jmp(L4); - Label(L1); - - (* a / b; a < 0 *) - L1 := NewLabel(); - L2 := NewLabel(); - L3 := NewLabel(); - L4 := NewLabel(); - - Label(L4); - CmpConst(R1, 0); - jcc(jge, L1); - MovConst(R3, 2); - mov(R4, R2); - LslImm(R4, 1); - Neg(R1); - Label(L3); - Cmp(R1, R4); - jcc(jl, L2); - CmpConst(R4, 0); - jcc(jle, L2); - LslImm(R4, 1); - LslImm(R3, 1); - jmp(L3); - Label(L2); - Neg(R1); - LsrImm(R4, 1); - LsrImm(R3, 1); - AddReg(R1, R1, R4); - SubReg(R0, R0, R3); - jmp(L4); - Label(L1); - - pop(R4); - Code(04770H); (* bx lr *) - END - -END epilog; - - -PROCEDURE SetTarget (FlashStart, FlashSize, FlashReserve, SRAMStart, SRAMSize, SRAMReserve: INTEGER; InstrSet: SET; isNXP: BOOLEAN); -BEGIN - Target.flash.start := FlashStart; - Target.flash.size := FlashSize; - (*Target.flash.startReserve := 0;*) - Target.flash.endReserve := FlashReserve; - - Target.sram.start := SRAMStart; - Target.sram.size := SRAMSize; - Target.sram.startReserve := 0; - Target.sram.endReserve := SRAMReserve; - - Target.InstrSet := InstrSet; - Target.isNXP := isNXP; - - Target.IVTLen := 256; (* >= 192 *) - Target.MinStkSize := 256; -END SetTarget; - - -PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); -VAR - opt: PROG.OPTIONS; - i, j, DataAdr, BssAdr, DataSize, BssSize, CodeSize: INTEGER; - -BEGIN - IF target = TARGETS.STM32CM3 THEN - SetTarget(08000000H, MIN(MAX(options.rom, minROM), maxROM) * 1024, 0, - 20000000H, MIN(MAX(options.ram, minRAM), maxRAM) * 1024, 0, - CortexM3, FALSE) - END; - - tcount := CHL.Length(IL.codes.types); - - opt := options; - CodeList := LISTS.create(NIL); - - program := BIN.create(IL.codes.lcount); - - REG.Init(R, push, pop, mov, xchg, {R0, R1, R2, R3}); - - StkCount := 0; - - DataAdr := Target.sram.start + Target.sram.startReserve; - DataSize := CHL.Length(IL.codes.data) + tcount * 4 + Target.sram.startReserve; - WHILE DataSize MOD 4 # 0 DO - CHL.PushByte(IL.codes.data, 0); - INC(DataSize) - END; - BssAdr := DataAdr + DataSize - Target.sram.startReserve; - - IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4))); - - BssSize := IL.codes.bss; - ASSERT(UTILS.Align(BssSize, 4)); - - prolog(BssSize, tcount, ORD(opt.pic), Target.sram.start + Target.sram.size - Target.sram.endReserve, Target.IVTLen); - translate(ORD(opt.pic), tcount * 4); - epilog; - - fixup(Target.flash.start, DataAdr, BssAdr); - - INC(DataSize, BssSize); - CodeSize := CHL.Length(program.code); - - IF CodeSize > Target.flash.size - Target.flash.endReserve THEN - ERRORS.Error(203) - END; - - IF DataSize > Target.sram.size - Target.MinStkSize - Target.sram.endReserve THEN - ERRORS.Error(204) - END; - - IF Target.isNXP THEN - BIN.put32le(program.code, 2FCH, 0H); (* code read protection (CRP) *) - (* NXP checksum *) - j := 0; - FOR i := 0 TO 6 DO - INC(j, BIN.get32le(program.code, i * 4)) - END; - BIN.put32le(program.code, 1CH, -j) - END; - - WR.Create(outname); - - HEX.Data2(program.code, 0, CodeSize, high(Target.flash.start)); - HEX.End; - - WR.Close; - - C.Dashes; - C.String( " rom: "); C.Int(CodeSize); C.String(" of "); C.Int(Target.flash.size - Target.flash.endReserve); - C.String(" ("); C.Int(CodeSize * 100 DIV (Target.flash.size - Target.flash.endReserve)); C.StringLn("%)"); - C.Ln; - C.String( " ram: "); C.Int(DataSize); C.String(" of "); C.Int(Target.sram.size - Target.sram.endReserve); - C.String(" ("); C.Int(DataSize * 100 DIV (Target.sram.size - Target.sram.endReserve)); C.StringLn("%)") -END CodeGen; - - -PROCEDURE SetIV* (idx: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - res := IVT[idx] = 0; - IVT[idx] := 1 - - RETURN res -END SetIV; - - -PROCEDURE init; -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO LEN(IVT) - 1 DO - IVT[i] := 0 - END -END init; - - -BEGIN - init -END THUMB. \ No newline at end of file diff --git a/programs/develop/oberon07/source/UTILS.ob07 b/programs/develop/oberon07/source/UTILS.ob07 deleted file mode 100644 index eead29b1b..000000000 --- a/programs/develop/oberon07/source/UTILS.ob07 +++ /dev/null @@ -1,217 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2023, Anton Krotov - All rights reserved. -*) - -MODULE UTILS; - -IMPORT HOST; - - -CONST - - slash* = HOST.slash; - eol* = HOST.eol; - - bit_depth* = HOST.bit_depth; - maxint* = HOST.maxint; - minint* = HOST.minint; - - min32* = -2147483647-1; - max32* = 2147483647; - - vMajor* = 1; - vMinor* = 64; - Date* = "22-jan-2023"; - - FILE_EXT* = ".ob07"; - RTL_NAME* = "RTL"; - - MAX_GLOBAL_SIZE* = 1600000000; - - -VAR - - time*: INTEGER; - - maxreal*, inf*: REAL; - - target*: - - RECORD - - bit_depth*, - maxInt*, - minInt*, - maxSet*, - maxHex*: INTEGER; - - maxReal*: REAL - - END; - - bit_diff*: INTEGER; - - -PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; - RETURN HOST.FileRead(F, Buffer, bytes) -END FileRead; - - -PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; - RETURN HOST.FileWrite(F, Buffer, bytes) -END FileWrite; - - -PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; - RETURN HOST.FileCreate(FName) -END FileCreate; - - -PROCEDURE FileClose* (F: INTEGER); -BEGIN - HOST.FileClose(F) -END FileClose; - - -PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; - RETURN HOST.FileOpen(FName) -END FileOpen; - - -PROCEDURE chmod* (FName: ARRAY OF CHAR); -BEGIN - HOST.chmod(FName) -END chmod; - - -PROCEDURE GetArg* (i: INTEGER; VAR str: ARRAY OF CHAR); -BEGIN - HOST.GetArg(i, str) -END GetArg; - - -PROCEDURE Exit* (code: INTEGER); -BEGIN - HOST.ExitProcess(code) -END Exit; - - -PROCEDURE GetTickCount* (): INTEGER; - RETURN HOST.GetTickCount() -END GetTickCount; - - -PROCEDURE OutChar* (c: CHAR); -BEGIN - HOST.OutChar(c) -END OutChar; - - -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; - RETURN HOST.splitf(x, a, b) -END splitf; - - -PROCEDURE d2s* (x: REAL): INTEGER; - RETURN HOST.d2s(x) -END d2s; - - -PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; - RETURN HOST.isRelative(path) -END isRelative; - - -PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); -BEGIN - HOST.GetCurrentDirectory(path) -END GetCurrentDirectory; - - -PROCEDURE UnixTime* (): INTEGER; - RETURN HOST.UnixTime() -END UnixTime; - - -PROCEDURE SetBitDepth* (BitDepth: INTEGER; Double: BOOLEAN); -BEGIN - ASSERT((BitDepth = 16) OR (BitDepth = 32) OR (BitDepth = 64)); - bit_diff := bit_depth - BitDepth; - ASSERT(bit_diff >= 0); - - target.bit_depth := BitDepth; - target.maxSet := BitDepth - 1; - target.maxHex := BitDepth DIV 4; - target.minInt := ASR(minint, bit_diff); - target.maxInt := ASR(maxint, bit_diff); - - IF Double THEN - target.maxReal := maxreal - ELSE - target.maxReal := 1.9; - PACK(target.maxReal, 127) - END -END SetBitDepth; - - -PROCEDURE Byte* (n: INTEGER; idx: INTEGER): BYTE; - RETURN ASR(n, 8 * idx) MOD 256 -END Byte; - - -PROCEDURE Align* (VAR bytes: INTEGER; align: INTEGER): BOOLEAN; -BEGIN - INC(bytes, (-bytes) MOD align) - RETURN bytes >= 0 -END Align; - - -PROCEDURE Long* (value: INTEGER): INTEGER; - RETURN ASR(LSL(value, bit_diff), bit_diff) -END Long; - - -PROCEDURE Short* (value: INTEGER): INTEGER; - RETURN LSR(LSL(value, bit_diff), bit_diff) -END Short; - - -PROCEDURE Log2* (x: INTEGER): INTEGER; -VAR - n: INTEGER; - -BEGIN - n := 0; - WHILE ~ODD(x) DO - x := x DIV 2; - INC(n) - END; - - IF x # 1 THEN - n := -1 - END - - RETURN n -END Log2; - - -PROCEDURE hexdgt* (n: BYTE): BYTE; -BEGIN - IF n < 10 THEN - INC(n, ORD("0")) - ELSE - INC(n, ORD("A") - 10) - END - - RETURN n -END hexdgt; - - -BEGIN - time := HOST.GetTickCount(); - inf := HOST.inf; - maxreal := HOST.maxreal -END UTILS. \ No newline at end of file diff --git a/programs/develop/oberon07/source/WRITER.ob07 b/programs/develop/oberon07/source/WRITER.ob07 deleted file mode 100644 index 14d7882ca..000000000 --- a/programs/develop/oberon07/source/WRITER.ob07 +++ /dev/null @@ -1,104 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2021, Anton Krotov - All rights reserved. -*) - -MODULE WRITER; - -IMPORT FILES, ERRORS, UTILS; - - -VAR - - counter*: INTEGER; - file: FILES.FILE; - - -PROCEDURE align* (n, _align: INTEGER): INTEGER; -BEGIN - ASSERT(UTILS.Align(n, _align)) - RETURN n -END align; - - -PROCEDURE WriteByte* (n: BYTE); -BEGIN - IF FILES.WriteByte(file, n) THEN - INC(counter) - ELSE - ERRORS.Error(201) - END -END WriteByte; - - -PROCEDURE Write* (chunk: ARRAY OF BYTE; bytes: INTEGER); -VAR - n: INTEGER; - -BEGIN - n := FILES.write(file, chunk, bytes); - IF n # bytes THEN - ERRORS.Error(201) - END; - INC(counter, n) -END Write; - - -PROCEDURE Write64LE* (n: INTEGER); -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO 7 DO - WriteByte(UTILS.Byte(n, i)) - END -END Write64LE; - - -PROCEDURE Write32LE* (n: INTEGER); -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO 3 DO - WriteByte(UTILS.Byte(n, i)) - END -END Write32LE; - - -PROCEDURE Write16LE* (n: INTEGER); -BEGIN - WriteByte(UTILS.Byte(n, 0)); - WriteByte(UTILS.Byte(n, 1)) -END Write16LE; - - -PROCEDURE Padding* (FileAlignment: INTEGER); -VAR - i: INTEGER; - -BEGIN - i := align(counter, FileAlignment) - counter; - WHILE i > 0 DO - WriteByte(0); - DEC(i) - END -END Padding; - - -PROCEDURE Create* (FileName: ARRAY OF CHAR); -BEGIN - counter := 0; - file := FILES.create(FileName) -END Create; - - -PROCEDURE Close*; -BEGIN - FILES.close(file) -END Close; - - -END WRITER. \ No newline at end of file diff --git a/programs/develop/oberon07/source/X86.ob07 b/programs/develop/oberon07/source/X86.ob07 deleted file mode 100644 index 45a40589a..000000000 --- a/programs/develop/oberon07/source/X86.ob07 +++ /dev/null @@ -1,2507 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2023, Anton Krotov - All rights reserved. -*) - -MODULE X86; - -IMPORT IL, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, PROG, - CHL := CHUNKLISTS, PATHS, TARGETS, ERRORS; - - -CONST - - eax = REG.R0; ecx = REG.R1; edx = REG.R2; - - al = eax; cl = ecx; dl = edx; ah = 4; - - ax = eax; cx = ecx; dx = edx; - - esp = 4; - ebp = 5; - - MAX_FR = 7; - - sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H; - - je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H; jnb = 83H; - - - CODECHUNK = 8; - - FPR_ERR = 41; - - -TYPE - - COMMAND = IL.COMMAND; - - - ANYCODE = POINTER TO RECORD (LISTS.ITEM) - - offset: INTEGER - - END; - - CODE = POINTER TO RECORD (ANYCODE) - - code: ARRAY CODECHUNK OF BYTE; - length: INTEGER - - END; - - LABEL = POINTER TO RECORD (ANYCODE) - - label: INTEGER - - END; - - JUMP = POINTER TO RECORD (ANYCODE) - - label, diff: INTEGER; - short: BOOLEAN - - END; - - JMP = POINTER TO RECORD (JUMP) - - END; - - JCC = POINTER TO RECORD (JUMP) - - jmp: INTEGER - - END; - - CALL = POINTER TO RECORD (JUMP) - - END; - - RELOC = POINTER TO RECORD (ANYCODE) - - op, value: INTEGER - - END; - - -VAR - - R: REG.REGS; - - program: BIN.PROGRAM; - - CodeList: LISTS.LIST; - - tcount, LocVarSize, mainLocVarSize: INTEGER; - - FR: ARRAY 1000 OF INTEGER; - - fname: PATHS.PATH; - - FltConstLabel, mainFltConstLabel: LABEL; - - -PROCEDURE OutByte* (n: BYTE); -VAR - c: CODE; - last: ANYCODE; - -BEGIN - last := CodeList.last(ANYCODE); - - IF (last IS CODE) & (last(CODE).length < CODECHUNK) THEN - c := last(CODE); - c.code[c.length] := n; - INC(c.length) - ELSE - NEW(c); - c.code[0] := n; - c.length := 1; - LISTS.push(CodeList, c) - END - -END OutByte; - - -PROCEDURE OutInt (n: INTEGER); -BEGIN - OutByte(n MOD 256); - OutByte(UTILS.Byte(n, 1)); - OutByte(UTILS.Byte(n, 2)); - OutByte(UTILS.Byte(n, 3)) -END OutInt; - - -PROCEDURE OutByte2 (a, b: BYTE); -BEGIN - OutByte(a); - OutByte(b) -END OutByte2; - - -PROCEDURE OutByte3 (a, b, c: BYTE); -BEGIN - OutByte(a); - OutByte(b); - OutByte(c) -END OutByte3; - - -PROCEDURE OutWord (n: INTEGER); -BEGIN - ASSERT((0 <= n) & (n <= 65535)); - OutByte2(n MOD 256, n DIV 256) -END OutWord; - - -PROCEDURE isByte* (n: INTEGER): BOOLEAN; - RETURN (-128 <= n) & (n <= 127) -END isByte; - - -PROCEDURE short (n: INTEGER): INTEGER; - RETURN 2 * ORD(isByte(n)) -END short; - - -PROCEDURE long (n: INTEGER): INTEGER; - RETURN 40H * ORD(~isByte(n)) -END long; - - -PROCEDURE OutIntByte (n: INTEGER); -BEGIN - IF isByte(n) THEN - OutByte(n MOD 256) - ELSE - OutInt(n) - END -END OutIntByte; - - -PROCEDURE shift* (op, reg: INTEGER); -BEGIN - CASE op OF - |IL.opASR, IL.opASR1, IL.opASR2: OutByte(0F8H + reg) - |IL.opROR, IL.opROR1, IL.opROR2: OutByte(0C8H + reg) - |IL.opLSL, IL.opLSL1, IL.opLSL2: OutByte(0E0H + reg) - |IL.opLSR, IL.opLSR1, IL.opLSR2: OutByte(0E8H + reg) - END -END shift; - - -PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *) -BEGIN - OutByte2(op, 0C0H + 8 * reg2 + reg1) -END oprr; - - -PROCEDURE mov (reg1, reg2: INTEGER); (* mov reg1, reg2 *) -BEGIN - oprr(89H, reg1, reg2) -END mov; - - -PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *) -BEGIN - IF eax IN {reg1, reg2} THEN - OutByte(90H + reg1 + reg2) - ELSE - oprr(87H, reg1, reg2) - END -END xchg; - - -PROCEDURE pop (reg: INTEGER); -BEGIN - OutByte(58H + reg) (* pop reg *) -END pop; - - -PROCEDURE push (reg: INTEGER); -BEGIN - OutByte(50H + reg) (* push reg *) -END push; - - -PROCEDURE xor (reg1, reg2: INTEGER); (* xor reg1, reg2 *) -BEGIN - oprr(31H, reg1, reg2) -END xor; - - -PROCEDURE movrc (reg, n: INTEGER); -BEGIN - IF n = 0 THEN - xor(reg, reg) - ELSE - OutByte(0B8H + reg); (* mov reg, n *) - OutInt(n) - END -END movrc; - - -PROCEDURE pushc* (n: INTEGER); -BEGIN - OutByte(68H + short(n)); (* push n *) - OutIntByte(n) -END pushc; - - -PROCEDURE test (reg: INTEGER); -BEGIN - OutByte2(85H, 0C0H + reg * 9) (* test reg, reg *) -END test; - - -PROCEDURE neg (reg: INTEGER); -BEGIN - OutByte2(0F7H, 0D8H + reg) (* neg reg *) -END neg; - - -PROCEDURE not (reg: INTEGER); -BEGIN - OutByte2(0F7H, 0D0H + reg) (* not reg *) -END not; - - -PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *) -BEGIN - oprr(01H, reg1, reg2) -END add; - - -PROCEDURE oprc* (op, reg, n: INTEGER); -BEGIN - IF (reg = eax) & ~isByte(n) THEN - CASE op OF - |0C0H: op := 05H (* add *) - |0E8H: op := 2DH (* sub *) - |0F8H: op := 3DH (* cmp *) - |0E0H: op := 25H (* and *) - |0C8H: op := 0DH (* or *) - |0F0H: op := 35H (* xor *) - END; - OutByte(op); - OutInt(n) - ELSE - OutByte2(81H + short(n), op + reg MOD 8); - OutIntByte(n) - END -END oprc; - - -PROCEDURE andrc (reg, n: INTEGER); (* and reg, n *) -BEGIN - oprc(0E0H, reg, n) -END andrc; - - -PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *) -BEGIN - oprc(0C8H, reg, n) -END orrc; - - -PROCEDURE xorrc (reg, n: INTEGER); (* xor reg, n *) -BEGIN - oprc(0F0H, reg, n) -END xorrc; - - -PROCEDURE addrc (reg, n: INTEGER); (* add reg, n *) -BEGIN - oprc(0C0H, reg, n) -END addrc; - - -PROCEDURE subrc (reg, n: INTEGER); (* sub reg, n *) -BEGIN - oprc(0E8H, reg, n) -END subrc; - - -PROCEDURE cmprc (reg, n: INTEGER); (* cmp reg, n *) -BEGIN - IF n = 0 THEN - test(reg) - ELSE - oprc(0F8H, reg, n) - END -END cmprc; - - -PROCEDURE cmprr (reg1, reg2: INTEGER); (* cmp reg1, reg2 *) -BEGIN - oprr(39H, reg1, reg2) -END cmprr; - - -PROCEDURE setcc* (cc, reg: INTEGER); (* setcc reg *) -BEGIN - IF reg >= 8 THEN - OutByte(41H) - END; - OutByte3(0FH, cc, 0C0H + reg MOD 8) -END setcc; - - -PROCEDURE ret*; -BEGIN - OutByte(0C3H) -END ret; - - -PROCEDURE drop; -BEGIN - REG.Drop(R) -END drop; - - -PROCEDURE GetAnyReg (): INTEGER; - RETURN REG.GetAnyReg(R) -END GetAnyReg; - - -PROCEDURE cond* (op: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - CASE op OF - |IL.opGT, IL.opGTC: res := jg - |IL.opGE, IL.opGEC: res := jge - |IL.opLT, IL.opLTC: res := jl - |IL.opLE, IL.opLEC: res := jle - |IL.opEQ, IL.opEQC: res := je - |IL.opNE, IL.opNEC: res := jne - END - - RETURN res -END cond; - - -PROCEDURE inv0* (op: INTEGER): INTEGER; - RETURN ORD(BITS(op) / {0}) -END inv0; - - -PROCEDURE Reloc* (op, value: INTEGER); -VAR - reloc: RELOC; - -BEGIN - NEW(reloc); - reloc.op := op; - reloc.value := value; - LISTS.push(CodeList, reloc) -END Reloc; - - -PROCEDURE PushFlt (label: LABEL; value: REAL); -VAR - a, b, n: INTEGER; - - - PROCEDURE pushImm (label: LABEL; value: INTEGER); - VAR - c: CODE; - i: INTEGER; - - BEGIN - NEW(c); - IF isByte(value) THEN - c.code[0] := 6AH; - c.code[1] := value MOD 256; - c.length := 2 - ELSE - c.code[0] := 68H; - FOR i := 1 TO 4 DO - c.code[i] := UTILS.Byte(value, i - 1) - END; - c.length := 5 - END; - LISTS.insertL(CodeList, label, c) - END pushImm; - - -BEGIN - n := UTILS.splitf(value, a, b); - pushImm(label, b); - pushImm(label, a) -END PushFlt; - - -PROCEDURE jcc* (cc, label: INTEGER); -VAR - j: JCC; - -BEGIN - NEW(j); - j.label := label; - j.jmp := cc; - j.short := FALSE; - LISTS.push(CodeList, j) -END jcc; - - -PROCEDURE jmp* (label: INTEGER); -VAR - j: JMP; - -BEGIN - NEW(j); - j.label := label; - j.short := FALSE; - LISTS.push(CodeList, j) -END jmp; - - -PROCEDURE call* (label: INTEGER); -VAR - c: CALL; - -BEGIN - NEW(c); - c.label := label; - c.short := TRUE; - LISTS.push(CodeList, c) -END call; - - -PROCEDURE Pic (reg, opcode, value: INTEGER); -BEGIN - OutByte(0E8H); OutInt(0); (* call L - L: *) - pop(reg); - OutByte2(081H, 0C0H + reg); (* add reg, ... *) - Reloc(opcode, value) -END Pic; - - -PROCEDURE CallRTL (pic: BOOLEAN; proc: INTEGER); -VAR - label: INTEGER; - reg1: INTEGER; - -BEGIN - label := IL.codes.rtl[proc]; - - IF label < 0 THEN - label := -label; - IF pic THEN - reg1 := GetAnyReg(); - Pic(reg1, BIN.PICIMP, label); - OutByte2(0FFH, 010H + reg1); (* call dword[reg1] *) - drop - ELSE - OutByte2(0FFH, 015H); (* call dword[label] *) - Reloc(BIN.RIMP, label) - END - ELSE - call(label) - END -END CallRTL; - - -PROCEDURE SetLabel* (label: INTEGER); -VAR - L: LABEL; - -BEGIN - NEW(L); - L.label := label; - LISTS.push(CodeList, L) -END SetLabel; - - -PROCEDURE fixup*; -VAR - code: ANYCODE; - count, i: INTEGER; - shorted: BOOLEAN; - jump: JUMP; - -BEGIN - - REPEAT - - shorted := FALSE; - count := 0; - - code := CodeList.first(ANYCODE); - WHILE code # NIL DO - code.offset := count; - - CASE code OF - |CODE: INC(count, code.length) - |LABEL: BIN.SetLabel(program, code.label, count) - |JMP: IF code.short THEN INC(count, 2) ELSE INC(count, 5) END; code.offset := count - |JCC: IF code.short THEN INC(count, 2) ELSE INC(count, 6) END; code.offset := count - |CALL: INC(count, 5); code.offset := count - |RELOC: INC(count, 4) - END; - - code := code.next(ANYCODE) - END; - - code := CodeList.first(ANYCODE); - WHILE code # NIL DO - - IF code IS JUMP THEN - jump := code(JUMP); - jump.diff := BIN.GetLabel(program, jump.label) - code.offset; - IF ~jump.short & isByte(jump.diff) THEN - jump.short := TRUE; - shorted := TRUE - END - END; - - code := code.next(ANYCODE) - END - - UNTIL ~shorted; - - code := CodeList.first(ANYCODE); - WHILE code # NIL DO - - CASE code OF - - |CODE: - FOR i := 0 TO code.length - 1 DO - BIN.PutCode(program, code.code[i]) - END - - |LABEL: - - |JMP: - IF code.short THEN - BIN.PutCode(program, 0EBH); - BIN.PutCode(program, code.diff MOD 256) - ELSE - BIN.PutCode(program, 0E9H); - BIN.PutCode32LE(program, code.diff) - END - - |JCC: - IF code.short THEN - BIN.PutCode(program, code.jmp - 16); - BIN.PutCode(program, code.diff MOD 256) - ELSE - BIN.PutCode(program, 0FH); - BIN.PutCode(program, code.jmp); - BIN.PutCode32LE(program, code.diff) - END - - |CALL: - BIN.PutCode(program, 0E8H); - BIN.PutCode32LE(program, code.diff) - - |RELOC: - BIN.PutReloc(program, code.op); - BIN.PutCode32LE(program, code.value) - - END; - - code := code.next(ANYCODE) - END - -END fixup; - - -PROCEDURE UnOp (VAR reg: INTEGER); -BEGIN - REG.UnOp(R, reg) -END UnOp; - - -PROCEDURE BinOp (VAR reg1, reg2: INTEGER); -BEGIN - REG.BinOp(R, reg1, reg2) -END BinOp; - - -PROCEDURE PushAll (NumberOfParameters: INTEGER); -BEGIN - REG.PushAll(R); - DEC(R.pushed, NumberOfParameters) -END PushAll; - - -PROCEDURE NewLabel (): INTEGER; -BEGIN - BIN.NewLabel(program) - RETURN IL.NewLabel() -END NewLabel; - - -PROCEDURE GetRegA; -BEGIN - ASSERT(REG.GetReg(R, eax)) -END GetRegA; - - -PROCEDURE fcmp; -BEGIN - GetRegA; - OutByte2(0DAH, 0E9H); (* fucompp *) - OutByte3(09BH, 0DFH, 0E0H); (* fstsw ax *) - OutByte(09EH); (* sahf *) - OutByte(0B8H); OutInt(0) (* mov eax, 0 *) -END fcmp; - - -PROCEDURE movzx* (reg1, reg2, offs: INTEGER; word: BOOLEAN); (* movzx reg1, byte/word[reg2 + offs] *) -VAR - b: BYTE; - -BEGIN - OutByte2(0FH, 0B6H + ORD(word)); - IF (offs = 0) & (reg2 # ebp) THEN - b := 0 - ELSE - b := 40H + long(offs) - END; - OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8); - IF reg2 = esp THEN - OutByte(24H) - END; - IF b # 0 THEN - OutIntByte(offs) - END -END movzx; - - -PROCEDURE _movrm* (reg1, reg2, offs, size: INTEGER; mr: BOOLEAN); -VAR - b: BYTE; - -BEGIN - IF size = 16 THEN - OutByte(66H) - END; - IF (reg1 >= 8) OR (reg2 >= 8) OR (size = 64) THEN - OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8) + 8 * ORD(size = 64)) - END; - OutByte(8BH - 2 * ORD(mr) - ORD(size = 8)); - IF (offs = 0) & (reg2 # ebp) THEN - b := 0 - ELSE - b := 40H + long(offs) - END; - OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8); - IF reg2 = esp THEN - OutByte(24H) - END; - IF b # 0 THEN - OutIntByte(offs) - END -END _movrm; - - -PROCEDURE movmr (reg1, offs, reg2: INTEGER); (* mov dword[reg1+offs], reg2 *) -BEGIN - _movrm(reg2, reg1, offs, 32, TRUE) -END movmr; - - -PROCEDURE movrm (reg1, reg2, offs: INTEGER); (* mov reg1, dword[reg2 + offs] *) -BEGIN - _movrm(reg1, reg2, offs, 32, FALSE) -END movrm; - - -PROCEDURE movmr8* (reg1, offs, reg2: INTEGER); (* mov byte[reg1+offs], reg2_8 *) -BEGIN - _movrm(reg2, reg1, offs, 8, TRUE) -END movmr8; - - -PROCEDURE movrm8* (reg1, reg2, offs: INTEGER); (* mov reg1_8, byte[reg2+offs] *) -BEGIN - _movrm(reg1, reg2, offs, 8, FALSE) -END movrm8; - - -PROCEDURE movmr16* (reg1, offs, reg2: INTEGER); (* mov word[reg1+offs], reg2_16 *) -BEGIN - _movrm(reg2, reg1, offs, 16, TRUE) -END movmr16; - - -PROCEDURE movrm16* (reg1, reg2, offs: INTEGER); (* mov reg1_16, word[reg2+offs] *) -BEGIN - _movrm(reg1, reg2, offs, 16, FALSE) -END movrm16; - - -PROCEDURE pushm* (reg, offs: INTEGER); (* push qword[reg+offs] *) -VAR - b: BYTE; - -BEGIN - IF reg >= 8 THEN - OutByte(41H) - END; - OutByte(0FFH); - IF (offs = 0) & (reg # ebp) THEN - b := 30H - ELSE - b := 70H + long(offs) - END; - OutByte(b + reg MOD 8); - IF reg = esp THEN - OutByte(24H) - END; - IF b # 30H THEN - OutIntByte(offs) - END -END pushm; - - -PROCEDURE LoadFltConst (value: REAL); -BEGIN - PushFlt(FltConstLabel, value); - INC(LocVarSize, 8); - IF FltConstLabel = mainFltConstLabel THEN - mainLocVarSize := LocVarSize - END; - OutByte2(0DDH, 045H + long(-LocVarSize)); (* fld qword[ebp - LocVarSize] *) - OutIntByte(-LocVarSize) -END LoadFltConst; - - -PROCEDURE translate (pic: BOOLEAN; stroffs: INTEGER); -VAR - cmd, next: COMMAND; - - reg1, reg2, reg3, fr: INTEGER; - - n, a, label, cc: INTEGER; - - opcode, param1, param2: INTEGER; - - float: REAL; - -BEGIN - cmd := IL.codes.commands.first(COMMAND); - - fr := -1; - - WHILE cmd # NIL DO - - param1 := cmd.param1; - param2 := cmd.param2; - - opcode := cmd.opcode; - - CASE opcode OF - - |IL.opJMP: - jmp(param1) - - |IL.opCALL: - call(param1) - - |IL.opCALLI: - IF pic THEN - reg1 := GetAnyReg(); - Pic(reg1, BIN.PICIMP, param1); - OutByte2(0FFH, 010H + reg1); (* call dword[reg1] *) - drop - ELSE - OutByte2(0FFH, 015H); (* call dword[L] *) - Reloc(BIN.RIMP, param1) - END - - |IL.opCALLP: - UnOp(reg1); - OutByte2(0FFH, 0D0H + reg1); (* call reg1 *) - drop; - ASSERT(R.top = -1) - - |IL.opFASTCALL: - IF param2 = 1 THEN - pop(ecx) - ELSIF param2 = 2 THEN - pop(ecx); - pop(edx) - END - - |IL.opPRECALL: - PushAll(0); - IF (param2 # 0) & (fr >= 0) THEN - subrc(esp, 8) - END; - INC(FR[0]); - FR[FR[0]] := fr + 1; - WHILE fr >= 0 DO - subrc(esp, 8); - OutByte3(0DDH, 01CH, 024H); (* fstp qword[esp] *) - DEC(fr) - END; - ASSERT(fr = -1) - - |IL.opALIGN16: - ASSERT(eax IN R.regs); - mov(eax, esp); - andrc(esp, -16); - n := (3 - param2 MOD 4) * 4; - IF n > 0 THEN - subrc(esp, n) - END; - push(eax) - - |IL.opRESF, IL.opRES: - ASSERT(R.top = -1); - ASSERT(fr = -1); - n := FR[FR[0]]; DEC(FR[0]); - - IF opcode = IL.opRESF THEN - INC(fr); - IF n > 0 THEN - OutByte3(0DDH, 5CH + long(n * 8), 24H); - OutIntByte(n * 8); (* fstp qword[esp + n*8] *) - DEC(fr); - INC(n) - END; - - IF fr + n > MAX_FR THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END - ELSE - GetRegA - END; - - WHILE n > 0 DO - OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *) - addrc(esp, 8); - INC(fr); - DEC(n) - END - - |IL.opENTER: - ASSERT(R.top = -1); - - SetLabel(param1); - - IF cmd.param3 > 0 THEN - pop(eax); - IF cmd.param3 >= 2 THEN - push(edx) - END; - push(ecx); - push(eax) - END; - - push(ebp); - mov(ebp, esp); - - n := param2; - IF n > 4 THEN - movrc(ecx, n); - pushc(0); (* L: push 0 *) - OutByte2(0E2H, 0FCH) (* loop L *) - ELSE - WHILE n > 0 DO - pushc(0); - DEC(n) - END - END; - SetLabel(NewLabel()); - FltConstLabel := CodeList.last(LABEL); - LocVarSize := param2 * 4 - - |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: - IF opcode = IL.opLEAVER THEN - UnOp(reg1); - IF reg1 # eax THEN - mov(eax, reg1) - END; - drop - END; - - ASSERT(R.top = -1); - - IF opcode = IL.opLEAVEF THEN - DEC(fr) - END; - - ASSERT(fr = -1); - - IF LocVarSize > 0 THEN - mov(esp, ebp) - END; - - pop(ebp); - - IF param2 > 0 THEN - OutByte(0C2H); OutWord(param2 * 4 MOD 65536) (* ret param2*4 *) - ELSE - ret - END; - FltConstLabel := mainFltConstLabel; - LocVarSize := mainLocVarSize - - |IL.opPUSHC: - pushc(param2) - - |IL.opONERR: - pushc(param2); - jmp(param1) - - |IL.opPARAM: - IF param2 = 1 THEN - UnOp(reg1); - push(reg1); - drop - ELSE - ASSERT(R.top + 1 <= param2); - PushAll(param2) - END - - |IL.opCLEANUP: - IF param2 # 0 THEN - addrc(esp, param2 * 4) - END - - |IL.opPOPSP: - pop(esp) - - |IL.opCONST: - movrc(GetAnyReg(), param2) - - |IL.opLABEL: - SetLabel(param1) (* L: *) - - |IL.opNOP, IL.opAND, IL.opOR: - - |IL.opGADR: - next := cmd.next(COMMAND); - IF next.opcode = IL.opADDC THEN - INC(param2, next.param2); - cmd := next - END; - reg1 := GetAnyReg(); - IF pic THEN - Pic(reg1, BIN.PICBSS, param2) - ELSE - OutByte(0B8H + reg1); (* mov reg1, _bss + param2 *) - Reloc(BIN.RBSS, param2) - END - - |IL.opLADR: - next := cmd.next(COMMAND); - n := param2 * 4; - IF next.opcode = IL.opADDC THEN - INC(n, next.param2); - cmd := next - END; - OutByte2(8DH, 45H + GetAnyReg() * 8 + long(n)); (* lea reg1, dword[ebp + n] *) - OutIntByte(n) - - |IL.opVADR, IL.opLLOAD32: - movrm(GetAnyReg(), ebp, param2 * 4) - - |IL.opSADR: - reg1 := GetAnyReg(); - IF pic THEN - Pic(reg1, BIN.PICDATA, stroffs + param2); - ELSE - OutByte(0B8H + reg1); (* mov reg1, _data + stroffs + param2 *) - Reloc(BIN.RDATA, stroffs + param2) - END - - |IL.opSAVEC: - UnOp(reg1); - OutByte2(0C7H, reg1); OutInt(param2); (* mov dword[reg1], param2 *) - drop - - |IL.opSAVE8C: - UnOp(reg1); - OutByte3(0C6H, reg1, param2 MOD 256); (* mov byte[reg1], param2 *) - drop - - |IL.opSAVE16C: - UnOp(reg1); - OutByte3(66H, 0C7H, reg1); OutWord(param2 MOD 65536); (* mov word[reg1], param2 *) - drop - - |IL.opVLOAD32: - reg1 := GetAnyReg(); - movrm(reg1, ebp, param2 * 4); - movrm(reg1, reg1, 0) - - |IL.opGLOAD32: - reg1 := GetAnyReg(); - IF pic THEN - Pic(reg1, BIN.PICBSS, param2); - movrm(reg1, reg1, 0) - ELSE - OutByte2(08BH, 05H + reg1 * 8); (* mov reg1, dword[_bss + param2] *) - Reloc(BIN.RBSS, param2) - END - - |IL.opLOAD32: - UnOp(reg1); - movrm(reg1, reg1, 0) - - |IL.opVLOAD8: - reg1 := GetAnyReg(); - movrm(reg1, ebp, param2 * 4); - movzx(reg1, reg1, 0, FALSE) - - |IL.opGLOAD8: - reg1 := GetAnyReg(); - IF pic THEN - Pic(reg1, BIN.PICBSS, param2); - movzx(reg1, reg1, 0, FALSE) - ELSE - OutByte3(00FH, 0B6H, 05H + reg1 * 8); (* movzx reg1, byte[_bss + param2] *) - Reloc(BIN.RBSS, param2) - END - - |IL.opLLOAD8: - movzx(GetAnyReg(), ebp, param2 * 4, FALSE) - - |IL.opLOAD8: - UnOp(reg1); - movzx(reg1, reg1, 0, FALSE) - - |IL.opVLOAD16: - reg1 := GetAnyReg(); - movrm(reg1, ebp, param2 * 4); - movzx(reg1, reg1, 0, TRUE) - - |IL.opGLOAD16: - reg1 := GetAnyReg(); - IF pic THEN - Pic(reg1, BIN.PICBSS, param2); - movzx(reg1, reg1, 0, TRUE) - ELSE - OutByte3(00FH, 0B7H, 05H + reg1 * 8); (* movzx reg1, word[_bss + param2] *) - Reloc(BIN.RBSS, param2) - END - - |IL.opLLOAD16: - movzx(GetAnyReg(), ebp, param2 * 4, TRUE) - - |IL.opLOAD16: - UnOp(reg1); - movzx(reg1, reg1, 0, TRUE) - - |IL.opUMINUS: - UnOp(reg1); - neg(reg1) - - |IL.opADD: - BinOp(reg1, reg2); - add(reg1, reg2); - drop - - |IL.opADDC: - IF param2 # 0 THEN - UnOp(reg1); - next := cmd.next(COMMAND); - CASE next.opcode OF - |IL.opLOAD32: - movrm(reg1, reg1, param2); - cmd := next - |IL.opLOAD16: - movzx(reg1, reg1, param2, TRUE); - cmd := next - |IL.opLOAD8: - movzx(reg1, reg1, param2, FALSE); - cmd := next - |IL.opLOAD32_PARAM: - pushm(reg1, param2); - drop; - cmd := next - ELSE - IF param2 = 1 THEN - OutByte(40H + reg1) (* inc reg1 *) - ELSIF param2 = -1 THEN - OutByte(48H + reg1) (* dec reg1 *) - ELSE - addrc(reg1, param2) - END - END - END - - |IL.opSUB: - BinOp(reg1, reg2); - oprr(29H, reg1, reg2); (* sub reg1, reg2 *) - drop - - |IL.opSUBR, IL.opSUBL: - UnOp(reg1); - IF param2 = 1 THEN - OutByte(48H + reg1) (* dec reg1 *) - ELSIF param2 = -1 THEN - OutByte(40H + reg1) (* inc reg1 *) - ELSIF param2 # 0 THEN - subrc(reg1, param2) - END; - IF opcode = IL.opSUBL THEN - neg(reg1) - END - - |IL.opMULC: - IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN - BinOp(reg1, reg2); - OutByte3(8DH, 04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2)); (* lea reg1, [reg1 + reg2 * param2] *) - drop; - cmd := cmd.next(COMMAND) - ELSE - UnOp(reg1); - - a := param2; - IF a > 1 THEN - n := UTILS.Log2(a) - ELSIF a < -1 THEN - n := UTILS.Log2(-a) - ELSE - n := -1 - END; - - IF a = 1 THEN - - ELSIF a = -1 THEN - neg(reg1) - ELSIF a = 0 THEN - xor(reg1, reg1) - ELSE - IF n > 0 THEN - IF a < 0 THEN - neg(reg1) - END; - - IF n # 1 THEN - OutByte3(0C1H, 0E0H + reg1, n) (* shl reg1, n *) - ELSE - OutByte2(0D1H, 0E0H + reg1) (* shl reg1, 1 *) - END - ELSE - OutByte2(69H + short(a), 0C0H + reg1 * 9); (* imul reg1, a *) - OutIntByte(a) - END - END - END - - |IL.opMUL: - BinOp(reg1, reg2); - OutByte3(0FH, 0AFH, 0C0H + reg1 * 8 + reg2); (* imul reg1, reg2 *) - drop - - |IL.opSAVE, IL.opSAVE32: - BinOp(reg2, reg1); - movmr(reg1, 0, reg2); - drop; - drop - - |IL.opSAVE8: - BinOp(reg2, reg1); - movmr8(reg1, 0, reg2); - drop; - drop - - |IL.opSAVE16: - BinOp(reg2, reg1); - movmr16(reg1, 0, reg2); - drop; - drop - - |IL.opSAVEP: - UnOp(reg1); - IF pic THEN - reg2 := GetAnyReg(); - Pic(reg2, BIN.PICCODE, param2); - movmr(reg1, 0, reg2); - drop - ELSE - OutByte2(0C7H, reg1); (* mov dword[reg1], L *) - Reloc(BIN.RCODE, param2) - END; - drop - - |IL.opSAVEIP: - UnOp(reg1); - IF pic THEN - reg2 := GetAnyReg(); - Pic(reg2, BIN.PICIMP, param2); - pushm(reg2, 0); - OutByte2(08FH, reg1); (* pop dword[reg1] *) - drop - ELSE - OutByte2(0FFH, 035H); (* push dword[L] *) - Reloc(BIN.RIMP, param2); - OutByte2(08FH, reg1) (* pop dword[reg1] *) - END; - drop - - |IL.opPUSHP: - reg1 := GetAnyReg(); - IF pic THEN - Pic(reg1, BIN.PICCODE, param2) - ELSE - OutByte(0B8H + reg1); (* mov reg1, L *) - Reloc(BIN.RCODE, param2) - END - - |IL.opPUSHIP: - reg1 := GetAnyReg(); - IF pic THEN - Pic(reg1, BIN.PICIMP, param2); - movrm(reg1, reg1, 0) - ELSE - OutByte2(08BH, 05H + reg1 * 8); (* mov reg1, dword[L] *) - Reloc(BIN.RIMP, param2) - END - - |IL.opNOT: - UnOp(reg1); - test(reg1); - setcc(sete, reg1); - andrc(reg1, 1) - - |IL.opORD: - UnOp(reg1); - test(reg1); - setcc(setne, reg1); - andrc(reg1, 1) - - |IL.opSBOOL: - BinOp(reg2, reg1); - test(reg2); - OutByte3(0FH, 95H, reg1); (* setne byte[reg1] *) - drop; - drop - - |IL.opSBOOLC: - UnOp(reg1); - OutByte3(0C6H, reg1, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *) - drop - - |IL.opEQ..IL.opGE, - IL.opEQC..IL.opGEC: - - IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN - BinOp(reg1, reg2); - cmprr(reg1, reg2); - drop - ELSE - UnOp(reg1); - cmprc(reg1, param2) - END; - - drop; - cc := cond(opcode); - next := cmd.next(COMMAND); - - IF next.opcode = IL.opJNZ THEN - jcc(cc, next.param1); - cmd := next - ELSIF next.opcode = IL.opJZ THEN - jcc(inv0(cc), next.param1); - cmd := next - ELSE - reg1 := GetAnyReg(); - setcc(cc + 16, reg1); - andrc(reg1, 1) - END - - |IL.opEQB, IL.opNEB: - BinOp(reg1, reg2); - drop; - - test(reg1); - OutByte2(74H, 5); (* je @f *) - movrc(reg1, 1); (* mov reg1, 1 - @@: *) - test(reg2); - OutByte2(74H, 5); (* je @f *) - movrc(reg2, 1); (* mov reg2, 1 - @@: *) - - cmprr(reg1, reg2); - IF opcode = IL.opEQB THEN - setcc(sete, reg1) - ELSE - setcc(setne, reg1) - END; - andrc(reg1, 1) - - |IL.opDROP: - UnOp(reg1); - drop - - |IL.opJNZ1: - UnOp(reg1); - test(reg1); - jcc(jne, param1) - - |IL.opJG: - UnOp(reg1); - test(reg1); - jcc(jg, param1) - - |IL.opJNZ: - UnOp(reg1); - test(reg1); - jcc(jne, param1); - drop - - |IL.opJZ: - UnOp(reg1); - test(reg1); - jcc(je, param1); - drop - - |IL.opSWITCH: - UnOp(reg1); - IF param2 = 0 THEN - reg2 := eax - ELSE - reg2 := ecx - END; - IF reg1 # reg2 THEN - ASSERT(REG.GetReg(R, reg2)); - ASSERT(REG.Exchange(R, reg1, reg2)); - drop - END; - drop - - |IL.opENDSW: - - |IL.opCASEL: - cmprc(eax, param1); - jcc(jl, param2) - - |IL.opCASER: - cmprc(eax, param1); - jcc(jg, param2) - - |IL.opCASELR: - cmprc(eax, param1); - IF param2 = cmd.param3 THEN - jcc(jne, param2) - ELSE - jcc(jl, param2); - jcc(jg, cmd.param3) - END - - |IL.opCODE: - OutByte(param2) - - |IL.opGET, IL.opGETC: - IF opcode = IL.opGET THEN - BinOp(reg1, reg2) - ELSIF opcode = IL.opGETC THEN - UnOp(reg2); - reg1 := GetAnyReg(); - movrc(reg1, param1) - END; - drop; - drop; - - IF param2 # 8 THEN - _movrm(reg1, reg1, 0, param2 * 8, FALSE); - _movrm(reg1, reg2, 0, param2 * 8, TRUE) - ELSE - PushAll(0); - push(reg1); - push(reg2); - pushc(8); - CallRTL(pic, IL._move) - END - - |IL.opSAVES: - UnOp(reg2); - REG.PushAll_1(R); - - IF pic THEN - reg1 := GetAnyReg(); - Pic(reg1, BIN.PICDATA, stroffs + param2); - push(reg1); - drop - ELSE - OutByte(068H); (* push _data + stroffs + param2 *) - Reloc(BIN.RDATA, stroffs + param2); - END; - - push(reg2); - drop; - pushc(param1); - CallRTL(pic, IL._move) - - |IL.opCHKIDX: - UnOp(reg1); - cmprc(reg1, param2); - jcc(jb, param1) - - |IL.opCHKIDX2: - BinOp(reg1, reg2); - IF param2 # -1 THEN - cmprr(reg2, reg1); - jcc(jb, param1) - END; - INCL(R.regs, reg1); - DEC(R.top); - R.stk[R.top] := reg2 - - |IL.opLEN: - n := param2; - UnOp(reg1); - drop; - EXCL(R.regs, reg1); - - WHILE n > 0 DO - UnOp(reg2); - drop; - DEC(n) - END; - - INCL(R.regs, reg1); - ASSERT(REG.GetReg(R, reg1)) - - |IL.opINCC: - UnOp(reg1); - IF param2 = 1 THEN - OutByte2(0FFH, reg1) (* inc dword[reg1] *) - ELSIF param2 = -1 THEN - OutByte2(0FFH, reg1 + 8) (* dec dword[reg1] *) - ELSE - OutByte2(81H + short(param2), reg1); OutIntByte(param2) (* add dword[reg1], param2 *) - END; - drop - - |IL.opINC, IL.opDEC: - BinOp(reg1, reg2); - OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); (* add/sub dword[reg2], reg1 *) - drop; - drop - - |IL.opINCCB, IL.opDECCB: - UnOp(reg1); - OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, param2 MOD 256); (* add/sub byte[reg1], n *) - drop - - |IL.opINCB, IL.opDECB: - BinOp(reg1, reg2); - OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); (* add/sub byte[reg2], reg1 *) - drop; - drop - - |IL.opMULS: - BinOp(reg1, reg2); - oprr(21H, reg1, reg2); (* and reg1, reg2 *) - drop - - |IL.opMULSC: - UnOp(reg1); - andrc(reg1, param2) - - |IL.opDIVS: - BinOp(reg1, reg2); - xor(reg1, reg2); - drop - - |IL.opDIVSC: - UnOp(reg1); - xorrc(reg1, param2) - - |IL.opADDS: - BinOp(reg1, reg2); - oprr(9H, reg1, reg2); (* or reg1, reg2 *) - drop - - |IL.opSUBS: - BinOp(reg1, reg2); - not(reg2); - oprr(21H, reg1, reg2); (* and reg1, reg2 *) - drop - - |IL.opADDSC: - UnOp(reg1); - orrc(reg1, param2) - - |IL.opSUBSL: - UnOp(reg1); - not(reg1); - andrc(reg1, param2) - - |IL.opSUBSR: - UnOp(reg1); - andrc(reg1, ORD(-BITS(param2))) - - |IL.opUMINS: - UnOp(reg1); - not(reg1) - - |IL.opLENGTH: - PushAll(2); - CallRTL(pic, IL._length); - GetRegA - - |IL.opLENGTHW: - PushAll(2); - CallRTL(pic, IL._lengthw); - GetRegA - - |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: - UnOp(reg1); - IF reg1 # ecx THEN - ASSERT(REG.GetReg(R, ecx)); - ASSERT(REG.Exchange(R, reg1, ecx)); - drop - END; - - BinOp(reg1, reg2); - ASSERT(reg2 = ecx); - OutByte(0D3H); - shift(opcode, reg1); (* shift reg1, cl *) - drop - - |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: - UnOp(reg1); - IF reg1 # ecx THEN - ASSERT(REG.GetReg(R, ecx)); - ASSERT(REG.Exchange(R, reg1, ecx)); - drop - END; - - reg1 := GetAnyReg(); - movrc(reg1, param2); - BinOp(reg1, reg2); - ASSERT(reg1 = ecx); - OutByte(0D3H); - shift(opcode, reg2); (* shift reg2, cl *) - drop; - drop; - ASSERT(REG.GetReg(R, reg2)) - - |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: - UnOp(reg1); - n := param2 MOD 32; - IF n # 1 THEN - OutByte(0C1H) - ELSE - OutByte(0D1H) - END; - shift(opcode, reg1); (* shift reg1, n *) - IF n # 1 THEN - OutByte(n) - END - - |IL.opMAX, IL.opMIN: - BinOp(reg1, reg2); - cmprr(reg1, reg2); - OutByte2(07DH + ORD(opcode = IL.opMIN), 2); (* jge/jle L *) - mov(reg1, reg2); - (* L: *) - drop - - |IL.opMAXC, IL.opMINC: - UnOp(reg1); - cmprc(reg1, param2); - label := NewLabel(); - IF opcode = IL.opMINC THEN - cc := jle - ELSE - cc := jge - END; - jcc(cc, label); - movrc(reg1, param2); - SetLabel(label) - - |IL.opIN, IL.opINR: - IF opcode = IL.opINR THEN - reg2 := GetAnyReg(); - movrc(reg2, param2) - END; - label := NewLabel(); - BinOp(reg1, reg2); - cmprc(reg1, 32); - OutByte2(72H, 4); (* jb L *) - xor(reg1, reg1); - jmp(label); - (* L: *) - OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); (* bt reg2, reg1 *) - setcc(setc, reg1); - andrc(reg1, 1); - SetLabel(label); - drop - - |IL.opINL: - UnOp(reg1); - OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); (* bt reg1, param2 *) - setcc(setc, reg1); - andrc(reg1, 1) - - |IL.opRSET: - PushAll(2); - CallRTL(pic, IL._set); - GetRegA - - |IL.opRSETR: - PushAll(1); - pushc(param2); - CallRTL(pic, IL._set); - GetRegA - - |IL.opRSETL: - UnOp(reg1); - REG.PushAll_1(R); - pushc(param2); - push(reg1); - drop; - CallRTL(pic, IL._set); - GetRegA - - |IL.opRSET1: - PushAll(1); - CallRTL(pic, IL._set1); - GetRegA - - |IL.opINCL, IL.opEXCL: - BinOp(reg1, reg2); - cmprc(reg1, 32); - OutByte2(73H, 03H); (* jnb L *) - OutByte(0FH); - IF opcode = IL.opINCL THEN - OutByte(0ABH) (* bts dword[reg2], reg1 *) - ELSE - OutByte(0B3H) (* btr dword[reg2], reg1 *) - END; - OutByte(reg2 + 8 * reg1); - (* L: *) - drop; - drop - - |IL.opINCLC: - UnOp(reg1); - OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); (* bts dword[reg1], param2 *) - drop - - |IL.opEXCLC: - UnOp(reg1); - OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); (* btr dword[reg1], param2 *) - drop - - |IL.opDIV: - PushAll(2); - CallRTL(pic, IL._divmod); - GetRegA - - |IL.opDIVR: - n := UTILS.Log2(param2); - IF n > 0 THEN - UnOp(reg1); - IF n # 1 THEN - OutByte3(0C1H, 0F8H + reg1, n) (* sar reg1, n *) - ELSE - OutByte2(0D1H, 0F8H + reg1) (* sar reg1, 1 *) - END - ELSIF n < 0 THEN - PushAll(1); - pushc(param2); - CallRTL(pic, IL._divmod); - GetRegA - END - - |IL.opDIVL: - UnOp(reg1); - REG.PushAll_1(R); - pushc(param2); - push(reg1); - drop; - CallRTL(pic, IL._divmod); - GetRegA - - |IL.opMOD: - PushAll(2); - CallRTL(pic, IL._divmod); - mov(eax, edx); - GetRegA - - |IL.opMODR: - n := UTILS.Log2(param2); - IF n > 0 THEN - UnOp(reg1); - andrc(reg1, param2 - 1); - ELSIF n < 0 THEN - PushAll(1); - pushc(param2); - CallRTL(pic, IL._divmod); - mov(eax, edx); - GetRegA - ELSE - UnOp(reg1); - xor(reg1, reg1) - END - - |IL.opMODL: - UnOp(reg1); - REG.PushAll_1(R); - pushc(param2); - push(reg1); - drop; - CallRTL(pic, IL._divmod); - mov(eax, edx); - GetRegA - - |IL.opERR: - CallRTL(pic, IL._error) - - |IL.opABS: - UnOp(reg1); - test(reg1); - OutByte2(07DH, 002H); (* jge L *) - neg(reg1) (* neg reg1 - L: *) - - |IL.opCOPY: - IF (0 < param2) & (param2 <= 64) THEN - BinOp(reg1, reg2); - reg3 := GetAnyReg(); - FOR n := 0 TO param2 - param2 MOD 4 - 1 BY 4 DO - movrm(reg3, reg1, n); - movmr(reg2, n, reg3) - END; - n := param2 - param2 MOD 4; - IF param2 MOD 4 >= 2 THEN - movrm16(reg3, reg1, n); - movmr16(reg2, n, reg3); - INC(n, 2); - DEC(param2, 2) - END; - IF param2 MOD 4 = 1 THEN - movrm8(reg3, reg1, n); - movmr8(reg2, n, reg3); - END; - drop; - drop; - drop - ELSE - PushAll(2); - pushc(param2); - CallRTL(pic, IL._move) - END - - |IL.opMOVE: - PushAll(3); - CallRTL(pic, IL._move) - - |IL.opCOPYA: - PushAll(4); - pushc(param2); - CallRTL(pic, IL._arrcpy); - GetRegA - - |IL.opCOPYS: - PushAll(4); - pushc(param2); - CallRTL(pic, IL._strcpy) - - |IL.opROT: - PushAll(0); - push(esp); - pushc(param2); - CallRTL(pic, IL._rot) - - |IL.opNEW: - PushAll(1); - CASE TARGETS.OS OF - |TARGETS.osWIN32: - n := param2 + 4; - ASSERT(UTILS.Align(n, 4)) - |TARGETS.osLINUX32: - n := param2 + 16; - ASSERT(UTILS.Align(n, 16)) - |TARGETS.osKOS: - n := param2 + 8; - ASSERT(UTILS.Align(n, 32)) - END; - pushc(n); - pushc(param1); - CallRTL(pic, IL._new) - - |IL.opDISP: - PushAll(1); - CallRTL(pic, IL._dispose) - - |IL.opEQS .. IL.opGES: - PushAll(4); - pushc(opcode - IL.opEQS); - CallRTL(pic, IL._strcmp); - GetRegA - - |IL.opEQSW .. IL.opGESW: - PushAll(4); - pushc(opcode - IL.opEQSW); - CallRTL(pic, IL._strcmpw); - GetRegA - - |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP: - UnOp(reg1); - CASE opcode OF - |IL.opEQP, IL.opNEP: - IF pic THEN - reg2 := GetAnyReg(); - Pic(reg2, BIN.PICCODE, param1); - cmprr(reg1, reg2); - drop - ELSE - OutByte2(081H, 0F8H + reg1); (* cmp reg1, L *) - Reloc(BIN.RCODE, param1) - END - - |IL.opEQIP, IL.opNEIP: - IF pic THEN - reg2 := GetAnyReg(); - Pic(reg2, BIN.PICIMP, param1); - OutByte2(03BH, reg1 * 8 + reg2); (* cmp reg1, dword [reg2] *) - drop - ELSE - OutByte2(3BH, 05H + reg1 * 8); (* cmp reg1, dword[L] *) - Reloc(BIN.RIMP, param1) - END - - END; - drop; - reg1 := GetAnyReg(); - - CASE opcode OF - |IL.opEQP, IL.opEQIP: setcc(sete, reg1) - |IL.opNEP, IL.opNEIP: setcc(setne, reg1) - END; - - andrc(reg1, 1) - - |IL.opPUSHT: - UnOp(reg1); - movrm(GetAnyReg(), reg1, -4) - - |IL.opISREC: - PushAll(2); - pushc(param2 * tcount); - CallRTL(pic, IL._isrec); - GetRegA - - |IL.opIS: - PushAll(1); - pushc(param2 * tcount); - CallRTL(pic, IL._is); - GetRegA - - |IL.opTYPEGR: - PushAll(1); - pushc(param2 * tcount); - CallRTL(pic, IL._guardrec); - GetRegA - - |IL.opTYPEGP: - UnOp(reg1); - PushAll(0); - push(reg1); - pushc(param2 * tcount); - CallRTL(pic, IL._guard); - GetRegA - - |IL.opTYPEGD: - UnOp(reg1); - PushAll(0); - pushm(reg1, -4); - pushc(param2 * tcount); - CallRTL(pic, IL._guardrec); - GetRegA - - |IL.opCASET: - push(ecx); - push(ecx); - pushc(param2 * tcount); - CallRTL(pic, IL._guardrec); - pop(ecx); - test(eax); - jcc(jne, param1) - - |IL.opPACK: - BinOp(reg1, reg2); - push(reg2); - OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *) - OutByte2(0DDH, reg1); (* fld qword[reg1] *) - OutByte2(0D9H, 0FDH); (* fscale *) - OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) - OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *) - pop(reg2); - drop; - drop - - |IL.opPACKC: - UnOp(reg1); - pushc(param2); - OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *) - OutByte2(0DDH, reg1); (* fld qword[reg1] *) - OutByte2(0D9H, 0FDH); (* fscale *) - OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) - OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *) - pop(reg1); - drop - - |IL.opUNPK: - BinOp(reg1, reg2); - OutByte2(0DDH, reg1); (* fld qword[reg1] *) - OutByte2(0D9H, 0F4H); (* fxtract *) - OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) - OutByte2(0DBH, 018H + reg2); (* fistp dword[reg2] *) - drop; - drop - - |IL.opPUSHF: - ASSERT(fr >= 0); - DEC(fr); - subrc(esp, 8); - OutByte3(0DDH, 01CH, 024H) (* fstp qword[esp] *) - - |IL.opLOADF: - INC(fr); - IF fr > MAX_FR THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END; - UnOp(reg1); - OutByte2(0DDH, reg1); (* fld qword[reg1] *) - drop - - |IL.opCONSTF: - INC(fr); - IF fr > MAX_FR THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END; - float := cmd.float; - IF float = 0.0 THEN - OutByte2(0D9H, 0EEH) (* fldz *) - ELSIF float = 1.0 THEN - OutByte2(0D9H, 0E8H) (* fld1 *) - ELSIF float = -1.0 THEN - OutByte2(0D9H, 0E8H); (* fld1 *) - OutByte2(0D9H, 0E0H) (* fchs *) - ELSE - LoadFltConst(float) - END - - |IL.opSAVEF, IL.opSAVEFI: - ASSERT(fr >= 0); - DEC(fr); - UnOp(reg1); - OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) - drop - - |IL.opADDF: - ASSERT(fr >= 1); - DEC(fr); - OutByte2(0DEH, 0C1H) (* faddp st1, st *) - - |IL.opSUBF: - ASSERT(fr >= 1); - DEC(fr); - OutByte2(0DEH, 0E9H) (* fsubp st1, st *) - - |IL.opSUBFI: - ASSERT(fr >= 1); - DEC(fr); - OutByte2(0DEH, 0E1H) (* fsubrp st1, st *) - - |IL.opMULF: - ASSERT(fr >= 1); - DEC(fr); - OutByte2(0DEH, 0C9H) (* fmulp st1, st *) - - |IL.opDIVF: - ASSERT(fr >= 1); - DEC(fr); - OutByte2(0DEH, 0F9H) (* fdivp st1, st *) - - |IL.opDIVFI: - ASSERT(fr >= 1); - DEC(fr); - OutByte2(0DEH, 0F1H) (* fdivrp st1, st *) - - |IL.opUMINF: - ASSERT(fr >= 0); - OutByte2(0D9H, 0E0H) (* fchs *) - - |IL.opFABS: - ASSERT(fr >= 0); - OutByte2(0D9H, 0E1H) (* fabs *) - - |IL.opFLT: - INC(fr); - IF fr > MAX_FR THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END; - UnOp(reg1); - push(reg1); - OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *) - pop(reg1); - drop - - |IL.opFLOOR: - ASSERT(fr >= 0); - DEC(fr); - subrc(esp, 8); - OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H); (* fstcw word[esp+4] *) - OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H); (* fstcw word[esp+6] *) - OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH); (* and word[esp+4], 1111001111111111b *) - OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H); (* or word[esp+4], 0000010000000000b *) - OutByte2(0D9H, 06CH); OutByte2(024H, 004H); (* fldcw word[esp+4] *) - OutByte2(0D9H, 0FCH); (* frndint *) - OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *) - pop(GetAnyReg()); - OutByte2(0D9H, 06CH); OutByte2(024H, 002H); (* fldcw word[esp+2] *) - addrc(esp, 4) - - |IL.opEQF: - ASSERT(fr >= 1); - DEC(fr, 2); - fcmp; - OutByte2(07AH, 003H); (* jp L *) - setcc(sete, al) - (* L: *) - - |IL.opNEF: - ASSERT(fr >= 1); - DEC(fr, 2); - fcmp; - OutByte2(07AH, 003H); (* jp L *) - setcc(setne, al) - (* L: *) - - |IL.opLTF: - ASSERT(fr >= 1); - DEC(fr, 2); - fcmp; - OutByte2(07AH, 00EH); (* jp L *) - setcc(setc, al); - setcc(sete, ah); - test(eax); - setcc(sete, al); - andrc(eax, 1) - (* L: *) - - |IL.opGTF: - ASSERT(fr >= 1); - DEC(fr, 2); - fcmp; - OutByte2(07AH, 00FH); (* jp L *) - setcc(setc, al); - setcc(sete, ah); - cmprc(eax, 1); - setcc(sete, al); - andrc(eax, 1) - (* L: *) - - |IL.opLEF: - ASSERT(fr >= 1); - DEC(fr, 2); - fcmp; - OutByte2(07AH, 003H); (* jp L *) - setcc(setnc, al) - (* L: *) - - |IL.opGEF: - ASSERT(fr >= 1); - DEC(fr, 2); - fcmp; - OutByte2(07AH, 010H); (* jp L *) - setcc(setc, al); - setcc(sete, ah); - OutByte2(000H, 0E0H); (* add al, ah *) - OutByte2(03CH, 001H); (* cmp al, 1 *) - setcc(sete, al); - andrc(eax, 1) - (* L: *) - - |IL.opINF: - INC(fr); - IF fr > MAX_FR THEN - ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR) - END; - LoadFltConst(UTILS.inf) - - - |IL.opLADR_UNPK: - n := param2 * 4; - reg1 := GetAnyReg(); - OutByte2(8DH, 45H + reg1 * 8 + long(n)); (* lea reg1, dword[ebp + n] *) - OutIntByte(n); - BinOp(reg1, reg2); - OutByte2(0DDH, reg1); (* fld qword[reg1] *) - OutByte2(0D9H, 0F4H); (* fxtract *) - OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) - OutByte2(0DBH, 018H + reg2); (* fistp dword[reg2] *) - drop; - drop - - |IL.opSADR_PARAM: - IF pic THEN - reg1 := GetAnyReg(); - Pic(reg1, BIN.PICDATA, stroffs + param2); - push(reg1); - drop - ELSE - OutByte(068H); (* push _data + stroffs + param2 *) - Reloc(BIN.RDATA, stroffs + param2) - END - - |IL.opVADR_PARAM, IL.opLLOAD32_PARAM: - pushm(ebp, param2 * 4) - - |IL.opCONST_PARAM: - pushc(param2) - - |IL.opGLOAD32_PARAM: - IF pic THEN - reg1 := GetAnyReg(); - Pic(reg1, BIN.PICBSS, param2); - pushm(reg1, 0); - drop - ELSE - OutByte2(0FFH, 035H); (* push dword[_bss + param2] *) - Reloc(BIN.RBSS, param2) - END - - |IL.opLOAD32_PARAM: - UnOp(reg1); - pushm(reg1, 0); - drop - - |IL.opGADR_SAVEC: - IF pic THEN - reg1 := GetAnyReg(); - Pic(reg1, BIN.PICBSS, param1); - OutByte2(0C7H, reg1); (* mov dword[reg1], param2 *) - OutInt(param2); - drop - ELSE - OutByte2(0C7H, 05H); (* mov dword[_bss + param1], param2 *) - Reloc(BIN.RBSS, param1); - OutInt(param2) - END - - |IL.opLADR_SAVEC: - n := param1 * 4; - OutByte2(0C7H, 45H + long(n)); (* mov dword[ebp + n], param2 *) - OutIntByte(n); - OutInt(param2) - - |IL.opLADR_SAVE: - UnOp(reg1); - movmr(ebp, param2 * 4, reg1); - drop - - |IL.opLADR_INCC: - n := param1 * 4; - IF ABS(param2) = 1 THEN - OutByte2(0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec dword[ebp + n] *) - OutIntByte(n) - ELSE - OutByte2(81H + short(param2), 45H + long(n)); (* add dword[ebp + n], param2 *) - OutIntByte(n); - OutIntByte(param2) - END - - |IL.opLADR_INCCB, IL.opLADR_DECCB: - n := param1 * 4; - IF param2 = 1 THEN - OutByte2(0FEH, 45H + 8 * ORD(opcode = IL.opLADR_DECCB) + long(n)); (* inc/dec byte[ebp + n] *) - OutIntByte(n) - ELSE - OutByte2(80H, 45H + 28H * ORD(opcode = IL.opLADR_DECCB) + long(n)); (* add/sub byte[ebp + n], param2 *) - OutIntByte(n); - OutByte(param2 MOD 256) - END - - |IL.opLADR_INC, IL.opLADR_DEC: - n := param2 * 4; - UnOp(reg1); - OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); (* add/sub dword[ebp + n], reg1 *) - OutIntByte(n); - drop - - |IL.opLADR_INCB, IL.opLADR_DECB: - n := param2 * 4; - UnOp(reg1); - OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); (* add/sub byte[ebp + n], reg1 *) - OutIntByte(n); - drop - - |IL.opLADR_INCL, IL.opLADR_EXCL: - n := param2 * 4; - UnOp(reg1); - cmprc(reg1, 32); - label := NewLabel(); - jcc(jnb, label); - OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + reg1 * 8); (* bts(r) dword[ebp + n], reg1 *) - OutIntByte(n); - SetLabel(label); - drop - - |IL.opLADR_INCLC, IL.opLADR_EXCLC: - n := param1 * 4; - OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); (* bts(r) dword[ebp + n], param2 *) - OutIntByte(n); - OutByte(param2) - - |IL.opFNAME: - fname := cmd(IL.FNAMECMD).fname - - END; - - cmd := cmd.next(COMMAND) - END; - - ASSERT(R.pushed = 0); - ASSERT(R.top = -1); - ASSERT(fr = -1) -END translate; - - -PROCEDURE prolog (pic: BOOLEAN; target, stack, dllret: INTEGER): INTEGER; -VAR - reg1, entry, L, dcount: INTEGER; - -BEGIN - entry := NewLabel(); - SetLabel(entry); - dcount := CHL.Length(IL.codes.data); - - push(ebp); - mov(ebp, esp); - SetLabel(NewLabel()); - mainFltConstLabel := CodeList.last(LABEL); - FltConstLabel := mainFltConstLabel; - mainLocVarSize := 0; - LocVarSize := 0; - - IF target = TARGETS.Win32DLL THEN - pushm(ebp, 16); - pushm(ebp, 12); - pushm(ebp, 8); - CallRTL(pic, IL._dllentry); - test(eax); - jcc(je, dllret); - pushc(0) - ELSIF target = TARGETS.KolibriOSDLL THEN - OutByte(68H); (* push IMPORT *) - Reloc(BIN.IMPTAB, 0) - ELSIF target = TARGETS.KolibriOS THEN - reg1 := GetAnyReg(); - Pic(reg1, BIN.IMPTAB, 0); - push(reg1); (* push IMPORT *) - drop - ELSIF target = TARGETS.Linux32 THEN - mov(eax, ebp); - addrc(eax, 4); - push(eax) - ELSE - pushc(0) - END; - - IF pic THEN - reg1 := GetAnyReg(); - Pic(reg1, BIN.PICCODE, entry); - push(reg1); (* push CODE *) - Pic(reg1, BIN.PICDATA, 0); - push(reg1); (* push _data *) - pushc(tcount); - Pic(reg1, BIN.PICDATA, tcount * 4 + dcount); - push(reg1); (* push _data + tcount * 4 + dcount *) - drop - ELSE - OutByte(68H); (* push CODE *) - Reloc(BIN.RCODE, entry); - OutByte(68H); (* push _data *) - Reloc(BIN.RDATA, 0); - pushc(tcount); - OutByte(68H); (* push _data + tcount * 4 + dcount *) - Reloc(BIN.RDATA, tcount * 4 + dcount) - END; - - CallRTL(pic, IL._init); - - IF target IN {TARGETS.Win32C, TARGETS.Win32GUI, TARGETS.Linux32} THEN - L := NewLabel(); - pushc(0); - push(esp); - pushc(1024 * 1024 * stack); - pushc(0); - CallRTL(pic, IL._new); - pop(eax); - test(eax); - jcc(je, L); - addrc(eax, 1024 * 1024 * stack - 4); - mov(esp, eax); - SetLabel(L) - END - - RETURN entry -END prolog; - - -PROCEDURE epilog (pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret, sofinit: INTEGER); -VAR - exp: IL.EXPORT_PROC; - path, name, ext: PATHS.PATH; - - dcount, i: INTEGER; - - - PROCEDURE _import (imp: LISTS.LIST); - VAR - lib: IL.IMPORT_LIB; - proc: IL.IMPORT_PROC; - - BEGIN - - lib := imp.first(IL.IMPORT_LIB); - WHILE lib # NIL DO - BIN.Import(program, lib.name, 0); - proc := lib.procs.first(IL.IMPORT_PROC); - WHILE proc # NIL DO - BIN.Import(program, proc.name, proc.label); - proc := proc.next(IL.IMPORT_PROC) - END; - lib := lib.next(IL.IMPORT_LIB) - END - - END _import; - - -BEGIN - - IF target IN {TARGETS.Win32C, TARGETS.Win32GUI, TARGETS.KolibriOS, TARGETS.Linux32} THEN - pushc(0); - CallRTL(pic, IL._exit); - ELSIF target = TARGETS.Win32DLL THEN - SetLabel(dllret); - movrc(eax, 1); - OutByte(0C9H); (* leave *) - OutByte3(0C2H, 0CH, 0) (* ret 12 *) - ELSIF target = TARGETS.KolibriOSDLL THEN - movrc(eax, 1); - OutByte(0C9H); (* leave *) - ret - ELSIF target = TARGETS.Linux32SO THEN - OutByte(0C9H); (* leave *) - ret; - SetLabel(sofinit); - CallRTL(pic, IL._sofinit); - ret - END; - - fixup; - - dcount := CHL.Length(IL.codes.data); - - FOR i := 0 TO tcount - 1 DO - BIN.PutData32LE(program, CHL.GetInt(IL.codes.types, i)) - END; - - FOR i := 0 TO dcount - 1 DO - BIN.PutData(program, CHL.GetByte(IL.codes.data, i)) - END; - - program.modname := CHL.Length(program.data); - - PATHS.split(modname, path, name, ext); - BIN.PutDataStr(program, name); - BIN.PutDataStr(program, ext); - BIN.PutData(program, 0); - - IF target = TARGETS.KolibriOSDLL THEN - BIN.Export(program, "lib_init", dllinit); - END; - - exp := IL.codes.export.first(IL.EXPORT_PROC); - WHILE exp # NIL DO - BIN.Export(program, exp.name, exp.label); - exp := exp.next(IL.EXPORT_PROC) - END; - - _import(IL.codes._import); - - IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4))); - - BIN.SetParams(program, IL.codes.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536)) -END epilog; - - -PROCEDURE align16* (bit64: BOOLEAN); -BEGIN - IF TARGETS.WinLin THEN - WHILE CHL.Length(IL.codes.data) MOD 16 # 0 DO - CHL.PushByte(IL.codes.data, 0) - END; - WHILE CHL.Length(IL.codes.types) MOD (4 - 2*ORD(bit64)) # 0 DO - CHL.PushInt(IL.codes.types, 0) - END - END -END align16; - - -PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); -VAR - dllret, dllinit, sofinit: INTEGER; - opt: PROG.OPTIONS; - -BEGIN - FR[0] := 0; - align16(FALSE); - tcount := CHL.Length(IL.codes.types); - - opt := options; - CodeList := LISTS.create(NIL); - - program := BIN.create(IL.codes.lcount); - - dllret := NewLabel(); - sofinit := NewLabel(); - - IF target = TARGETS.KolibriOSDLL THEN - opt.pic := FALSE - END; - - IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32} THEN - opt.pic := TRUE - END; - - REG.Init(R, push, pop, mov, xchg, {eax, ecx, edx}); - - dllinit := prolog(opt.pic, target, opt.stack, dllret); - translate(opt.pic, tcount * 4); - 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) - ELSIF target = TARGETS.KolibriOS THEN - KOS.write(program, outname) - ELSIF target = TARGETS.KolibriOSDLL THEN - MSCOFF.write(program, outname, opt.version) - ELSIF TARGETS.OS = TARGETS.osLINUX32 THEN - ELF.write(program, outname, sofinit, target = TARGETS.Linux32SO, FALSE) - END -END CodeGen; - - -PROCEDURE SetProgram* (prog: BIN.PROGRAM); -BEGIN - program := prog; - CodeList := LISTS.create(NIL) -END SetProgram; - - -END X86. \ No newline at end of file