From c4dee82cbc5fb571ce62252b56f2df0125adc279 Mon Sep 17 00:00:00 2001 From: Anton Krotov Date: Thu, 26 Sep 2019 20:23:06 +0000 Subject: [PATCH] update git-svn-id: svn://kolibrios.org@7693 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/develop/oberon07/Compiler.kex | Bin 238061 -> 254941 bytes programs/develop/oberon07/Docs/About1251.txt | 22 +- programs/develop/oberon07/Docs/About866.txt | 22 +- programs/develop/oberon07/Docs/KOSLib1251.txt | 15 +- programs/develop/oberon07/Docs/KOSLib866.txt | 775 +++---- .../develop/oberon07/Lib/KolibriOS/File.ob07 | 30 +- .../develop/oberon07/Lib/KolibriOS/Math.ob07 | 77 +- .../oberon07/Lib/KolibriOS/NetDevices.ob07 | 18 +- .../develop/oberon07/Lib/KolibriOS/RTL.ob07 | 290 +-- .../oberon07/Lib/KolibriOS/Vector.ob07 | 2 +- .../develop/oberon07/Lib/Linux32/LINAPI.ob07 | 10 - .../develop/oberon07/Lib/Linux32/RTL.ob07 | 290 +-- .../develop/oberon07/Lib/Windows32/API.ob07 | 21 +- .../develop/oberon07/Lib/Windows32/RTL.ob07 | 290 +-- programs/develop/oberon07/Source/AMD64.ob07 | 1134 +++++------ programs/develop/oberon07/Source/ARITH.ob07 | 82 +- .../develop/oberon07/Source/AVLTREES.ob07 | 10 +- programs/develop/oberon07/Source/BIN.ob07 | 39 +- .../develop/oberon07/Source/CHUNKLISTS.ob07 | 39 +- .../develop/oberon07/Source/COLLECTIONS.ob07 | 4 +- programs/develop/oberon07/Source/CONSOLE.ob07 | 38 +- .../develop/oberon07/Source/CONSTANTS.ob07 | 12 +- .../develop/oberon07/Source/Compiler.ob07 | 142 +- programs/develop/oberon07/Source/ELF.ob07 | 399 +++- programs/develop/oberon07/Source/ERRORS.ob07 | 84 +- programs/develop/oberon07/Source/FILES.ob07 | 2 +- programs/develop/oberon07/Source/IL.ob07 | 1182 +++++++++++ programs/develop/oberon07/Source/KOS.ob07 | 8 +- programs/develop/oberon07/Source/LISTS.ob07 | 24 +- programs/develop/oberon07/Source/MSCOFF.ob07 | 4 +- programs/develop/oberon07/Source/MSP430.ob07 | 1793 +++++++++++++++++ .../develop/oberon07/Source/MSP430RTL.ob07 | 677 +++++++ programs/develop/oberon07/Source/PARS.ob07 | 443 ++-- programs/develop/oberon07/Source/PATHS.ob07 | 14 +- programs/develop/oberon07/Source/PROG.ob07 | 558 +++-- programs/develop/oberon07/Source/REG.ob07 | 54 +- programs/develop/oberon07/Source/SCAN.ob07 | 339 ++-- .../develop/oberon07/Source/STATEMENTS.ob07 | 1773 ++++++++-------- programs/develop/oberon07/Source/STRINGS.ob07 | 27 +- programs/develop/oberon07/Source/TEXTDRV.ob07 | 141 +- .../develop/oberon07/Source/UNIXTIME.ob07 | 9 +- programs/develop/oberon07/Source/UTILS.ob07 | 91 +- programs/develop/oberon07/Source/WRITER.ob07 | 16 +- programs/develop/oberon07/Source/X86.ob07 | 966 ++++----- 44 files changed, 8006 insertions(+), 3960 deletions(-) create mode 100644 programs/develop/oberon07/Source/IL.ob07 create mode 100644 programs/develop/oberon07/Source/MSP430.ob07 create mode 100644 programs/develop/oberon07/Source/MSP430RTL.ob07 diff --git a/programs/develop/oberon07/Compiler.kex b/programs/develop/oberon07/Compiler.kex index c3149a0f5f0d257dc4739701a7aae66940f878cf..4eaf1f48f95abd8f87881b4e768846c51a22af73 100644 GIT binary patch literal 254941 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 literal 238061 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 ðàçìåð ñòýêà â ìåãàáàéòàõ (ïî óìîë÷àíèþ 2 Ìá) -base
àäðåñ çàãðóçêè èñïîëíÿåìîãî ôàéëà â êèëîáàéòàõ @@ -144,10 +145,10 @@ UTF-8 äî 32 áèò, äëÿ çàïèñè áàéòîâ èñïîëüçîâàòü SYSTEM.PUT8, äëÿ WCHAR -- SYSTEM.PUT16 - PROCEDURE PUT8(a: INTEGER; x: INTEGER, BYTE, CHAR, WCHAR) + PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) Ïàìÿòü[a] := ìëàäøèå 8 áèò (x) - PROCEDURE PUT16(a: INTEGER; x: INTEGER, BYTE, CHAR, WCHAR) + PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) Ïàìÿòü[a] := ìëàäøèå 16 áèò (x) PROCEDURE MOVE(Source, Dest, n: INTEGER) @@ -358,8 +359,8 @@ Oberon- Âñå ïðîãðàììû íåÿâíî èñïîëüçóþò ìîäóëü RTL. Êîìïèëÿòîð òðàíñëèðóåò íåêîòîðûå îïåðàöèè (ïðîâåðêà è îõðàíà òèïà, ñðàâíåíèå ñòðîê, ñîîáùåíèÿ îá îøèáêàõ âðåìåíè âûïîëíåíèÿ è äð.) êàê âûçîâû ïðîöåäóð ýòîãî ìîäóëÿ. Íå -ñëåäóåò ÿâíî âûçûâàòü ýòè ïðîöåäóðû, çà èñêëþ÷åíèåì ïðîöåäóðû SetDll, -åñëè ïðèëîæåíèå êîìïèëèðóåòñÿ êàê Windows DLL: +ñëåäóåò ÿâíî âûçûâàòü ýòè ïðîöåäóðû, çà èñêëþ÷åíèåì ïðîöåäóð SetDll è SetFini +åñëè ïðèëîæåíèå êîìïèëèðóåòñÿ êàê Windows DLL èëè Linux SO, ñîîòâåòñòâåííî: PROCEDURE SetDll (process_detach, thread_detach, thread_attach: DLL_ENTRY); @@ -372,8 +373,15 @@ SetDll - ñîçäàíèè íîâîãî ïîòîêà (thread_attach) - óíè÷òîæåíèè ïîòîêà (thread_detach) -Äëÿ ïðî÷èõ òèïîâ ïðèëîæåíèé, âûçîâ ïðîöåäóðû SetDll íå âëèÿåò íà + + PROCEDURE SetFini (ProcFini: PROC); + ãäå TYPE PROC = PROCEDURE (* áåç ïàðàìåòðîâ *) + +SetFini íàçíà÷àåò ïðîöåäóðó ProcFini âûçûâàåìîé ïðè âûãðóçêå so-áèáëèîòåêè. + +Äëÿ ïðî÷èõ òèïîâ ïðèëîæåíèé, âûçîâ ïðîöåäóð SetDll è SetFini íå âëèÿåò íà ïîâåäåíèå ïðîãðàììû. + Ñîîáùåíèÿ îá îøèáêàõ âðåìåíè âûïîëíåíèÿ âûâîäÿòñÿ â äèàëîãîâûõ îêíàõ (Windows), â òåðìèíàë (Linux), íà äîñêó îòëàäêè (KolibriOS). @@ -395,6 +403,4 @@ SetDll PROCEDURE [stdcall] lib_init (): INTEGER Ýòà ïðîöåäóðà äîëæíà áûòü âûçâàíà ïåðåä èñïîëüçîâàíèåì DLL. -Ïðîöåäóðà âñåãäà âîçâðàùàåò 1. - - Äëÿ Linux, ãåíåðàöèÿ äèíàìè÷åñêèõ áèáëèîòåê íå ðåàëèçîâàíà. \ No newline at end of file +Ïðîöåäóðà âñåãäà âîçâðàùàåò 1. \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/About866.txt b/programs/develop/oberon07/Docs/About866.txt index 74af19c3bf..b0147dc787 100644 --- a/programs/develop/oberon07/Docs/About866.txt +++ b/programs/develop/oberon07/Docs/About866.txt @@ -17,6 +17,7 @@ UTF-8 "kos" - KolibriOS "obj" - KolibriOS DLL "elfexe" - Linux ELF-EXEC + "elfso" - Linux ELF-SO 4) ­¥®¡ï§ â¥«ì­ë¥ ¯ à ¬¥âàë-ª«îç¨ -stk à §¬¥à áâíª  ¢ ¬¥£ ¡ ©â å (¯® 㬮«ç ­¨î 2 Œ¡) -base
 ¤à¥á § £à㧪¨ ¨á¯®«­ï¥¬®£® ä ©«  ¢ ª¨«®¡ ©â å @@ -144,10 +145,10 @@ UTF-8 ¤® 32 ¡¨â, ¤«ï § ¯¨á¨ ¡ ©â®¢ ¨á¯®«ì§®¢ âì SYSTEM.PUT8, ¤«ï WCHAR -- SYSTEM.PUT16 - PROCEDURE PUT8(a: INTEGER; x: INTEGER, BYTE, CHAR, WCHAR) + PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR)  ¬ïâì[a] := ¬« ¤è¨¥ 8 ¡¨â (x) - PROCEDURE PUT16(a: INTEGER; x: INTEGER, BYTE, CHAR, WCHAR) + PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR)  ¬ïâì[a] := ¬« ¤è¨¥ 16 ¡¨â (x) PROCEDURE MOVE(Source, Dest, n: INTEGER) @@ -358,8 +359,8 @@ Oberon-ॠ ‚ᥠ¯à®£à ¬¬ë ­¥ï¢­® ¨á¯®«ì§ãîâ ¬®¤ã«ì RTL. Š®¬¯¨«ïâ®à â࠭᫨àã¥â ­¥ª®â®àë¥ ®¯¥à æ¨¨ (¯à®¢¥àª  ¨ ®åà ­  ⨯ , áà ¢­¥­¨¥ áâப, á®®¡é¥­¨ï ®¡ ®è¨¡ª å ¢à¥¬¥­¨ ¢ë¯®«­¥­¨ï ¨ ¤à.) ª ª ¢ë§®¢ë ¯à®æ¥¤ãà í⮣® ¬®¤ã«ï. ¥ -á«¥¤ã¥â ® ¢ë§ë¢ âì í⨠¯à®æ¥¤ãàë, §  ¨áª«î祭¨¥¬ ¯à®æ¥¤ãàë SetDll, -¥á«¨ ¯à¨«®¦¥­¨¥ ª®¬¯¨«¨àã¥âáï ª ª Windows DLL: +á«¥¤ã¥â ® ¢ë§ë¢ âì í⨠¯à®æ¥¤ãàë, §  ¨áª«î祭¨¥¬ ¯à®æ¥¤ãà SetDll ¨ SetFini +¥á«¨ ¯à¨«®¦¥­¨¥ ª®¬¯¨«¨àã¥âáï ª ª Windows DLL ¨«¨ Linux SO, ᮮ⢥âá⢥­­®: PROCEDURE SetDll (process_detach, thread_detach, thread_attach: DLL_ENTRY); @@ -372,8 +373,15 @@ SetDll - ᮧ¤ ­¨¨ ­®¢®£® ¯®â®ª  (thread_attach) - ã­¨ç⮦¥­¨¨ ¯®â®ª  (thread_detach) -„«ï ¯à®ç¨å ⨯®¢ ¯à¨«®¦¥­¨©, ¢ë§®¢ ¯à®æ¥¤ãàë SetDll ­¥ ¢«¨ï¥â ­  + + PROCEDURE SetFini (ProcFini: PROC); + £¤¥ TYPE PROC = PROCEDURE (* ¡¥§ ¯ à ¬¥â஢ *) + +SetFini ­ §­ ç ¥â ¯à®æ¥¤ãàã ProcFini ¢ë§ë¢ ¥¬®© ¯à¨ ¢ë£à㧪¥ so-¡¨¡«¨®â¥ª¨. + +„«ï ¯à®ç¨å ⨯®¢ ¯à¨«®¦¥­¨©, ¢ë§®¢ ¯à®æ¥¤ãà SetDll ¨ SetFini ­¥ ¢«¨ï¥â ­  ¯®¢¥¤¥­¨¥ ¯à®£à ¬¬ë. + ‘®®¡é¥­¨ï ®¡ ®è¨¡ª å ¢à¥¬¥­¨ ¢ë¯®«­¥­¨ï ¢ë¢®¤ïâáï ¢ ¤¨ «®£®¢ëå ®ª­ å (Windows), ¢ â¥à¬¨­ « (Linux), ­  ¤®áªã ®â« ¤ª¨ (KolibriOS). @@ -395,6 +403,4 @@ SetDll PROCEDURE [stdcall] lib_init (): INTEGER â  ¯à®æ¥¤ãà  ¤®«¦­  ¡ëâì ¢ë§¢ ­  ¯¥à¥¤ ¨á¯®«ì§®¢ ­¨¥¬ DLL. -à®æ¥¤ãà  ¢á¥£¤  ¢®§¢à é ¥â 1. - - „«ï Linux, £¥­¥à æ¨ï ¤¨­ ¬¨ç¥áª¨å ¡¨¡«¨®â¥ª ­¥ ॠ«¨§®¢ ­ . \ No newline at end of file +à®æ¥¤ãà  ¢á¥£¤  ¢®§¢à é ¥â 1. \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/KOSLib1251.txt b/programs/develop/oberon07/Docs/KOSLib1251.txt index 0f8175a68e..ea757d300c 100644 --- a/programs/develop/oberon07/Docs/KOSLib1251.txt +++ b/programs/develop/oberon07/Docs/KOSLib1251.txt @@ -98,8 +98,8 @@ MODULE Math - CONST - pi = 3.141592653589793D+00 - e = 2.718281828459045D+00 + pi = 3.141592653589793E+00 + e = 2.718281828459045E+00 PROCEDURE IsNan(x: REAL): BOOLEAN @@ -153,13 +153,13 @@ MODULE Math - PROCEDURE tanh(x: REAL): REAL ãèïåðáîëè÷åñêèé òàíãåíñ x - PROCEDURE arcsinh(x: REAL): REAL + PROCEDURE arsinh(x: REAL): REAL îáðàòíûé ãèïåðáîëè÷åñêèé ñèíóñ x - PROCEDURE arccosh(x: REAL): REAL + PROCEDURE arcosh(x: REAL): REAL îáðàòíûé ãèïåðáîëè÷åñêèé êîñèíóñ x - PROCEDURE arctanh(x: REAL): REAL + PROCEDURE artanh(x: REAL): REAL îáðàòíûé ãèïåðáîëè÷åñêèé òàíãåíñ x PROCEDURE round(x: REAL): REAL @@ -181,6 +181,9 @@ MODULE Math - åñëè x < 0 âîçâðàùàåò -1 åñëè x = 0 âîçâðàùàåò 0 + PROCEDURE fact(n: INTEGER): REAL + ôàêòîðèàë n + ------------------------------------------------------------------------------ MODULE Debug - âûâîä íà äîñêó îòëàäêè Èíòåðôåéñ êàê ìîäóëü Out @@ -337,7 +340,7 @@ MODULE DateTime - PROCEDURE Encode(Year, Month, Day, Hour, Min, Sec: INTEGER): REAL âîçâðàùàåò äàòó, ïîëó÷åííóþ èç êîìïîíåíòîâ Year, Month, Day, Hour, Min, Sec; - ïðè îøèáêå âîçâðàùàåò êîíñòàíòó ERR = -7.0D5 + ïðè îøèáêå âîçâðàùàåò êîíñòàíòó ERR = -7.0E5 PROCEDURE Decode(Date: REAL; VAR Year, Month, Day, Hour, Min, Sec: INTEGER): BOOLEAN diff --git a/programs/develop/oberon07/Docs/KOSLib866.txt b/programs/develop/oberon07/Docs/KOSLib866.txt index 4e3e15fb1f..a163da19ee 100644 --- a/programs/develop/oberon07/Docs/KOSLib866.txt +++ b/programs/develop/oberon07/Docs/KOSLib866.txt @@ -1,94 +1,94 @@ ============================================================================== - ¨¡«¨®â¥ª  (KolibriOS) + ¨¡«¨®â¥ª  (KolibriOS) ------------------------------------------------------------------------------ MODULE Out - ª®­á®«ì­ë© ¢ë¢®¤ - PROCEDURE Open - ä®à¬ «ì­® ®âªà뢠¥â ª®­á®«ì­ë© ¢ë¢®¤ + PROCEDURE Open + ä®à¬ «ì­® ®âªà뢠¥â ª®­á®«ì­ë© ¢ë¢®¤ - PROCEDURE Int(x, width: INTEGER) - ¢ë¢®¤ 楫®£® ç¨á«  x; - width - ª®«¨ç¥á⢮ §­ ª®¬¥áâ, ¨á¯®«ì§ã¥¬ëå ¤«ï ¢ë¢®¤  + PROCEDURE Int(x, width: INTEGER) + ¢ë¢®¤ 楫®£® ç¨á«  x; + width - ª®«¨ç¥á⢮ §­ ª®¬¥áâ, ¨á¯®«ì§ã¥¬ëå ¤«ï ¢ë¢®¤  - PROCEDURE Real(x: REAL; width: INTEGER) - ¢ë¢®¤ ¢¥é¥á⢥­­®£® ç¨á«  x ¢ ¯« ¢ î饬 ä®à¬ â¥; - width - ª®«¨ç¥á⢮ §­ ª®¬¥áâ, ¨á¯®«ì§ã¥¬ëå ¤«ï ¢ë¢®¤  + PROCEDURE Real(x: REAL; width: INTEGER) + ¢ë¢®¤ ¢¥é¥á⢥­­®£® ç¨á«  x ¢ ¯« ¢ î饬 ä®à¬ â¥; + width - ª®«¨ç¥á⢮ §­ ª®¬¥áâ, ¨á¯®«ì§ã¥¬ëå ¤«ï ¢ë¢®¤  - PROCEDURE Char(x: CHAR) - ¢ë¢®¤ ᨬ¢®«  x + PROCEDURE Char(x: CHAR) + ¢ë¢®¤ ᨬ¢®«  x - PROCEDURE FixReal(x: REAL; width, p: INTEGER) - ¢ë¢®¤ ¢¥é¥á⢥­­®£® ç¨á«  x ¢ 䨪á¨à®¢ ­­®¬ ä®à¬ â¥; - width - ª®«¨ç¥á⢮ §­ ª®¬¥áâ, ¨á¯®«ì§ã¥¬ëå ¤«ï ¢ë¢®¤ ; - p - ª®«¨ç¥á⢮ §­ ª®¢ ¯®á«¥ ¤¥áïâ¨ç­®© â®çª¨ + PROCEDURE FixReal(x: REAL; width, p: INTEGER) + ¢ë¢®¤ ¢¥é¥á⢥­­®£® ç¨á«  x ¢ 䨪á¨à®¢ ­­®¬ ä®à¬ â¥; + width - ª®«¨ç¥á⢮ §­ ª®¬¥áâ, ¨á¯®«ì§ã¥¬ëå ¤«ï ¢ë¢®¤ ; + p - ª®«¨ç¥á⢮ §­ ª®¢ ¯®á«¥ ¤¥áïâ¨ç­®© â®çª¨ - PROCEDURE Ln - ¯¥à¥å®¤ ­  á«¥¤ãîéãî áâபã + PROCEDURE Ln + ¯¥à¥å®¤ ­  á«¥¤ãîéãî áâபã - PROCEDURE String(s: ARRAY OF CHAR) - ¢ë¢®¤ áâப¨ s + PROCEDURE String(s: ARRAY OF CHAR) + ¢ë¢®¤ áâப¨ s ------------------------------------------------------------------------------ MODULE In - ª®­á®«ì­ë© ¢¢®¤ - VAR Done: BOOLEAN - ¯à¨­¨¬ ¥â §­ ç¥­¨¥ TRUE ¢ á«ãç ¥ ãᯥ譮£® ¢ë¯®«­¥­¨ï - ®¯¥à æ¨¨ ¢¢®¤ , ¨­ ç¥ FALSE + VAR Done: BOOLEAN + ¯à¨­¨¬ ¥â §­ ç¥­¨¥ TRUE ¢ á«ãç ¥ ãᯥ譮£® ¢ë¯®«­¥­¨ï + ®¯¥à æ¨¨ ¢¢®¤ , ¨­ ç¥ FALSE - PROCEDURE Open - ä®à¬ «ì­® ®âªà뢠¥â ª®­á®«ì­ë© ¢¢®¤, - â ª¦¥ ¯à¨á¢ ¨¢ ¥â ¯¥à¥¬¥­­®© Done §­ ç¥­¨¥ TRUE + PROCEDURE Open + ä®à¬ «ì­® ®âªà뢠¥â ª®­á®«ì­ë© ¢¢®¤, + â ª¦¥ ¯à¨á¢ ¨¢ ¥â ¯¥à¥¬¥­­®© Done §­ ç¥­¨¥ TRUE - PROCEDURE Int(VAR x: INTEGER) - ¢¢®¤ ç¨á«  ⨯  INTEGER + PROCEDURE Int(VAR x: INTEGER) + ¢¢®¤ ç¨á«  ⨯  INTEGER - PROCEDURE Char(VAR x: CHAR) - ¢¢®¤ ᨬ¢®«  + PROCEDURE Char(VAR x: CHAR) + ¢¢®¤ ᨬ¢®«  - PROCEDURE Real(VAR x: REAL) - ¢¢®¤ ç¨á«  ⨯  REAL + PROCEDURE Real(VAR x: REAL) + ¢¢®¤ ç¨á«  ⨯  REAL - PROCEDURE String(VAR s: ARRAY OF CHAR) - ¢¢®¤ áâப¨ + PROCEDURE String(VAR s: ARRAY OF CHAR) + ¢¢®¤ áâப¨ - PROCEDURE Ln - ®¦¨¤ ­¨¥ ­ ¦ â¨ï ENTER + PROCEDURE Ln + ®¦¨¤ ­¨¥ ­ ¦ â¨ï ENTER ------------------------------------------------------------------------------ MODULE Console - ¤®¯®«­¨â¥«ì­ë¥ ¯à®æ¥¤ãàë ª®­á®«ì­®£® ¢ë¢®¤  - CONST + 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 + 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 Cls + ®ç¨á⪠ ®ª­  ª®­á®«¨ - PROCEDURE SetColor(FColor, BColor: INTEGER) - ãáâ ­®¢ª  æ¢¥â  ª®­á®«ì­®£® ¢ë¢®¤ : FColor - 梥â ⥪áâ , - BColor - 梥â ä®­ , ¢®§¬®¦­ë¥ §­ ç¥­¨ï - ¢ë襯¥à¥ç¨á«¥­­ë¥ - ª®­áâ ­âë + PROCEDURE SetColor(FColor, BColor: INTEGER) + ãáâ ­®¢ª  æ¢¥â  ª®­á®«ì­®£® ¢ë¢®¤ : FColor - 梥â ⥪áâ , + BColor - 梥â ä®­ , ¢®§¬®¦­ë¥ §­ ç¥­¨ï - ¢ë襯¥à¥ç¨á«¥­­ë¥ + ª®­áâ ­âë - PROCEDURE SetCursor(x, y: INTEGER) - ãáâ ­®¢ª  ªãàá®à  ª®­á®«¨ ¢ ¯®§¨æ¨î (x, y) + PROCEDURE SetCursor(x, y: INTEGER) + ãáâ ­®¢ª  ªãàá®à  ª®­á®«¨ ¢ ¯®§¨æ¨î (x, y) - PROCEDURE GetCursor(VAR x, y: INTEGER) - § ¯¨á뢠¥â ¢ ¯ à ¬¥âàë ⥪ã騥 ª®®à¤¨­ âë ªãàá®à  ª®­á®«¨ + PROCEDURE GetCursor(VAR x, y: INTEGER) + § ¯¨á뢠¥â ¢ ¯ à ¬¥âàë ⥪ã騥 ª®®à¤¨­ âë ªãàá®à  ª®­á®«¨ - PROCEDURE GetCursorX(): INTEGER - ¢®§¢à é ¥â ⥪ãéãî x-ª®®à¤¨­ âã ªãàá®à  ª®­á®«¨ + PROCEDURE GetCursorX(): INTEGER + ¢®§¢à é ¥â ⥪ãéãî x-ª®®à¤¨­ âã ªãàá®à  ª®­á®«¨ - PROCEDURE GetCursorY(): INTEGER - ¢®§¢à é ¥â ⥪ãéãî y-ª®®à¤¨­ âã ªãàá®à  ª®­á®«¨ + PROCEDURE GetCursorY(): INTEGER + ¢®§¢à é ¥â ⥪ãéãî y-ª®®à¤¨­ âã ªãàá®à  ª®­á®«¨ ------------------------------------------------------------------------------ MODULE ConsoleLib - ®¡¥à⪠ ¡¨¡«¨®â¥ª¨ console.obj @@ -96,466 +96,469 @@ MODULE ConsoleLib - ------------------------------------------------------------------------------ MODULE Math - ¬ â¥¬ â¨ç¥áª¨¥ ä㭪樨 - CONST + CONST - pi = 3.141592653589793D+00 - e = 2.718281828459045D+00 + pi = 3.141592653589793E+00 + e = 2.718281828459045E+00 - PROCEDURE IsNan(x: REAL): BOOLEAN - ¢®§¢à é ¥â TRUE, ¥á«¨ x - ­¥ ç¨á«® + PROCEDURE IsNan(x: REAL): BOOLEAN + ¢®§¢à é ¥â TRUE, ¥á«¨ x - ­¥ ç¨á«® - PROCEDURE IsInf(x: REAL): BOOLEAN - ¢®§¢à é ¥â TRUE, ¥á«¨ x - ¡¥áª®­¥ç­®áâì + PROCEDURE IsInf(x: REAL): BOOLEAN + ¢®§¢à é ¥â TRUE, ¥á«¨ x - ¡¥áª®­¥ç­®áâì - PROCEDURE sqrt(x: REAL): REAL - ª¢ ¤à â­ë© ª®à¥­ì x + PROCEDURE sqrt(x: REAL): REAL + ª¢ ¤à â­ë© ª®à¥­ì x - PROCEDURE exp(x: REAL): REAL - íªá¯®­¥­â  x + PROCEDURE exp(x: REAL): REAL + íªá¯®­¥­â  x - PROCEDURE ln(x: REAL): REAL - ­ âãà «ì­ë© «®£ à¨ä¬ x + PROCEDURE ln(x: REAL): REAL + ­ âãà «ì­ë© «®£ à¨ä¬ x - PROCEDURE sin(x: REAL): REAL - ᨭãá x + PROCEDURE sin(x: REAL): REAL + ᨭãá x - PROCEDURE cos(x: REAL): REAL - ª®á¨­ãá x + PROCEDURE cos(x: REAL): REAL + ª®á¨­ãá x - PROCEDURE tan(x: REAL): REAL - â ­£¥­á x + PROCEDURE tan(x: REAL): REAL + â ­£¥­á x - PROCEDURE arcsin(x: REAL): REAL -  àªá¨­ãá x + PROCEDURE arcsin(x: REAL): REAL +  àªá¨­ãá x - PROCEDURE arccos(x: REAL): REAL -  àªª®á¨­ãá x + PROCEDURE arccos(x: REAL): REAL +  àªª®á¨­ãá x - PROCEDURE arctan(x: REAL): REAL -  àªâ ­£¥­á x + PROCEDURE arctan(x: REAL): REAL +  àªâ ­£¥­á x - PROCEDURE arctan2(y, x: REAL): REAL -  àªâ ­£¥­á y/x + PROCEDURE arctan2(y, x: REAL): REAL +  àªâ ­£¥­á y/x - PROCEDURE power(base, exponent: REAL): REAL - ¢®§¢¥¤¥­¨¥ ç¨á«  base ¢ á⥯¥­ì exponent + PROCEDURE power(base, exponent: REAL): REAL + ¢®§¢¥¤¥­¨¥ ç¨á«  base ¢ á⥯¥­ì exponent - PROCEDURE log(base, x: REAL): REAL - «®£ à¨ä¬ x ¯® ®á­®¢ ­¨î base + PROCEDURE log(base, x: REAL): REAL + «®£ à¨ä¬ x ¯® ®á­®¢ ­¨î base - PROCEDURE sinh(x: REAL): REAL - £¨¯¥à¡®«¨ç¥áª¨© ᨭãá x + PROCEDURE sinh(x: REAL): REAL + £¨¯¥à¡®«¨ç¥áª¨© ᨭãá x - PROCEDURE cosh(x: REAL): REAL - £¨¯¥à¡®«¨ç¥áª¨© ª®á¨­ãá x + PROCEDURE cosh(x: REAL): REAL + £¨¯¥à¡®«¨ç¥áª¨© ª®á¨­ãá x - PROCEDURE tanh(x: REAL): REAL - £¨¯¥à¡®«¨ç¥áª¨© â ­£¥­á x + PROCEDURE tanh(x: REAL): REAL + £¨¯¥à¡®«¨ç¥áª¨© â ­£¥­á x - PROCEDURE arcsinh(x: REAL): REAL - ®¡à â­ë© £¨¯¥à¡®«¨ç¥áª¨© ᨭãá x + PROCEDURE arsinh(x: REAL): REAL + ®¡à â­ë© £¨¯¥à¡®«¨ç¥áª¨© ᨭãá x - PROCEDURE arccosh(x: REAL): REAL - ®¡à â­ë© £¨¯¥à¡®«¨ç¥áª¨© ª®á¨­ãá x + PROCEDURE arcosh(x: REAL): REAL + ®¡à â­ë© £¨¯¥à¡®«¨ç¥áª¨© ª®á¨­ãá x - PROCEDURE arctanh(x: REAL): REAL - ®¡à â­ë© £¨¯¥à¡®«¨ç¥áª¨© â ­£¥­á x + PROCEDURE artanh(x: REAL): REAL + ®¡à â­ë© £¨¯¥à¡®«¨ç¥áª¨© â ­£¥­á x - PROCEDURE round(x: REAL): REAL - ®ªà㣫¥­¨¥ x ¤® ¡«¨¦ ©è¥£® 楫®£® + PROCEDURE round(x: REAL): REAL + ®ªà㣫¥­¨¥ x ¤® ¡«¨¦ ©è¥£® 楫®£® - PROCEDURE frac(x: REAL): REAL; - ¤à®¡­ ï ç áâì ç¨á«  x + PROCEDURE frac(x: REAL): REAL; + ¤à®¡­ ï ç áâì ç¨á«  x - PROCEDURE floor(x: REAL): REAL - ­ ¨¡®«ì襥 楫®¥ ç¨á«® (¯à¥¤áâ ¢«¥­¨¥ ª ª REAL), - ­¥ ¡®«ìè¥ x: floor(1.2) = 1.0 + 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 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 sgn(x: REAL): INTEGER + ¥á«¨ x > 0 ¢®§¢à é ¥â 1 + ¥á«¨ x < 0 ¢®§¢à é ¥â -1 + ¥á«¨ x = 0 ¢®§¢à é ¥â 0 + + PROCEDURE fact(n: INTEGER): REAL + ä ªâ®à¨ « n ------------------------------------------------------------------------------ MODULE Debug - ¢ë¢®¤ ­  ¤®áªã ®â« ¤ª¨ - ˆ­â¥àä¥©á ª ª ¬®¤ã«ì Out + ˆ­â¥àä¥©á ª ª ¬®¤ã«ì Out - PROCEDURE Open - ®âªà뢠¥â ¤®áªã ®â« ¤ª¨ + PROCEDURE Open + ®âªà뢠¥â ¤®áªã ®â« ¤ª¨ ------------------------------------------------------------------------------ MODULE File - à ¡®â  á ä ©«®¢®© á¨á⥬®© - TYPE + TYPE - FNAME = ARRAY 520 OF CHAR + FNAME = ARRAY 520 OF CHAR - FS = POINTER TO rFS + FS = POINTER TO rFS - rFS = RECORD (* ¨­ä®à¬ æ¨®­­ ï áâàãªâãà  ä ©«  *) - subfunc, pos, hpos, bytes, buffer: INTEGER; - name: FNAME - END + rFS = RECORD (* ¨­ä®à¬ æ¨®­­ ï áâàãªâãà  ä ©«  *) + subfunc, pos, hpos, bytes, buffer: INTEGER; + name: FNAME + END - FD = POINTER TO rFD + 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 + 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 + CONST - SEEK_BEG = 0 - SEEK_CUR = 1 - SEEK_END = 2 + SEEK_BEG = 0 + SEEK_CUR = 1 + SEEK_END = 2 - PROCEDURE Load(FName: ARRAY OF CHAR; VAR size: INTEGER): INTEGER; - ‡ £à㦠¥â ¢ ¯ ¬ïâì ä ©« á ¨¬¥­¥¬ FName, § ¯¨á뢠¥â ¢ ¯ à ¬¥âà - size à §¬¥à ä ©« , ¢®§¢à é ¥â  ¤à¥á § £à㦥­­®£® ä ©«  - ¨«¨ 0 (®è¨¡ª ). ਠ­¥®¡å®¤¨¬®áâ¨, à á¯ ª®¢ë¢ ¥â - ä ©« (kunpack). + 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 GetFileInfo(FName: ARRAY OF CHAR; VAR Info: rFD): BOOLEAN + ‡ ¯¨á뢠¥â áâàãªâãàã ¡«®ª  ¤ ­­ëå ¢å®¤  ª â «®£  ¤«ï ä ©«  + ¨«¨ ¯ ¯ª¨ á ¨¬¥­¥¬ FName ¢ ¯ à ¬¥âà Info. + ਠ®è¨¡ª¥ ¢®§¢à é ¥â FALSE. - PROCEDURE Exists(FName: ARRAY OF CHAR): BOOLEAN - ¢®§¢à é ¥â TRUE, ¥á«¨ ä ©« á ¨¬¥­¥¬ FName áãé¥áâ¢ã¥â + PROCEDURE Exists(FName: ARRAY OF CHAR): BOOLEAN + ¢®§¢à é ¥â TRUE, ¥á«¨ ä ©« á ¨¬¥­¥¬ FName áãé¥áâ¢ã¥â - PROCEDURE Close(VAR F: FS) - ®á¢®¡®¦¤ ¥â ¯ ¬ïâì, ¢ë¤¥«¥­­ãî ¤«ï ¨­ä®à¬ æ¨®­­®© áâàãªâãàë - ä ©«  F ¨ ¯à¨á¢ ¨¢ ¥â F §­ ç¥­¨¥ NIL + PROCEDURE Close(VAR F: FS) + ®á¢®¡®¦¤ ¥â ¯ ¬ïâì, ¢ë¤¥«¥­­ãî ¤«ï ¨­ä®à¬ æ¨®­­®© áâàãªâãàë + ä ©«  F ¨ ¯à¨á¢ ¨¢ ¥â F §­ ç¥­¨¥ NIL - PROCEDURE Open(FName: ARRAY OF CHAR): FS - ¢®§¢à é ¥â 㪠§ â¥«ì ­  ¨­ä®à¬ æ¨®­­ãî áâàãªâãàã ä ©«  á - ¨¬¥­¥¬ FName, ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â NIL + PROCEDURE Open(FName: ARRAY OF CHAR): FS + ¢®§¢à é ¥â 㪠§ â¥«ì ­  ¨­ä®à¬ æ¨®­­ãî áâàãªâãàã ä ©«  á + ¨¬¥­¥¬ FName, ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â NIL - PROCEDURE Delete(FName: ARRAY OF CHAR): BOOLEAN - 㤠«ï¥â ä ©« á ¨¬¥­¥¬ FName, ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â FALSE + 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 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 Read(F: FS; Buffer, Count: INTEGER): INTEGER + —¨â ¥â ¤ ­­ë¥ ¨§ ä ©«  ¢ ¯ ¬ïâì. F - 㪠§ â¥«ì ­  + ¨­ä®à¬ æ¨®­­ãî áâàãªâãàã ä ©« , Buffer -  ¤à¥á ®¡« á⨠+ ¯ ¬ïâ¨, Count - ª®«¨ç¥á⢮ ¡ ©â, ª®â®à®¥ âॡã¥âáï ¯à®ç¨â âì + ¨§ ä ©« ; ¢®§¢à é ¥â ª®«¨ç¥á⢮ ¡ ©â, ª®â®à®¥ ¡ë«® ¯à®ç¨â ­® + ¨ ᮮ⢥âáâ¢ãî騬 ®¡à §®¬ ¨§¬¥­ï¥â ¯®§¨æ¨î ç⥭¨ï/§ ¯¨á¨ ¢ + ¨­ä®à¬ æ¨®­­®© áâàãªâãॠF. - PROCEDURE Write(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 Create(FName: ARRAY OF CHAR): FS + ᮧ¤ ¥â ­®¢ë© ä ©« á ¨¬¥­¥¬ FName (¯®«­®¥ ¨¬ï), ¢®§¢à é ¥â + 㪠§ â¥«ì ­  ¨­ä®à¬ æ¨®­­ãî áâàãªâãàã ä ©« , + ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â NIL - PROCEDURE CreateDir(DirName: ARRAY OF CHAR): BOOLEAN - ᮧ¤ ¥â ¯ ¯ªã á ¨¬¥­¥¬ DirName, ¢á¥ ¯à®¬¥¦ãâ®ç­ë¥ ¯ ¯ª¨ - ¤®«¦­ë áãé¥á⢮¢ âì, ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â FALSE + PROCEDURE CreateDir(DirName: ARRAY OF CHAR): BOOLEAN + ᮧ¤ ¥â ¯ ¯ªã á ¨¬¥­¥¬ DirName, ¢á¥ ¯à®¬¥¦ãâ®ç­ë¥ ¯ ¯ª¨ + ¤®«¦­ë áãé¥á⢮¢ âì, ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â FALSE - PROCEDURE DeleteDir(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 áãé¥áâ¢ã¥â + PROCEDURE DirExists(DirName: ARRAY OF CHAR): BOOLEAN + ¢®§¢à é ¥â TRUE, ¥á«¨ ¯ ¯ª  á ¨¬¥­¥¬ DirName áãé¥áâ¢ã¥â ------------------------------------------------------------------------------ MODULE Read - ç⥭¨¥ ®á­®¢­ëå ⨯®¢ ¤ ­­ëå ¨§ ä ©«  F - à®æ¥¤ãàë ¢®§¢à é îâ TRUE ¢ á«ãç ¥ ãᯥ譮© ®¯¥à æ¨¨ ç⥭¨ï ¨ - ᮮ⢥âáâ¢ãî騬 ®¡à §®¬ ¨§¬¥­ïîâ ¯®§¨æ¨î ç⥭¨ï/§ ¯¨á¨ ¢ - ¨­ä®à¬ æ¨®­­®© áâàãªâãॠF + à®æ¥¤ãàë ¢®§¢à é îâ TRUE ¢ á«ãç ¥ ãᯥ譮© ®¯¥à æ¨¨ ç⥭¨ï ¨ + ᮮ⢥âáâ¢ãî騬 ®¡à §®¬ ¨§¬¥­ïîâ ¯®§¨æ¨î ç⥭¨ï/§ ¯¨á¨ ¢ + ¨­ä®à¬ æ¨®­­®© áâàãªâãॠF - PROCEDURE Char(F: File.FS; VAR x: CHAR): BOOLEAN + PROCEDURE Char(F: File.FS; VAR x: CHAR): BOOLEAN - PROCEDURE Int(F: File.FS; VAR x: INTEGER): BOOLEAN + PROCEDURE Int(F: File.FS; VAR x: INTEGER): BOOLEAN - PROCEDURE Real(F: File.FS; VAR x: REAL): BOOLEAN + PROCEDURE Real(F: File.FS; VAR x: REAL): BOOLEAN - PROCEDURE Boolean(F: File.FS; VAR x: BOOLEAN): BOOLEAN + PROCEDURE Boolean(F: File.FS; VAR x: BOOLEAN): BOOLEAN - PROCEDURE Set(F: File.FS; VAR x: SET): BOOLEAN + PROCEDURE Set(F: File.FS; VAR x: SET): BOOLEAN - PROCEDURE Card16(F: File.FS; VAR x: SYSTEM.CARD16): BOOLEAN + PROCEDURE Card16(F: File.FS; VAR x: SYSTEM.CARD16): BOOLEAN ------------------------------------------------------------------------------ MODULE Write - § ¯¨áì ®á­®¢­ëå ⨯®¢ ¤ ­­ëå ¢ ä ©« F - à®æ¥¤ãàë ¢®§¢à é îâ TRUE ¢ á«ãç ¥ ãᯥ譮© ®¯¥à æ¨¨ § ¯¨á¨ ¨ - ᮮ⢥âáâ¢ãî騬 ®¡à §®¬ ¨§¬¥­ïîâ ¯®§¨æ¨î ç⥭¨ï/§ ¯¨á¨ ¢ - ¨­ä®à¬ æ¨®­­®© áâàãªâãॠF + à®æ¥¤ãàë ¢®§¢à é îâ TRUE ¢ á«ãç ¥ ãᯥ譮© ®¯¥à æ¨¨ § ¯¨á¨ ¨ + ᮮ⢥âáâ¢ãî騬 ®¡à §®¬ ¨§¬¥­ïîâ ¯®§¨æ¨î ç⥭¨ï/§ ¯¨á¨ ¢ + ¨­ä®à¬ æ¨®­­®© áâàãªâãॠF - PROCEDURE Char(F: File.FS; x: CHAR): BOOLEAN + PROCEDURE Char(F: File.FS; x: CHAR): BOOLEAN - PROCEDURE Int(F: File.FS; x: INTEGER): BOOLEAN + PROCEDURE Int(F: File.FS; x: INTEGER): BOOLEAN - PROCEDURE Real(F: File.FS; x: REAL): BOOLEAN + PROCEDURE Real(F: File.FS; x: REAL): BOOLEAN - PROCEDURE Boolean(F: File.FS; x: BOOLEAN): BOOLEAN + PROCEDURE Boolean(F: File.FS; x: BOOLEAN): BOOLEAN - PROCEDURE Set(F: File.FS; x: SET): BOOLEAN + PROCEDURE Set(F: File.FS; x: SET): BOOLEAN - PROCEDURE Card16(F: File.FS; x: SYSTEM.CARD16): BOOLEAN + PROCEDURE Card16(F: File.FS; x: SYSTEM.CARD16): BOOLEAN ------------------------------------------------------------------------------ MODULE DateTime - ¤ â , ¢à¥¬ï - CONST ERR = -7.0E5 + CONST ERR = -7.0E5 - PROCEDURE Now(VAR Year, Month, Day, Hour, Min, Sec: INTEGER) - § ¯¨á뢠¥â ¢ ¯ à ¬¥âàë ª®¬¯®­¥­âë ⥪ã饩 á¨á⥬­®© ¤ âë ¨ - ¢à¥¬¥­¨ + 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.0D5 + 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 + 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 - ª®«¨ç¥á⢮ ¯ à ¬¥â஢ ¯à®£à ¬¬ë, ¢ª«îç ï ¨¬ï - ¨á¯®«­ï¥¬®£® ä ©«  + VAR argc: INTEGER + ª®«¨ç¥á⢮ ¯ à ¬¥â஢ ¯à®£à ¬¬ë, ¢ª«îç ï ¨¬ï + ¨á¯®«­ï¥¬®£® ä ©«  - PROCEDURE GetArg(n: INTEGER; VAR s: ARRAY OF CHAR) - § ¯¨á뢠¥â ¢ áâபã s n-© ¯ à ¬¥âà ¯à®£à ¬¬ë, - ­ã¬¥à æ¨ï ¯ à ¬¥â஢ ®â 0 ¤® argc - 1, - ­ã«¥¢®© ¯ à ¬¥âà -- ¨¬ï ¨á¯®«­ï¥¬®£® ä ©«  + 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 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 sysfunc22(arg1, arg2: INTEGER; VAR res2: INTEGER): INTEGER + Ž¡¥à⪠ ¤«ï ä㭪権 API ï¤à  KolibriOS. + arg1 - ॣ¨áâà eax, arg2 - ॣ¨áâà ebx, + res2 - §­ ç¥­¨¥ ॣ¨áâà  ebx ¯®á«¥ á¨á⥬­®£® ¢ë§®¢ ; + ¢®§¢à é ¥â §­ ç¥­¨¥ ॣ¨áâà  eax ¯®á«¥ á¨á⥬­®£® ¢ë§®¢ . - PROCEDURE malloc(size: INTEGER): INTEGER - ‚뤥«ï¥â ¡«®ª ¯ ¬ïâ¨. - size - à §¬¥à ¡«®ª  ¢ ¡ ©â å, - ¢®§¢à é ¥â  ¤à¥á ¢ë¤¥«¥­­®£® ¡«®ª  + PROCEDURE malloc(size: INTEGER): INTEGER + ‚뤥«ï¥â ¡«®ª ¯ ¬ïâ¨. + size - à §¬¥à ¡«®ª  ¢ ¡ ©â å, + ¢®§¢à é ¥â  ¤à¥á ¢ë¤¥«¥­­®£® ¡«®ª  - PROCEDURE free(ptr: INTEGER): INTEGER - Žá¢®¡®¦¤ ¥â à ­¥¥ ¢ë¤¥«¥­­ë© ¡«®ª ¯ ¬ïâ¨ á  ¤à¥á®¬ ptr, - ¢®§¢à é ¥â 0 + PROCEDURE free(ptr: INTEGER): INTEGER + Žá¢®¡®¦¤ ¥â à ­¥¥ ¢ë¤¥«¥­­ë© ¡«®ª ¯ ¬ïâ¨ á  ¤à¥á®¬ ptr, + ¢®§¢à é ¥â 0 - PROCEDURE realloc(ptr, size: INTEGER): INTEGER - ¥à¥à á¯à¥¤¥«ï¥â ¡«®ª ¯ ¬ïâ¨, - ptr -  ¤à¥á à ­¥¥ ¢ë¤¥«¥­­®£® ¡«®ª , - size - ­®¢ë© à §¬¥à, - ¢®§¢à é ¥â 㪠§ â¥«ì ­  ¯¥à¥à á¯à¥¤¥«¥­­ë© ¡«®ª, - 0 ¯à¨ ®è¨¡ª¥ + PROCEDURE realloc(ptr, size: INTEGER): INTEGER + ¥à¥à á¯à¥¤¥«ï¥â ¡«®ª ¯ ¬ïâ¨, + ptr -  ¤à¥á à ­¥¥ ¢ë¤¥«¥­­®£® ¡«®ª , + size - ­®¢ë© à §¬¥à, + ¢®§¢à é ¥â 㪠§ â¥«ì ­  ¯¥à¥à á¯à¥¤¥«¥­­ë© ¡«®ª, + 0 ¯à¨ ®è¨¡ª¥ - PROCEDURE GetCommandLine(): INTEGER - ‚®§¢à é ¥â  ¤à¥á áâப¨ ¯ à ¬¥â஢ + PROCEDURE GetCommandLine(): INTEGER + ‚®§¢à é ¥â  ¤à¥á áâப¨ ¯ à ¬¥â஢ - PROCEDURE GetName(): INTEGER - ‚®§¢à é ¥â  ¤à¥á áâப¨ á ¨¬¥­¥¬ ¯à®£à ¬¬ë + PROCEDURE GetName(): INTEGER + ‚®§¢à é ¥â  ¤à¥á áâப¨ á ¨¬¥­¥¬ ¯à®£à ¬¬ë - PROCEDURE LoadLib(name: ARRAY OF CHAR): INTEGER - ‡ £à㦠¥â DLL á ¯®«­ë¬ ¨¬¥­¥¬ name. ‚®§¢à é ¥â  ¤à¥á â ¡«¨æë - íªá¯®àâ . ਠ®è¨¡ª¥ ¢®§¢à é ¥â 0. + PROCEDURE LoadLib(name: ARRAY OF CHAR): INTEGER + ‡ £à㦠¥â DLL á ¯®«­ë¬ ¨¬¥­¥¬ name. ‚®§¢à é ¥â  ¤à¥á â ¡«¨æë + íªá¯®àâ . ਠ®è¨¡ª¥ ¢®§¢à é ¥â 0. - PROCEDURE GetProcAdr(name: ARRAY OF CHAR; lib: INTEGER): INTEGER - name - ¨¬ï ¯à®æ¥¤ãàë - lib -  ¤à¥á â ¡«¨æë íªá¯®àâ  DLL - ‚®§¢à é ¥â  ¤à¥á ¯à®æ¥¤ãàë. ਠ®è¨¡ª¥ ¢®§¢à é ¥â 0. + PROCEDURE GetProcAdr(name: ARRAY OF CHAR; lib: INTEGER): INTEGER + name - ¨¬ï ¯à®æ¥¤ãàë + lib -  ¤à¥á â ¡«¨æë íªá¯®àâ  DLL + ‚®§¢à é ¥â  ¤à¥á ¯à®æ¥¤ãàë. ਠ®è¨¡ª¥ ¢®§¢à é ¥â 0. ------------------------------------------------------------------------------ MODULE ColorDlg - à ¡®â  á ¤¨ «®£®¬ "Color Dialog" - TYPE + TYPE - Dialog = POINTER TO RECORD (* áâàãªâãà  ¤¨ «®£  *) - status: INTEGER (* á®áâ®ï­¨¥ ¤¨ «®£ : - 0 - ¯®«ì§®¢ â¥«ì ­ ¦ « Cancel - 1 - ¯®«ì§®¢ â¥«ì ­ ¦ « OK - 2 - ¤¨ «®£ ®âªàëâ *) + Dialog = POINTER TO RECORD (* áâàãªâãà  ¤¨ «®£  *) + status: INTEGER (* á®áâ®ï­¨¥ ¤¨ «®£ : + 0 - ¯®«ì§®¢ â¥«ì ­ ¦ « Cancel + 1 - ¯®«ì§®¢ â¥«ì ­ ¦ « OK + 2 - ¤¨ «®£ ®âªàëâ *) - color: INTEGER (* ¢ë¡à ­­ë© 梥â *) - END + color: INTEGER (* ¢ë¡à ­­ë© 梥â *) + END - PROCEDURE Create(draw_window: DRAW_WINDOW): Dialog - ᮧ¤ âì ¤¨ «®£ - draw_window - ¯à®æ¥¤ãà  ¯¥à¥à¨á®¢ª¨ ®á­®¢­®£® ®ª­  - (TYPE DRAW_WINDOW = PROCEDURE); - ¯à®æ¥¤ãà  ¢®§¢à é ¥â 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  + PROCEDURE Create(draw_window: DRAW_WINDOW): Dialog + ᮧ¤ âì ¤¨ «®£ + draw_window - ¯à®æ¥¤ãà  ¯¥à¥à¨á®¢ª¨ ®á­®¢­®£® ®ª­  + (TYPE DRAW_WINDOW = PROCEDURE); + ¯à®æ¥¤ãà  ¢®§¢à é ¥â 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  - PROCEDURE Show(cd: Dialog) - ¯®ª § âì ¤¨ «®£ - cd - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£ , ª®â®àë© ¡ë« ᮧ¤ ­ à ­¥¥ - ¯à®æ¥¤ãன Create + PROCEDURE Show(cd: Dialog) + ¯®ª § âì ¤¨ «®£ + cd - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£ , ª®â®àë© ¡ë« ᮧ¤ ­ à ­¥¥ + ¯à®æ¥¤ãன Create - PROCEDURE Destroy(VAR cd: Dialog) - ã­¨ç⮦¨âì ¤¨ «®£ - cd - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  + PROCEDURE Destroy(VAR cd: Dialog) + ã­¨ç⮦¨âì ¤¨ «®£ + cd - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  ------------------------------------------------------------------------------ MODULE OpenDlg - à ¡®â  á ¤¨ «®£®¬ "Open Dialog" - TYPE + TYPE - Dialog = POINTER TO RECORD (* áâàãªâãà  ¤¨ «®£  *) - status: INTEGER (* á®áâ®ï­¨¥ ¤¨ «®£ : - 0 - ¯®«ì§®¢ â¥«ì ­ ¦ « Cancel - 1 - ¯®«ì§®¢ â¥«ì ­ ¦ « OK - 2 - ¤¨ «®£ ®âªàëâ *) + Dialog = POINTER TO RECORD (* áâàãªâãà  ¤¨ «®£  *) + status: INTEGER (* á®áâ®ï­¨¥ ¤¨ «®£ : + 0 - ¯®«ì§®¢ â¥«ì ­ ¦ « Cancel + 1 - ¯®«ì§®¢ â¥«ì ­ ¦ « OK + 2 - ¤¨ «®£ ®âªàëâ *) - FileName: ARRAY 4096 OF CHAR (* ¨¬ï ¢ë¡à ­­®£® ä ©«  *) - FilePath: ARRAY 4096 OF CHAR (* ¯®«­®¥ ¨¬ï ¢ë¡à ­­®£® - ä ©«  *) - END + 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 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 Show(od: Dialog; Width, Height: INTEGER) + ¯®ª § âì ¤¨ «®£ + od - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£ , ª®â®àë© ¡ë« ᮧ¤ ­ à ­¥¥ + ¯à®æ¥¤ãன Create + Width ¨ Height - è¨à¨­  ¨ ¢ëá®â  ¤¨ «®£®¢®£® ®ª­  - PROCEDURE Destroy(VAR od: Dialog) - ã­¨ç⮦¨âì ¤¨ «®£ - od - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  + PROCEDURE Destroy(VAR od: Dialog) + ã­¨ç⮦¨âì ¤¨ «®£ + od - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  ------------------------------------------------------------------------------ MODULE kfonts - à ¡®â  á kf-èà¨äâ ¬¨ - CONST + CONST - bold = 1 - italic = 2 - underline = 4 - strike_through = 8 - smoothing = 16 - bpp32 = 32 + bold = 1 + italic = 2 + underline = 4 + strike_through = 8 + smoothing = 16 + bpp32 = 32 - TYPE + TYPE - TFont = POINTER TO TFont_desc (* 㪠§ â¥«ì ­  èà¨äâ *) + TFont = POINTER TO TFont_desc (* 㪠§ â¥«ì ­  èà¨äâ *) - PROCEDURE LoadFont(file_name: ARRAY OF CHAR): TFont - § £à㧨âì èà¨äâ ¨§ ä ©«  - file_name ¨¬ï kf-ä ©«  - १-â: 㪠§ â¥«ì ­  èà¨äâ/NIL (®è¨¡ª ) + 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 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 Enabled(Font: TFont; font_size: INTEGER): BOOLEAN + ¯à®¢¥à¨âì, ¥áâì «¨ èà¨äâ, § ¤ ­­®£® à §¬¥à  + Font 㪠§ â¥«ì ­  èà¨äâ + font_size à §¬¥à èà¨äâ  + १-â: TRUE/FALSE (èà¨äâ  ­¥â) - PROCEDURE Destroy(VAR Font: TFont) - ¢ë£à㧨âì èà¨äâ, ®á¢®¡®¤¨âì ¤¨­ ¬¨ç¥áªãî ¯ ¬ïâì - Font 㪠§ â¥«ì ­  èà¨äâ - à¨á¢ ¨¢ ¥â ¯¥à¥¬¥­­®© Font §­ ç¥­¨¥ NIL + PROCEDURE Destroy(VAR Font: TFont) + ¢ë£à㧨âì èà¨äâ, ®á¢®¡®¤¨âì ¤¨­ ¬¨ç¥áªãî ¯ ¬ïâì + Font 㪠§ â¥«ì ­  èà¨äâ + à¨á¢ ¨¢ ¥â ¯¥à¥¬¥­­®© Font §­ ç¥­¨¥ NIL - PROCEDURE TextHeight(Font: TFont): INTEGER - ¯®«ãç¨âì ¢ëá®âã áâப¨ ⥪áâ  - Font 㪠§ â¥«ì ­  èà¨äâ - १-â: ¢ëá®â  áâப¨ ⥪áâ  ¢ ¯¨ªá¥«ïå + PROCEDURE TextHeight(Font: TFont): INTEGER + ¯®«ãç¨âì ¢ëá®âã áâப¨ ⥪áâ  + Font 㪠§ â¥«ì ­  èà¨äâ + १-â: ¢ëá®â  áâப¨ ⥪áâ  ¢ ¯¨ªá¥«ïå - PROCEDURE TextWidth(Font: TFont; - str, length, params: INTEGER): INTEGER - ¯®«ãç¨âì è¨à¨­ã áâப¨ ⥪áâ  - Font 㪠§ â¥«ì ­  èà¨äâ - str  ¤à¥á áâப¨ ⥪áâ  ¢ ª®¤¨à®¢ª¥ Win-1251 - length ª®«¨ç¥á⢮ ᨬ¢®«®¢ ¢ áâப¥ ¨«¨ -1, ¥á«¨ áâப  - § ¢¥àè ¥âáï ­ã«¥¬ - params ¯ à ¬¥âàë-ä« £¨ á¬. ­¨¦¥ - १-â: è¨à¨­  áâப¨ ⥪áâ  ¢ ¯¨ªá¥«ïå + 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-¡¨â­ë© ¡ãä¥à - ¢®§¬®¦­® ¨á¯®«ì§®¢ ­¨¥ ä« £®¢ ¢ «î¡ëå á®ç¥â ­¨ïå + 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 ------------------------------------------------------------------------------ diff --git a/programs/develop/oberon07/Lib/KolibriOS/File.ob07 b/programs/develop/oberon07/Lib/KolibriOS/File.ob07 index 729c365a9f..d25a8d6938 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/File.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/File.ob07 @@ -17,7 +17,7 @@ MODULE File; -IMPORT sys := SYSTEM, KOSAPI; +IMPORT sys := SYSTEM, KOSAPI; CONST @@ -47,7 +47,7 @@ TYPE time_modif*, date_modif*, size*, hsize*: INTEGER; name*: FNAME - END; + END; PROCEDURE [stdcall] f_68_27 (file_name: INTEGER; VAR size: INTEGER): INTEGER; @@ -67,7 +67,7 @@ BEGIN 0C2H, 008H, 000H (* ret 8 *) ) RETURN 0 -END f_68_27; +END f_68_27; PROCEDURE Load* (FName: ARRAY OF CHAR; VAR size: INTEGER): INTEGER; @@ -77,7 +77,7 @@ END Load; PROCEDURE GetFileInfo* (FName: ARRAY OF CHAR; VAR Info: rFD): BOOLEAN; VAR - res2: INTEGER; fs: rFS; + res2: INTEGER; fs: rFS; BEGIN fs.subfunc := 5; @@ -88,7 +88,7 @@ BEGIN COPY(FName, fs.name) RETURN KOSAPI.sysfunc22(70, sys.ADR(fs), res2) = 0 -END GetFileInfo; +END GetFileInfo; PROCEDURE Exists* (FName: ARRAY OF CHAR): BOOLEAN; @@ -97,7 +97,7 @@ VAR BEGIN RETURN GetFileInfo(FName, fd) & ~(4 IN BITS(fd.attr)) END Exists; - + PROCEDURE Close* (VAR F: FS); BEGIN @@ -109,9 +109,9 @@ END Close; PROCEDURE Open* (FName: ARRAY OF CHAR): FS; VAR - F: FS; + F: FS; -BEGIN +BEGIN IF Exists(FName) THEN NEW(F); @@ -128,7 +128,7 @@ BEGIN END RETURN F -END Open; +END Open; PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; @@ -158,7 +158,7 @@ BEGIN RETURN res = 0 END Delete; - + PROCEDURE Seek* (F: FS; Offset, Origin: INTEGER): INTEGER; VAR @@ -202,7 +202,7 @@ BEGIN END RETURN res2 -END Read; +END Read; PROCEDURE Write* (F: FS; Buffer, Count: INTEGER): INTEGER; @@ -225,7 +225,7 @@ BEGIN RETURN res2 END Write; - + PROCEDURE Create* (FName: ARRAY OF CHAR): FS; VAR @@ -249,14 +249,14 @@ BEGIN 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; +END DirExists; PROCEDURE CreateDir* (DirName: ARRAY OF CHAR): BOOLEAN; @@ -282,7 +282,7 @@ BEGIN RETURN res = 0 END CreateDir; - + PROCEDURE DeleteDir* (DirName: ARRAY OF CHAR): BOOLEAN; VAR diff --git a/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 index 6031e758ee..b1fe62acc0 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 @@ -1,5 +1,5 @@ (* - Copyright 2013, 2014, 2018 Anton Krotov + Copyright 2013, 2014, 2018, 2019 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 @@ -167,10 +167,10 @@ END ln; PROCEDURE [stdcall] log* (base, x: REAL): REAL; -BEGIN +BEGIN SYSTEM.CODE( 0D9H, 0E8H, (* fld1 *) - 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) + 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) 0D9H, 0F1H, (* fyl2x *) 0D9H, 0E8H, (* fld1 *) 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) @@ -251,58 +251,45 @@ END arctan; PROCEDURE sinh* (x: REAL): REAL; -VAR - res: REAL; - BEGIN - IF IsZero(x) THEN - res := 0.0 - ELSE - res := (exp(x) - exp(-x)) / 2.0 - END - RETURN res + x := exp(x) + RETURN (x - 1.0 / x) * 0.5 END sinh; PROCEDURE cosh* (x: REAL): REAL; -VAR - res: REAL; - BEGIN - IF IsZero(x) THEN - res := 1.0 - ELSE - res := (exp(x) + exp(-x)) / 2.0 - END - RETURN res + x := exp(x) + RETURN (x + 1.0 / x) * 0.5 END cosh; PROCEDURE tanh* (x: REAL): REAL; -VAR - res: REAL; - BEGIN - IF IsZero(x) THEN - res := 0.0 + IF x > 15.0 THEN + x := 1.0 + ELSIF x < -15.0 THEN + x := -1.0 ELSE - res := sinh(x) / cosh(x) + x := exp(2.0 * x); + x := (x - 1.0) / (x + 1.0) END - RETURN res + + RETURN x END tanh; -PROCEDURE arcsinh* (x: REAL): REAL; - RETURN ln(x + sqrt((x * x) + 1.0)) -END arcsinh; +PROCEDURE arsinh* (x: REAL): REAL; + RETURN ln(x + sqrt(x * x + 1.0)) +END arsinh; -PROCEDURE arccosh* (x: REAL): REAL; - RETURN ln(x + sqrt((x - 1.0) / (x + 1.0)) * (x + 1.0)) -END arccosh; +PROCEDURE arcosh* (x: REAL): REAL; + RETURN ln(x + sqrt(x * x - 1.0)) +END arcosh; -PROCEDURE arctanh* (x: REAL): REAL; +PROCEDURE artanh* (x: REAL): REAL; VAR res: REAL; @@ -315,7 +302,7 @@ BEGIN res := 0.5 * ln((1.0 + x) / (1.0 - x)) END RETURN res -END arctanh; +END artanh; PROCEDURE floor* (x: REAL): REAL; @@ -374,8 +361,24 @@ BEGIN 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; + 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 index 9ed2bfacdb..c0ed629f9c 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/NetDevices.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/NetDevices.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2017 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -24,18 +24,18 @@ CONST //net devices types - LOOPBACK* = 0; - ETH* = 1; - SLIP* = 2; + LOOPBACK* = 0; + ETH* = 1; + SLIP* = 2; //Link status - LINK_DOWN* = 0; + LINK_DOWN* = 0; LINK_UNKNOWN* = 1; - LINK_FD* = 2; //full duplex flag - LINK_10M* = 4; - LINK_100M* = 8; - LINK_1G* = 12; + LINK_FD* = 2; //full duplex flag + LINK_10M* = 4; + LINK_100M* = 8; + LINK_1G* = 12; TYPE diff --git a/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 b/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 index 2758c1e417..0a33a3269c 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 @@ -10,7 +10,7 @@ MODULE RTL; IMPORT SYSTEM, API; -CONST +CONST bit_depth* = 32; maxint* = 7FFFFFFFH; @@ -22,11 +22,13 @@ CONST DLL_PROCESS_DETACH = 0; SIZE_OF_DWORD = 4; + MAX_SET = 31; TYPE DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); + PROC = PROCEDURE; VAR @@ -40,6 +42,8 @@ VAR thread_attach: DLL_ENTRY END; + fini: PROC; + PROCEDURE [stdcall] _move* (bytes, source, dest: INTEGER); BEGIN @@ -107,18 +111,12 @@ BEGIN END _arrcpy; -PROCEDURE [stdcall] _strcpy* (chr_size, len_dst, dst, len_src, src: INTEGER); +PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); BEGIN _move(MIN(len_dst, len_src) * chr_size, src, dst) END _strcpy; -PROCEDURE [stdcall] _strcpy2* (chr_size, len_src, src, len_dst, dst: INTEGER); -BEGIN - _move(MIN(len_dst, len_src) * chr_size, src, dst) -END _strcpy2; - - PROCEDURE [stdcall] _rot* (VAR A: ARRAY OF INTEGER); VAR i, n, k: INTEGER; @@ -137,32 +135,29 @@ BEGIN END _rot; -PROCEDURE [stdcall] _set2* (a, b: INTEGER): INTEGER; -VAR - res: INTEGER; - +PROCEDURE [stdcall] _set* (b, a: INTEGER): INTEGER; BEGIN - IF (a <= b) & (a <= 31) & (b >= 0) THEN - IF b > 31 THEN - b := 31 + IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN + IF b > MAX_SET THEN + b := MAX_SET END; IF a < 0 THEN a := 0 END; - res := LSR(ASR(ROR(1, 1), b - a), 31 - b) + a := LSR(ASR(ROR(1, 1), b - a), MAX_SET - b) ELSE - res := 0 + a := 0 END - RETURN res -END _set2; - - -PROCEDURE [stdcall] _set* (b, a: INTEGER): INTEGER; - RETURN _set2(a, b) + RETURN a END _set; +PROCEDURE [stdcall] _set2* (a, b: INTEGER): INTEGER; + RETURN _set(b, a) +END _set2; + + PROCEDURE [stdcall] divmod (a, b: INTEGER; VAR mod: INTEGER): INTEGER; BEGIN SYSTEM.CODE( @@ -185,7 +180,7 @@ BEGIN END divmod; -PROCEDURE div_ (x, y: INTEGER): INTEGER; +PROCEDURE [stdcall] _div2* (x, y: INTEGER): INTEGER; VAR div, mod: INTEGER; @@ -196,10 +191,10 @@ BEGIN END RETURN div -END div_; +END _div2; -PROCEDURE mod_ (x, y: INTEGER): INTEGER; +PROCEDURE [stdcall] _mod2* (x, y: INTEGER): INTEGER; VAR div, mod: INTEGER; @@ -210,29 +205,19 @@ BEGIN END RETURN mod -END mod_; +END _mod2; PROCEDURE [stdcall] _div* (b, a: INTEGER): INTEGER; - RETURN div_(a, b) + RETURN _div2(a, b) END _div; -PROCEDURE [stdcall] _div2* (a, b: INTEGER): INTEGER; - RETURN div_(a, b) -END _div2; - - PROCEDURE [stdcall] _mod* (b, a: INTEGER): INTEGER; - RETURN mod_(a, b) + RETURN _mod2(a, b) END _mod; -PROCEDURE [stdcall] _mod2* (a, b: INTEGER): INTEGER; - RETURN mod_(a, b) -END _mod2; - - PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER); BEGIN ptr := API._NEW(size); @@ -251,50 +236,6 @@ BEGIN END _dispose; -PROCEDURE strncmp (a, b, n: INTEGER): INTEGER; -VAR - A, B: CHAR; - res: INTEGER; - -BEGIN - res := 0; - WHILE n > 0 DO - SYSTEM.GET(a, A); INC(a); - SYSTEM.GET(b, B); INC(b); - DEC(n); - IF A # B THEN - res := ORD(A) - ORD(B); - n := 0 - ELSIF A = 0X THEN - n := 0 - END - END - RETURN res -END strncmp; - - -PROCEDURE strncmpw (a, b, n: INTEGER): INTEGER; -VAR - A, B: WCHAR; - res: INTEGER; - -BEGIN - res := 0; - WHILE n > 0 DO - SYSTEM.GET(a, A); INC(a, 2); - SYSTEM.GET(b, B); INC(b, 2); - DEC(n); - IF A # B THEN - res := ORD(A) - ORD(B); - n := 0 - ELSIF A = 0X THEN - n := 0 - END - END - RETURN res -END strncmpw; - - PROCEDURE [stdcall] _length* (len, str: INTEGER): INTEGER; BEGIN SYSTEM.CODE( @@ -345,16 +286,71 @@ BEGIN END _lengthw; +PROCEDURE strncmp (a, b, n: INTEGER): INTEGER; +VAR + A, B: CHAR; + res: INTEGER; + +BEGIN + res := minint; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a); + SYSTEM.GET(b, B); INC(b); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + res := 0; + n := 0 + END + END + RETURN res +END strncmp; + + +PROCEDURE strncmpw (a, b, n: INTEGER): INTEGER; +VAR + A, B: WCHAR; + res: INTEGER; + +BEGIN + res := minint; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a, 2); + SYSTEM.GET(b, B); INC(b, 2); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + res := 0; + n := 0 + END + END + RETURN res +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 = 0 THEN - res := _length(len1, str1) - _length(len2, str2) + 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 @@ -370,21 +366,25 @@ BEGIN END _strcmp; -PROCEDURE [stdcall] _strcmp2* (op, len1, str1, len2, str2: INTEGER): BOOLEAN; - RETURN _strcmp(op, len2, str2, len1, str1) -END _strcmp2; - - 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 = 0 THEN - res := _lengthw(len1, str1) - _lengthw(len2, str2) + 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 @@ -400,11 +400,6 @@ BEGIN END _strcmpw; -PROCEDURE [stdcall] _strcmpw2* (op, len1, str1, len2, str2: INTEGER): BOOLEAN; - RETURN _strcmpw(op, len2, str2, len1, str1) -END _strcmpw2; - - PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); VAR c: CHAR; @@ -470,14 +465,14 @@ BEGIN END append; -PROCEDURE [stdcall] _error* (module, err: INTEGER); +PROCEDURE [stdcall] _error* (module, err, line: INTEGER); VAR s, temp: ARRAY 1024 OF CHAR; BEGIN s := ""; - CASE err MOD 16 OF + CASE err OF | 1: append(s, "assertion failure") | 2: append(s, "NIL dereference") | 3: append(s, "division by zero") @@ -493,8 +488,8 @@ BEGIN append(s, API.eol); - append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); - append(s, "line: "); IntToStr(LSR(err, 4), temp); append(s, temp); + append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); + append(s, "line: "); IntToStr(line, temp); append(s, temp); API.DebugMsg(SYSTEM.ADR(s[0]), name); @@ -502,69 +497,42 @@ BEGIN END _error; -PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): BOOLEAN; +PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): INTEGER; BEGIN - (* r IS t0 *) - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END - - RETURN t1 = t0 + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 END _isrec; -PROCEDURE [stdcall] _is* (t0, p: INTEGER): BOOLEAN; -VAR - t1: INTEGER; - +PROCEDURE [stdcall] _is* (t0, p: INTEGER): INTEGER; BEGIN - (* p IS t0 *) - IF p # 0 THEN - DEC(p, SIZE_OF_DWORD); - SYSTEM.GET(p, t1); - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END - ELSE - t1 := -1 + SYSTEM.GET(p - SIZE_OF_DWORD, p); + SYSTEM.GET(t0 + p + types, p) END - RETURN t1 = t0 + RETURN p MOD 2 END _is; -PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): BOOLEAN; +PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): INTEGER; BEGIN - (* r:t1 IS t0 *) - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END - - RETURN t1 = t0 + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 END _guardrec; -PROCEDURE [stdcall] _guard* (t0, p: INTEGER): BOOLEAN; -VAR - t1: INTEGER; - +PROCEDURE [stdcall] _guard* (t0, p: INTEGER): INTEGER; BEGIN - (* p IS t0 *) SYSTEM.GET(p, p); IF p # 0 THEN - DEC(p, SIZE_OF_DWORD); - SYSTEM.GET(p, t1); - WHILE (t1 # t0) & (t1 # 0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END + SYSTEM.GET(p - SIZE_OF_DWORD, p); + SYSTEM.GET(t0 + p + types, p) ELSE - t1 := t0 + p := 1 END - RETURN t1 = t0 + RETURN p MOD 2 END _guard; @@ -613,18 +581,50 @@ BEGIN END _exit; -PROCEDURE [stdcall] _init* (modname: INTEGER; typesc, _types: INTEGER; code, param: INTEGER); +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 := _types; + 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 * SIZE_OF_DWORD, t1) + END; + + SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) + END + END; + name := modname; dll.process_detach := NIL; dll.thread_detach := NIL; dll.thread_attach := NIL; + + fini := NIL END _init; +PROCEDURE [stdcall] _sofinit*; +BEGIN + IF fini # NIL THEN + fini + END +END _sofinit; + + +PROCEDURE SetFini* (ProcFini: PROC); +BEGIN + fini := ProcFini +END SetFini; + + END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Vector.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Vector.ob07 index 1dc5069bc6..46de391ccd 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Vector.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Vector.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016 Anton Krotov This program is free software: you can redistribute it and/or modify diff --git a/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 b/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 index 339516e58e..9506a44109 100644 --- a/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 @@ -38,16 +38,6 @@ VAR clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; -PROCEDURE dlopen* (filename: ARRAY OF CHAR): INTEGER; - RETURN API.dlopen(SYSTEM.ADR(filename[0]), 1) -END dlopen; - - -PROCEDURE dlsym* (handle: INTEGER; symbol: ARRAY OF CHAR): INTEGER; - RETURN API.dlsym(handle, SYSTEM.ADR(symbol[0])) -END dlsym; - - PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); VAR i, len, ptr: INTEGER; diff --git a/programs/develop/oberon07/Lib/Linux32/RTL.ob07 b/programs/develop/oberon07/Lib/Linux32/RTL.ob07 index 2758c1e417..0a33a3269c 100644 --- a/programs/develop/oberon07/Lib/Linux32/RTL.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/RTL.ob07 @@ -10,7 +10,7 @@ MODULE RTL; IMPORT SYSTEM, API; -CONST +CONST bit_depth* = 32; maxint* = 7FFFFFFFH; @@ -22,11 +22,13 @@ CONST DLL_PROCESS_DETACH = 0; SIZE_OF_DWORD = 4; + MAX_SET = 31; TYPE DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); + PROC = PROCEDURE; VAR @@ -40,6 +42,8 @@ VAR thread_attach: DLL_ENTRY END; + fini: PROC; + PROCEDURE [stdcall] _move* (bytes, source, dest: INTEGER); BEGIN @@ -107,18 +111,12 @@ BEGIN END _arrcpy; -PROCEDURE [stdcall] _strcpy* (chr_size, len_dst, dst, len_src, src: INTEGER); +PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); BEGIN _move(MIN(len_dst, len_src) * chr_size, src, dst) END _strcpy; -PROCEDURE [stdcall] _strcpy2* (chr_size, len_src, src, len_dst, dst: INTEGER); -BEGIN - _move(MIN(len_dst, len_src) * chr_size, src, dst) -END _strcpy2; - - PROCEDURE [stdcall] _rot* (VAR A: ARRAY OF INTEGER); VAR i, n, k: INTEGER; @@ -137,32 +135,29 @@ BEGIN END _rot; -PROCEDURE [stdcall] _set2* (a, b: INTEGER): INTEGER; -VAR - res: INTEGER; - +PROCEDURE [stdcall] _set* (b, a: INTEGER): INTEGER; BEGIN - IF (a <= b) & (a <= 31) & (b >= 0) THEN - IF b > 31 THEN - b := 31 + IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN + IF b > MAX_SET THEN + b := MAX_SET END; IF a < 0 THEN a := 0 END; - res := LSR(ASR(ROR(1, 1), b - a), 31 - b) + a := LSR(ASR(ROR(1, 1), b - a), MAX_SET - b) ELSE - res := 0 + a := 0 END - RETURN res -END _set2; - - -PROCEDURE [stdcall] _set* (b, a: INTEGER): INTEGER; - RETURN _set2(a, b) + RETURN a END _set; +PROCEDURE [stdcall] _set2* (a, b: INTEGER): INTEGER; + RETURN _set(b, a) +END _set2; + + PROCEDURE [stdcall] divmod (a, b: INTEGER; VAR mod: INTEGER): INTEGER; BEGIN SYSTEM.CODE( @@ -185,7 +180,7 @@ BEGIN END divmod; -PROCEDURE div_ (x, y: INTEGER): INTEGER; +PROCEDURE [stdcall] _div2* (x, y: INTEGER): INTEGER; VAR div, mod: INTEGER; @@ -196,10 +191,10 @@ BEGIN END RETURN div -END div_; +END _div2; -PROCEDURE mod_ (x, y: INTEGER): INTEGER; +PROCEDURE [stdcall] _mod2* (x, y: INTEGER): INTEGER; VAR div, mod: INTEGER; @@ -210,29 +205,19 @@ BEGIN END RETURN mod -END mod_; +END _mod2; PROCEDURE [stdcall] _div* (b, a: INTEGER): INTEGER; - RETURN div_(a, b) + RETURN _div2(a, b) END _div; -PROCEDURE [stdcall] _div2* (a, b: INTEGER): INTEGER; - RETURN div_(a, b) -END _div2; - - PROCEDURE [stdcall] _mod* (b, a: INTEGER): INTEGER; - RETURN mod_(a, b) + RETURN _mod2(a, b) END _mod; -PROCEDURE [stdcall] _mod2* (a, b: INTEGER): INTEGER; - RETURN mod_(a, b) -END _mod2; - - PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER); BEGIN ptr := API._NEW(size); @@ -251,50 +236,6 @@ BEGIN END _dispose; -PROCEDURE strncmp (a, b, n: INTEGER): INTEGER; -VAR - A, B: CHAR; - res: INTEGER; - -BEGIN - res := 0; - WHILE n > 0 DO - SYSTEM.GET(a, A); INC(a); - SYSTEM.GET(b, B); INC(b); - DEC(n); - IF A # B THEN - res := ORD(A) - ORD(B); - n := 0 - ELSIF A = 0X THEN - n := 0 - END - END - RETURN res -END strncmp; - - -PROCEDURE strncmpw (a, b, n: INTEGER): INTEGER; -VAR - A, B: WCHAR; - res: INTEGER; - -BEGIN - res := 0; - WHILE n > 0 DO - SYSTEM.GET(a, A); INC(a, 2); - SYSTEM.GET(b, B); INC(b, 2); - DEC(n); - IF A # B THEN - res := ORD(A) - ORD(B); - n := 0 - ELSIF A = 0X THEN - n := 0 - END - END - RETURN res -END strncmpw; - - PROCEDURE [stdcall] _length* (len, str: INTEGER): INTEGER; BEGIN SYSTEM.CODE( @@ -345,16 +286,71 @@ BEGIN END _lengthw; +PROCEDURE strncmp (a, b, n: INTEGER): INTEGER; +VAR + A, B: CHAR; + res: INTEGER; + +BEGIN + res := minint; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a); + SYSTEM.GET(b, B); INC(b); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + res := 0; + n := 0 + END + END + RETURN res +END strncmp; + + +PROCEDURE strncmpw (a, b, n: INTEGER): INTEGER; +VAR + A, B: WCHAR; + res: INTEGER; + +BEGIN + res := minint; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a, 2); + SYSTEM.GET(b, B); INC(b, 2); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + res := 0; + n := 0 + END + END + RETURN res +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 = 0 THEN - res := _length(len1, str1) - _length(len2, str2) + 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 @@ -370,21 +366,25 @@ BEGIN END _strcmp; -PROCEDURE [stdcall] _strcmp2* (op, len1, str1, len2, str2: INTEGER): BOOLEAN; - RETURN _strcmp(op, len2, str2, len1, str1) -END _strcmp2; - - 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 = 0 THEN - res := _lengthw(len1, str1) - _lengthw(len2, str2) + 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 @@ -400,11 +400,6 @@ BEGIN END _strcmpw; -PROCEDURE [stdcall] _strcmpw2* (op, len1, str1, len2, str2: INTEGER): BOOLEAN; - RETURN _strcmpw(op, len2, str2, len1, str1) -END _strcmpw2; - - PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); VAR c: CHAR; @@ -470,14 +465,14 @@ BEGIN END append; -PROCEDURE [stdcall] _error* (module, err: INTEGER); +PROCEDURE [stdcall] _error* (module, err, line: INTEGER); VAR s, temp: ARRAY 1024 OF CHAR; BEGIN s := ""; - CASE err MOD 16 OF + CASE err OF | 1: append(s, "assertion failure") | 2: append(s, "NIL dereference") | 3: append(s, "division by zero") @@ -493,8 +488,8 @@ BEGIN append(s, API.eol); - append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); - append(s, "line: "); IntToStr(LSR(err, 4), temp); append(s, temp); + append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); + append(s, "line: "); IntToStr(line, temp); append(s, temp); API.DebugMsg(SYSTEM.ADR(s[0]), name); @@ -502,69 +497,42 @@ BEGIN END _error; -PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): BOOLEAN; +PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): INTEGER; BEGIN - (* r IS t0 *) - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END - - RETURN t1 = t0 + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 END _isrec; -PROCEDURE [stdcall] _is* (t0, p: INTEGER): BOOLEAN; -VAR - t1: INTEGER; - +PROCEDURE [stdcall] _is* (t0, p: INTEGER): INTEGER; BEGIN - (* p IS t0 *) - IF p # 0 THEN - DEC(p, SIZE_OF_DWORD); - SYSTEM.GET(p, t1); - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END - ELSE - t1 := -1 + SYSTEM.GET(p - SIZE_OF_DWORD, p); + SYSTEM.GET(t0 + p + types, p) END - RETURN t1 = t0 + RETURN p MOD 2 END _is; -PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): BOOLEAN; +PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): INTEGER; BEGIN - (* r:t1 IS t0 *) - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END - - RETURN t1 = t0 + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 END _guardrec; -PROCEDURE [stdcall] _guard* (t0, p: INTEGER): BOOLEAN; -VAR - t1: INTEGER; - +PROCEDURE [stdcall] _guard* (t0, p: INTEGER): INTEGER; BEGIN - (* p IS t0 *) SYSTEM.GET(p, p); IF p # 0 THEN - DEC(p, SIZE_OF_DWORD); - SYSTEM.GET(p, t1); - WHILE (t1 # t0) & (t1 # 0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END + SYSTEM.GET(p - SIZE_OF_DWORD, p); + SYSTEM.GET(t0 + p + types, p) ELSE - t1 := t0 + p := 1 END - RETURN t1 = t0 + RETURN p MOD 2 END _guard; @@ -613,18 +581,50 @@ BEGIN END _exit; -PROCEDURE [stdcall] _init* (modname: INTEGER; typesc, _types: INTEGER; code, param: INTEGER); +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 := _types; + 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 * SIZE_OF_DWORD, t1) + END; + + SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) + END + END; + name := modname; dll.process_detach := NIL; dll.thread_detach := NIL; dll.thread_attach := NIL; + + fini := NIL END _init; +PROCEDURE [stdcall] _sofinit*; +BEGIN + IF fini # NIL THEN + fini + END +END _sofinit; + + +PROCEDURE SetFini* (ProcFini: PROC); +BEGIN + fini := ProcFini +END SetFini; + + END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/API.ob07 b/programs/develop/oberon07/Lib/Windows32/API.ob07 index 07b4226363..588669fa75 100644 --- a/programs/develop/oberon07/Lib/Windows32/API.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/API.ob07 @@ -13,14 +13,16 @@ VAR eol*: ARRAY 3 OF CHAR; base*: INTEGER; + heap: INTEGER; -PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] ExitProcess (code: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "ExitThread"] ExitThread (code: INTEGER); -PROCEDURE [windows-, "kernel32.dll", "GlobalAlloc"] Alloc (uFlags, dwBytes: INTEGER): INTEGER; -PROCEDURE [windows-, "kernel32.dll", "GlobalFree"] Free (hMem: INTEGER): INTEGER; +PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] ExitProcess (code: INTEGER); +PROCEDURE [windows-, "kernel32.dll", "ExitThread"] ExitThread (code: INTEGER); +PROCEDURE [windows-, "kernel32.dll", "GetProcessHeap"] GetProcessHeap (): INTEGER; +PROCEDURE [windows-, "kernel32.dll", "HeapAlloc"] HeapAlloc (hHeap, dwFlags, dwBytes: INTEGER): INTEGER; +PROCEDURE [windows-, "kernel32.dll", "HeapFree"] HeapFree(hHeap, dwFlags, lpMem: INTEGER); -PROCEDURE [windows-, "user32.dll", "MessageBoxA"] MessageBoxA (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; +PROCEDURE [windows-, "user32.dll", "MessageBoxA"] MessageBoxA (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); @@ -30,19 +32,22 @@ END DebugMsg; PROCEDURE _NEW* (size: INTEGER): INTEGER; - RETURN Alloc(64, size) + RETURN HeapAlloc(heap, 8, size) END _NEW; PROCEDURE _DISPOSE* (p: INTEGER): INTEGER; - RETURN Free(p) +BEGIN + HeapFree(heap, 0, p) + RETURN 0 END _DISPOSE; PROCEDURE init* (reserved, code: INTEGER); BEGIN eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; - base := code - 4096 + base := code - 4096; + heap := GetProcessHeap() END init; diff --git a/programs/develop/oberon07/Lib/Windows32/RTL.ob07 b/programs/develop/oberon07/Lib/Windows32/RTL.ob07 index 2758c1e417..0a33a3269c 100644 --- a/programs/develop/oberon07/Lib/Windows32/RTL.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/RTL.ob07 @@ -10,7 +10,7 @@ MODULE RTL; IMPORT SYSTEM, API; -CONST +CONST bit_depth* = 32; maxint* = 7FFFFFFFH; @@ -22,11 +22,13 @@ CONST DLL_PROCESS_DETACH = 0; SIZE_OF_DWORD = 4; + MAX_SET = 31; TYPE DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); + PROC = PROCEDURE; VAR @@ -40,6 +42,8 @@ VAR thread_attach: DLL_ENTRY END; + fini: PROC; + PROCEDURE [stdcall] _move* (bytes, source, dest: INTEGER); BEGIN @@ -107,18 +111,12 @@ BEGIN END _arrcpy; -PROCEDURE [stdcall] _strcpy* (chr_size, len_dst, dst, len_src, src: INTEGER); +PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); BEGIN _move(MIN(len_dst, len_src) * chr_size, src, dst) END _strcpy; -PROCEDURE [stdcall] _strcpy2* (chr_size, len_src, src, len_dst, dst: INTEGER); -BEGIN - _move(MIN(len_dst, len_src) * chr_size, src, dst) -END _strcpy2; - - PROCEDURE [stdcall] _rot* (VAR A: ARRAY OF INTEGER); VAR i, n, k: INTEGER; @@ -137,32 +135,29 @@ BEGIN END _rot; -PROCEDURE [stdcall] _set2* (a, b: INTEGER): INTEGER; -VAR - res: INTEGER; - +PROCEDURE [stdcall] _set* (b, a: INTEGER): INTEGER; BEGIN - IF (a <= b) & (a <= 31) & (b >= 0) THEN - IF b > 31 THEN - b := 31 + IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN + IF b > MAX_SET THEN + b := MAX_SET END; IF a < 0 THEN a := 0 END; - res := LSR(ASR(ROR(1, 1), b - a), 31 - b) + a := LSR(ASR(ROR(1, 1), b - a), MAX_SET - b) ELSE - res := 0 + a := 0 END - RETURN res -END _set2; - - -PROCEDURE [stdcall] _set* (b, a: INTEGER): INTEGER; - RETURN _set2(a, b) + RETURN a END _set; +PROCEDURE [stdcall] _set2* (a, b: INTEGER): INTEGER; + RETURN _set(b, a) +END _set2; + + PROCEDURE [stdcall] divmod (a, b: INTEGER; VAR mod: INTEGER): INTEGER; BEGIN SYSTEM.CODE( @@ -185,7 +180,7 @@ BEGIN END divmod; -PROCEDURE div_ (x, y: INTEGER): INTEGER; +PROCEDURE [stdcall] _div2* (x, y: INTEGER): INTEGER; VAR div, mod: INTEGER; @@ -196,10 +191,10 @@ BEGIN END RETURN div -END div_; +END _div2; -PROCEDURE mod_ (x, y: INTEGER): INTEGER; +PROCEDURE [stdcall] _mod2* (x, y: INTEGER): INTEGER; VAR div, mod: INTEGER; @@ -210,29 +205,19 @@ BEGIN END RETURN mod -END mod_; +END _mod2; PROCEDURE [stdcall] _div* (b, a: INTEGER): INTEGER; - RETURN div_(a, b) + RETURN _div2(a, b) END _div; -PROCEDURE [stdcall] _div2* (a, b: INTEGER): INTEGER; - RETURN div_(a, b) -END _div2; - - PROCEDURE [stdcall] _mod* (b, a: INTEGER): INTEGER; - RETURN mod_(a, b) + RETURN _mod2(a, b) END _mod; -PROCEDURE [stdcall] _mod2* (a, b: INTEGER): INTEGER; - RETURN mod_(a, b) -END _mod2; - - PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER); BEGIN ptr := API._NEW(size); @@ -251,50 +236,6 @@ BEGIN END _dispose; -PROCEDURE strncmp (a, b, n: INTEGER): INTEGER; -VAR - A, B: CHAR; - res: INTEGER; - -BEGIN - res := 0; - WHILE n > 0 DO - SYSTEM.GET(a, A); INC(a); - SYSTEM.GET(b, B); INC(b); - DEC(n); - IF A # B THEN - res := ORD(A) - ORD(B); - n := 0 - ELSIF A = 0X THEN - n := 0 - END - END - RETURN res -END strncmp; - - -PROCEDURE strncmpw (a, b, n: INTEGER): INTEGER; -VAR - A, B: WCHAR; - res: INTEGER; - -BEGIN - res := 0; - WHILE n > 0 DO - SYSTEM.GET(a, A); INC(a, 2); - SYSTEM.GET(b, B); INC(b, 2); - DEC(n); - IF A # B THEN - res := ORD(A) - ORD(B); - n := 0 - ELSIF A = 0X THEN - n := 0 - END - END - RETURN res -END strncmpw; - - PROCEDURE [stdcall] _length* (len, str: INTEGER): INTEGER; BEGIN SYSTEM.CODE( @@ -345,16 +286,71 @@ BEGIN END _lengthw; +PROCEDURE strncmp (a, b, n: INTEGER): INTEGER; +VAR + A, B: CHAR; + res: INTEGER; + +BEGIN + res := minint; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a); + SYSTEM.GET(b, B); INC(b); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + res := 0; + n := 0 + END + END + RETURN res +END strncmp; + + +PROCEDURE strncmpw (a, b, n: INTEGER): INTEGER; +VAR + A, B: WCHAR; + res: INTEGER; + +BEGIN + res := minint; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a, 2); + SYSTEM.GET(b, B); INC(b, 2); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + res := 0; + n := 0 + END + END + RETURN res +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 = 0 THEN - res := _length(len1, str1) - _length(len2, str2) + 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 @@ -370,21 +366,25 @@ BEGIN END _strcmp; -PROCEDURE [stdcall] _strcmp2* (op, len1, str1, len2, str2: INTEGER): BOOLEAN; - RETURN _strcmp(op, len2, str2, len1, str1) -END _strcmp2; - - 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 = 0 THEN - res := _lengthw(len1, str1) - _lengthw(len2, str2) + 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 @@ -400,11 +400,6 @@ BEGIN END _strcmpw; -PROCEDURE [stdcall] _strcmpw2* (op, len1, str1, len2, str2: INTEGER): BOOLEAN; - RETURN _strcmpw(op, len2, str2, len1, str1) -END _strcmpw2; - - PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); VAR c: CHAR; @@ -470,14 +465,14 @@ BEGIN END append; -PROCEDURE [stdcall] _error* (module, err: INTEGER); +PROCEDURE [stdcall] _error* (module, err, line: INTEGER); VAR s, temp: ARRAY 1024 OF CHAR; BEGIN s := ""; - CASE err MOD 16 OF + CASE err OF | 1: append(s, "assertion failure") | 2: append(s, "NIL dereference") | 3: append(s, "division by zero") @@ -493,8 +488,8 @@ BEGIN append(s, API.eol); - append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); - append(s, "line: "); IntToStr(LSR(err, 4), temp); append(s, temp); + append(s, "module: "); PCharToStr(module, temp); append(s, temp); append(s, API.eol); + append(s, "line: "); IntToStr(line, temp); append(s, temp); API.DebugMsg(SYSTEM.ADR(s[0]), name); @@ -502,69 +497,42 @@ BEGIN END _error; -PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): BOOLEAN; +PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): INTEGER; BEGIN - (* r IS t0 *) - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END - - RETURN t1 = t0 + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 END _isrec; -PROCEDURE [stdcall] _is* (t0, p: INTEGER): BOOLEAN; -VAR - t1: INTEGER; - +PROCEDURE [stdcall] _is* (t0, p: INTEGER): INTEGER; BEGIN - (* p IS t0 *) - IF p # 0 THEN - DEC(p, SIZE_OF_DWORD); - SYSTEM.GET(p, t1); - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END - ELSE - t1 := -1 + SYSTEM.GET(p - SIZE_OF_DWORD, p); + SYSTEM.GET(t0 + p + types, p) END - RETURN t1 = t0 + RETURN p MOD 2 END _is; -PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): BOOLEAN; +PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): INTEGER; BEGIN - (* r:t1 IS t0 *) - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END - - RETURN t1 = t0 + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 END _guardrec; -PROCEDURE [stdcall] _guard* (t0, p: INTEGER): BOOLEAN; -VAR - t1: INTEGER; - +PROCEDURE [stdcall] _guard* (t0, p: INTEGER): INTEGER; BEGIN - (* p IS t0 *) SYSTEM.GET(p, p); IF p # 0 THEN - DEC(p, SIZE_OF_DWORD); - SYSTEM.GET(p, t1); - WHILE (t1 # t0) & (t1 # 0) DO - SYSTEM.GET(types + t1 * SIZE_OF_DWORD, t1) - END + SYSTEM.GET(p - SIZE_OF_DWORD, p); + SYSTEM.GET(t0 + p + types, p) ELSE - t1 := t0 + p := 1 END - RETURN t1 = t0 + RETURN p MOD 2 END _guard; @@ -613,18 +581,50 @@ BEGIN END _exit; -PROCEDURE [stdcall] _init* (modname: INTEGER; typesc, _types: INTEGER; code, param: INTEGER); +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 := _types; + 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 * SIZE_OF_DWORD, t1) + END; + + SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) + END + END; + name := modname; dll.process_detach := NIL; dll.thread_detach := NIL; dll.thread_attach := NIL; + + fini := NIL END _init; +PROCEDURE [stdcall] _sofinit*; +BEGIN + IF fini # NIL THEN + fini + END +END _sofinit; + + +PROCEDURE SetFini* (ProcFini: PROC); +BEGIN + fini := ProcFini +END SetFini; + + END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/AMD64.ob07 b/programs/develop/oberon07/Source/AMD64.ob07 index c1fa1f65c0..fb34e0754d 100644 --- a/programs/develop/oberon07/Source/AMD64.ob07 +++ b/programs/develop/oberon07/Source/AMD64.ob07 @@ -7,7 +7,7 @@ MODULE AMD64; -IMPORT CODE, BIN, WR := WRITER, CHL := CHUNKLISTS, MACHINE, LISTS, PATHS, +IMPORT IL, BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PATHS, PROG, REG, C := CONSOLE, UTILS, mConst := CONSTANTS, S := STRINGS, PE32, ELF, X86; @@ -31,7 +31,7 @@ CONST sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H; - shl = CODE.opLSL2; shr = CODE.opLSR2; sar = CODE.opASR2; ror = CODE.opROR2; + shl = IL.opLSL2; shr = IL.opLSR2; sar = IL.opASR2; ror = IL.opROR2; sCODE = BIN.PICCODE; sDATA = BIN.PICDATA; @@ -41,7 +41,7 @@ CONST TYPE - COMMAND = CODE.COMMAND; + COMMAND = IL.COMMAND; Number = POINTER TO RECORD (LISTS.ITEM) value: INTEGER END; @@ -58,7 +58,9 @@ VAR prog: BIN.PROGRAM; - dllret: INTEGER; + tcount: INTEGER; + + dllret, sofinit: INTEGER; Win64RegPar: ARRAY 4 OF INTEGER; SystemVRegPar: ARRAY 6 OF INTEGER; @@ -87,10 +89,10 @@ END OutByte3; PROCEDURE OutInt (n: INTEGER); BEGIN - OutByte(MACHINE.Byte(n, 0)); - OutByte(MACHINE.Byte(n, 1)); - OutByte(MACHINE.Byte(n, 2)); - OutByte(MACHINE.Byte(n, 3)) + OutByte(UTILS.Byte(n, 0)); + OutByte(UTILS.Byte(n, 1)); + OutByte(UTILS.Byte(n, 2)); + OutByte(UTILS.Byte(n, 3)) END OutInt; @@ -112,7 +114,7 @@ END long; PROCEDURE OutIntByte (n: INTEGER); BEGIN IF isByte(n) THEN - OutByte(MACHINE.Byte(n, 0)) + OutByte(UTILS.Byte(n, 0)) ELSE OutInt(n) END @@ -120,7 +122,7 @@ END OutIntByte; PROCEDURE isLong (n: INTEGER): BOOLEAN; - RETURN (n > MACHINE.max32) OR (n < MACHINE.min32) + RETURN (n > UTILS.max32) OR (n < UTILS.min32) END isLong; @@ -139,7 +141,7 @@ END NewNumber; PROCEDURE NewLabel (): INTEGER; BEGIN BIN.NewLabel(prog) - RETURN CODE.NewLabel() + RETURN IL.NewLabel() END NewLabel; @@ -257,12 +259,22 @@ BEGIN END drop; +PROCEDURE GetAnyReg (): INTEGER; + RETURN REG.GetAnyReg(R) +END GetAnyReg; + + +PROCEDURE GetVarReg (offs: INTEGER): INTEGER; + RETURN REG.GetVarReg(R, offs) +END GetVarReg; + + PROCEDURE callimp (label: INTEGER); VAR reg: INTEGER; BEGIN - reg := REG.GetAnyReg(R); + reg := GetAnyReg(); lea(reg, label, sIMP); IF reg >= 8 THEN // call qword[reg] OutByte(41H) @@ -277,7 +289,7 @@ VAR reg: INTEGER; BEGIN - reg := REG.GetAnyReg(R); + reg := GetAnyReg(); lea(reg, offs, sDATA); push(reg); drop @@ -290,7 +302,7 @@ VAR BEGIN REG.Store(R); - label := CODE.codes.rtl[proc]; + label := IL.codes.rtl[proc]; IF label < 0 THEN callimp(-label) ELSE @@ -315,7 +327,7 @@ END BinOp; PROCEDURE PushAll (NumberOfParameters: INTEGER); BEGIN REG.PushAll(R); - R.pushed := R.pushed - NumberOfParameters + DEC(R.pushed, NumberOfParameters) END PushAll; @@ -327,7 +339,7 @@ BEGIN Rex(reg, 0); OutByte(0B8H + reg MOD 8); // movabs reg, n FOR i := 0 TO 7 DO - OutByte(MACHINE.Byte(n, i)) + OutByte(UTILS.Byte(n, i)) END END movabs; @@ -336,6 +348,8 @@ 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); @@ -355,7 +369,7 @@ VAR reg2: INTEGER; BEGIN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); movabs(reg2, n); oprr(reg, reg2); drop @@ -404,7 +418,7 @@ VAR BEGIN IF isLong(n) THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); movabs(reg2, n); push(reg2); drop @@ -642,14 +656,14 @@ BEGIN END shiftrc; -PROCEDURE getVar (variables: LISTS.LIST; offset: INTEGER): CODE.LOCALVAR; +PROCEDURE getVar (variables: LISTS.LIST; offset: INTEGER): IL.LOCALVAR; VAR - cur: CODE.LOCALVAR; + cur: IL.LOCALVAR; BEGIN - cur := variables.first(CODE.LOCALVAR); + cur := variables.first(IL.LOCALVAR); WHILE (cur # NIL) & (cur.offset # offset) DO - cur := cur.next(CODE.LOCALVAR) + cur := cur.next(IL.LOCALVAR) END RETURN cur @@ -662,7 +676,7 @@ VAR leaf: BOOLEAN; cur: COMMAND; variables: LISTS.LIST; - lvar, rvar: CODE.LOCALVAR; + lvar, rvar: IL.LOCALVAR; reg: INTEGER; max: INTEGER; loop: INTEGER; @@ -677,83 +691,76 @@ BEGIN cur := cmd.next(COMMAND); REPEAT CASE cur.opcode OF - |CODE.opLLOAD64, - CODE.opLLOAD8, - CODE.opLLOAD16, - CODE.opLLOAD32, - CODE.opLLOAD64_PARAM, - CODE.opLLOAD32_PARAM, - CODE.opLADR_SAVE, - CODE.opLADR_INC1, - CODE.opLADR_DEC1, - CODE.opLADR_INC, - CODE.opLADR_DEC, - CODE.opLADR_INC1B, - CODE.opLADR_DEC1B, - CODE.opLADR_INCB, - CODE.opLADR_DECB, - CODE.opLADR_INCL, - CODE.opLADR_EXCL, - CODE.opLADR_UNPK: + |IL.opLLOAD64, + IL.opLLOAD8, + IL.opLLOAD16, + IL.opLLOAD32, + IL.opLLOAD64_PARAM, + IL.opLLOAD32_PARAM, + IL.opLADR_SAVE, + IL.opLADR_INC, + IL.opLADR_DEC, + IL.opLADR_INCB, + IL.opLADR_DECB, + IL.opLADR_INCL, + IL.opLADR_EXCL, + IL.opLADR_UNPK: lvar := getVar(variables, cur.param2); IF (lvar # NIL) & (lvar.count # -1) THEN INC(lvar.count, loop) END - |CODE.opLADR_SAVEC, - CODE.opLADR_INCC, - CODE.opLADR_DECC, - CODE.opLADR_INCCB, - CODE.opLADR_DECCB, - CODE.opLADR_INCLC, - CODE.opLADR_EXCLC: + |IL.opLADR_SAVEC, + IL.opLADR_INCC, + IL.opLADR_INCCB, + IL.opLADR_DECCB, + IL.opLADR_INCLC, + IL.opLADR_EXCLC: lvar := getVar(variables, cur.param1); IF (lvar # NIL) & (lvar.count # -1) THEN INC(lvar.count, loop) END - |CODE.opLADR: + |IL.opLADR: lvar := getVar(variables, cur.param2); IF (lvar # NIL) & (lvar.count # -1) THEN lvar.count := -1 END - |CODE.opLOOP: + |IL.opLOOP: INC(loop, 10) - |CODE.opENDLOOP: + |IL.opENDLOOP: DEC(loop, 10) - |CODE.opLEAVE, - CODE.opLEAVER, - CODE.opLEAVEF: + |IL.opLEAVE, + IL.opLEAVER, + IL.opLEAVEF: leave := TRUE - |CODE.opCALL, CODE.opCALLP, CODE.opCALLI, - CODE.opWIN64CALL, CODE.opWIN64CALLP, CODE.opWIN64CALLI, - CODE.opSYSVCALL, CODE.opSYSVCALLP, CODE.opSYSVCALLI, + |IL.opCALL, IL.opCALLP, IL.opCALLI, + IL.opWIN64CALL, IL.opWIN64CALLP, IL.opWIN64CALLI, + IL.opSYSVCALL, IL.opSYSVCALLP, IL.opSYSVCALLI, - CODE.opSAVES, CODE.opRSET, CODE.opRSETR, - CODE.opRSETL, CODE.opRSET1, - CODE.opEQS .. CODE.opGES, - CODE.opEQS2 .. CODE.opGES2, - CODE.opEQSW .. CODE.opGESW, - CODE.opEQSW2 .. CODE.opGESW2, - CODE.opCOPY, CODE.opMOVE, CODE.opCOPYA, - CODE.opCOPYS, CODE.opCOPYS2, CODE.opROT, - CODE.opNEW, CODE.opDISP, CODE.opISREC, - CODE.opIS, CODE.opTYPEGR, CODE.opTYPEGP, - CODE.opCASET, CODE.opDIV, - CODE.opDIVL, CODE.opMOD, - CODE.opMODL, CODE.opLENGTH, CODE.opLENGTHW: + IL.opSAVES, IL.opRSET, IL.opRSETR, + IL.opRSETL, IL.opRSET1, + IL.opEQS .. IL.opGES, + IL.opEQSW .. IL.opGESW, + IL.opCOPY, IL.opMOVE, IL.opCOPYA, + IL.opCOPYS, IL.opROT, + IL.opNEW, IL.opDISP, IL.opISREC, + IL.opIS, IL.opTYPEGR, IL.opTYPEGP, + IL.opCASET, IL.opDIV, + IL.opDIVL, IL.opMOD, + IL.opMODL, IL.opLENGTH, IL.opLENGTHW: leaf := FALSE - |CODE.opDIVR, CODE.opMODR: + |IL.opDIVR, IL.opMODR: param2 := cur.param2; IF param2 >= 1 THEN - param2 := X86.log2(param2) + param2 := UTILS.Log2(param2) ELSIF param2 <= -1 THEN - param2 := X86.log2(-param2) + param2 := UTILS.Log2(-param2) ELSE param2 := -1 END; @@ -772,13 +779,13 @@ BEGIN reg := -1; max := -1; rvar := NIL; - lvar := variables.first(CODE.LOCALVAR); + lvar := variables.first(IL.LOCALVAR); WHILE lvar # NIL DO IF lvar.count > max THEN max := lvar.count; rvar := lvar END; - lvar := lvar.next(CODE.LOCALVAR) + lvar := lvar.next(IL.LOCALVAR) END; IF rvar # NIL THEN @@ -878,30 +885,30 @@ VAR cc, reg: INTEGER; BEGIN - reg := REG.GetAnyReg(R); + reg := GetAnyReg(); xor(reg, reg); CASE op OF - |CODE.opEQF, CODE.opEQFI: + |IL.opEQF: comisd(xmm - 1, xmm); cc := sete - |CODE.opNEF, CODE.opNEFI: + |IL.opNEF: comisd(xmm - 1, xmm); cc := setne - |CODE.opLTF, CODE.opGTFI: + |IL.opLTF: comisd(xmm - 1, xmm); cc := setc - |CODE.opGTF, CODE.opLTFI: + |IL.opGTF: comisd(xmm, xmm - 1); cc := setc - |CODE.opLEF, CODE.opGEFI: + |IL.opLEF: comisd(xmm, xmm - 1); cc := setnc - |CODE.opGEF, CODE.opLEFI: + |IL.opGEF: comisd(xmm - 1, xmm); cc := setnc END; @@ -915,7 +922,7 @@ PROCEDURE translate (commands: LISTS.LIST; stroffs: INTEGER); VAR cmd, next: COMMAND; - param1, param2, param3, a, b, c, n, label, L, i, cc: INTEGER; + opcode, param1, param2, param3, a, b, c, n, label, L, i, cc: INTEGER; reg1, reg2, xmm: INTEGER; @@ -931,22 +938,24 @@ BEGIN param1 := cmd.param1; param2 := cmd.param2; - CASE cmd.opcode OF + opcode := cmd.opcode; - |CODE.opJMP: + CASE opcode OF + + |IL.opJMP: jmp(param1) - |CODE.opCALL, CODE.opWIN64CALL, CODE.opSYSVCALL: + |IL.opCALL, IL.opWIN64CALL, IL.opSYSVCALL: REG.Store(R); - CASE cmd.opcode OF - |CODE.opCALL: - |CODE.opWIN64CALL: Win64Passing(param2) - |CODE.opSYSVCALL: SysVPassing(param2) + CASE opcode OF + |IL.opCALL: + |IL.opWIN64CALL: Win64Passing(param2) + |IL.opSYSVCALL: SysVPassing(param2) END; X86.call(param1); REG.Restore(R) - |CODE.opCALLP, CODE.opWIN64CALLP, CODE.opSYSVCALLP: + |IL.opCALLP, IL.opWIN64CALLP, IL.opSYSVCALLP: UnOp(reg1); IF reg1 # rax THEN GetRegA; @@ -955,35 +964,35 @@ BEGIN END; drop; REG.Store(R); - CASE cmd.opcode OF - |CODE.opCALLP: - |CODE.opWIN64CALLP: Win64Passing(param2) - |CODE.opSYSVCALLP: SysVPassing(param2) + CASE opcode OF + |IL.opCALLP: + |IL.opWIN64CALLP: Win64Passing(param2) + |IL.opSYSVCALLP: SysVPassing(param2) END; OutByte2(0FFH, 0D0H); // call rax REG.Restore(R); ASSERT(R.top = -1) - |CODE.opCALLI, CODE.opWIN64CALLI, CODE.opSYSVCALLI: + |IL.opCALLI, IL.opWIN64CALLI, IL.opSYSVCALLI: REG.Store(R); - CASE cmd.opcode OF - |CODE.opCALLI: - |CODE.opWIN64CALLI: Win64Passing(param2) - |CODE.opSYSVCALLI: SysVPassing(param2) + CASE opcode OF + |IL.opCALLI: + |IL.opWIN64CALLI: Win64Passing(param2) + |IL.opSYSVCALLI: SysVPassing(param2) END; callimp(param1); REG.Restore(R) - |CODE.opLABEL: - X86.SetLabel(param2) + |IL.opLABEL: + X86.SetLabel(param1) - |CODE.opERR: - CallRTL(CODE._error) + |IL.opERR: + CallRTL(IL._error) - |CODE.opERRC: + |IL.opPUSHC: pushc(param2) - |CODE.opPRECALL: + |IL.opPRECALL: n := param2; IF (param1 # 0) & (n # 0) THEN subrc(rsp, 8) @@ -997,14 +1006,14 @@ BEGIN ASSERT(xmm = -1); PushAll(0) - |CODE.opWIN64ALIGN16: + |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) - |CODE.opSYSVALIGN16: + |IL.opSYSVALIGN16: ASSERT(rax IN R.regs); mov(rax, rsp); andrc(rsp, -16); @@ -1013,7 +1022,7 @@ BEGIN push(rax) END - |CODE.opRESF: + |IL.opRESF: ASSERT(xmm = -1); INC(xmm); n := param2; @@ -1030,7 +1039,7 @@ BEGIN DEC(n) END - |CODE.opRES: + |IL.opRES: ASSERT(R.top = -1); GetRegA; n := param2; @@ -1041,7 +1050,7 @@ BEGIN DEC(n) END - |CODE.opENTER: + |IL.opENTER: ASSERT(R.top = -1); X86.SetLabel(param1); @@ -1122,8 +1131,8 @@ BEGIN allocReg(cmd) END - |CODE.opLEAVE, CODE.opLEAVER, CODE.opLEAVEF: - IF cmd.opcode = CODE.opLEAVER THEN + |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: + IF opcode = IL.opLEAVER THEN UnOp(reg1); IF reg1 # rax THEN GetRegA; @@ -1135,13 +1144,16 @@ BEGIN ASSERT(R.top = -1); - IF cmd.opcode = CODE.opLEAVEF THEN + IF opcode = IL.opLEAVEF THEN DEC(xmm) END; ASSERT(xmm = -1); - mov(rsp, rbp); + 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 @@ -1150,59 +1162,55 @@ BEGIN END; REG.Reset(R) - |CODE.opSAVES: - UnOp(reg1); - drop; - PushAll(0); - push(reg1); + |IL.opSAVES: + PushAll(1); pushDA(stroffs + param2); pushc(param1); - CallRTL(CODE._move) + CallRTL(IL._move) - |CODE.opSADR: - reg1 := REG.GetAnyReg(R); - lea(reg1, stroffs + param2, sDATA) + |IL.opSADR: + lea(GetAnyReg(), stroffs + param2, sDATA) - |CODE.opLOAD8: + |IL.opLOAD8: UnOp(reg1); movzx(reg1, reg1, 0, FALSE) - |CODE.opLOAD16: + |IL.opLOAD16: UnOp(reg1); movzx(reg1, reg1, 0, TRUE) - |CODE.opLOAD32: + |IL.opLOAD32: UnOp(reg1); movrm32(reg1, reg1, 0); shiftrc(shl, reg1, 32); shiftrc(shr, reg1, 32) - |CODE.opLOAD64: + |IL.opLOAD64: UnOp(reg1); movrm(reg1, reg1, 0) - |CODE.opLLOAD64: - reg1 := REG.GetAnyReg(R); - reg2 := REG.GetVarReg(R, param2); + |IL.opLLOAD64: + reg1 := GetAnyReg(); + reg2 := GetVarReg(param2); IF reg2 # -1 THEN mov(reg1, reg2) ELSE movrm(reg1, rbp, param2 * 8) END - |CODE.opLLOAD8, - CODE.opLLOAD16: - reg1 := REG.GetAnyReg(R); - reg2 := REG.GetVarReg(R, param2); + |IL.opLLOAD8, + IL.opLLOAD16: + reg1 := GetAnyReg(); + reg2 := GetVarReg(param2); IF reg2 # -1 THEN mov(reg1, reg2) ELSE - movzx(reg1, rbp, param2 * 8, cmd.opcode = CODE.opLLOAD16) + movzx(reg1, rbp, param2 * 8, opcode = IL.opLLOAD16) END - |CODE.opLLOAD32: - reg1 := REG.GetAnyReg(R); - reg2 := REG.GetVarReg(R, param2); + |IL.opLLOAD32: + reg1 := GetAnyReg(); + reg2 := GetVarReg(param2); IF reg2 # -1 THEN mov(reg1, reg2) ELSE @@ -1211,73 +1219,71 @@ BEGIN movrm32(reg1, rbp, n) END - |CODE.opGLOAD64: - reg1 := REG.GetAnyReg(R); + |IL.opGLOAD64: + reg1 := GetAnyReg(); lea(reg1, param2, sBSS); movrm(reg1, reg1, 0) - |CODE.opGLOAD8: - reg1 := REG.GetAnyReg(R); + |IL.opGLOAD8: + reg1 := GetAnyReg(); lea(reg1, param2, sBSS); movzx(reg1, reg1, 0, FALSE) - |CODE.opGLOAD16: - reg1 := REG.GetAnyReg(R); + |IL.opGLOAD16: + reg1 := GetAnyReg(); lea(reg1, param2, sBSS); movzx(reg1, reg1, 0, TRUE) - |CODE.opGLOAD32: - reg1 := REG.GetAnyReg(R); + |IL.opGLOAD32: + reg1 := GetAnyReg(); xor(reg1, reg1); lea(reg1, param2, sBSS); movrm32(reg1, reg1, 0) - |CODE.opVLOAD64: - reg1 := REG.GetAnyReg(R); + |IL.opVLOAD64: + reg1 := GetAnyReg(); movrm(reg1, rbp, param2 * 8); movrm(reg1, reg1, 0) - |CODE.opVLOAD8, - CODE.opVLOAD16: - reg1 := REG.GetAnyReg(R); + |IL.opVLOAD8, + IL.opVLOAD16: + reg1 := GetAnyReg(); movrm(reg1, rbp, param2 * 8); - movzx(reg1, reg1, 0, cmd.opcode = CODE.opVLOAD16) + movzx(reg1, reg1, 0, opcode = IL.opVLOAD16) - |CODE.opVLOAD32: - reg1 := REG.GetAnyReg(R); - reg2 := REG.GetAnyReg(R); + |IL.opVLOAD32: + reg1 := GetAnyReg(); + reg2 := GetAnyReg(); xor(reg1, reg1); movrm(reg2, rbp, param2 * 8); movrm32(reg1, reg2, 0); drop - |CODE.opLADR: + |IL.opLADR: n := param2 * 8; next := cmd.next(COMMAND); - IF next.opcode = CODE.opSAVEF THEN + IF next.opcode = IL.opSAVEF THEN movsdmr(rbp, n, xmm); DEC(xmm); cmd := next - ELSIF next.opcode = CODE.opLOADF THEN + ELSIF next.opcode = IL.opLOADF THEN INC(xmm); movsdrm(xmm, rbp, n); cmd := next ELSE - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Rex(0, reg1); OutByte2(8DH, 45H + long(n) + (reg1 MOD 8) * 8); // lea reg1, qword[rbp+n] OutIntByte(n) END - |CODE.opGADR: - reg1 := REG.GetAnyReg(R); - lea(reg1, param2, sBSS) + |IL.opGADR: + lea(GetAnyReg(), param2, sBSS) - |CODE.opVADR: - reg1 := REG.GetAnyReg(R); - movrm(reg1, rbp, param2 * 8) + |IL.opVADR: + movrm(GetAnyReg(), rbp, param2 * 8) - |CODE.opSAVE8C: + |IL.opSAVE8C: UnOp(reg1); IF reg1 >= 8 THEN OutByte(41H) @@ -1285,7 +1291,7 @@ BEGIN OutByte3(0C6H, reg1 MOD 8, param2); // mov byte[reg1], param2 drop - |CODE.opSAVE16C: + |IL.opSAVE16C: UnOp(reg1); OutByte(66H); IF reg1 >= 8 THEN @@ -1295,10 +1301,10 @@ BEGIN OutByte2(param2 MOD 256, param2 DIV 256); // mov word[reg1], param2 drop - |CODE.opSAVEC: + |IL.opSAVEC: UnOp(reg1); IF isLong(param2) THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); movrc(reg2, param2); movmr(reg1, 0, reg2); drop @@ -1309,142 +1315,106 @@ BEGIN END; drop - |CODE.opRSET: + |IL.opRSET: PushAll(2); - CallRTL(CODE._set); + CallRTL(IL._set); GetRegA - |CODE.opRSETR: + |IL.opRSETR: PushAll(1); pushc(param2); - CallRTL(CODE._set); + CallRTL(IL._set); GetRegA - |CODE.opRSETL: + |IL.opRSETL: PushAll(1); pushc(param2); - CallRTL(CODE._set2); + CallRTL(IL._set2); GetRegA - |CODE.opRSET1: + |IL.opRSET1: UnOp(reg1); PushAll(1); push(reg1); - CallRTL(CODE._set); + CallRTL(IL._set); GetRegA - |CODE.opINCL, CODE.opEXCL: + |IL.opINCL, IL.opEXCL: BinOp(reg1, reg2); cmprc(reg1, 64); OutByte2(73H, 04H); // jnb L Rex(reg2, reg1); - OutByte3(0FH, 0ABH + 8 * ORD(cmd.opcode = CODE.opEXCL), 8 * (reg1 MOD 8) + reg2 MOD 8); // bts/btr qword[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 - |CODE.opINCLC, CODE.opEXCLC: + |IL.opINCLC, IL.opEXCLC: UnOp(reg1); Rex(reg1, 0); OutByte2(0FH, 0BAH); // bts/btr qword[reg1], param2 - OutByte2(28H + 8 * ORD(cmd.opcode = CODE.opEXCLC) + reg1 MOD 8, param2); + OutByte2(28H + 8 * ORD(opcode = IL.opEXCLC) + reg1 MOD 8, param2); drop - |CODE.opEQS .. CODE.opGES: + |IL.opEQS .. IL.opGES: PushAll(4); - pushc(cmd.opcode - CODE.opEQS); - CallRTL(CODE._strcmp); + pushc(opcode - IL.opEQS); + CallRTL(IL._strcmp); GetRegA - |CODE.opEQS2 .. CODE.opGES2: + |IL.opEQSW .. IL.opGESW: PushAll(4); - pushc(cmd.opcode - CODE.opEQS2); - CallRTL(CODE._strcmp2); + pushc(opcode - IL.opEQSW); + CallRTL(IL._strcmpw); GetRegA - |CODE.opEQSW .. CODE.opGESW: - PushAll(4); - pushc(cmd.opcode - CODE.opEQSW); - CallRTL(CODE._strcmpw); - GetRegA + |IL.opCONST: + movrc(GetAnyReg(), param2) - |CODE.opEQSW2 .. CODE.opGESW2: - PushAll(4); - pushc(cmd.opcode - CODE.opEQSW2); - CallRTL(CODE._strcmpw2); - GetRegA - - |CODE.opINC1, CODE.opDEC1: - UnOp(reg1); - Rex(reg1, 0); - OutByte2(0FFH, reg1 MOD 8 + 8 * ORD(cmd.opcode = CODE.opDEC1)); - drop - - |CODE.opCONST: - reg1 := REG.GetAnyReg(R); - movrc(reg1, param2) - - |CODE.opGT, CODE.opGE, CODE.opLT, - CODE.opLE, CODE.opEQ, CODE.opNE: - BinOp(reg1, reg2); - cmprr(reg1, reg2); - drop; - drop; - cc := X86.cond(cmd.opcode); - - IF cmd.next(COMMAND).opcode = CODE.opJE THEN - label := cmd.next(COMMAND).param1; - jcc(cc, label); - cmd := cmd.next(COMMAND) - - ELSIF cmd.next(COMMAND).opcode = CODE.opJNE THEN - label := cmd.next(COMMAND).param1; - jcc(X86.inv1(cc), label); - cmd := cmd.next(COMMAND) + |IL.opEQ..IL.opGE, + IL.opEQC..IL.opGEC: + IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN + BinOp(reg1, reg2); + cmprr(reg1, reg2); + drop ELSE - reg1 := REG.GetAnyReg(R); - setcc(cc + 16, reg1); - andrc(reg1, 1) - END - - |CODE.opGTR, CODE.opLTL, CODE.opGER, CODE.opLEL, - CODE.opLER, CODE.opGEL, CODE.opLTR, CODE.opGTL, - CODE.opEQR, CODE.opEQL, CODE.opNER, CODE.opNEL: - UnOp(reg1); - IF param2 = 0 THEN - test(reg1) - ELSE - cmprc(reg1, param2) + UnOp(reg1); + IF param2 = 0 THEN + test(reg1) + ELSE + cmprc(reg1, param2) + END END; - drop; - cc := X86.cond(cmd.opcode); - IF cmd.next(COMMAND).opcode = CODE.opJE THEN + drop; + cc := X86.cond(opcode); + + IF cmd.next(COMMAND).opcode = IL.opJE THEN label := cmd.next(COMMAND).param1; jcc(cc, label); cmd := cmd.next(COMMAND) - ELSIF cmd.next(COMMAND).opcode = CODE.opJNE THEN + ELSIF cmd.next(COMMAND).opcode = IL.opJNE THEN label := cmd.next(COMMAND).param1; - jcc(X86.inv1(cc), label); + jcc(X86.inv0(cc), label); cmd := cmd.next(COMMAND) ELSE - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); setcc(cc + 16, reg1); andrc(reg1, 1) END - |CODE.opCODE: + |IL.opCODE: OutByte(param2) - |CODE.opPUSHIP: - reg1 := REG.GetAnyReg(R); + |IL.opPUSHIP: + reg1 := GetAnyReg(); lea(reg1, param2, sIMP); movrm(reg1, reg1, 0) - |CODE.opPARAM: + |IL.opPARAM: n := param2; IF n = 1 THEN UnOp(reg1); @@ -1453,9 +1423,9 @@ BEGIN ELSE ASSERT(R.top + 1 <= n); PushAll(n) - END - - |CODE.opACC: + END + + |IL.opACC: IF (R.top # 0) OR (R.stk[0] # rax) THEN PushAll(0); GetRegA; @@ -1463,29 +1433,29 @@ BEGIN DEC(R.pushed) END - |CODE.opJNZ: + |IL.opJNZ: UnOp(reg1); test(reg1); jcc(jne, param1) - |CODE.opJZ: + |IL.opJZ: UnOp(reg1); test(reg1); jcc(je, param1) - |CODE.opJE: + |IL.opJE: UnOp(reg1); test(reg1); jcc(jne, param1); drop - |CODE.opJNE: + |IL.opJNE: UnOp(reg1); test(reg1); jcc(je, param1); drop - |CODE.opIN: + |IL.opIN: label := NewLabel(); L := NewLabel(); BinOp(reg1, reg2); @@ -1501,11 +1471,11 @@ BEGIN X86.SetLabel(label); drop - |CODE.opINR: + |IL.opINR: label := NewLabel(); L := NewLabel(); UnOp(reg1); - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); cmprc(reg1, 64); jcc(jb, L); xor(reg1, reg1); @@ -1519,7 +1489,7 @@ BEGIN X86.SetLabel(label); drop - |CODE.opINL: + |IL.opINL: UnOp(reg1); Rex(reg1, 0); OutByte2(0FH, 0BAH); // bt reg1, param2 @@ -1527,237 +1497,233 @@ BEGIN setcc(setc, reg1); andrc(reg1, 1) - |CODE.opNOT: + |IL.opNOT: UnOp(reg1); test(reg1); setcc(sete, reg1); andrc(reg1, 1) - |CODE.opORD: + |IL.opORD: UnOp(reg1); test(reg1); setcc(setne, reg1); andrc(reg1, 1) - |CODE.opABS: + |IL.opABS: UnOp(reg1); test(reg1); OutByte2(7DH, 03H); // jge L neg(reg1) // L: - |CODE.opEQB, CODE.opNEB: + |IL.opEQB, IL.opNEB: BinOp(reg1, reg2); drop; - drop; - test(reg1); - OutByte2(74H, 07H); // je L1 + label := NewLabel(); + jcc(je, label); movrc(reg1, 1); - // L1: + X86.SetLabel(label); test(reg2); - OutByte2(74H, 07H); // je L2 + label := NewLabel(); + jcc(je, label); movrc(reg2, 1); - // L2: + X86.SetLabel(label); cmprr(reg1, reg2); - reg1 := REG.GetAnyReg(R); - IF cmd.opcode = CODE.opEQB THEN + IF opcode = IL.opEQB THEN setcc(sete, reg1) ELSE setcc(setne, reg1) END; andrc(reg1, 1) - |CODE.opMULSC: + |IL.opMULSC: UnOp(reg1); andrc(reg1, param2) - |CODE.opDIVSC, CODE.opADDSL, CODE.opADDSR: + |IL.opDIVSC, IL.opADDSL, IL.opADDSR: UnOp(reg1); Rex(reg1, 0); - OutByte2(81H + short(param2), 0C8H + 28H * ORD(cmd.opcode = CODE.opDIVSC) + reg1 MOD 8); // or/xor reg1, param2 + OutByte2(81H + short(param2), 0C8H + 28H * ORD(opcode = IL.opDIVSC) + reg1 MOD 8); // or/xor reg1, param2 OutIntByte(param2) - |CODE.opSUBSL: + |IL.opSUBSL: UnOp(reg1); not(reg1); andrc(reg1, param2) - |CODE.opSUBSR: + |IL.opSUBSR: UnOp(reg1); andrc(reg1, ORD(-BITS(param2))) - |CODE.opMULS: + |IL.opMULS: BinOp(reg1, reg2); and(reg1, reg2); drop - |CODE.opDIVS: + |IL.opDIVS: BinOp(reg1, reg2); xor(reg1, reg2); drop - |CODE.opUMINS: + |IL.opUMINS: UnOp(reg1); not(reg1) - |CODE.opCOPY: + |IL.opCOPY: PushAll(2); pushc(param2); - CallRTL(CODE._move2) + CallRTL(IL._move2) - |CODE.opMOVE: + |IL.opMOVE: PushAll(3); - CallRTL(CODE._move2) + CallRTL(IL._move2) - |CODE.opCOPYA: + |IL.opCOPYA: PushAll(4); pushc(param2); - CallRTL(CODE._arrcpy); + CallRTL(IL._arrcpy); GetRegA - |CODE.opCOPYS: + |IL.opCOPYS: PushAll(4); pushc(param2); - CallRTL(CODE._strcpy) + CallRTL(IL._strcpy) - |CODE.opCOPYS2: - PushAll(4); - pushc(param2); - CallRTL(CODE._strcpy2) - - |CODE.opROT: + |IL.opROT: PushAll(0); push(rsp); pushc(param2); - CallRTL(CODE._rot) + CallRTL(IL._rot) - |CODE.opNEW: + |IL.opNEW: PushAll(1); n := param2 + 16; - ASSERT(MACHINE.Align(n, 64)); + ASSERT(UTILS.Align(n, 64)); pushc(n); pushc(param1); - CallRTL(CODE._new) + CallRTL(IL._new) - |CODE.opDISP: + |IL.opDISP: PushAll(1); - CallRTL(CODE._dispose) + CallRTL(IL._dispose) - |CODE.opPUSHT: + |IL.opPUSHT: UnOp(reg1); - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); movrm(reg2, reg1, -8) - |CODE.opISREC: + |IL.opISREC: PushAll(2); - pushc(param2); - CallRTL(CODE._isrec); + pushc(param2 * tcount); + CallRTL(IL._isrec); GetRegA - |CODE.opIS: + |IL.opIS: PushAll(1); - pushc(param2); - CallRTL(CODE._is); + pushc(param2 * tcount); + CallRTL(IL._is); GetRegA - |CODE.opTYPEGR: + |IL.opTYPEGR: PushAll(1); - pushc(param2); - CallRTL(CODE._guardrec); + pushc(param2 * tcount); + CallRTL(IL._guardrec); GetRegA - |CODE.opTYPEGP: + |IL.opTYPEGP: UnOp(reg1); PushAll(0); push(reg1); - pushc(param2); - CallRTL(CODE._guard); + pushc(param2 * tcount); + CallRTL(IL._guard); GetRegA - |CODE.opTYPEGD: + |IL.opTYPEGD: UnOp(reg1); PushAll(0); pushm(reg1, -8); - pushc(param2); - CallRTL(CODE._guardrec); + pushc(param2 * tcount); + CallRTL(IL._guardrec); GetRegA - |CODE.opCASET: + |IL.opCASET: push(r10); push(r10); - pushc(param2); - CallRTL(CODE._guardrec); + pushc(param2 * tcount); + CallRTL(IL._guardrec); pop(r10); test(rax); jcc(jne, param1) - |CODE.opSAVEP: + |IL.opSAVEP: UnOp(reg1); - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); lea(reg2, param2, sCODE); movmr(reg1, 0, reg2); drop; drop - |CODE.opPUSHP: - reg1 := REG.GetAnyReg(R); - lea(reg1, param2, sCODE) + |IL.opPUSHP: + lea(GetAnyReg(), param2, sCODE) - |CODE.opINC, CODE.opDEC: + |IL.opINC, IL.opDEC: BinOp(reg1, reg2); // add/sub qword[reg2], reg1 Rex(reg2, reg1); - OutByte2(01H + 28H * ORD(cmd.opcode = CODE.opDEC), reg2 MOD 8 + (reg1 MOD 8) * 8); + OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg2 MOD 8 + (reg1 MOD 8) * 8); drop; drop - |CODE.opINCC, CODE.opDECC: + |IL.opINCC: UnOp(reg1); IF isLong(param2) THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); movrc(reg2, param2); - // add/sub qword[reg1], reg2 + // add qword[reg1], reg2 Rex(reg1, reg2); - OutByte2(01H + 28H * ORD(cmd.opcode = CODE.opDECC), reg1 MOD 8 + (reg2 MOD 8) * 8); + OutByte2(01H, reg1 MOD 8 + (reg2 MOD 8) * 8); drop - ELSE - // add/sub qword[reg1], param2 + ELSIF ABS(param2) = 1 THEN Rex(reg1, 0); - OutByte2(81H + short(param2), 28H * ORD(cmd.opcode = CODE.opDECC) + reg1 MOD 8); + 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 - |CODE.opDROP: + |IL.opDROP: UnOp(reg1); drop - |CODE.opSAVE, CODE.opSAVE64: + |IL.opSAVE, IL.opSAVE64: BinOp(reg2, reg1); movmr(reg1, 0, reg2); drop; drop - |CODE.opSAVE8: + |IL.opSAVE8: BinOp(reg2, reg1); movmr8(reg1, 0, reg2); drop; drop - |CODE.opSAVE16: + |IL.opSAVE16: BinOp(reg2, reg1); movmr16(reg1, 0, reg2); drop; drop - |CODE.opSAVE32: + |IL.opSAVE32: BinOp(reg2, reg1); movmr32(reg1, 0, reg2); drop; drop - |CODE.opMIN: + |IL.opMIN: BinOp(reg1, reg2); cmprr(reg1, reg2); OutByte2(7EH, 3); // jle L @@ -1765,7 +1731,7 @@ BEGIN // L: drop - |CODE.opMAX: + |IL.opMAX: BinOp(reg1, reg2); cmprr(reg1, reg2); OutByte2(7DH, 3); // jge L @@ -1773,7 +1739,7 @@ BEGIN // L: drop - |CODE.opMINC: + |IL.opMINC: UnOp(reg1); cmprc(reg1, param2); label := NewLabel(); @@ -1781,7 +1747,7 @@ BEGIN movrc(reg1, param2); X86.SetLabel(label) - |CODE.opMAXC: + |IL.opMAXC: UnOp(reg1); cmprc(reg1, param2); label := NewLabel(); @@ -1789,41 +1755,43 @@ BEGIN movrc(reg1, param2); X86.SetLabel(label) - |CODE.opSBOOL: + |IL.opSBOOL: BinOp(reg2, reg1); test(reg2); - setcc(setne, reg2); - movmr8(reg1, 0, reg2); + IF reg1 >= 8 THEN + OutByte(41H) + END; + OutByte3(0FH, 95H, reg1 MOD 8); // setne byte[reg1] drop; drop - |CODE.opSBOOLC: + |IL.opSBOOLC: UnOp(reg1); IF reg1 >= 8 THEN OutByte(41H) END; - OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); + OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); // mov byte[reg1], 0/1 drop - |CODE.opODD: + |IL.opODD: UnOp(reg1); andrc(reg1, 1) - |CODE.opUMINUS: + |IL.opUMINUS: UnOp(reg1); neg(reg1) - |CODE.opADD: + |IL.opADD: BinOp(reg1, reg2); add(reg1, reg2); drop - |CODE.opSUB: + |IL.opSUB: BinOp(reg1, reg2); sub(reg1, reg2); drop - |CODE.opSUBR, CODE.opSUBL: + |IL.opSUBR, IL.opSUBL: UnOp(reg1); n := param2; IF n = 1 THEN @@ -1833,11 +1801,11 @@ BEGIN ELSIF n # 0 THEN subrc(reg1, n) END; - IF cmd.opcode = CODE.opSUBL THEN + IF opcode = IL.opSUBL THEN neg(reg1) END - |CODE.opADDL, CODE.opADDR: + |IL.opADDL, IL.opADDR: IF param2 # 0 THEN UnOp(reg1); IF param2 = 1 THEN @@ -1849,17 +1817,17 @@ BEGIN END END - |CODE.opDIV: + |IL.opDIV: PushAll(2); - CallRTL(CODE._div); + CallRTL(IL._div); GetRegA - |CODE.opDIVR: + |IL.opDIVR: a := param2; IF a > 1 THEN - n := X86.log2(a) + n := UTILS.Log2(a) ELSIF a < -1 THEN - n := X86.log2(-a) + n := UTILS.Log2(-a) ELSE n := -1 END; @@ -1874,7 +1842,7 @@ BEGIN UnOp(reg1); IF a < 0 THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); mov(reg2, reg1); shiftrc(sar, reg1, n); sub(reg1, reg2); @@ -1886,28 +1854,28 @@ BEGIN ELSE PushAll(1); pushc(param2); - CallRTL(CODE._div); + CallRTL(IL._div); GetRegA END END - |CODE.opDIVL: + |IL.opDIVL: PushAll(1); pushc(param2); - CallRTL(CODE._div2); + CallRTL(IL._div2); GetRegA - |CODE.opMOD: + |IL.opMOD: PushAll(2); - CallRTL(CODE._mod); + CallRTL(IL._mod); GetRegA - |CODE.opMODR: + |IL.opMODR: a := param2; IF a > 1 THEN - n := X86.log2(a) + n := UTILS.Log2(a) ELSIF a < -1 THEN - n := X86.log2(-a) + n := UTILS.Log2(-a) ELSE n := -1 END; @@ -1931,30 +1899,30 @@ BEGIN ELSE PushAll(1); pushc(param2); - CallRTL(CODE._mod); + CallRTL(IL._mod); GetRegA END END - |CODE.opMODL: + |IL.opMODL: PushAll(1); pushc(param2); - CallRTL(CODE._mod2); + CallRTL(IL._mod2); GetRegA - |CODE.opMUL: + |IL.opMUL: BinOp(reg1, reg2); oprr2(0FH, 0AFH, reg2, reg1); // imul reg1, reg2 drop - |CODE.opMULC: + |IL.opMULC: UnOp(reg1); a := param2; IF a > 1 THEN - n := X86.log2(a) + n := UTILS.Log2(a) ELSIF a < -1 THEN - n := X86.log2(-a) + n := UTILS.Log2(-a) ELSE n := -1 END; @@ -1979,20 +1947,20 @@ BEGIN END END - |CODE.opADDS: + |IL.opADDS: BinOp(reg1, reg2); or(reg1, reg2); drop - |CODE.opSUBS: + |IL.opSUBS: BinOp(reg1, reg2); not(reg2); and(reg1, reg2); drop - |CODE.opNOP: + |IL.opNOP: - |CODE.opSWITCH: + |IL.opSWITCH: UnOp(reg1); IF param2 = 0 THEN reg2 := rax @@ -2006,65 +1974,71 @@ BEGIN END; drop - |CODE.opENDSW: + |IL.opENDSW: - |CODE.opCASEL: + |IL.opCASEL: cmprc(rax, param1); jcc(jl, param2) - |CODE.opCASER: + |IL.opCASER: cmprc(rax, param1); jcc(jg, param2) - |CODE.opCASELR: + |IL.opCASELR: cmprc(rax, param1); jcc(jl, param2); jcc(jg, cmd.param3) - |CODE.opASR, CODE.opROR, CODE.opLSL, CODE.opLSR: + |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: BinOp(reg1, reg2); xchg(reg2, rcx); Rex(reg1, 0); OutByte(0D3H); - X86.shift(cmd.opcode, reg1 MOD 8); // shift reg1, cl + X86.shift(opcode, reg1 MOD 8); // shift reg1, cl xchg(reg2, rcx); drop - |CODE.opASR1, CODE.opROR1, CODE.opLSL1, CODE.opLSR1: - reg1 := REG.GetAnyReg(R); + |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: + reg1 := GetAnyReg(); movrc(reg1, param2); BinOp(reg1, reg2); xchg(reg1, rcx); Rex(reg2, 0); OutByte(0D3H); - X86.shift(cmd.opcode, reg2 MOD 8); // shift reg2, cl + X86.shift(opcode, reg2 MOD 8); // shift reg2, cl xchg(reg1, rcx); drop; drop; ASSERT(REG.GetReg(R, reg2)) - |CODE.opASR2, CODE.opROR2, CODE.opLSL2, CODE.opLSR2: + |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: UnOp(reg1); - shiftrc(cmd.opcode, reg1, ORD(BITS(param2) * {0..5})) + shiftrc(opcode, reg1, param2 MOD 64) - |CODE.opGET: - BinOp(reg1, reg2); + |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; _movrm(reg1, reg1, 0, param2 * 8, FALSE); _movrm(reg1, reg2, 0, param2 * 8, TRUE) - |CODE.opCHKBYTE: + |IL.opCHKBYTE: BinOp(reg1, reg2); cmprc(reg1, 256); jcc(jb, param1) - |CODE.opCHKIDX: + |IL.opCHKIDX: UnOp(reg1); cmprc(reg1, param2); jcc(jb, param1) - |CODE.opCHKIDX2: + |IL.opCHKIDX2: BinOp(reg1, reg2); IF param2 # -1 THEN cmprr(reg2, reg1); @@ -2077,17 +2051,17 @@ BEGIN R.stk[R.top] := reg2 END - |CODE.opLENGTH: + |IL.opLENGTH: PushAll(2); - CallRTL(CODE._length); + CallRTL(IL._length); GetRegA - |CODE.opLENGTHW: + |IL.opLENGTHW: PushAll(2); - CallRTL(CODE._lengthw); + CallRTL(IL._lengthw); GetRegA - |CODE.opLEN: + |IL.opLEN: n := param2; UnOp(reg1); drop; @@ -2102,23 +2076,23 @@ BEGIN INCL(R.regs, reg1); ASSERT(REG.GetReg(R, reg1)) - |CODE.opCHR: + |IL.opCHR: UnOp(reg1); andrc(reg1, 255) - |CODE.opWCHR: + |IL.opWCHR: UnOp(reg1); andrc(reg1, 65535) - |CODE.opEQP, CODE.opNEP, CODE.opEQIP, CODE.opNEIP: + |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP: UnOp(reg1); - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); - CASE cmd.opcode OF - |CODE.opEQP, CODE.opNEP: + CASE opcode OF + |IL.opEQP, IL.opNEP: lea(reg2, param1, sCODE) - |CODE.opEQIP, CODE.opNEIP: + |IL.opEQIP, IL.opNEIP: lea(reg2, param1, sIMP); movrm(reg2, reg2, 0) END; @@ -2126,43 +2100,35 @@ BEGIN cmprr(reg1, reg2); drop; drop; - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); - CASE cmd.opcode OF - |CODE.opEQP, CODE.opEQIP: setcc(sete, reg1) - |CODE.opNEP, CODE.opNEIP: setcc(setne, reg1) + CASE opcode OF + |IL.opEQP, IL.opEQIP: setcc(sete, reg1) + |IL.opNEP, IL.opNEIP: setcc(setne, reg1) END; andrc(reg1, 1) - |CODE.opINC1B, CODE.opDEC1B: + |IL.opINCCB, IL.opDECCB: UnOp(reg1); IF reg1 >= 8 THEN OutByte(41H) END; - OutByte2(0FEH, 8 * ORD(cmd.opcode = CODE.opDEC1B) + reg1 MOD 8); // inc/dec byte[reg1] + OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1 MOD 8, param2 MOD 256); // add/sub byte[reg1], param2 MOD 256 drop - |CODE.opINCCB, CODE.opDECCB: - UnOp(reg1); - IF reg1 >= 8 THEN - OutByte(41H) - END; - OutByte3(80H, 28H * ORD(cmd.opcode = CODE.opDECCB) + reg1 MOD 8, param2 MOD 256); // add/sub byte[reg1], param2 MOD 256 - drop - - |CODE.opINCB, CODE.opDECB: + |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(cmd.opcode = CODE.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); // add/sub byte[reg2], reg1_8 + OutByte2(28H * ORD(opcode = IL.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); // add/sub byte[reg2], reg1_8 drop; drop - |CODE.opSAVEIP: + |IL.opSAVEIP: UnOp(reg1); - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); lea(reg2, param2, sIMP); movrm(reg2, reg2, 0); push(reg2); @@ -2173,90 +2139,90 @@ BEGIN OutByte2(8FH, reg1 MOD 8); // pop qword[reg1] drop - |CODE.opCLEANUP: + |IL.opCLEANUP: n := param2 * 8; IF n # 0 THEN addrc(rsp, n) END - |CODE.opPOPSP: + |IL.opPOPSP: pop(rsp) - |CODE.opLOADF: + |IL.opLOADF: UnOp(reg1); INC(xmm); movsdrm(xmm, reg1, 0); drop - |CODE.opPUSHF: + |IL.opPUSHF: subrc(rsp, 8); movsdmr(rsp, 0, xmm); DEC(xmm) - |CODE.opCONSTF: + |IL.opCONSTF: float := cmd.float; INC(xmm); - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); lea(reg1, Numbers_Offs + Numbers_Count * 8, sDATA); movsdrm(xmm, reg1, 0); drop; NewNumber(UTILS.splitf(float, a, b)) - |CODE.opSAVEF: + |IL.opSAVEF: UnOp(reg1); movsdmr(reg1, 0, xmm); DEC(xmm); drop - |CODE.opADDF, CODE.opADDFI: + |IL.opADDF, IL.opADDFI: opxx(58H, xmm - 1, xmm); DEC(xmm) - |CODE.opSUBF: + |IL.opSUBF: opxx(5CH, xmm - 1, xmm); DEC(xmm) - |CODE.opSUBFI: + |IL.opSUBFI: opxx(5CH, xmm, xmm - 1); opxx(10H, xmm - 1, xmm); DEC(xmm) - |CODE.opMULF: + |IL.opMULF: opxx(59H, xmm - 1, xmm); DEC(xmm) - |CODE.opDIVF: + |IL.opDIVF: opxx(5EH, xmm - 1, xmm); DEC(xmm) - |CODE.opDIVFI: + |IL.opDIVFI: opxx(5EH, xmm, xmm - 1); opxx(10H, xmm - 1, xmm); DEC(xmm) - |CODE.opUMINF: - reg1 := REG.GetAnyReg(R); + |IL.opUMINF: + reg1 := GetAnyReg(); lea(reg1, Numbers_Offs, sDATA); OutByte3(66H, 40H + reg1 DIV 8 + (xmm DIV 8) * 4, 0FH); // xorpd xmm, xmmword[reg1] OutByte2(57H, reg1 MOD 8 + (xmm MOD 8) * 8); drop - |CODE.opFABS: - reg1 := REG.GetAnyReg(R); + |IL.opFABS: + reg1 := GetAnyReg(); lea(reg1, Numbers_Offs + 16, sDATA); OutByte3(66H, 40H + reg1 DIV 8 + (xmm DIV 8) * 4, 0FH); // andpd xmm, xmmword[reg1] OutByte2(54H, reg1 MOD 8 + (xmm MOD 8) * 8); drop - |CODE.opFLT: + |IL.opFLT: UnOp(reg1); INC(xmm); OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); // cvtsi2sd xmm, reg1 OutByte2(2AH, 0C0H + (xmm MOD 8) * 8 + reg1 MOD 8); drop - |CODE.opFLOOR: - reg1 := REG.GetAnyReg(R); + |IL.opFLOOR: + 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]; @@ -2269,23 +2235,23 @@ BEGIN addrc(rsp, 8); DEC(xmm) - |CODE.opEQF .. CODE.opGEFI: - fcmp(cmd.opcode, xmm); + |IL.opEQF .. IL.opGEF: + fcmp(opcode, xmm); DEC(xmm, 2) - |CODE.opINF: + |IL.opINF: INC(xmm); - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); lea(reg1, Numbers_Offs + 32, sDATA); movsdrm(xmm, reg1, 0); drop - |CODE.opPACK, CODE.opPACKC: - IF cmd.opcode = CODE.opPACK THEN + |IL.opPACK, IL.opPACKC: + IF opcode = IL.opPACK THEN BinOp(reg1, reg2) ELSE UnOp(reg1); - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); movrc(reg2, param2) END; push(reg1); @@ -2310,15 +2276,15 @@ BEGIN drop; drop - |CODE.opUNPK, CODE.opLADR_UNPK: + |IL.opUNPK, IL.opLADR_UNPK: - IF cmd.opcode = CODE.opLADR_UNPK THEN + IF opcode = IL.opLADR_UNPK THEN n := param2 * 8; UnOp(reg1); - reg2 := REG.GetVarReg(R, param2); + reg2 := GetVarReg(param2); regVar := reg2 # -1; IF ~regVar THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); Rex(0, reg2); OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); // lea reg2, qword[rbp+n] OutIntByte(n) @@ -2336,7 +2302,7 @@ BEGIN IF regVar THEN mov(reg2, reg1); - reg2 := REG.GetAnyReg(R) + reg2 := GetAnyReg() ELSE movmr(reg2, 0, reg1) END; @@ -2357,44 +2323,44 @@ BEGIN drop; drop - |CODE.opSADR_PARAM: + |IL.opSADR_PARAM: pushDA(stroffs + param2) - |CODE.opVADR_PARAM: + |IL.opVADR_PARAM: pushm(rbp, param2 * 8) - |CODE.opLOAD64_PARAM: + |IL.opLOAD64_PARAM: UnOp(reg1); pushm(reg1, 0); drop - |CODE.opLLOAD64_PARAM: - reg1 := REG.GetVarReg(R, param2); + |IL.opLLOAD64_PARAM: + reg1 := GetVarReg(param2); IF reg1 # -1 THEN push(reg1) ELSE pushm(rbp, param2 * 8) END - |CODE.opGLOAD64_PARAM: - reg2 := REG.GetAnyReg(R); + |IL.opGLOAD64_PARAM: + reg2 := GetAnyReg(); lea(reg2, param2, sBSS); movrm(reg2, reg2, 0); push(reg2); drop - |CODE.opCONST_PARAM: + |IL.opCONST_PARAM: pushc(param2) - |CODE.opGLOAD32_PARAM: - reg1 := REG.GetAnyReg(R); + |IL.opGLOAD32_PARAM: + reg1 := GetAnyReg(); xor(reg1, reg1); lea(reg1, param2, sBSS); movrm32(reg1, reg1, 0); push(reg1); drop - |CODE.opLOAD32_PARAM: + |IL.opLOAD32_PARAM: UnOp(reg1); movrm32(reg1, reg1, 0); shiftrc(shl, reg1, 32); @@ -2402,10 +2368,10 @@ BEGIN push(reg1); drop - |CODE.opLLOAD32_PARAM: - reg1 := REG.GetAnyReg(R); + |IL.opLLOAD32_PARAM: + reg1 := GetAnyReg(); xor(reg1, reg1); - reg2 := REG.GetVarReg(R, param2); + reg2 := GetVarReg(param2); IF reg2 # -1 THEN mov(reg1, reg2) ELSE @@ -2414,14 +2380,14 @@ BEGIN push(reg1); drop - |CODE.opLADR_SAVEC: + |IL.opLADR_SAVEC: n := param1 * 8; - reg1 := REG.GetVarReg(R, param1); + reg1 := GetVarReg(param1); IF reg1 # -1 THEN movrc(reg1, param2) ELSE IF isLong(param2) THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); movrc(reg2, param2); movmr(rbp, n, reg2); drop @@ -2432,17 +2398,17 @@ BEGIN END END - |CODE.opGADR_SAVEC: + |IL.opGADR_SAVEC: IF isLong(param2) THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); movrc(reg1, param2); - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); lea(reg2, param1, sBSS); movmr(reg2, 0, reg1); drop; drop ELSE - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); lea(reg2, param1, sBSS); Rex(reg2, 0); OutByte2(0C7H, reg2 MOD 8); // mov qword[reg2], param2 @@ -2450,9 +2416,9 @@ BEGIN drop END - |CODE.opLADR_SAVE: + |IL.opLADR_SAVE: UnOp(reg1); - reg2 := REG.GetVarReg(R, param2); + reg2 := GetVarReg(param2); IF reg2 # -1 THEN mov(reg2, reg1) ELSE @@ -2460,79 +2426,48 @@ BEGIN END; drop - |CODE.opLADR_INC1: - reg1 := REG.GetVarReg(R, param2); - IF reg1 # -1 THEN - incr(reg1) - ELSE - n := param2 * 8; - OutByte3(48H, 0FFH, 45H + long(n)); // inc qword[rbp+n] - OutIntByte(n) - END - - |CODE.opLADR_DEC1: - reg1 := REG.GetVarReg(R, param2); - IF reg1 # -1 THEN - decr(reg1) - ELSE - n := param2 * 8; - OutByte3(48H, 0FFH, 4DH + long(n)); // dec qword[rbp+n] - OutIntByte(n) - END - - |CODE.opLADR_INCC, CODE.opLADR_DECC: - reg1 := REG.GetVarReg(R, param1); + |IL.opLADR_INCC: + reg1 := GetVarReg(param1); IF isLong(param2) THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); movrc(reg2, param2); IF reg1 # -1 THEN - IF cmd.opcode = CODE.opLADR_DECC THEN - sub(reg1, reg2) - ELSE - add(reg1, reg2) - END + add(reg1, reg2) ELSE n := param1 * 8; Rex(0, reg2); - OutByte2(01H + 28H * ORD(cmd.opcode = CODE.opLADR_DECC), 45H + long(n) + (reg2 MOD 8) * 8); - OutIntByte(n) // add/sub qword[rbp+n],reg2 + OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8); + OutIntByte(n) // add qword[rbp+n],reg2 END; drop - ELSE + ELSIF ABS(param2) = 1 THEN IF reg1 # -1 THEN - IF cmd.opcode = CODE.opLADR_DECC THEN - subrc(reg1, param2) + IF param2 = 1 THEN + incr(reg1) ELSE - addrc(reg1, param2) + decr(reg1) END ELSE n := param1 * 8; - OutByte3(48H, 81H + short(param2), 45H + long(n) + 28H * ORD(cmd.opcode = CODE.opLADR_DECC)); + OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); // inc/dec qword[rbp+n] + OutIntByte(n) + END + ELSE + IF reg1 # -1 THEN + addrc(reg1, param2) + ELSE + n := param1 * 8; + OutByte3(48H, 81H + short(param2), 45H + long(n)); OutIntByte(n); - OutIntByte(param2) // add/sub qword[rbp+n],param2 + OutIntByte(param2) // add qword[rbp+n],param2 END END - |CODE.opLADR_INC1B, CODE.opLADR_DEC1B: - reg1 := REG.GetVarReg(R, param2); - IF reg1 # -1 THEN - IF cmd.opcode = CODE.opLADR_DEC1B THEN - decr(reg1) - ELSE - incr(reg1) - END; - andrc(reg1, 255) - ELSE - n := param2 * 8; - OutByte2(0FEH, 45H + long(n) + 8 * ORD(cmd.opcode = CODE.opLADR_DEC1B)); - OutIntByte(n) // inc/dec byte[rbp+n] - END - - |CODE.opLADR_INCCB, CODE.opLADR_DECCB: - reg1 := REG.GetVarReg(R, param1); + |IL.opLADR_INCCB, IL.opLADR_DECCB: + reg1 := GetVarReg(param1); param2 := param2 MOD 256; IF reg1 # -1 THEN - IF cmd.opcode = CODE.opLADR_DECCB THEN + IF opcode = IL.opLADR_DECCB THEN subrc(reg1, param2) ELSE addrc(reg1, param2) @@ -2540,16 +2475,16 @@ BEGIN andrc(reg1, 255) ELSE n := param1 * 8; - OutByte2(80H, 45H + long(n) + 28H * ORD(cmd.opcode = CODE.opLADR_DECCB)); + OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB)); OutIntByte(n); OutByte(param2) // add/sub byte[rbp+n],param2 END - |CODE.opLADR_INC, CODE.opLADR_DEC: + |IL.opLADR_INC, IL.opLADR_DEC: UnOp(reg1); - reg2 := REG.GetVarReg(R, param2); + reg2 := GetVarReg(param2); IF reg2 # -1 THEN - IF cmd.opcode = CODE.opLADR_DEC THEN + IF opcode = IL.opLADR_DEC THEN sub(reg2, reg1) ELSE add(reg2, reg1) @@ -2557,16 +2492,16 @@ BEGIN ELSE n := param2 * 8; Rex(0, reg1); - OutByte2(01H + 28H * ORD(cmd.opcode = CODE.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8); + OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8); OutIntByte(n) // add/sub qword[rbp+n],reg1 END; drop - |CODE.opLADR_INCB, CODE.opLADR_DECB: + |IL.opLADR_INCB, IL.opLADR_DECB: UnOp(reg1); - reg2 := REG.GetVarReg(R, param2); + reg2 := GetVarReg(param2); IF reg2 # -1 THEN - IF cmd.opcode = CODE.opLADR_DECB THEN + IF opcode = IL.opLADR_DECB THEN sub(reg2, reg1) ELSE add(reg2, reg1) @@ -2577,43 +2512,43 @@ BEGIN IF reg1 >= 8 THEN OutByte(44H) END; - OutByte2(28H * ORD(cmd.opcode = CODE.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8)); + OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8)); OutIntByte(n) // add/sub byte[rbp+n], reg1_8 END; drop - |CODE.opLADR_INCL, CODE.opLADR_EXCL: + |IL.opLADR_INCL, IL.opLADR_EXCL: UnOp(reg1); cmprc(reg1, 64); - reg2 := REG.GetVarReg(R, param2); + reg2 := GetVarReg(param2); IF reg2 # -1 THEN OutByte2(73H, 4); // jnb L - oprr2(0FH, 0ABH + 8 * ORD(cmd.opcode = CODE.opLADR_EXCL), reg2, reg1) // bts/btr reg2, reg1 + oprr2(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), reg2, reg1) // bts/btr reg2, reg1 ELSE n := param2 * 8; OutByte2(73H, 5 + 3 * ORD(~isByte(n))); // jnb L Rex(0, reg1); - OutByte3(0FH, 0ABH + 8 * ORD(cmd.opcode = CODE.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8)); + OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8)); OutIntByte(n) // bts/btr qword[rbp+n], reg1 END; // L: drop - |CODE.opLADR_INCLC, CODE.opLADR_EXCLC: - reg1 := REG.GetVarReg(R, param1); + |IL.opLADR_INCLC, IL.opLADR_EXCLC: + reg1 := GetVarReg(param1); IF reg1 # -1 THEN Rex(reg1, 0); OutByte3(0FH, 0BAH, 0E8H); // bts/btr reg1, param2 - OutByte2(reg1 MOD 8 + 8 * ORD(cmd.opcode = CODE.opLADR_EXCLC), param2) + OutByte2(reg1 MOD 8 + 8 * ORD(opcode = IL.opLADR_EXCLC), param2) ELSE n := param1 * 8; OutByte3(48H, 0FH, 0BAH); // bts/btr qword[rbp+n], param2 - OutByte(6DH + long(n) + 8 * ORD(cmd.opcode = CODE.opLADR_EXCLC)); + OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); OutIntByte(n); OutByte(param2) END - |CODE.opLOOP, CODE.opENDLOOP: + |IL.opLOOP, IL.opENDLOOP: END; @@ -2626,14 +2561,14 @@ BEGIN END translate; -PROCEDURE prolog (code: CODE.CODES; modname: ARRAY OF CHAR; target, stack_size: INTEGER); +PROCEDURE prolog (code: IL.CODES; modname: ARRAY OF CHAR; target, stack_size: INTEGER); VAR - ModName_Offs, entry: INTEGER; + ModName_Offs, entry, L: INTEGER; BEGIN - ModName_Offs := CHL.Length(code.types) * 8 + CHL.Length(code.data); + ModName_Offs := tcount * 8 + CHL.Length(code.data); Numbers_Offs := ModName_Offs + LENGTH(modname) + 1; - ASSERT(MACHINE.Align(Numbers_Offs, 16)); + ASSERT(UTILS.Align(Numbers_Offs, 16)); entry := NewLabel(); X86.SetLabel(entry); @@ -2643,44 +2578,64 @@ BEGIN push(r8); push(rdx); push(rcx); - CallRTL(CODE._dllentry); + CallRTL(IL._dllentry); test(rax); jcc(je, dllret) END; - push(rsp); + IF target = mConst.Target_iELF64 THEN + push(rsp) + ELSE + pushc(0) + END; + lea(rax, entry, sCODE); push(rax); pushDA(0); //TYPES - pushc(CHL.Length(code.types)); + pushc(tcount); pushDA(ModName_Offs); //MODNAME - CallRTL(CODE._init) + CallRTL(IL._init); + + IF target IN {mConst.Target_iConsole64, mConst.Target_iGUI64} THEN + L := NewLabel(); + pushc(0); + push(rsp); + pushc(1024 * 1024 * stack_size); + pushc(0); + CallRTL(IL._new); + pop(rax); + test(rax); + jcc(je, L); + addrc(rax, 1024 * 1024 * stack_size - 8); + mov(rsp, rax); + X86.SetLabel(L) + END END prolog; -PROCEDURE epilog (code: CODE.CODES; modname: ARRAY OF CHAR; target: INTEGER); +PROCEDURE epilog (code: IL.CODES; modname: ARRAY OF CHAR; target: INTEGER); VAR i, n: INTEGER; number: Number; - exp: CODE.EXPORT_PROC; + exp: IL.EXPORT_PROC; PROCEDURE import (imp: LISTS.LIST); VAR - lib: CODE.IMPORT_LIB; - proc: CODE.IMPORT_PROC; + lib: IL.IMPORT_LIB; + proc: IL.IMPORT_PROC; BEGIN - lib := imp.first(CODE.IMPORT_LIB); + lib := imp.first(IL.IMPORT_LIB); WHILE lib # NIL DO BIN.Import(prog, lib.name, 0); - proc := lib.procs.first(CODE.IMPORT_PROC); + proc := lib.procs.first(IL.IMPORT_PROC); WHILE proc # NIL DO BIN.Import(prog, proc.name, proc.label); - proc := proc.next(CODE.IMPORT_PROC) + proc := proc.next(IL.IMPORT_PROC) END; - lib := lib.next(CODE.IMPORT_LIB) + lib := lib.next(IL.IMPORT_LIB) END END import; @@ -2690,15 +2645,21 @@ BEGIN IF target = mConst.Target_iDLL64 THEN X86.SetLabel(dllret); OutByte(0C3H) // ret + ELSIF target = mConst.Target_iELFSO64 THEN + sofinit := NewLabel(); + OutByte(0C3H); // ret + X86.SetLabel(sofinit); + CallRTL(IL._sofinit); + OutByte(0C3H) // ret ELSE pushc(0); - CallRTL(CODE._exit) + CallRTL(IL._exit) END; X86.fixup; i := 0; - WHILE i < CHL.Length(code.types) DO + WHILE i < tcount DO BIN.PutData64LE(prog, CHL.GetInt(code.types, i)); INC(i) END; @@ -2712,7 +2673,7 @@ BEGIN BIN.PutDataStr(prog, modname); BIN.PutData(prog, 0); n := CHL.Length(prog.data); - ASSERT(MACHINE.Align(n, 16)); + ASSERT(UTILS.Align(n, 16)); i := n - CHL.Length(prog.data); WHILE i > 0 DO BIN.PutData(prog, 0); @@ -2724,10 +2685,10 @@ BEGIN number := number.next(Number) END; - exp := code.export.first(CODE.EXPORT_PROC); + exp := code.export.first(IL.EXPORT_PROC); WHILE exp # NIL DO BIN.Export(prog, exp.name, exp.label); - exp := exp.next(CODE.EXPORT_PROC) + exp := exp.next(IL.EXPORT_PROC) END; import(code.import) @@ -2758,12 +2719,13 @@ BEGIN END rsave; -PROCEDURE CodeGen* (code: CODE.CODES; outname: ARRAY OF CHAR; target, stack, base: INTEGER); +PROCEDURE CodeGen* (code: IL.CODES; outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); VAR path, modname, ext: PATHS.PATH; - n: INTEGER; BEGIN + tcount := CHL.Length(code.types); + Win64RegPar[0] := rcx; Win64RegPar[1] := rdx; Win64RegPar[2] := r8; @@ -2779,13 +2741,9 @@ BEGIN PATHS.split(outname, path, modname, ext); S.append(modname, ext); - R := REG.Create(push, pop, mov, xchg, rload, rsave, {rax, r10, r11}, {rcx, rdx, r8, r9}); + REG.Init(R, push, pop, mov, xchg, rload, rsave, {rax, r10, r11}, {rcx, rdx, r8, r9}); - n := code.dmin - CHL.Length(code.data); - IF n > 0 THEN - INC(code.bss, n) - END; - code.bss := MAX(code.bss, 8); + code.bss := MAX(code.bss, MAX(code.dmin - CHL.Length(code.data), 8)); Numbers := LISTS.create(NIL); Numbers_Count := 0; @@ -2798,19 +2756,19 @@ BEGIN NewNumber(LSR(ASR(ROR(1, 1), 9), 2)); (* {52..61} *) prog := BIN.create(code.lcount); - BIN.SetParams(prog, code.bss, stack, WCHR(1), WCHR(0)); + BIN.SetParams(prog, code.bss, 1, WCHR(1), WCHR(0)); X86.SetProgram(prog); - prolog(code, modname, target, stack); - translate(code.commands, CHL.Length(code.types) * 8); + prolog(code, modname, target, options.stack); + translate(code.commands, tcount * 8); epilog(code, modname, target); BIN.fixup(prog); IF target IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64} THEN - PE32.write(prog, outname, base, target = mConst.Target_iConsole64, target = mConst.Target_iDLL64, TRUE) - ELSIF target = mConst.Target_iELF64 THEN - ELF.write(prog, outname, TRUE) + PE32.write(prog, outname, options.base, target = mConst.Target_iConsole64, target = mConst.Target_iDLL64, TRUE) + ELSIF target IN {mConst.Target_iELF64, mConst.Target_iELFSO64} THEN + ELF.write(prog, outname, sofinit, target = mConst.Target_iELFSO64, TRUE) END END CodeGen; diff --git a/programs/develop/oberon07/Source/ARITH.ob07 b/programs/develop/oberon07/Source/ARITH.ob07 index 3ee0ab9a6e..7a5734ab46 100644 --- a/programs/develop/oberon07/Source/ARITH.ob07 +++ b/programs/develop/oberon07/Source/ARITH.ob07 @@ -7,7 +7,7 @@ MODULE ARITH; -IMPORT AVLTREES, STRINGS, MACHINE, UTILS; +IMPORT AVLTREES, STRINGS, UTILS; CONST @@ -53,10 +53,7 @@ BEGIN ELSIF v.typ = tWCHAR THEN res := v.int ELSIF v.typ = tSET THEN - res := ORD(v.set); - IF MACHINE._64to32 THEN - res := MACHINE.Int32To64(res) - END + res := UTILS.Long(ORD(v.set)) ELSIF v.typ = tBOOLEAN THEN res := ORD(v.bool) END @@ -88,13 +85,13 @@ VAR BEGIN error := FALSE; - IF (v.typ = tINTEGER) & ((v.int < MACHINE.target.minInt) OR (v.int > MACHINE.target.maxInt)) THEN + IF (v.typ = tINTEGER) & ((v.int < UTILS.target.minInt) OR (v.int > UTILS.target.maxInt)) THEN error := TRUE ELSIF (v.typ = tCHAR) & ((v.int < 0) OR (v.int > 255)) THEN error := TRUE ELSIF (v.typ = tWCHAR) & ((v.int < 0) OR (v.int > 65535)) THEN error := TRUE - ELSIF (v.typ = tREAL) & ((v.float < -MACHINE.target.maxReal) OR (v.float > MACHINE.target.maxReal)) THEN + ELSIF (v.typ = tREAL) & ((v.float < -UTILS.target.maxReal) OR (v.float > UTILS.target.maxReal)) THEN error := TRUE END @@ -172,7 +169,7 @@ BEGIN n := i END; - IF (n # -1) & (i - n + 1 > MACHINE.target.maxHex) THEN + IF (n # -1) & (i - n + 1 > UTILS.target.maxHex) THEN error := 2 ELSE value := value * 16 + d; @@ -181,9 +178,7 @@ BEGIN END; - IF MACHINE._64to32 THEN - value := MACHINE.Int32To64(value); - END; + value := UTILS.Long(value); IF (s[i] = "X") & (n # -1) & (i - n > 4) THEN error := 3 @@ -471,58 +466,53 @@ END mulInt; PROCEDURE _ASR (x, n: INTEGER): INTEGER; -BEGIN - IF MACHINE._64to32 THEN - x := MACHINE.Int32To64(x) - END - - RETURN ASR(x, n) + RETURN ASR(UTILS.Long(x), n) END _ASR; PROCEDURE _LSR (x, n: INTEGER): INTEGER; -BEGIN - IF MACHINE._64to32 THEN - x := MACHINE.Int64To32(x); - x := LSR(x, n); - x := MACHINE.Int32To64(x) - ELSE - x := LSR(x, n) - END - - RETURN x + RETURN UTILS.Long(LSR(UTILS.Short(x), n)) END _LSR; PROCEDURE _LSL (x, n: INTEGER): INTEGER; -BEGIN - x := LSL(x, n); - IF MACHINE._64to32 THEN - x := MACHINE.Int32To64(x) - END - - RETURN x + RETURN UTILS.Long(LSL(x, n)) END _LSL; PROCEDURE _ROR1_32 (x: INTEGER): INTEGER; BEGIN - x := MACHINE.Int64To32(x); + x := UTILS.Short(x); x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31))) - RETURN MACHINE.Int32To64(x) + 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 - IF MACHINE._64to32 THEN + + 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 - ELSE - x := ROR(x, n) END RETURN x @@ -587,11 +577,7 @@ BEGIN CASE v.typ OF |tCHAR, tWCHAR: |tBOOLEAN: v.int := ORD(v.bool) - |tSET: - v.int := ORD(v.set); - IF MACHINE._64to32 THEN - v.int := MACHINE.Int32To64(v.int) - END + |tSET: v.int := UTILS.Long(ORD(v.set)) END; v.typ := tINTEGER END ord; @@ -616,7 +602,7 @@ VAR res: BOOLEAN; BEGIN - res := FALSE; + res := FALSE; CASE v.typ OF |tREAL: @@ -627,8 +613,8 @@ BEGIN v.int := ABS(v.int); res := TRUE END - END - + END + RETURN res END abs; @@ -787,7 +773,7 @@ BEGIN |"I": IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN - IF range(v, 0, MACHINE.target.maxSet) THEN + IF range(v, 0, UTILS.target.maxSet) THEN res := v.int IN v2.set ELSE error := 2 diff --git a/programs/develop/oberon07/Source/AVLTREES.ob07 b/programs/develop/oberon07/Source/AVLTREES.ob07 index 2fe539173a..84053be03e 100644 --- a/programs/develop/oberon07/Source/AVLTREES.ob07 +++ b/programs/develop/oberon07/Source/AVLTREES.ob07 @@ -1,11 +1,11 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) -MODULE AVLTREES; +MODULE AVLTREES; IMPORT C := COLLECTIONS; @@ -39,7 +39,7 @@ VAR node: NODE; citem: C.ITEM; -BEGIN +BEGIN citem := C.pop(nodes); IF citem = NIL THEN NEW(node) @@ -181,8 +181,8 @@ BEGIN IF destructor # NIL THEN destructor(node.data) - END; - + END; + C.push(nodes, node); node := NIL; diff --git a/programs/develop/oberon07/Source/BIN.ob07 b/programs/develop/oberon07/Source/BIN.ob07 index faba2e6fc2..a3f7db6433 100644 --- a/programs/develop/oberon07/Source/BIN.ob07 +++ b/programs/develop/oberon07/Source/BIN.ob07 @@ -7,7 +7,7 @@ MODULE BIN; -IMPORT LISTS, MACHINE, CHL := CHUNKLISTS, ARITH, UTILS; +IMPORT LISTS, CHL := CHUNKLISTS, ARITH, UTILS; CONST @@ -138,7 +138,10 @@ BEGIN END; IF UTILS.bit_depth = 64 THEN - x := MACHINE.Int32To64(x) + x := LSL(x, 16); + x := LSL(x, 16); + x := ASR(x, 16); + x := ASR(x, 16) END RETURN x @@ -151,7 +154,7 @@ VAR BEGIN FOR i := 0 TO 3 DO - CHL.SetByte(array, idx + i, MACHINE.Byte(x, i)) + CHL.SetByte(array, idx + i, UTILS.Byte(x, i)) END END put32le; @@ -162,7 +165,7 @@ VAR BEGIN FOR i := 0 TO 3 DO - CHL.PushByte(program.data, MACHINE.Byte(x, i)) + CHL.PushByte(program.data, UTILS.Byte(x, i)) END END PutData32LE; @@ -173,7 +176,7 @@ VAR BEGIN FOR i := 0 TO 7 DO - CHL.PushByte(program.data, MACHINE.Byte(x, i)) + CHL.PushByte(program.data, UTILS.Byte(x, i)) END END PutData64LE; @@ -203,7 +206,7 @@ VAR BEGIN FOR i := 0 TO 3 DO - CHL.PushByte(program.code, MACHINE.Byte(x, i)) + CHL.PushByte(program.code, UTILS.Byte(x, i)) END END PutCode32LE; @@ -217,7 +220,6 @@ END SetLabel; PROCEDURE Import* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER); VAR imp: IMPRT; - i: INTEGER; BEGIN CHL.PushByte(program.import, 0); @@ -228,16 +230,9 @@ BEGIN END; NEW(imp); - imp.nameoffs := CHL.Length(program.import); + imp.nameoffs := CHL.PushStr(program.import, name); imp.label := label; - LISTS.push(program.imp_list, imp); - - i := 0; - WHILE name[i] # 0X DO - CHL.PushByte(program.import, ORD(name[i])); - INC(i) - END; - CHL.PushByte(program.import, 0) + LISTS.push(program.imp_list, imp) END Import; @@ -262,19 +257,11 @@ END less; PROCEDURE Export* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER); VAR exp, cur: EXPRT; - i: INTEGER; BEGIN NEW(exp); - exp.nameoffs := CHL.Length(program.export); exp.label := CHL.GetInt(program.labels, label); - - i := 0; - WHILE name[i] # 0X DO - CHL.PushByte(program.export, ORD(name[i])); - INC(i) - END; - CHL.PushByte(program.export, 0); + exp.nameoffs := CHL.PushStr(program.export, name); cur := program.exp_list.first(EXPRT); WHILE (cur # NIL) & less(program.export, cur, exp) DO @@ -389,7 +376,7 @@ BEGIN array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1]) END; - idx := idx + k + INC(idx, k) END InitArray; diff --git a/programs/develop/oberon07/Source/CHUNKLISTS.ob07 b/programs/develop/oberon07/Source/CHUNKLISTS.ob07 index 015fe6f1bb..b604c2d6cc 100644 --- a/programs/develop/oberon07/Source/CHUNKLISTS.ob07 +++ b/programs/develop/oberon07/Source/CHUNKLISTS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) @@ -118,11 +118,46 @@ BEGIN 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* (file: WR.FILE; list: BYTELIST); VAR chunk: BYTECHUNK; -BEGIN +BEGIN chunk := list.first(BYTECHUNK); WHILE chunk # NIL DO WR.Write(file, chunk.data, chunk.count); diff --git a/programs/develop/oberon07/Source/COLLECTIONS.ob07 b/programs/develop/oberon07/Source/COLLECTIONS.ob07 index 3e4175af1d..311d6dfac3 100644 --- a/programs/develop/oberon07/Source/COLLECTIONS.ob07 +++ b/programs/develop/oberon07/Source/COLLECTIONS.ob07 @@ -1,12 +1,12 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) MODULE COLLECTIONS; - + TYPE diff --git a/programs/develop/oberon07/Source/CONSOLE.ob07 b/programs/develop/oberon07/Source/CONSOLE.ob07 index e5c293a429..7b4072faa9 100644 --- a/programs/develop/oberon07/Source/CONSOLE.ob07 +++ b/programs/develop/oberon07/Source/CONSOLE.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) @@ -23,29 +23,39 @@ BEGIN END String; -PROCEDURE Int* (n: INTEGER); +PROCEDURE Int* (x: INTEGER); VAR - s: ARRAY 32 OF CHAR; + s: ARRAY 24 OF CHAR; BEGIN - STRINGS.IntToStr(n, s); + STRINGS.IntToStr(x, s); String(s) END Int; -PROCEDURE Int2* (n: INTEGER); +PROCEDURE Hex* (x, n: INTEGER); +VAR + s: ARRAY 24 OF CHAR; + BEGIN - IF n < 10 THEN + STRINGS.IntToHex(x, s, n); + String(s) +END Hex; + + +PROCEDURE Int2* (x: INTEGER); +BEGIN + IF x < 10 THEN String("0") END; - Int(n) + Int(x) END Int2; PROCEDURE Ln*; BEGIN String(UTILS.eol) -END Ln; +END Ln; PROCEDURE StringLn* (s: ARRAY OF CHAR); @@ -55,16 +65,16 @@ BEGIN END StringLn; -PROCEDURE IntLn* (n: INTEGER); -BEGIN - Int(n); +PROCEDURE IntLn* (x: INTEGER); +BEGIN + Int(x); Ln END IntLn; -PROCEDURE Int2Ln* (n: INTEGER); -BEGIN - Int2(n); +PROCEDURE Int2Ln* (x: INTEGER); +BEGIN + Int2(x); Ln END Int2Ln; diff --git a/programs/develop/oberon07/Source/CONSTANTS.ob07 b/programs/develop/oberon07/Source/CONSTANTS.ob07 index db218cada1..a3b2b2de2b 100644 --- a/programs/develop/oberon07/Source/CONSTANTS.ob07 +++ b/programs/develop/oberon07/Source/CONSTANTS.ob07 @@ -9,8 +9,8 @@ MODULE CONSTANTS; CONST - vMajor* = 0; - vMinor* = 98; + vMajor* = 1; + vMinor* = 0; FILE_EXT* = ".ob07"; RTL_NAME* = "RTL"; @@ -26,7 +26,10 @@ CONST Target_iGUI64* = 7; Target_iDLL64* = 8; Target_iELF32* = 9; - Target_iELF64* = 10; + Target_iELFSO32* = 10; + Target_iELF64* = 11; + Target_iELFSO64* = 12; + Target_iMSP430* = 13; Target_sConsole* = "console"; Target_sGUI* = "gui"; @@ -37,7 +40,10 @@ CONST Target_sGUI64* = "gui64"; Target_sDLL64* = "dll64"; Target_sELF32* = "elfexe"; + Target_sELFSO32* = "elfso"; Target_sELF64* = "elfexe64"; + Target_sELFSO64* = "elfso64"; + Target_sMSP430* = "msp430"; END CONSTANTS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/Compiler.ob07 b/programs/develop/oberon07/Source/Compiler.ob07 index d53c866736..0156182889 100644 --- a/programs/develop/oberon07/Source/Compiler.ob07 +++ b/programs/develop/oberon07/Source/Compiler.ob07 @@ -7,7 +7,7 @@ MODULE Compiler; -IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, C := CONSOLE, ERRORS, STRINGS, mConst := CONSTANTS, WRITER; +IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, PROG, C := CONSOLE, ERRORS, STRINGS, mConst := CONSTANTS, WRITER, MSP430; PROCEDURE Target (s: ARRAY OF CHAR): INTEGER; @@ -33,8 +33,14 @@ BEGIN res := mConst.Target_iDLL64 ELSIF s = mConst.Target_sELF32 THEN res := mConst.Target_iELF32 + ELSIF s = mConst.Target_sELFSO32 THEN + res := mConst.Target_iELFSO32 ELSIF s = mConst.Target_sELF64 THEN res := mConst.Target_iELF64 + ELSIF s = mConst.Target_sELFSO64 THEN + res := mConst.Target_iELFSO64 + ELSIF s = mConst.Target_sMSP430 THEN + res := mConst.Target_iMSP430 ELSE res := 0 END @@ -43,7 +49,7 @@ BEGIN END Target; -PROCEDURE keys (VAR StackSize, BaseAddress, Version: INTEGER; VAR pic: BOOLEAN; VAR checking: SET); +PROCEDURE keys (VAR options: PROG.OPTIONS); VAR param: PARS.PATH; i, j: INTEGER; @@ -51,8 +57,10 @@ VAR value: INTEGER; minor, major: INTEGER; + checking: SET; BEGIN + checking := options.checking; end := FALSE; i := 4; REPEAT @@ -62,7 +70,7 @@ BEGIN INC(i); UTILS.GetArg(i, param); IF STRINGS.StrToInt(param, value) & (1 <= value) & (value <= 32) THEN - StackSize := value + options.stack := value END; IF param[0] = "-" THEN DEC(i) @@ -72,7 +80,27 @@ BEGIN INC(i); UTILS.GetArg(i, param); IF STRINGS.StrToInt(param, value) THEN - BaseAddress := ((value DIV 64) * 64) * 1024 + options.base := ((value DIV 64) * 64) * 1024 + END; + IF param[0] = "-" THEN + DEC(i) + END + + ELSIF param = "-ram" THEN + INC(i); + UTILS.GetArg(i, param); + IF STRINGS.StrToInt(param, value) THEN + options.ram := value + END; + IF param[0] = "-" THEN + DEC(i) + END + + ELSIF param = "-rom" THEN + INC(i); + UTILS.GetArg(i, param); + IF STRINGS.StrToInt(param, value) THEN + options.rom := value END; IF param[0] = "-" THEN DEC(i) @@ -109,32 +137,34 @@ BEGIN END; INC(j) - END + END; + END ELSIF param = "-ver" THEN INC(i); UTILS.GetArg(i, param); IF STRINGS.StrToVer(param, major, minor) THEN - Version := major * 65536 + minor + options.version := major * 65536 + minor END; IF param[0] = "-" THEN DEC(i) END ELSIF param = "-pic" THEN - pic := TRUE + options.pic := TRUE ELSIF param = "" THEN end := TRUE ELSE - ERRORS.error3("bad parameter: ", param, "") + ERRORS.BadParam(param) END; INC(i) - UNTIL end + UNTIL end; + options.checking := checking END keys; @@ -149,38 +179,34 @@ VAR outname: PARS.PATH; param: PARS.PATH; temp: PARS.PATH; - target: INTEGER; - + bit_depth: INTEGER; time: INTEGER; - - StackSize, - Version, - BaseAdr: INTEGER; - pic: BOOLEAN; - checking: SET; - - bits64: BOOLEAN; + options: PROG.OPTIONS; BEGIN - StackSize := 2; - Version := 65536; - pic := FALSE; - checking := ST.chkALL; + options.stack := 2; + options.version := 65536; + options.pic := FALSE; + options.checking := ST.chkALL; PATHS.GetCurrentDirectory(app_path); lib_path := app_path; UTILS.GetArg(1, inname); + C.Ln; + C.String("Akron Oberon Compiler v"); C.Int(mConst.vMajor); C.String("."); C.Int2(mConst.vMinor); + C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit)"); + C.StringLn("Copyright (c) 2018-2019, Anton Krotov"); + IF inname = "" THEN - C.String("Akron Oberon-07/16 Compiler v"); C.Int(mConst.vMajor); C.String("."); C.Int2(mConst.vMinor); - C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit)"); C.Ln; + C.Ln; C.StringLn("Usage: Compiler
[optional settings]"); C.Ln; IF UTILS.bit_depth = 64 THEN - C.StringLn('target = console | gui | dll | console64 | gui64 | dll64 | kos | obj | elfexe | elfexe64'); C.Ln; + C.StringLn('target = console | gui | dll | console64 | gui64 | dll64 | kos | obj | elfexe | elfso | elfexe64 | elfso64 | msp430'); C.Ln; ELSIF UTILS.bit_depth = 32 THEN - C.StringLn('target = console | gui | dll | kos | obj | elfexe'); C.Ln; + C.StringLn('target = console | gui | dll | kos | obj | elfexe | elfso | msp430'); C.Ln; END; C.StringLn("optional settings:"); C.Ln; C.StringLn(" -stk set size of stack in megabytes"); C.Ln; @@ -188,14 +214,17 @@ BEGIN C.StringLn(' -ver set version of program'); C.Ln; C.StringLn(' -nochk <"ptibcwra"> disable runtime checking (pointers, types, indexes,'); C.StringLn(' BYTE, CHR, WCHR)'); C.Ln; + C.StringLn(" -ram set size of RAM in bytes (MSP430)"); C.Ln; + C.StringLn(" -rom set size of ROM in bytes (MSP430)"); C.Ln; UTILS.Exit(0) END; PATHS.split(inname, path, modname, ext); IF ext # mConst.FILE_EXT THEN - ERRORS.error3('inputfile name extension must be "', mConst.FILE_EXT, '"') + ERRORS.Error(207) END; + IF PATHS.isRelative(path) THEN PATHS.RelPath(app_path, path, temp); path := temp @@ -203,7 +232,7 @@ BEGIN UTILS.GetArg(2, outname); IF outname = "" THEN - ERRORS.error1("not enough parameters") + ERRORS.Error(205) END; IF PATHS.isRelative(outname) THEN PATHS.RelPath(app_path, outname, temp); @@ -212,59 +241,70 @@ BEGIN UTILS.GetArg(3, param); IF param = "" THEN - ERRORS.error1("not enough parameters") + ERRORS.Error(205) END; target := Target(param); IF target = 0 THEN - ERRORS.error1("bad parameter ") + ERRORS.Error(206) END; - bits64 := target IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64, mConst.Target_iELF64}; - - IF bits64 THEN - IF UTILS.bit_depth = 32 THEN - ERRORS.error1("bad parameter ") - END; - PARS.init(64, target) - ELSE - PARS.init(32, target) + CASE target OF + |mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64, mConst.Target_iELF64, mConst.Target_iELFSO64: + bit_depth := 64 + |mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, + mConst.Target_iKolibri, mConst.Target_iObject, mConst.Target_iELF32, mConst.Target_iELFSO32: + bit_depth := 32 + |mConst.Target_iMSP430: + bit_depth := 16; + options.ram := MSP430.minRAM; + options.rom := MSP430.minROM END; - PARS.program.dll := target IN {mConst.Target_iDLL, mConst.Target_iObject, mConst.Target_iDLL64}; - PARS.program.obj := target = mConst.Target_iObject; + IF UTILS.bit_depth < bit_depth THEN + ERRORS.Error(206) + END; STRINGS.append(lib_path, "lib"); STRINGS.append(lib_path, UTILS.slash); - IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN + CASE target OF + |mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL: IF target = mConst.Target_iDLL THEN - BaseAdr := 10000000H + options.base := 10000000H ELSE - BaseAdr := 400000H + options.base := 400000H END; STRINGS.append(lib_path, "Windows32") - ELSIF target IN {mConst.Target_iKolibri, mConst.Target_iObject} THEN + |mConst.Target_iKolibri, mConst.Target_iObject: STRINGS.append(lib_path, "KolibriOS") - ELSIF target = mConst.Target_iELF32 THEN + |mConst.Target_iELF32, mConst.Target_iELFSO32: STRINGS.append(lib_path, "Linux32") - ELSIF target = mConst.Target_iELF64 THEN + |mConst.Target_iELF64, mConst.Target_iELFSO64: STRINGS.append(lib_path, "Linux64") - ELSIF target IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64} THEN + |mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64: STRINGS.append(lib_path, "Windows64") + |mConst.Target_iMSP430: + STRINGS.append(lib_path, "MSP430") + END; STRINGS.append(lib_path, UTILS.slash); - keys(StackSize, BaseAdr, Version, pic, checking); + keys(options); - ST.compile(path, lib_path, modname, outname, target, Version, StackSize, BaseAdr, pic, checking); + PARS.init(bit_depth, target, options); + + PARS.program.dll := target IN {mConst.Target_iELFSO32, mConst.Target_iELFSO64, mConst.Target_iDLL, mConst.Target_iDLL64, mConst.Target_iObject}; + PARS.program.obj := target = mConst.Target_iObject; + + ST.compile(path, lib_path, modname, outname, target, options); time := UTILS.GetTickCount() - UTILS.time; diff --git a/programs/develop/oberon07/Source/ELF.ob07 b/programs/develop/oberon07/Source/ELF.ob07 index 749ee5632a..2c74d467f0 100644 --- a/programs/develop/oberon07/Source/ELF.ob07 +++ b/programs/develop/oberon07/Source/ELF.ob07 @@ -7,7 +7,7 @@ MODULE ELF; -IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS; +IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS; CONST @@ -68,9 +68,35 @@ TYPE 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; + + FILE = WR.FILE; +VAR + + dynamic: LISTS.LIST; + strtab: CHL.BYTELIST; + symtab: LISTS.LIST; + + hashtab, bucket, chain: CHL.INTLIST; + + PROCEDURE align (n, _align: INTEGER): INTEGER; BEGIN IF n MOD _align # 0 THEN @@ -136,7 +162,75 @@ BEGIN END fixup; -PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; amd64: BOOLEAN); +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 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; + + +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; @@ -145,33 +239,67 @@ CONST 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, LoadAdr, offset, pad, VA: INTEGER; + i, BaseAdr, offset, pad, VA, symCount: INTEGER; SizeOf: RECORD header, code, data, bss: INTEGER END; + Offset: RECORD symtab, reltab, hash, strtab, dyn: INTEGER END; + File: FILE; - str: ARRAY 40 OF CHAR; lstr: INTEGER; - Dyn: ARRAY 350 OF BYTE; + Interpreter: ARRAY 40 OF CHAR; lenInterpreter: INTEGER; + + item: LISTS.ITEM; + + Name: ARRAY 2048 OF CHAR; BEGIN - IF amd64 THEN - str := "/lib64/ld-linux-x86-64.so.2" - ELSE - str := "/lib/ld-linux.so.2" - END; - lstr := LENGTH(str); + dynamic := LISTS.create(NIL); + symtab := LISTS.create(NIL); + strtab := CHL.CreateByteList(); IF amd64 THEN - LoadAdr := 400000H + BaseAdr := exeBaseAddress64; + Interpreter := linuxInterpreter64 ELSE - LoadAdr := 08048000H + 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; @@ -192,7 +320,12 @@ BEGIN ehdr.e_ident[i] := 0 END; - ehdr.e_type := WCHR(ET_EXEC); + 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; @@ -218,24 +351,92 @@ BEGIN phdr[interp].p_type := 3; phdr[interp].p_offset := SizeOf.header; - phdr[interp].p_vaddr := LoadAdr + phdr[interp].p_offset; - phdr[interp].p_paddr := LoadAdr + phdr[interp].p_offset; - phdr[interp].p_filesz := lstr + 1; - phdr[interp].p_memsz := lstr + 1; + 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 := LoadAdr + phdr[dyn].p_offset; - phdr[dyn].p_paddr := LoadAdr + phdr[dyn].p_offset; - IF amd64 THEN - phdr[dyn].p_filesz := 0A0H; - phdr[dyn].p_memsz := 0A0H - ELSE - phdr[dyn].p_filesz := 50H; - phdr[dyn].p_memsz := 50H + phdr[dyn].p_vaddr := BaseAdr + phdr[dyn].p_offset; + phdr[dyn].p_paddr := phdr[dyn].p_vaddr; + + hashtab := CHL.CreateIntList(); + + CHL.PushInt(hashtab, HashStr("")); + NewSym(CHL.PushStr(strtab, ""), 0, 0, 0X, 0X, 0X); + CHL.PushInt(hashtab, HashStr("dlopen")); + NewSym(CHL.PushStr(strtab, "dlopen"), 0, 0, 12X, 0X, 0X); + CHL.PushInt(hashtab, 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, 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; + + Offset.dyn := phdr[dyn].p_offset; + + item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + Offset.dyn + BaseAdr; + item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + Offset.dyn + BaseAdr; + item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + Offset.dyn + BaseAdr; + item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash + Offset.dyn + BaseAdr; + + 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; @@ -243,20 +444,15 @@ BEGIN phdr[header].p_type := 1; phdr[header].p_offset := offset; - phdr[header].p_vaddr := LoadAdr; - phdr[header].p_paddr := LoadAdr; - IF amd64 THEN - phdr[header].p_filesz := 305H; - phdr[header].p_memsz := 305H - ELSE - phdr[header].p_filesz := 1D0H; - phdr[header].p_memsz := 1D0H - END; + phdr[header].p_vaddr := BaseAdr; + phdr[header].p_paddr := BaseAdr; + phdr[header].p_filesz := 244 + 156 * ORD(amd64) + 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; - + offset := offset + phdr[header].p_filesz; - VA := LoadAdr + offset + 1000H; + VA := BaseAdr + offset + 1000H; phdr[text].p_type := 1; phdr[text].p_offset := offset; @@ -268,9 +464,9 @@ BEGIN phdr[text].p_align := 1000H; ehdr.e_entry := phdr[text].p_vaddr; - + offset := offset + phdr[text].p_filesz; - VA := LoadAdr + offset + 2000H; + VA := BaseAdr + offset + 2000H; pad := (16 - VA MOD 16) MOD 16; phdr[data].p_type := 1; @@ -281,9 +477,9 @@ BEGIN phdr[data].p_memsz := SizeOf.data + pad; phdr[data].p_flags := PF_R + PF_W; phdr[data].p_align := 1000H; - + offset := offset + phdr[data].p_filesz; - VA := LoadAdr + offset + 3000H; + VA := BaseAdr + offset + 3000H; phdr[bss].p_type := 1; phdr[bss].p_offset := offset; @@ -294,7 +490,20 @@ BEGIN phdr[bss].p_flags := PF_R + PF_W; phdr[bss].p_align := 1000H; - fixup(program, phdr[text].p_vaddr, phdr[data].p_vaddr + pad, align(phdr[bss].p_vaddr, 16), amd64); + fixup(program, ehdr.e_entry, phdr[data].p_vaddr + pad, align(phdr[bss].p_vaddr, 16), 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; File := WR.Create(FileName); @@ -340,34 +549,94 @@ BEGIN WritePH(File, phdr[bss]) END; - FOR i := 0 TO lstr DO - WR.WriteByte(File, ORD(str[i])) + FOR i := 0 TO lenInterpreter - 1 DO + WR.WriteByte(File, ORD(Interpreter[i])) END; i := 0; IF amd64 THEN - BIN.InitArray(Dyn, i, "01000000000000000E000000000000000500000000000000DC02400000000000"); - BIN.InitArray(Dyn, i, "0A00000000000000190000000000000006000000000000004C02400000000000"); - BIN.InitArray(Dyn, i, "0B00000000000000180000000000000007000000000000009402400000000000"); - BIN.InitArray(Dyn, i, "0800000000000000300000000000000009000000000000001800000000000000"); - BIN.InitArray(Dyn, i, "0400000000000000C40240000000000000000000000000000000000000000000"); - BIN.InitArray(Dyn, i, "0000000000000000000000000000000000000000000000000100000012000000"); - BIN.InitArray(Dyn, i, "0000000000000000000000000000000008000000120000000000000000000000"); - BIN.InitArray(Dyn, i, "0000000000000000F50240000000000001000000010000000000000000000000"); - BIN.InitArray(Dyn, i, "FD02400000000000010000000200000000000000000000000100000003000000"); - BIN.InitArray(Dyn, i, "0000000001000000020000000000000000646C6F70656E00646C73796D006C69"); - BIN.InitArray(Dyn, i, "62646C2E736F2E320000000000000000000000000000000000") - ELSE - BIN.InitArray(Dyn, i, "010000000E00000005000000AF8104080A000000190000000600000057810408"); - BIN.InitArray(Dyn, i, "0B00000010000000110000008781040812000000100000001300000008000000"); - BIN.InitArray(Dyn, i, "0400000097810408000000000000000000000000000000000000000000000000"); - BIN.InitArray(Dyn, i, "0100000000000000000000001200000008000000000000000000000012000000"); - BIN.InitArray(Dyn, i, "C881040801010000CC8104080102000001000000030000000000000001000000"); - BIN.InitArray(Dyn, i, "020000000000000000646C6F70656E00646C73796D006C6962646C2E736F2E32"); - BIN.InitArray(Dyn, i, "000000000000000000") - END; + item := dynamic.first; + WHILE item # NIL DO + WR.Write64LE(File, item(Elf32_Dyn).d_tag); + WR.Write64LE(File, item(Elf32_Dyn).d_val); + item := item.next + END; - WR.Write(File, Dyn, i); + item := symtab.first; + WHILE item # NIL DO + WR.Write32LE(File, item(Elf32_Sym).name); + WR.WriteByte(File, ORD(item(Elf32_Sym).info)); + WR.WriteByte(File, ORD(item(Elf32_Sym).other)); + Write16(File, item(Elf32_Sym).shndx); + WR.Write64LE(File, item(Elf32_Sym).value); + WR.Write64LE(File, item(Elf32_Sym).size); + item := item.next + END; + + WR.Write64LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 16); + WR.Write32LE(File, 1); + WR.Write32LE(File, 1); + WR.Write64LE(File, 0); + WR.Write64LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 8); + WR.Write32LE(File, 1); + WR.Write32LE(File, 2); + WR.Write64LE(File, 0); + + WR.Write32LE(File, symCount); + WR.Write32LE(File, symCount); + + FOR i := 0 TO symCount - 1 DO + WR.Write32LE(File, CHL.GetInt(bucket, i)) + END; + + FOR i := 0 TO symCount - 1 DO + WR.Write32LE(File, CHL.GetInt(chain, i)) + END; + + CHL.WriteToFile(File, strtab); + WR.Write64LE(File, 0); + WR.Write64LE(File, 0) + + ELSE + item := dynamic.first; + WHILE item # NIL DO + WR.Write32LE(File, item(Elf32_Dyn).d_tag); + WR.Write32LE(File, item(Elf32_Dyn).d_val); + item := item.next + END; + + item := symtab.first; + WHILE item # NIL DO + WR.Write32LE(File, item(Elf32_Sym).name); + WR.Write32LE(File, item(Elf32_Sym).value); + WR.Write32LE(File, item(Elf32_Sym).size); + WR.WriteByte(File, ORD(item(Elf32_Sym).info)); + WR.WriteByte(File, ORD(item(Elf32_Sym).other)); + Write16(File, item(Elf32_Sym).shndx); + item := item.next + END; + + WR.Write32LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 8); + WR.Write32LE(File, 00000101H); + WR.Write32LE(File, phdr[dyn].p_filesz + Offset.dyn + BaseAdr - 4); + WR.Write32LE(File, 00000201H); + + WR.Write32LE(File, symCount); + WR.Write32LE(File, symCount); + + FOR i := 0 TO symCount - 1 DO + WR.Write32LE(File, CHL.GetInt(bucket, i)) + END; + + FOR i := 0 TO symCount - 1 DO + WR.Write32LE(File, CHL.GetInt(chain, i)) + END; + + CHL.WriteToFile(File, strtab); + WR.Write32LE(File, 0); + WR.Write32LE(File, 0) + + END; CHL.WriteToFile(File, program.code); WHILE pad > 0 DO diff --git a/programs/develop/oberon07/Source/ERRORS.ob07 b/programs/develop/oberon07/Source/ERRORS.ob07 index 9d242e62d9..6738d047b9 100644 --- a/programs/develop/oberon07/Source/ERRORS.ob07 +++ b/programs/develop/oberon07/Source/ERRORS.ob07 @@ -7,25 +7,35 @@ MODULE ERRORS; -IMPORT C := CONSOLE, UTILS; +IMPORT C := CONSOLE, UTILS, mConst := CONSTANTS; -PROCEDURE hintmsg* (name: ARRAY OF CHAR; line, col, hint: INTEGER); +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") + 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; +END HintMsg; -PROCEDURE errormsg* (fname: ARRAY OF CHAR; line, col, errno: INTEGER); +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") + 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(line); C.String(":"); C.Int(col); C.String(") "); + 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'" @@ -36,6 +46,7 @@ BEGIN | 6: str := "identifier 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" @@ -79,7 +90,7 @@ BEGIN | 60: str := "identifier does not match procedure name" | 61: str := "illegally marked identifier" | 62: str := "expression should be constant" - | 63: str := "'stdcall', 'ccall', 'ccall16', 'windows' or 'linux' expected" + | 63: str := "not enough RAM" | 64: str := "'(' expected" | 65: str := "',' expected" | 66: str := "incompatible parameter" @@ -126,46 +137,81 @@ BEGIN |107: str := "too large parameter of CHR" |108: str := "a variable or a procedure expected" |109: str := "expression should be constant" - |110: str := "'noalign' expected" + |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 := "'stdcall64', 'win64', 'systemv', 'windows' or 'linux' expected" - |118: str := "this flag for Windows only" - |119: str := "this flag for Linux only" + |120: str := "too many formal parameters" + + |122: str := "negative divisor" + |123: str := "illegal flag" + |124: str := "unknown flag" + |125: str := "flag not supported" END; C.StringLn(str); C.String(" file: "); C.StringLn(fname); UTILS.Exit(1) -END errormsg; +END ErrorMsg; -PROCEDURE error1* (s1: ARRAY OF CHAR); +PROCEDURE Error1 (s1: ARRAY OF CHAR); BEGIN C.Ln; C.StringLn(s1); UTILS.Exit(1) -END error1; +END Error1; -PROCEDURE error3* (s1, s2, s3: ARRAY OF CHAR); +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; +END Error3; -PROCEDURE error5* (s1, s2, s3, s4, s5: ARRAY OF CHAR); +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; +END Error5; + + +PROCEDURE WrongRTL* (ProcName: ARRAY OF CHAR); +BEGIN + Error5("procedure ", mConst.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 global variables is too large") + |205: Error1("not enough parameters") + |206: Error1("bad parameter ") + |207: Error3('inputfile name extension must be "', mConst.FILE_EXT, '"') + 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 index 23032ca6cc..fc67c1fecd 100644 --- a/programs/develop/oberon07/Source/FILES.ob07 +++ b/programs/develop/oberon07/Source/FILES.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) diff --git a/programs/develop/oberon07/Source/IL.ob07 b/programs/develop/oberon07/Source/IL.ob07 new file mode 100644 index 0000000000..89278d5bc7 --- /dev/null +++ b/programs/develop/oberon07/Source/IL.ob07 @@ -0,0 +1,1182 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018, 2019, Anton Krotov + All rights reserved. +*) + +MODULE IL; + +IMPORT LISTS, SCAN, STRINGS, CHL := CHUNKLISTS, C := COLLECTIONS; + + +CONST + + little_endian* = 0; + big_endian* = 1; + + call_stack* = 0; + call_win64* = 1; + call_sysv* = 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; opADDL* = 19; opSUBL* = 20; opADDR* = 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; + + opJNE* = 62; opJE* = 63; + + opSAVE32* = 64; opLLOAD8* = 65; + + opCONSTF* = 66; opLOADF* = 67; opSAVEF* = 68; opMULF* = 69; opDIVF* = 70; opDIVFI* = 71; + opUMINF* = 72; opADDFI* = 73; opSUBFI* = 74; opADDF* = 75; opSUBF* = 76; + + opACC* = 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; opLOOP* = 90; opENDLOOP* = 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; opADDSL* = 109; opSUBSL* = 110; opADDSR* = 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; + opODD* = 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; opERR* = 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; opJNZ* = 192; + opEQB* = 193; opNEB* = 194; opINF* = 195; opJZ* = 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; opGETC* = 215; opLENGTHW* = 216; + + opSYSVCALL* = 217; opSYSVCALLI* = 218; opSYSVCALLP* = 219; opSYSVALIGN16* = 220; opWIN64ALIGN16* = 221; + + + 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; + + + _move *= 0; + _move2 *= 1; + _strcmpw *= 2; + _exit *= 3; + _set *= 4; + _set2 *= 5; + _lengthw *= 6; + _strcpy *= 7; + _div *= 8; + _mod *= 9; + _div2 *= 10; + _mod2 *= 11; + _arrcpy *= 12; + _rot *= 13; + _new *= 14; + _dispose *= 15; + _strcmp *= 16; + _error *= 17; + _is *= 18; + _isrec *= 19; + _guard *= 20; + _guardrec *= 21; + _length *= 22; + _init *= 23; + _dllentry *= 24; + _sofinit *= 25; + + +TYPE + + LOCALVAR* = POINTER TO RECORD (LISTS.ITEM) + + offset*, size*, count*: INTEGER + + END; + + COMMAND* = POINTER TO RECORD (LISTS.ITEM) + + opcode*: INTEGER; + param1*: INTEGER; + param2*: INTEGER; + param3*: INTEGER; + float*: REAL; + variables*: LISTS.LIST; + allocReg*: BOOLEAN + + END; + + CMDSTACK = POINTER TO RECORD + + data: ARRAY 1000 OF COMMAND; + top: INTEGER + + END; + + EXPORT_PROC* = POINTER TO RECORD (LISTS.ITEM) + + label*: INTEGER; + name*: SCAN.LEXSTR + + END; + + IMPORT_LIB* = POINTER TO RECORD (LISTS.ITEM) + + name*: SCAN.LEXSTR; + procs*: LISTS.LIST + + END; + + IMPORT_PROC* = POINTER TO RECORD (LISTS.ITEM) + + label*: INTEGER; + lib*: IMPORT_LIB; + name*: SCAN.LEXSTR; + count: INTEGER + + END; + + + CODES* = POINTER TO 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 26 OF INTEGER; + errlabels*: ARRAY 12 OF INTEGER; + + charoffs: ARRAY 256 OF INTEGER; + wcharoffs: ARRAY 65536 OF INTEGER; + + fregs: INTEGER; + wstr: ARRAY 4*1024 OF WCHAR + END; + + +VAR + + codes*: CODES; + endianness: INTEGER; + numRegsFloat: INTEGER; + + commands, variables: C.COLLECTION; + + +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; + + cmd.allocReg := FALSE + + RETURN cmd +END NewCmd; + + +PROCEDURE NewVar* (): LOCALVAR; +VAR + lvar: LOCALVAR; + citem: C.ITEM; + +BEGIN + citem := C.pop(variables); + IF citem = NIL THEN + NEW(lvar) + ELSE + lvar := citem(LOCALVAR) + END; + + lvar.count := 0 + + RETURN lvar +END NewVar; + + +PROCEDURE setlast* (cmd: COMMAND); +BEGIN + codes.last := cmd +END setlast; + + +PROCEDURE getlast* (): COMMAND; + RETURN codes.last +END getlast; + + +PROCEDURE PutByte (codes: CODES; b: BYTE); +BEGIN + CHL.PushByte(codes.data, b) +END PutByte; + + +PROCEDURE putstr* (s: ARRAY OF CHAR): INTEGER; +VAR + i, n, res: INTEGER; +BEGIN + res := CHL.Length(codes.data); + + i := 0; + n := LENGTH(s); + WHILE i < n DO + PutByte(codes, ORD(s[i])); + INC(i) + END; + + PutByte(codes, 0) + + RETURN res +END putstr; + + +PROCEDURE putstr1* (c: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF codes.charoffs[c] = -1 THEN + res := CHL.Length(codes.data); + PutByte(codes, c); + PutByte(codes, 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 + res := CHL.Length(codes.data); + + IF ODD(res) THEN + PutByte(codes, 0); + INC(res) + END; + + n := STRINGS.Utf8To16(s, codes.wstr); + + i := 0; + WHILE i < n DO + IF endianness = little_endian THEN + PutByte(codes, ORD(codes.wstr[i]) MOD 256); + PutByte(codes, ORD(codes.wstr[i]) DIV 256) + ELSIF endianness = big_endian THEN + PutByte(codes, ORD(codes.wstr[i]) DIV 256); + PutByte(codes, ORD(codes.wstr[i]) MOD 256) + END; + INC(i) + END; + + PutByte(codes, 0); + PutByte(codes, 0) + + RETURN res +END putstrW; + + +PROCEDURE putstrW1* (c: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF codes.wcharoffs[c] = -1 THEN + res := CHL.Length(codes.data); + + IF ODD(res) THEN + PutByte(codes, 0); + INC(res) + END; + + IF endianness = little_endian THEN + PutByte(codes, c MOD 256); + PutByte(codes, c DIV 256) + ELSIF endianness = big_endian THEN + PutByte(codes, c DIV 256); + PutByte(codes, c MOD 256) + END; + + PutByte(codes, 0); + PutByte(codes, 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 + 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 := param2 * cur.param2 + + 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 deleteVarList (list: LISTS.LIST); +VAR + last: LISTS.ITEM; + +BEGIN + WHILE list.last # NIL DO + last := LISTS.pop(list); + C.push(variables, last) + END +END deleteVarList; + + +PROCEDURE delete (cmd: COMMAND); +BEGIN + IF cmd.variables # NIL THEN + deleteVarList(cmd.variables) + END; + 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 AddJmpCmd* (opcode: INTEGER; label: INTEGER); +VAR + prev: COMMAND; + not: BOOLEAN; + +BEGIN + prev := codes.last; + not := prev.opcode = opNOT; + IF not THEN + IF opcode = opJE THEN + opcode := opJNE + ELSIF opcode = opJNE THEN + opcode := opJE + ELSE + not := FALSE + END + END; + + AddCmd2(opcode, label, label); + + IF not THEN + delete(prev) + END + +END AddJmpCmd; + + +PROCEDURE OnError* (line, error: INTEGER); +BEGIN + AddCmd(opPUSHC, line); + AddJmpCmd(opJMP, codes.errlabels[error]) +END OnError; + + +PROCEDURE TypeGuard* (op, t: INTEGER; line, error: INTEGER); +VAR + label: INTEGER; +BEGIN + AddCmd(op, t); + label := NewLabel(); + AddJmpCmd(opJE, 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 fcmp* (opcode: INTEGER); +BEGIN + AddCmd(opcode, 0); + DEC(codes.fregs, 2); + ASSERT(codes.fregs >= 0) +END fcmp; + + +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 Enter* (label, params: INTEGER): COMMAND; +VAR + cmd: COMMAND; + +BEGIN + cmd := NewCmd(); + cmd.opcode := opENTER; + cmd.param1 := label; + cmd.param3 := params; + cmd.allocReg := TRUE; + 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 Call* (proc, callconv, fparams: INTEGER); +BEGIN + CASE callconv OF + |call_stack: AddJmpCmd(opCALL, proc) + |call_win64: AddJmpCmd(opWIN64CALL, proc) + |call_sysv: AddJmpCmd(opSYSVCALL, proc) + END; + codes.last(COMMAND).param2 := fparams +END Call; + + +PROCEDURE CallImp* (proc: LISTS.ITEM; callconv, fparams: INTEGER); +BEGIN + CASE callconv OF + |call_stack: AddJmpCmd(opCALLI, proc(IMPORT_PROC).label) + |call_win64: AddJmpCmd(opWIN64CALLI, proc(IMPORT_PROC).label) + |call_sysv: AddJmpCmd(opSYSVCALLI, proc(IMPORT_PROC).label) + END; + codes.last(COMMAND).param2 := fparams +END CallImp; + + +PROCEDURE CallP* (callconv, fparams: INTEGER); +BEGIN + 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 + AddJmpCmd(opSAVEP, proc) +END AssignProc; + + +PROCEDURE AssignImpProc* (proc: LISTS.ITEM); +BEGIN + AddJmpCmd(opSAVEIP, proc(IMPORT_PROC).label) +END AssignImpProc; + + +PROCEDURE PushProc* (proc: INTEGER); +BEGIN + AddJmpCmd(opPUSHP, proc) +END PushProc; + + +PROCEDURE PushImpProc* (proc: LISTS.ITEM); +BEGIN + AddJmpCmd(opPUSHIP, proc(IMPORT_PROC).label) +END PushImpProc; + + +PROCEDURE ProcCmp* (proc: INTEGER; eq: BOOLEAN); +BEGIN + IF eq THEN + AddJmpCmd(opEQP, proc) + ELSE + AddJmpCmd(opNEP, proc) + END +END ProcCmp; + + +PROCEDURE ProcImpCmp* (proc: LISTS.ITEM; eq: BOOLEAN); +BEGIN + IF eq THEN + AddJmpCmd(opEQIP, proc(IMPORT_PROC).label) + ELSE + AddJmpCmd(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*; +BEGIN + AddCmd0(opSAVEF); + DEC(codes.fregs); + ASSERT(codes.fregs >= 0) +END savef; + + +PROCEDURE pushf*; +BEGIN + AddCmd0(opPUSHF); + DEC(codes.fregs); + ASSERT(codes.fregs >= 0) +END pushf; + + +PROCEDURE loadf* (): BOOLEAN; +BEGIN + AddCmd0(opLOADF); + INC(codes.fregs) + RETURN codes.fregs < numRegsFloat +END loadf; + + +PROCEDURE inf* (): BOOLEAN; +BEGIN + AddCmd0(opINF); + INC(codes.fregs) + RETURN codes.fregs < numRegsFloat +END inf; + + +PROCEDURE fbinop* (opcode: INTEGER); +BEGIN + AddCmd0(opcode); + DEC(codes.fregs); + ASSERT(codes.fregs > 0) +END fbinop; + + +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 floor*; +BEGIN + AddCmd0(opFLOOR); + DEC(codes.fregs); + ASSERT(codes.fregs >= 0) +END floor; + + +PROCEDURE flt* (): BOOLEAN; +BEGIN + AddCmd0(opFLT); + INC(codes.fregs) + RETURN codes.fregs < numRegsFloat +END flt; + + +PROCEDURE odd*; +BEGIN + AddCmd0(opODD) +END odd; + + +PROCEDURE ord*; +BEGIN + AddCmd0(opORD) +END ord; + + +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); +VAR + cmd: COMMAND; + +BEGIN + cmd := NewCmd(); + cmd.opcode := opCONSTF; + cmd.float := r; + insert(codes.last, cmd); + INC(codes.fregs); + ASSERT(codes.fregs <= numRegsFloat) +END Float; + + +PROCEDURE precall* (flt: BOOLEAN): INTEGER; +VAR + res: INTEGER; +BEGIN + res := codes.fregs; + AddCmd2(opPRECALL, ORD(flt), res); + codes.fregs := 0 + RETURN res +END precall; + + +PROCEDURE resf* (fregs: INTEGER): BOOLEAN; +BEGIN + AddCmd(opRESF, fregs); + codes.fregs := fregs + 1 + RETURN codes.fregs < numRegsFloat +END resf; + + +PROCEDURE res* (fregs: INTEGER); +BEGIN + AddCmd(opRES, fregs); + codes.fregs := fregs +END res; + + +PROCEDURE retf*; +BEGIN + DEC(codes.fregs); + ASSERT(codes.fregs = 0) +END retf; + + +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 caset* (a, label: INTEGER); +BEGIN + AddCmd2(opCASET, label, a) +END caset; + + +PROCEDURE AddExp* (label: INTEGER; name: SCAN.LEXSTR); +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.LEXSTR): 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* (pNumRegsFloat, pEndianness: INTEGER); +VAR + cmd: COMMAND; + i: INTEGER; + +BEGIN + commands := C.create(); + variables := C.create(); + numRegsFloat := pNumRegsFloat; + endianness := pEndianness; + + NEW(codes); + 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; + + codes.fregs := 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 index 6d7258a34a..fe44eed0a5 100644 --- a/programs/develop/oberon07/Source/KOS.ob07 +++ b/programs/develop/oberon07/Source/KOS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) @@ -197,7 +197,7 @@ BEGIN WR.Write32LE(File, header.sp); WR.Write32LE(File, header.param); WR.Write32LE(File, header.path); - + CHL.WriteToFile(File, program.code); WR.Padding(File, FileAlignment); @@ -206,8 +206,8 @@ BEGIN FOR i := 0 TO ILen - 1 DO WR.Write32LE(File, CHL.GetInt(ImportTable, i)) - END; - + END; + CHL.WriteToFile(File, program.import); WR.Close(File) diff --git a/programs/develop/oberon07/Source/LISTS.ob07 b/programs/develop/oberon07/Source/LISTS.ob07 index 3e3188dc94..59b1342ca6 100644 --- a/programs/develop/oberon07/Source/LISTS.ob07 +++ b/programs/develop/oberon07/Source/LISTS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) @@ -168,14 +168,32 @@ BEGIN 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 + list.first := NIL; + list.last := NIL RETURN list END create; diff --git a/programs/develop/oberon07/Source/MSCOFF.ob07 b/programs/develop/oberon07/Source/MSCOFF.ob07 index c05c3e4033..5abc8310d9 100644 --- a/programs/develop/oberon07/Source/MSCOFF.ob07 +++ b/programs/develop/oberon07/Source/MSCOFF.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) @@ -136,7 +136,7 @@ VAR PROCEDURE SetNumberOfRelocations (VAR section: SH; NumberOfRelocations: INTEGER); BEGIN IF NumberOfRelocations >= 65536 THEN - ERRORS.error1("too many relocations") + ERRORS.Error(202) END; section.NumberOfRelocations := WCHR(NumberOfRelocations) END SetNumberOfRelocations; diff --git a/programs/develop/oberon07/Source/MSP430.ob07 b/programs/develop/oberon07/Source/MSP430.ob07 new file mode 100644 index 0000000000..a2edaffab1 --- /dev/null +++ b/programs/develop/oberon07/Source/MSP430.ob07 @@ -0,0 +1,1793 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE MSP430; + +IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, FILES, WRITER, + UTILS, C := CONSOLE, PROG, RTL := MSP430RTL; + + +CONST + + minRAM* = 128; maxRAM* = 10240; + minROM* = 2048; maxROM* = 49152; + + minStackSize = 64; + + IntVectorSize* = RTL.IntVectorSize; + + PC = 0; SP = 1; SR = 2; CG = 3; + + R4 = 4; R5 = 5; R6 = 6; R7 = 7; + + IR = 13; HP = 14; BP = 15; + + 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; + + +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 bw (b: BOOLEAN): INTEGER; + RETURN BW * ORD(b) +END bw; + + +PROCEDURE src_x (x, Rn: INTEGER): INTEGER; +BEGIN + IdxWords.src := x + RETURN Rn * 256 + sIDX +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 := src_x(0, CG); IdxWords.src := NOWORD + | 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} = {6, 12..15}); + ASSERT(BITS(src) + {4, 5, 8..11} = {4, 5, 8..11}); + ASSERT(BITS(dst) + {0..3, 7} = {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 +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) +END Push; + + +PROCEDURE Pop (reg: INTEGER); +BEGIN + Op2(opMOV, incr(SP), reg) +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); + Push(reg2); + Pop(reg1); + 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 + EmitCall(RTL.rtl[proc].label); + RTL.Used(proc); + IF params > 0 THEN + Op2(opADD, imm(params * 2), SP) + 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 translate (code: IL.CODES); +VAR + cmd, next: COMMAND; + + opcode, param1, param2, label, L, a, n, c1, c2: INTEGER; + + reg1, reg2: INTEGER; + + cc: INTEGER; + +BEGIN + cmd := code.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: + EmitCall(param1) + + |IL.opCALLP: + 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); + EmitWord(param2); + Reloc(RDATA) + + |IL.opERR: + CallRTL(RTL._error, 2) + + |IL.opPUSHC: + PushImm(param2) + + |IL.opLEAVEC: + Pop(PC) + + |IL.opENTER: + ASSERT(R.top = -1); + + EmitLabel(param1); + + Push(BP); + MovRR(SP, BP); + + IF param2 > 8 THEN + Op2(opMOV, imm(param2), R4); + L := NewLabel(); + EmitLabel(L); + Push(CG); + Op2(opSUB, imm(1), R4); + jcc(jne, L) + ELSIF param2 > 0 THEN + WHILE param2 > 0 DO + Push(CG); + DEC(param2) + END + END + + |IL.opLEAVE, IL.opLEAVER: + ASSERT(param2 = 0); + IF opcode = IL.opLEAVER THEN + UnOp(reg1); + IF reg1 # ACC THEN + GetRegA; + ASSERT(REG.Exchange(R, reg1, ACC)); + drop + END; + drop + END; + + ASSERT(R.top = -1); + + IF param1 > 0 THEN + MovRR(BP, SP) + END; + + Pop(BP); + Pop(PC) + + |IL.opRES: + ASSERT(R.top = -1); + GetRegA + + |IL.opCLEANUP: + IF param2 # 0 THEN + Op2(opADD, imm(param2 * 2), SP) + 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(); + MovRR(BP, reg1); + Op2(opADD, imm(param2 * 2), reg1) + + |IL.opLLOAD8: + Op2(opMOV + BW, src_x(param2 * 2, BP), GetAnyReg()) + + |IL.opLLOAD16, IL.opVADR: + Op2(opMOV, src_x(param2 * 2, BP), 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, src_x(param2 * 2, BP), reg1); + Op2(opMOV + BW, indir(reg1), reg1) + + |IL.opVLOAD16: + reg1 := GetAnyReg(); + Op2(opMOV, src_x(param2 * 2, BP), 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.opADDL, IL.opADDR: + 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 + reg2 := GetAnyReg(); + Clear(reg2); + Op2(opSUB, reg1 * 256, reg2); + drop; + drop; + ASSERT(REG.GetReg(R, reg2)) + END + + |IL.opLADR_SAVEC: + Op2(opMOV, imm(param2), dst_x(param1 * 2, BP)) + + |IL.opLADR_SAVE: + UnOp(reg1); + Op2(opMOV, reg1 * 256, dst_x(param2 * 2, BP)); + 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); + + IF cmd.next(COMMAND).opcode = IL.opJE THEN + label := cmd.next(COMMAND).param1; + jcc(cc, label); + cmd := cmd.next(COMMAND) + + ELSIF cmd.next(COMMAND).opcode = IL.opJNE THEN + label := cmd.next(COMMAND).param1; + jcc(ORD(BITS(cc) / {0}), label); + cmd := cmd.next(COMMAND) + + ELSE + setcc(cc, GetAnyReg()) + END + + |IL.opNOP: + + |IL.opCODE: + EmitWord(param2) + + |IL.opACC: + IF (R.top # 0) OR (R.stk[0] # ACC) THEN + PushAll(0); + GetRegA; + Pop(ACC); + DEC(R.pushed) + END + + |IL.opDROP: + UnOp(reg1); + drop + + |IL.opJNZ: + UnOp(reg1); + Test(reg1); + jcc(jne, param1) + + |IL.opJZ: + UnOp(reg1); + Test(reg1); + jcc(je, param1) + + |IL.opJG: + UnOp(reg1); + Test(reg1); + jcc(jg, param1) + + |IL.opJE: + UnOp(reg1); + Test(reg1); + jcc(jne, param1); + drop + + |IL.opJNE: + 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.opLOOP: + |IL.opENDLOOP: + + |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); + MovRR(reg2, reg1); + drop; + jcc(jb, param1) + ELSE + INCL(R.regs, reg1); + DEC(R.top); + R.stk[R.top] := reg2 + END + + |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), dst_x(param1 * 2, BP)) + + |IL.opLADR_DECCB: + Op2(opSUB + BW, imm(param2), dst_x(param1 * 2, BP)) + + |IL.opLADR_INC, IL.opLADR_INCB: + UnOp(reg1); + Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, dst_x(param2 * 2, BP)); + drop + + |IL.opLADR_DEC, IL.opLADR_DECB: + UnOp(reg1); + Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, dst_x(param2 * 2, BP)); + 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); + 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.opADDSL, IL.opADDSR: + 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.opMIN: + BinOp(reg1, reg2); + Op2(opCMP, reg2 * 256, reg1); + EmitWord(opJL + 1); (* jl L *) + MovRR(reg2, reg1); + (* L: *) + drop + + + |IL.opMAX: + BinOp(reg1, reg2); + Op2(opCMP, reg2 * 256, reg1); + EmitWord(opJGE + 1); (* jge L *) + MovRR(reg2, reg1); + (* L: *) + drop + + |IL.opMINC: + UnOp(reg1); + Op2(opCMP, imm(param2), reg1); + L := NewLabel(); + jcc(jl, L); + Op2(opMOV, imm(param2), reg1); + EmitLabel(L) + + |IL.opMAXC: + UnOp(reg1); + Op2(opCMP, imm(param2), reg1); + L := NewLabel(); + jcc(jge, 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); + jcc(jl, param2); + jcc(jg, cmd.param3) + + |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.opODD: + UnOp(reg1); + Op2(opAND, imm(1), reg1) + + |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.opCHKBYTE: + BinOp(reg1, reg2); + Op2(opCMP, imm(256), reg1); + jcc(jb, param1) + + |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); + 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.opCHR: + UnOp(reg1); + Op2(opAND, imm(255), reg1) + + |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: + Op1(opPUSH, BP, sIDX); + EmitWord(param2 * 2) + + |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(BP, ACC); + Op2(opADD, imm(param2 * 2), ACC); + 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})), dst_x(param1 * 2, BP)) + + |IL.opLADR_EXCLC: + Op2(opBIC, imm(ORD({param2})), dst_x(param1 * 2, BP)) + + END; + + cmd := cmd.next(COMMAND) + END; + + ASSERT(R.pushed = 0); + ASSERT(R.top = -1) +END translate; + + +PROCEDURE prolog (ramSize: INTEGER); +VAR + i: INTEGER; + +BEGIN + RTL.Init(EmitLabel, EmitWord, EmitCall, ramSize); + 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(RTL.int, SR)); + Op2(opMOV, imm(0), dst_x(RTL.trap, SR)) +END prolog; + + +PROCEDURE epilog; +VAR + L1, i: 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); + + MovRR(SP, IR); + + FOR i := 0 TO 15 DO + IF i IN R.regs + R.vregs THEN + Push(i) + END + END; + + Push(IR); + Op1(opPUSH, IR, sINDIR); + Op1(opCALL, SR, sIDX); + EmitWord(RTL.int); + Op2(opADD, imm(4), SP); + + FOR i := 15 TO 0 BY -1 DO + IF i IN R.regs + R.vregs THEN + Pop(i) + END + END; + + Op2(opADD, imm(2), SP); + Op1(opRETI, 0, 0); + + RTL.Gen +END epilog; + + +PROCEDURE hexdgt (n: BYTE): BYTE; +BEGIN + IF n < 10 THEN + n := n + ORD("0") + ELSE + n := n - 10 + ORD("A") + END + + RETURN n +END hexdgt; + + +PROCEDURE WriteHexByte (file: FILES.FILE; byte: BYTE); +BEGIN + WRITER.WriteByte(file, hexdgt(byte DIV 16)); + WRITER.WriteByte(file, hexdgt(byte MOD 16)); +END WriteHexByte; + + +PROCEDURE WriteHex (file: FILES.FILE; mem: ARRAY OF BYTE; idx, cnt: INTEGER); +VAR + i, len, chksum: INTEGER; + +BEGIN + WHILE cnt > 0 DO + len := MIN(cnt, 16); + chksum := len + idx DIV 256 + idx MOD 256; + WRITER.WriteByte(file, ORD(":")); + WriteHexByte(file, len); + WriteHexByte(file, idx DIV 256); + WriteHexByte(file, idx MOD 256); + WriteHexByte(file, 0); + FOR i := 1 TO len DO + WriteHexByte(file, mem[idx]); + INC(chksum, mem[idx]); + INC(idx) + END; + WriteHexByte(file, (-chksum) MOD 256); + DEC(cnt, len); + WRITER.WriteByte(file, 0DH); + WRITER.WriteByte(file, 0AH) + END +END WriteHex; + + +PROCEDURE CodeGen* (code: IL.CODES; outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); +VAR + i, adr, heap, stack, TextSize, TypesSize, bits, n: INTEGER; + + Code, Data, Bss, Free: RECORD address, size: INTEGER END; + + ram, rom: INTEGER; + + reloc: RELOC; + + file: FILES.FILE; + +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 code.bss > ram - minStackSize - RTL.VarSize THEN + ERRORS.Error(204) + END; + + Labels := CHL.CreateIntList(); + FOR i := 1 TO code.lcount DO + CHL.PushInt(Labels, 0) + END; + + FOR i := 0 TO LEN(mem) - 1 DO + mem[i] := 0 + END; + + TypesSize := CHL.Length(code.types) * 2; + CodeList := LISTS.create(NIL); + RelList := LISTS.create(NIL); + REG.Init(R, Push, Pop, mov, xchg, NIL, NIL, {R4, R5, R6, R7}, {}); + + prolog(ram); + translate(code); + epilog; + + Code.address := 10000H - rom; + Code.size := Fixup(Code.address, IntVectorSize + TypesSize); + Data.address := Code.address + Code.size; + Data.size := CHL.Length(code.data); + Data.size := Data.size + ORD(ODD(Data.size)); + TextSize := Code.size + Data.size; + + IF Code.address + TextSize + MAX(code.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN + ERRORS.Error(203) + END; + + Bss.address := RTL.ram + RTL.VarSize; + Bss.size := code.bss + ORD(ODD(code.bss)); + heap := Bss.address + Bss.size; + stack := RTL.ram + ram; + ASSERT(stack - heap >= minStackSize); + 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; + CASE reloc.section OF + |RCODE: PutWord(LabelOffs(reloc.WordPtr.val) * 2, adr) + |RDATA: PutWord(reloc.WordPtr.val + Data.address, adr) + |RBSS: PutWord(reloc.WordPtr.val + Bss.address, adr) + END; + reloc := reloc.next(RELOC) + END; + + adr := Data.address; + + FOR i := 0 TO CHL.Length(code.data) - 1 DO + mem[adr] := CHL.GetByte(code.data, i); + INC(adr) + END; + + adr := 10000H - IntVectorSize - TypesSize; + + FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO + PutWord(CHL.GetInt(code.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; + + Free.address := Code.address + TextSize; + Free.size := rom - (IntVectorSize + TypesSize + TextSize); + + PutWord(Free.address, adr); + PutWord(Free.size, adr); + PutWord(4130H, adr); (* RET *) + PutWord(stack, adr); + + FOR i := 0 TO LEN(IV) - 1 DO + PutWord(LabelOffs(IV[i]) * 2, adr) + END; + + file := FILES.create(outname); + WriteHex(file, mem, Code.address, TextSize); + WriteHex(file, mem, 10000H - IntVectorSize - TypesSize, IntVectorSize + TypesSize); + + WRITER.WriteByte(file, ORD(":")); + WriteHexByte(file, 0); + WriteHexByte(file, 0); + WriteHexByte(file, 0); + WriteHexByte(file, 1); + WriteHexByte(file, 255); + WRITER.WriteByte(file, 0DH); + WRITER.WriteByte(file, 0AH); + + FILES.close(file); + + INC(TextSize, IntVectorSize + TypesSize); + INC(Bss.size, minStackSize + RTL.VarSize); + + C.StringLn("--------------------------------------------"); + C.String( " rom: "); C.Int(TextSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(TextSize * 100 DIV rom); C.StringLn("%)"); + IF Free.size > 0 THEN + C.String( " "); C.Int(Free.size); C.String(" bytes free (0"); + C.Hex(Free.address, 4); C.String("H..0"); C.Hex(Free.address + Free.size - 1, 4); C.StringLn("H)") + END; + 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("%)"); + 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 new file mode 100644 index 0000000000..86e4278c2f --- /dev/null +++ b/programs/develop/oberon07/Source/MSP430RTL.ob07 @@ -0,0 +1,677 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, 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 = 14; + + LenIV* = 32; + + iv = 10000H - LenIV * 2; + sp = iv - 2; + empty_proc* = sp - 2; + free_size = empty_proc - 2; + free_adr = free_size - 2; + bits = free_adr - 272; + bits_offs = bits - 32; + DataSize* = iv - bits_offs; + types = bits_offs - 2; + + IntVectorSize* = LenIV * 2 + DataSize; + + VarSize* = 4; + + +TYPE + + EMITPROC = PROCEDURE (n: INTEGER); + + +VAR + + ram*, trap*, int*: 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); (* MOV @SP+, PC *) + (* 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); (* MOV @SP+, PC *) + (* 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); (* MOV @SP+, PC *) + (* 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 (module, err, line: INTEGER) *) + IF rtl[_error].used THEN + Label(rtl[_error].label); + Word1(0C232H); (* BIC #8, SR; DINT *) + Word1(4303H); (* MOV R3, R3; NOP *) + Word2(4114H, 2); (* MOV 2(SP), R4; R4 <- module *) + Word2(4115H, 4); (* MOV 4(SP), R5; R5 <- err *) + Word2(4116H, 6); (* MOV 6(SP), R6; R6 <- line *) + Word2(4211H, sp); (* MOV sp(SR), SP *) + Word1(1206H); (* PUSH R6 *) + Word1(1204H); (* PUSH R4 *) + Word1(1205H); (* PUSH R5 *) + Word2(4214H, trap); (* MOV trap(SR), R4 *) + Word1(9304H); (* TST R4 *) + Word1(2400H + 1); (* JZ L *) + Word1(1284H); (* CALL R4 *) + (* L: *) + 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, 16); (* SUB #16, 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); (* MOV @SP+, PC *) + (* 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; ramSize: INTEGER); +BEGIN + Label := pLabel; + Word := pWord; + Call := pCall; + + IF ramSize > 2048 THEN + ram := 1100H + ELSE + ram := 200H + END; + trap := ram; + int := trap + 2 +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 index 136988f316..3f183a2c18 100644 --- a/programs/develop/oberon07/Source/PARS.ob07 +++ b/programs/develop/oberon07/Source/PARS.ob07 @@ -7,7 +7,7 @@ MODULE PARS; -IMPORT PROG, SCAN, ARITH, STRINGS, ERRORS, LISTS, CODE, CONSOLE, PATHS, MACHINE, C := COLLECTIONS, mConst := CONSTANTS; +IMPORT PROG, SCAN, ARITH, STRINGS, ERRORS, LISTS, IL, CONSOLE, PATHS, UTILS, C := COLLECTIONS, mConst := CONSTANTS; CONST @@ -24,6 +24,12 @@ TYPE PARSER* = POINTER TO rPARSER; + POSITION* = RECORD (SCAN.POSITION) + + parser*: PARSER + + END; + EXPR* = RECORD obj*: INTEGER; @@ -37,7 +43,7 @@ TYPE STATPROC = PROCEDURE (parser: PARSER); EXPRPROC = PROCEDURE (parser: PARSER; VAR e: EXPR); - RETPROC = PROCEDURE (parser: PARSER; e: EXPR; t: PROG.TYPE_; pos: SCAN.POSITION): BOOLEAN; + RETPROC = PROCEDURE (parser: PARSER; e: EXPR; t: PROG.TYPE_; pos: POSITION): BOOLEAN; rPARSER = RECORD (C.ITEM) @@ -67,7 +73,7 @@ TYPE VAR - program*: PROG.PROGRAM; + program*: PROG.PROGRAM; parsers: C.COLLECTION; @@ -83,34 +89,40 @@ BEGIN END destroy; -PROCEDURE error* (parser: PARSER; pos: SCAN.POSITION; errno: INTEGER); +PROCEDURE getpos (parser: PARSER; VAR pos: POSITION); BEGIN - ERRORS.errormsg(parser.fname, pos.line, pos.col, errno) + 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; parser: PARSER; pos: SCAN.POSITION; errno: INTEGER); +PROCEDURE check* (condition: BOOLEAN; pos: POSITION; errno: INTEGER); BEGIN IF ~condition THEN - error(parser, pos, errno) + error(pos, errno) END END check; PROCEDURE check1* (condition: BOOLEAN; parser: PARSER; errno: INTEGER); +VAR + pos: POSITION; + BEGIN IF ~condition THEN - error(parser, parser.lex.pos, errno) + getpos(parser, pos); + error(pos, errno) END END check1; -PROCEDURE getpos (parser: PARSER; VAR pos: SCAN.POSITION); -BEGIN - pos := parser.lex.pos -END getpos; - - PROCEDURE Next* (parser: PARSER); VAR errno: INTEGER; @@ -118,6 +130,14 @@ VAR BEGIN SCAN.Next(parser.scanner, parser.lex); errno := parser.lex.error; + IF (errno = 0) & (program.target.sys = mConst.Target_iMSP430) THEN + IF parser.lex.sym = SCAN.lxFLOAT THEN + errno := -SCAN.lxERROR13 + ELSIF (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; @@ -125,10 +145,10 @@ BEGIN END Next; -PROCEDURE NextPos* (parser: PARSER; VAR pos: SCAN.POSITION); +PROCEDURE NextPos (parser: PARSER; VAR pos: POSITION); BEGIN Next(parser); - pos := parser.lex.pos + getpos(parser, pos) END NextPos; @@ -178,17 +198,14 @@ END ExpectSym; PROCEDURE ImportList (parser: PARSER); VAR - name: SCAN.IDENT; - parser2: PARSER; - pos: SCAN.POSITION; - alias: BOOLEAN; - unit: PROG.UNIT; - ident: PROG.IDENT; - units: PROG.UNITS; + name: SCAN.IDENT; + parser2: PARSER; + pos: POSITION; + alias: BOOLEAN; + unit: PROG.UNIT; + ident: PROG.IDENT; BEGIN - units := program.units; - alias := FALSE; REPEAT @@ -199,18 +216,18 @@ BEGIN getpos(parser, pos); IF ~alias THEN - ident := parser.unit.idents.add(parser.unit, name, PROG.idMODULE); - check(ident # NIL, parser, pos, 30) + ident := PROG.addIdent(parser.unit, name, PROG.idMODULE); + check(ident # NIL, pos, 30) END; Next(parser); IF (parser.sym = SCAN.lxCOMMA) OR (parser.sym = SCAN.lxSEMI) THEN alias := FALSE; - unit := units.get(units, name); + unit := PROG.getUnit(program, name); IF unit # NIL THEN - check(unit.closed, parser, pos, 31) + check(unit.closed, pos, 31) ELSE parser2 := parser.create(parser.path, parser.lib_path, parser.StatSeq, parser.expression, parser.designator, parser.chkreturn); @@ -220,9 +237,9 @@ BEGIN destroy(parser2); parser2 := parser.create(parser.lib_path, parser.lib_path, parser.StatSeq, parser.expression, parser.designator, parser.chkreturn); - check(parser2.open(parser2, name.s), parser, pos, 29) + check(parser2.open(parser2, name.s), pos, 29) ELSE - check(FALSE, parser, pos, 29) + error(pos, 29) END END; @@ -257,7 +274,7 @@ VAR BEGIN ASSERT(parser.sym = SCAN.lxIDENT); - ident := parser.unit.idents.get(parser.unit, parser.lex.ident, FALSE); + ident := PROG.getIdent(parser.unit, parser.lex.ident, FALSE); IF ~forward THEN check1(ident # NIL, parser, 48) @@ -267,7 +284,7 @@ BEGIN unit := ident.unit; ExpectSym(parser, SCAN.lxPOINT); ExpectSym(parser, SCAN.lxIDENT); - ident := unit.idents.get(unit, parser.lex.ident, FALSE); + ident := PROG.getIdent(unit, parser.lex.ident, FALSE); check1((ident # NIL) & ident.export, parser, 48) END @@ -312,30 +329,29 @@ BEGIN END; ARITH.setbool(v, bool) - END strcmp; PROCEDURE ConstExpression* (parser: PARSER; VAR v: ARITH.VALUE); VAR e: EXPR; - pos: SCAN.POSITION; + pos: POSITION; BEGIN getpos(parser, pos); parser.constexp := TRUE; parser.expression(parser, e); parser.constexp := FALSE; - check(e.obj = eCONST, parser, pos, 62); + 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: SCAN.POSITION; + name: SCAN.IDENT; + export: BOOLEAN; + pos: POSITION; BEGIN ASSERT(parser.sym = SCAN.lxIDENT); @@ -355,7 +371,7 @@ BEGIN Next(parser) END; - check(rec.fields.add(rec, name, export), parser, pos, 30); + check(PROG.addField(rec, name, export), pos, 30); IF parser.sym = SCAN.lxCOMMA THEN ExpectSym(parser, SCAN.lxIDENT) @@ -391,7 +407,7 @@ VAR exit := FALSE; WHILE (parser.sym = SCAN.lxIDENT) & ~exit DO - check1(type.params.add(type, parser.lex.ident, vPar), parser, 30); + check1(PROG.addParam(type, parser.lex.ident, vPar), parser, 30); Next(parser); IF parser.sym = SCAN.lxCOMMA THEN ExpectSym(parser, SCAN.lxIDENT) @@ -412,13 +428,13 @@ VAR t1 := t0; WHILE dim > 0 DO - t1 := program.enterType(program, PROG.tARRAY, -1, 0, parser.unit); + t1 := PROG.enterType(program, PROG.tARRAY, -1, 0, parser.unit); t1.base := t0; t0 := t1; DEC(dim) END; - type.params.set(type, t1); + PROG.setParams(type, t1); Next(parser); exit := TRUE ELSE @@ -449,7 +465,7 @@ BEGIN ExpectSym(parser, SCAN.lxIDENT); ident := QIdent(parser, FALSE); check1(ident.typ = PROG.idTYPE, parser, 68); - check1((ident.type.typ # PROG.tRECORD) & (ident.type.typ # PROG.tARRAY), parser, 69); + 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) @@ -461,54 +477,83 @@ BEGIN END FormalParameters; -PROCEDURE sysflag (parser: PARSER): INTEGER; +PROCEDURE sysflag (parser: PARSER; proc: BOOLEAN): INTEGER; VAR - res: INTEGER; + res, sf: INTEGER; BEGIN IF parser.lex.s = "stdcall" THEN - res := PROG.stdcall + sf := PROG.sf_stdcall ELSIF parser.lex.s = "stdcall64" THEN - res := PROG.stdcall64 + sf := PROG.sf_stdcall64 ELSIF parser.lex.s = "ccall" THEN - res := PROG.ccall + sf := PROG.sf_ccall ELSIF parser.lex.s = "ccall16" THEN - res := PROG.ccall16 + sf := PROG.sf_ccall16 ELSIF parser.lex.s = "win64" THEN - res := PROG.win64 + sf := PROG.sf_win64 ELSIF parser.lex.s = "systemv" THEN - res := PROG.systemv + sf := PROG.sf_systemv ELSIF parser.lex.s = "windows" THEN + sf := PROG.sf_windows + ELSIF parser.lex.s = "linux" THEN + sf := PROG.sf_linux + ELSIF parser.lex.s = "code" THEN + sf := PROG.sf_code + ELSIF parser.lex.s = "noalign" THEN + sf := PROG.sf_noalign + ELSE + check1(FALSE, parser, 124) + END; + + check1(sf IN program.target.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_stdcall64: + res := PROG.stdcall64 + |PROG.sf_ccall: + res := PROG.ccall + |PROG.sf_ccall16: + res := PROG.ccall16 + |PROG.sf_win64: + res := PROG.win64 + |PROG.sf_systemv: + res := PROG.systemv + |PROG.sf_code: + res := PROG.code + |PROG.sf_windows: IF program.target.sys IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN res := PROG.stdcall ELSIF program.target.sys IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64} THEN res := PROG.win64 - ELSE - check1(FALSE, parser, 118) END - ELSIF parser.lex.s = "linux" THEN - IF program.target.sys = mConst.Target_iELF32 THEN + |PROG.sf_linux: + IF program.target.sys IN {mConst.Target_iELF32, mConst.Target_iELFSO32} THEN res := PROG.ccall16 - ELSIF program.target.sys = mConst.Target_iELF64 THEN + ELSIF program.target.sys IN {mConst.Target_iELF64, mConst.Target_iELFSO64} THEN res := PROG.systemv - ELSE - check1(FALSE, parser, 119) END - ELSIF parser.lex.s = "noalign" THEN + |PROG.sf_noalign: res := PROG.noalign - ELSE - res := 0 END RETURN res END sysflag; -PROCEDURE procflag (parser: PARSER; VAR import: CODE.IMPORT_PROC; isProc: BOOLEAN): INTEGER; +PROCEDURE procflag (parser: PARSER; VAR import: IL.IMPORT_PROC; isProc: BOOLEAN): INTEGER; VAR call: INTEGER; dll, proc: SCAN.LEXSTR; - pos: SCAN.POSITION; + pos: POSITION; BEGIN @@ -518,12 +563,7 @@ BEGIN getpos(parser, pos); check1(parser.unit.sysimport, parser, 54); Next(parser); - call := sysflag(parser); - IF program.target.bit_depth = 64 THEN - check1(call IN PROG.callconv64, parser, 117) - ELSIF program.target.bit_depth = 32 THEN - check1(call IN PROG.callconv32, parser, 63) - END; + call := sysflag(parser, TRUE); Next(parser); IF parser.sym = SCAN.lxMINUS THEN Next(parser); @@ -539,20 +579,21 @@ BEGIN ExpectSym(parser, SCAN.lxSTRING); proc := parser.lex.s; Next(parser); - import := CODE.AddImp(dll, proc) + import := IL.AddImp(dll, proc) END; checklex(parser, SCAN.lxRSQUARE); Next(parser) ELSE - IF program.target.bit_depth = 32 THEN - call := PROG.default - ELSIF program.target.bit_depth = 64 THEN - call := PROG.default64 + CASE program.target.bit_depth OF + |16: call := PROG.default16 + |32: call := PROG.default32 + |64: call := PROG.default64 END END; IF import # NIL THEN - check(~(program.target.sys IN {mConst.Target_iELF32, mConst.Target_iELF64}), parser, pos, 70) + check(~(program.target.sys IN {mConst.Target_iELF32, mConst.Target_iELF64, mConst.Target_iELFSO32, + mConst.Target_iELFSO64, mConst.Target_iMSP430}), pos, 70) END RETURN call @@ -570,12 +611,12 @@ VAR typeSize: ARITH.VALUE; ident: PROG.IDENT; unit: PROG.UNIT; - pos, pos2: SCAN.POSITION; + pos, pos2: POSITION; fieldType: PROG.TYPE_; baseIdent: SCAN.IDENT; a, b: INTEGER; RecFlag: INTEGER; - import: CODE.IMPORT_PROC; + import: IL.IMPORT_PROC; BEGIN unit := parser.unit; @@ -604,11 +645,11 @@ BEGIN ConstExpression(parser, arrLen); - check(arrLen.typ = ARITH.tINTEGER, parser, pos, 43); - check(ARITH.check(arrLen), parser, pos, 39); - check(ARITH.getInt(arrLen) > 0, parser, pos, 51); + check(arrLen.typ = ARITH.tINTEGER, pos, 43); + check(ARITH.check(arrLen), pos, 39); + check(ARITH.getInt(arrLen) > 0, pos, 51); - t := program.enterType(program, PROG.tARRAY, -1, ARITH.getInt(arrLen), unit); + t := PROG.enterType(program, PROG.tARRAY, -1, ARITH.getInt(arrLen), unit); IF parser.sym = SCAN.lxCOMMA THEN type(parser, t.base, {comma, closed}) @@ -623,8 +664,8 @@ BEGIN a := t.length; b := t.base.size; - check(ARITH.mulInt(a, b), parser, pos2, 104); - check(ARITH.setInt(typeSize, a), parser, pos2, 104); + check(ARITH.mulInt(a, b), pos2, 104); + check(ARITH.setInt(typeSize, a), pos2, 104); t.size := a; t.closed := TRUE @@ -633,19 +674,14 @@ BEGIN getpos(parser, pos2); Next(parser); - t := program.enterType(program, PROG.tRECORD, 0, 0, unit); + t := PROG.enterType(program, 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); - IF RecFlag = PROG.noalign THEN - t.noalign := TRUE - ELSE - check1(FALSE, parser, 110) - END; - + RecFlag := sysflag(parser, FALSE); + t.noalign := RecFlag = PROG.noalign; ExpectSym(parser, SCAN.lxRSQUARE); Next(parser) END; @@ -657,14 +693,14 @@ BEGIN type(parser, t.base, {closed}); - check(t.base.typ IN {PROG.tRECORD, PROG.tPOINTER}, parser, pos, 52); + 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, parser, pos, 55) + check(t.base # NIL, pos, 55) END; - check(~t.base.noalign, parser, pos, 112); + check(~t.base.noalign, pos, 112); checklex(parser, SCAN.lxRROUND); Next(parser); @@ -684,7 +720,7 @@ BEGIN Next(parser); type(parser, fieldType, {closed}); - check(t.fields.set(t, fieldType), parser, pos2, 104); + check(PROG.setFields(t, fieldType), pos2, 104); IF (fieldType.align > t.align) & ~t.noalign THEN t.align := fieldType.align @@ -699,21 +735,21 @@ BEGIN t.closed := TRUE; - CODE.AddRec(t.base.num); + IL.AddRec(t.base.num); IF ~t.noalign THEN - check(MACHINE.Align(t.size, t.align), parser, pos2, 104); - check(ARITH.setInt(typeSize, t.size), parser, pos2, 104) + 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 + ELSIF parser.sym = SCAN.lxPOINTER THEN ExpectSym(parser, SCAN.lxTO); Next(parser); - t := program.enterType(program, PROG.tPOINTER, program.target.adr, 0, unit); + t := PROG.enterType(program, PROG.tPOINTER, program.target.adr, 0, unit); t.align := program.target.adr; getpos(parser, pos); @@ -725,14 +761,14 @@ BEGIN type(parser, t.base, {forward}); IF t.base # NIL THEN - check(t.base.typ = PROG.tRECORD, parser, pos, 58) + check(t.base.typ = PROG.tRECORD, pos, 58) ELSE - unit.pointers.add(unit, t, baseIdent, pos) + PROG.frwPtr(unit, t, baseIdent, pos) END ELSIF parser.sym = SCAN.lxPROCEDURE THEN NextPos(parser, pos); - t := program.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit); + t := PROG.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit); t.align := program.target.adr; t.call := procflag(parser, import, FALSE); FormalParameters(parser, t) @@ -746,15 +782,15 @@ END type; PROCEDURE IdentDef (parser: PARSER; typ: INTEGER; VAR name: SCAN.IDENT): PROG.IDENT; VAR ident: PROG.IDENT; - pos: SCAN.POSITION; + pos: POSITION; BEGIN ASSERT(parser.sym = SCAN.lxIDENT); name := parser.lex.ident; getpos(parser, pos); - ident := parser.unit.idents.add(parser.unit, name, typ); - check(ident # NIL, parser, pos, 30); + ident := PROG.addIdent(parser.unit, name, typ); + check(ident # NIL, pos, 30); ident.pos := pos; Next(parser); @@ -770,9 +806,9 @@ END IdentDef; PROCEDURE ConstTypeDeclaration (parser: PARSER; const: BOOLEAN); VAR - ident: PROG.IDENT; - name: SCAN.IDENT; - pos: SCAN.POSITION; + ident: PROG.IDENT; + name: SCAN.IDENT; + pos: POSITION; BEGIN IF const THEN @@ -787,12 +823,12 @@ BEGIN IF const THEN ConstExpression(parser, ident.value); IF ident.value.typ = ARITH.tINTEGER THEN - check(ARITH.check(ident.value), parser, pos, 39) + check(ARITH.check(ident.value), pos, 39) ELSIF ident.value.typ = ARITH.tREAL THEN - check(ARITH.check(ident.value), parser, pos, 40) + check(ARITH.check(ident.value), pos, 40) END; ident.typ := PROG.idCONST; - ident.type := program.getType(program, ident.value.typ) + ident.type := PROG.getType(program, ident.value.typ) ELSE type(parser, ident.type, {}) END; @@ -805,9 +841,9 @@ END ConstTypeDeclaration; PROCEDURE VarDeclaration (parser: PARSER); VAR - ident: PROG.IDENT; - name: SCAN.IDENT; - t: PROG.TYPE_; + ident: PROG.IDENT; + name: SCAN.IDENT; + t: PROG.TYPE_; BEGIN @@ -819,7 +855,7 @@ BEGIN ELSIF parser.sym = SCAN.lxCOLON THEN Next(parser); type(parser, t, {}); - parser.unit.setvars(parser.unit, t); + PROG.setVarsType(parser.unit, t); checklex(parser, SCAN.lxSEMI); Next(parser) ELSE @@ -835,6 +871,7 @@ PROCEDURE DeclarationSequence (parser: PARSER): BOOLEAN; VAR ptr: PROG.FRWPTR; endmod: BOOLEAN; + pos: POSITION; PROCEDURE ProcDeclaration (parser: PARSER): BOOLEAN; @@ -842,20 +879,24 @@ VAR proc: PROG.IDENT; endname, name: SCAN.IDENT; - param: LISTS.ITEM; + param: PROG.PARAM; unit: PROG.UNIT; ident: PROG.IDENT; e: EXPR; - pos: SCAN.POSITION; + pos, pos1, + pos2: POSITION; label: INTEGER; - enter: CODE.COMMAND; + enter: IL.COMMAND; call: INTEGER; t: PROG.TYPE_; - import: CODE.IMPORT_PROC; + import: IL.IMPORT_PROC; endmod, b: BOOLEAN; fparams: SET; variables: LISTS.LIST; int, flt: INTEGER; + comma: BOOLEAN; + code: ARITH.VALUE; + codeProc: BOOLEAN; BEGIN endmod := FALSE; @@ -865,6 +906,7 @@ VAR call := procflag(parser, import, TRUE); getpos(parser, pos); + pos1 := pos; checklex(parser, SCAN.lxIDENT); IF import # NIL THEN @@ -875,29 +917,56 @@ VAR proc := IdentDef(parser, PROG.idPROC, name) END; - check(unit.scope.open(unit, proc.proc), parser, pos, 116); + check(PROG.openScope(unit, proc.proc), pos, 116); - proc.type := program.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit); + proc.type := PROG.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit); t := proc.type; - t.align := program.target.adr; - t.call := call; + t.align := program.target.adr; + t.call := call; FormalParameters(parser, t); - + + codeProc := call IN {PROG.code, PROG._code}; + IF call IN {PROG.systemv, PROG._systemv} THEN - check(t.params.size <= PROG.MAXSYSVPARAM, parser, pos, 120) + check(t.parSize <= PROG.MAXSYSVPARAM, pos, 120) END; - param := t.params.first; + param := t.params.first(PROG.PARAM); WHILE param # NIL DO - ident := unit.idents.add(unit, param(PROG.PARAM).name, PROG.idPARAM); + ident := PROG.addIdent(unit, param.name, PROG.idPARAM); ASSERT(ident # NIL); - ident.type := param(PROG.PARAM).type; - ident.offset := param(PROG.PARAM).offset; - IF param(PROG.PARAM).vPar THEN + ident.type := param.type; + ident.offset := param.offset; + IF param.vPar THEN ident.typ := PROG.idVPAR END; - param := param.next + param := param.next(PROG.PARAM) + END; + + IF import = NIL THEN + label := IL.NewLabel(); + proc.proc.label := label + 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 program.target.sys # mConst.Target_iMSP430 THEN + check(ARITH.range(code, 0, 255), pos2, 42) + 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); @@ -905,55 +974,64 @@ VAR IF import = NIL THEN - label := CODE.NewLabel(); - proc.proc.label := label; - IF parser.main & proc.export & program.dll THEN IF program.obj THEN - check((proc.name.s # "lib_init") & (proc.name.s # "version"), parser, pos, 114) + check((proc.name.s # "lib_init") & (proc.name.s # "version"), pos, 114) END; - CODE.AddExp(label, proc.name.s); + IL.AddExp(label, proc.name.s); proc.proc.used := TRUE END; - b := DeclarationSequence(parser); + IF ~codeProc THEN + b := DeclarationSequence(parser) + END; program.locsize := 0; IF call IN {PROG._win64, PROG.win64} THEN - fparams := proc.type.params.getfparams(proc.type, 3, int, flt); - enter := CODE.Enter(label, LSL(ORD(fparams), 5) + MIN(proc.type.params.size, 4)) + 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 := proc.type.params.getfparams(proc.type, PROG.MAXSYSVPARAM - 1, int, flt); - enter := CODE.Enter(label, -(LSL(ORD(fparams), 5) + proc.type.params.size)) + fparams := PROG.getFloatParamsPos(proc.type, PROG.MAXSYSVPARAM - 1, int, flt); + enter := IL.Enter(label, -(LSL(ORD(fparams), 5) + proc.type.parSize)) + ELSIF codeProc THEN + ELSE - enter := CODE.Enter(label, 0) + enter := IL.Enter(label, 0) END; proc.proc.enter := enter; - IF parser.sym = SCAN.lxBEGIN THEN + IF ~codeProc & (parser.sym = SCAN.lxBEGIN) THEN Next(parser); parser.StatSeq(parser) END; - IF t.base # NIL THEN + 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), parser, pos, 87) + check(parser.chkreturn(parser, e, t.base, pos), pos, 87) END; - proc.proc.leave := CODE.Leave(t.base # NIL, (t.base # NIL) & (t.base.typ = PROG.tREAL), - t.params.size * ORD((t.call IN PROG.callee_clean_up) OR (t.call IN {PROG.systemv, PROG._systemv}))); - enter.param2 := program.locsize; - checklex(parser, SCAN.lxEND) + IF ~codeProc THEN + proc.proc.leave := IL.Leave(t.base # NIL, (t.base # NIL) & (t.base.typ = PROG.tREAL), program.locsize, + t.parSize * ORD((t.call IN PROG.callee_clean_up) OR (t.call IN {PROG.systemv, PROG._systemv}))); + enter.param2 := program.locsize; + checklex(parser, SCAN.lxEND) + ELSE + proc.proc.leave := IL.LeaveC() + END; + + IF program.target.sys = mConst.Target_iMSP430 THEN + check((enter.param2 * ORD(~codeProc) + proc.type.parSize) * 2 + 16 < program.target.options.ram, pos1, 63) + END END; IF parser.sym = SCAN.lxEND THEN ExpectSym(parser, SCAN.lxIDENT); getpos(parser, pos); endname := parser.lex.ident; - IF import = NIL THEN - check(endname = name, parser, pos, 60); + IF ~codeProc & (import = NIL) THEN + check(endname = name, pos, 60); ExpectSym(parser, SCAN.lxSEMI); Next(parser) ELSE @@ -965,20 +1043,20 @@ VAR ExpectSym(parser, SCAN.lxSEMI); Next(parser) ELSE - check(FALSE, parser, pos, 60) + error(pos, 60) END END END; - IF import = NIL THEN + IF ~codeProc & (import = NIL) THEN variables := LISTS.create(NIL); ELSE variables := NIL END; - unit.scope.close(unit, variables); + PROG.closeScope(unit, variables); - IF import = NIL THEN + IF ~codeProc & (import = NIL) THEN enter.variables := variables END @@ -1001,12 +1079,15 @@ BEGIN END END; - ptr := parser.unit.pointers.link(parser.unit); + 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(parser, ptr.pos, 58) + error(pos, 58) ELSE - error(parser, ptr.pos, 48) + error(pos, 48) END END; @@ -1029,10 +1110,12 @@ END DeclarationSequence; PROCEDURE parse (parser: PARSER); VAR - unit: PROG.UNIT; - label: INTEGER; - name: INTEGER; - endmod: BOOLEAN; + unit: PROG.UNIT; + label: INTEGER; + name: INTEGER; + endmod: BOOLEAN; + errlabel: INTEGER; + errno: INTEGER; BEGIN ASSERT(parser # NIL); @@ -1045,7 +1128,7 @@ BEGIN check1(parser.lex.s = parser.modname, parser, 23) END; - unit := program.units.create(program.units, parser.lex.ident); + unit := PROG.newUnit(program, parser.lex.ident); parser.unit := unit; @@ -1062,19 +1145,26 @@ BEGIN END; CONSOLE.Ln; - label := CODE.NewLabel(); - CODE.AddJmpCmd(CODE.opJMP, label); + label := IL.NewLabel(); + IL.AddJmpCmd(IL.opJMP, label); - name := CODE.putstr(unit.name.s); + name := IL.putstr(unit.name.s); - CODE.SetErrLabel; - CODE.AddCmd(CODE.opSADR, name); - CODE.AddCmd(CODE.opPARAM, 1); - CODE.AddCmd0(CODE.opERR); + errlabel := IL.NewLabel(); + IL.SetLabel(errlabel); + IL.StrAdr(name); + IL.Param1; + IL.AddCmd0(IL.opERR); + + FOR errno := 1 TO LEN(IL.codes.errlabels) - 1 DO + IL.SetErrLabel(errno); + IL.AddCmd(IL.opPUSHC, errno); + IL.AddJmpCmd(IL.opJMP, errlabel) + END; endmod := DeclarationSequence(parser); - CODE.SetLabel(label); + IL.SetLabel(label); IF ~endmod THEN @@ -1091,8 +1181,7 @@ BEGIN END; - unit.close(unit) - + PROG.closeUnit(unit) END parse; @@ -1156,9 +1245,9 @@ BEGIN END create; -PROCEDURE init* (bit_depth, sys: INTEGER); +PROCEDURE init* (bit_depth, target: INTEGER; options: PROG.OPTIONS); BEGIN - program := PROG.create(bit_depth, sys); + program := PROG.create(bit_depth, target, options); parsers := C.create() END init; diff --git a/programs/develop/oberon07/Source/PATHS.ob07 b/programs/develop/oberon07/Source/PATHS.ob07 index 4a86cfdd52..e6ea79255e 100644 --- a/programs/develop/oberon07/Source/PATHS.ob07 +++ b/programs/develop/oberon07/Source/PATHS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) @@ -12,11 +12,11 @@ IMPORT STRINGS, UTILS; CONST - slash = UTILS.slash; - + slash = UTILS.slash; + PATHLEN = 2048; - - + + TYPE PATH* = ARRAY PATHLEN OF CHAR; @@ -92,12 +92,12 @@ BEGIN res[i] := 0X END -END RelPath; +END RelPath; PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; RETURN UTILS.isRelative(path) -END isRelative; +END isRelative; PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); diff --git a/programs/develop/oberon07/Source/PROG.ob07 b/programs/develop/oberon07/Source/PROG.ob07 index d08a984a0c..a5e090126f 100644 --- a/programs/develop/oberon07/Source/PROG.ob07 +++ b/programs/develop/oberon07/Source/PROG.ob07 @@ -7,7 +7,7 @@ MODULE PROG; -IMPORT SCAN, LISTS, ARITH, ERRORS, MACHINE, C := COLLECTIONS, mConst := CONSTANTS, CODE, UTILS; +IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, mConst := CONSTANTS, IL, UTILS; CONST @@ -39,9 +39,10 @@ CONST 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; + sysWSADR* = 39; sysPUT32* = 40; (*sysNOP* = 41; sysEINT* = 42; + sysDINT* = 43;*) - default* = 2; + default32* = 2; stdcall* = 4; _stdcall* = stdcall + 1; ccall* = 6; _ccall* = ccall + 1; ccall16* = 8; _ccall16* = ccall16 + 1; @@ -49,19 +50,34 @@ CONST stdcall64* = 12; _stdcall64* = stdcall64 + 1; default64* = 14; systemv* = 16; _systemv* = systemv + 1; + default16* = 18; + code* = 20; _code* = code + 1; - noalign* = 20; + noalign* = 22; - callee_clean_up* = {default, stdcall, _stdcall, default64, stdcall64, _stdcall64}; - caller_clean_up* = {ccall, ccall16, win64, systemv, _ccall, _ccall16, _win64, _systemv}; - callconv32* = {default, stdcall, ccall, ccall16, _stdcall, _ccall, _ccall16}; - callconv64* = {default64, win64, stdcall64, systemv, _win64, _stdcall64, _systemv}; + callee_clean_up* = {default32, stdcall, _stdcall, default64, stdcall64, _stdcall64}; + + sf_stdcall* = 0; sf_stdcall64* = 1; sf_ccall* = 2; sf_ccall16* = 3; + sf_win64* = 4; sf_systemv* = 5; sf_windows* = 6; sf_linux* = 7; + sf_code* = 8; + sf_noalign* = 9; + + proc_flags* = {sf_stdcall, sf_stdcall64, sf_ccall, sf_ccall16, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code}; + rec_flags* = {sf_noalign}; STACK_FRAME = 2; TYPE + OPTIONS* = RECORD + + version*, stack*, base*, ram*, rom*: INTEGER; + pic*: BOOLEAN; + checking*: SET + + END; + IDENT* = POINTER TO rIDENT; UNIT* = POINTER TO rUNIT; @@ -81,13 +97,6 @@ TYPE END; - IDENTS = POINTER TO RECORD (LISTS.LIST) - - add*: PROCEDURE (unit: UNIT; ident: SCAN.IDENT; typ: INTEGER): IDENT; - get*: PROCEDURE (unit: UNIT; ident: SCAN.IDENT; currentScope: BOOLEAN): IDENT - - END; - PROC* = POINTER TO RECORD (LISTS.ITEM) label*: INTEGER; @@ -110,31 +119,13 @@ TYPE program*: PROGRAM; name*: SCAN.IDENT; - idents*: IDENTS; + idents*: LISTS.LIST; frwPointers: LISTS.LIST; gscope: IDENT; closed*: BOOLEAN; scopeLvl*: INTEGER; sysimport*: BOOLEAN; - - scopes*: ARRAY MAXSCOPE OF PROC; - - scope*: RECORD - - open*: PROCEDURE (unit: UNIT; proc: PROC): BOOLEAN; - close*: PROCEDURE (unit: UNIT; variables: LISTS.LIST) - - END; - - close*: PROCEDURE (unit: UNIT); - setvars*: PROCEDURE (unit: UNIT; type: TYPE_); - - pointers*: RECORD - - add*: PROCEDURE (unit: UNIT; type: TYPE_; baseIdent: SCAN.IDENT; pos: SCAN.POSITION); - link*: PROCEDURE (unit: UNIT): FRWPTR - - END + scopes*: ARRAY MAXSCOPE OF PROC END; @@ -142,34 +133,16 @@ TYPE PARAM* = POINTER TO rPARAM; - FIELDS = POINTER TO RECORD (LISTS.LIST) - - add*: PROCEDURE (rec: TYPE_; name: SCAN.IDENT; export: BOOLEAN): BOOLEAN; - get*: PROCEDURE (rec: TYPE_; name: SCAN.IDENT; unit: UNIT): FIELD; - set*: PROCEDURE (rec: TYPE_; type: TYPE_): BOOLEAN - - END; - - PARAMS = POINTER TO RECORD (LISTS.LIST) - - size*: INTEGER; - - add*: PROCEDURE (proc: TYPE_; name: SCAN.IDENT; vPar: BOOLEAN): BOOLEAN; - get*: PROCEDURE (proc: TYPE_; name: SCAN.IDENT): PARAM; - set*: PROCEDURE (proc: TYPE_; type: TYPE_); - getfparams*: PROCEDURE (proc: TYPE_; maxparam: INTEGER; VAR int, flt: INTEGER): SET - - END; - rTYPE_ = RECORD (LISTS.ITEM) typ*: INTEGER; size*: INTEGER; + parSize*: INTEGER; length*: INTEGER; align*: INTEGER; base*: TYPE_; - fields*: FIELDS; - params*: PARAMS; + fields*: LISTS.LIST; + params*: LISTS.LIST; unit*: UNIT; closed*: BOOLEAN; num*: INTEGER; @@ -215,19 +188,10 @@ TYPE END; - UNITS* = POINTER TO RECORD (LISTS.LIST) - - program: PROGRAM; - - create*: PROCEDURE (units: UNITS; name: SCAN.IDENT): UNIT; - get*: PROCEDURE (units: UNITS; name: SCAN.IDENT): UNIT - - END; - rPROGRAM = RECORD recCount: INTEGER; - units*: UNITS; + units*: LISTS.LIST; types*: LISTS.LIST; sysunit*: UNIT; rtl*: UNIT; @@ -238,10 +202,10 @@ TYPE dll*: BOOLEAN; obj*: BOOLEAN; - stTypes*: RECORD + stTypes*: RECORD - tINTEGER*, tBYTE*, tCHAR*, tWCHAR*, tSET*, tBOOLEAN*, tREAL*, tSTRING*, tNIL*, - tCARD16*, tCARD32*, tANYREC*: TYPE_ + tINTEGER*, tBYTE*, tCHAR*, tWCHAR*, tSET*, tBOOLEAN*, tREAL*, + tSTRING*, tNIL*, tCARD16*, tCARD32*, tANYREC*: TYPE_ END; @@ -250,12 +214,11 @@ TYPE bit_depth*: INTEGER; word*: INTEGER; adr*: INTEGER; - sys*: INTEGER + sys*: INTEGER; + sysflags*: SET; + options*: OPTIONS - END; - - enterType*: PROCEDURE (program: PROGRAM; typ, size, length: INTEGER; unit: UNIT): TYPE_; - getType*: PROCEDURE (program: PROGRAM; typ: INTEGER): TYPE_ + END END; @@ -292,7 +255,7 @@ VAR BEGIN IF varIdent.offset = -1 THEN IF varIdent.global THEN - IF MACHINE.Align(program.bss, varIdent.type.align) THEN + IF UTILS.Align(program.bss, varIdent.type.align) THEN IF UTILS.maxint - program.bss >= varIdent.type.size THEN varIdent.offset := program.bss; INC(program.bss, varIdent.type.size) @@ -301,7 +264,7 @@ BEGIN ELSE word := program.target.word; size := varIdent.type.size; - IF MACHINE.Align(size, word) THEN + IF UTILS.Align(size, word) THEN size := size DIV word; IF UTILS.maxint - program.locsize >= size THEN INC(program.locsize, size); @@ -315,7 +278,7 @@ BEGIN END getOffset; -PROCEDURE close (unit: UNIT); +PROCEDURE closeUnit* (unit: UNIT); VAR ident, prev: IDENT; offset: INTEGER; @@ -324,7 +287,7 @@ 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); + ERRORS.HintMsg(ident.name.s, ident.pos.line, ident.pos.col, 0); IF ident.export THEN offset := getOffset(unit.program, ident) END @@ -343,7 +306,7 @@ BEGIN END; unit.closed := TRUE -END close; +END closeUnit; PROCEDURE unique (unit: UNIT; ident: SCAN.IDENT): BOOLEAN; @@ -362,12 +325,12 @@ BEGIN END unique; -PROCEDURE addIdent (unit: UNIT; ident: SCAN.IDENT; typ: INTEGER): IDENT; +PROCEDURE addIdent* (unit: UNIT; ident: SCAN.IDENT; typ: INTEGER): IDENT; VAR - item: IDENT; - res: BOOLEAN; - proc: PROC; - procs: LISTS.LIST; + item: IDENT; + res: BOOLEAN; + proc: PROC; + procs: LISTS.LIST; BEGIN ASSERT(unit # NIL); @@ -414,9 +377,9 @@ END addIdent; PROCEDURE UseProc* (unit: UNIT; call_proc: PROC); VAR - procs: LISTS.LIST; - cur: LISTS.ITEM; - proc: USED_PROC; + procs: LISTS.LIST; + cur: LISTS.ITEM; + proc: USED_PROC; BEGIN IF unit.scopeLvl = 0 THEN @@ -438,7 +401,7 @@ BEGIN END UseProc; -PROCEDURE setvars (unit: UNIT; type: TYPE_); +PROCEDURE setVarsType* (unit: UNIT; type: TYPE_); VAR item: IDENT; @@ -450,10 +413,10 @@ BEGIN item.type := type; item := item.prev(IDENT) END -END setvars; +END setVarsType; -PROCEDURE getIdent (unit: UNIT; ident: SCAN.IDENT; currentScope: BOOLEAN): IDENT; +PROCEDURE getIdent* (unit: UNIT; ident: SCAN.IDENT; currentScope: BOOLEAN): IDENT; VAR item: IDENT; @@ -462,26 +425,28 @@ BEGIN item := unit.idents.last(IDENT); - ASSERT(item # NIL); + IF item # NIL THEN - IF currentScope THEN - WHILE (item.name # ident) & (item.typ # idGUARD) DO - item := item.prev(IDENT) - END; - IF item.name # ident THEN - item := NIL - END - ELSE - WHILE (item # NIL) & (item.name # ident) DO - item := item.prev(IDENT) + IF currentScope THEN + WHILE (item.name # ident) & (item.typ # idGUARD) DO + item := item.prev(IDENT) + END; + IF item.name # ident THEN + item := NIL + END + ELSE + WHILE (item # NIL) & (item.name # ident) DO + item := item.prev(IDENT) + END END + END RETURN item END getIdent; -PROCEDURE openScope (unit: UNIT; proc: PROC): BOOLEAN; +PROCEDURE openScope* (unit: UNIT; proc: PROC): BOOLEAN; VAR item: IDENT; res: BOOLEAN; @@ -508,11 +473,11 @@ BEGIN END openScope; -PROCEDURE closeScope (unit: UNIT; variables: LISTS.LIST); +PROCEDURE closeScope* (unit: UNIT; variables: LISTS.LIST); VAR item: IDENT; del: IDENT; - lvar: CODE.LOCALVAR; + lvar: IL.LOCALVAR; BEGIN item := unit.idents.last(IDENT); @@ -521,11 +486,11 @@ BEGIN 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) + ERRORS.HintMsg(del.name.s, del.pos.line, del.pos.col, 0) END; IF (variables # NIL) & (del.typ IN {idVAR, idPARAM}) & (del.offset # -1) THEN IF del.type.typ IN BASICTYPES - {tREAL} + {tPOINTER, tPROCEDURE} THEN - lvar := CODE.NewVar(); + lvar := IL.NewVar(); lvar.offset := del.offset; lvar.size := del.type.size; IF del.typ = idVAR THEN @@ -548,7 +513,7 @@ BEGIN END closeScope; -PROCEDURE frwptr (unit: UNIT; type: TYPE_; baseIdent: SCAN.IDENT; pos: SCAN.POSITION); +PROCEDURE frwPtr* (unit: UNIT; type: TYPE_; baseIdent: SCAN.IDENT; pos: SCAN.POSITION); VAR newptr: FRWPTR; @@ -559,17 +524,17 @@ BEGIN NEW(newptr); - newptr.type := type; - newptr.baseIdent := baseIdent; - newptr.pos := pos; - newptr.linked := FALSE; - newptr.notRecord := FALSE; + newptr.type := type; + newptr.baseIdent := baseIdent; + newptr.pos := pos; + newptr.linked := FALSE; + newptr.notRecord := FALSE; LISTS.push(unit.frwPointers, newptr) -END frwptr; +END frwPtr; -PROCEDURE linkptr (unit: UNIT): FRWPTR; +PROCEDURE linkPtr* (unit: UNIT): FRWPTR; VAR item: FRWPTR; ident: IDENT; @@ -580,7 +545,7 @@ BEGIN item := unit.frwPointers.last(FRWPTR); WHILE (item # NIL) & ~item.linked & (res = NIL) DO - ident := unit.idents.get(unit, item.baseIdent, TRUE); + ident := getIdent(unit, item.baseIdent, TRUE); IF (ident # NIL) THEN IF (ident.typ = idTYPE) & (ident.type.typ = tRECORD) THEN @@ -599,7 +564,7 @@ BEGIN END RETURN res -END linkptr; +END linkPtr; PROCEDURE isTypeEq* (t1, t2: TYPE_): BOOLEAN; @@ -617,7 +582,7 @@ BEGIN param1 := t1.params.first; param2 := t2.params.first; - res := (t1.call = t2.call) & ((param1 # NIL) = (param2 # NIL)); + 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); @@ -643,18 +608,21 @@ VAR res: BOOLEAN; BEGIN - res := ((t0.typ = tPOINTER) & (t1.typ = tPOINTER)) OR ((t0.typ = tRECORD) & (t1.typ = tRECORD)); + res := (t0.typ = t1.typ) & (t0.typ IN {tPOINTER, tRECORD}); - IF (t0.typ = tPOINTER) & (t1.typ = tPOINTER) THEN + IF res & (t0.typ = tPOINTER) THEN t0 := t0.base; t1 := t1.base END; - WHILE res & (t1 # NIL) & (t1 # t0) DO - t1 := t1.base + IF res THEN + WHILE (t1 # NIL) & (t1 # t0) DO + t1 := t1.base + END; + res := t1 # NIL END - RETURN res & (t1 = t0) + RETURN res END isBaseOf; @@ -663,61 +631,54 @@ PROCEDURE isOpenArray* (t: TYPE_): BOOLEAN; END isOpenArray; -PROCEDURE getunit (units: UNITS; name: SCAN.IDENT): UNIT; +PROCEDURE getUnit* (program: PROGRAM; name: SCAN.IDENT): UNIT; VAR item: UNIT; BEGIN ASSERT(name # NIL); - item := units.first(UNIT); + item := program.units.first(UNIT); WHILE (item # NIL) & (item.name # name) DO item := item.next(UNIT) END; IF (item = NIL) & (name.s = "SYSTEM") THEN - item := units.program.sysunit + item := program.sysunit END RETURN item -END getunit; +END getUnit; PROCEDURE enterStTypes (unit: UNIT; program: PROGRAM); VAR - ident: IDENT; - stName: SCAN.IDENT; + ident: IDENT; BEGIN - - stName := SCAN.enterid("INTEGER"); - ident := addIdent(unit, stName, idTYPE); + ident := addIdent(unit, SCAN.enterid("INTEGER"), idTYPE); ident.type := program.stTypes.tINTEGER; - stName := SCAN.enterid("BYTE"); - ident := addIdent(unit, stName, idTYPE); + ident := addIdent(unit, SCAN.enterid("BYTE"), idTYPE); ident.type := program.stTypes.tBYTE; - stName := SCAN.enterid("CHAR"); - ident := addIdent(unit, stName, idTYPE); + ident := addIdent(unit, SCAN.enterid("CHAR"), idTYPE); ident.type := program.stTypes.tCHAR; - stName := SCAN.enterid("WCHAR"); - ident := addIdent(unit, stName, idTYPE); - ident.type := program.stTypes.tWCHAR; - - stName := SCAN.enterid("SET"); - ident := addIdent(unit, stName, idTYPE); + ident := addIdent(unit, SCAN.enterid("SET"), idTYPE); ident.type := program.stTypes.tSET; - stName := SCAN.enterid("BOOLEAN"); - ident := addIdent(unit, stName, idTYPE); + ident := addIdent(unit, SCAN.enterid("BOOLEAN"), idTYPE); ident.type := program.stTypes.tBOOLEAN; - stName := SCAN.enterid("REAL"); - ident := addIdent(unit, stName, idTYPE); - ident.type := program.stTypes.tREAL; + IF program.target.sys # mConst.Target_iMSP430 THEN + ident := addIdent(unit, SCAN.enterid("REAL"), idTYPE); + ident.type := program.stTypes.tREAL; + + ident := addIdent(unit, SCAN.enterid("WCHAR"), idTYPE); + ident.type := program.stTypes.tWCHAR + END END enterStTypes; @@ -725,86 +686,86 @@ END enterStTypes; PROCEDURE enterStProcs (unit: UNIT); - PROCEDURE EnterProc (unit: UNIT; name: SCAN.LEXSTR; idtyp, proc: INTEGER); + PROCEDURE EnterProc (unit: UNIT; name: SCAN.LEXSTR; proc: INTEGER); VAR ident: IDENT; BEGIN - ident := addIdent(unit, SCAN.enterid(name), idtyp); + ident := addIdent(unit, SCAN.enterid(name), idSTPROC); ident.stproc := proc END EnterProc; -BEGIN - EnterProc(unit, "ASSERT", idSTPROC, stASSERT); - EnterProc(unit, "DEC", idSTPROC, stDEC); - EnterProc(unit, "EXCL", idSTPROC, stEXCL); - EnterProc(unit, "INC", idSTPROC, stINC); - EnterProc(unit, "INCL", idSTPROC, stINCL); - EnterProc(unit, "NEW", idSTPROC, stNEW); - EnterProc(unit, "PACK", idSTPROC, stPACK); - EnterProc(unit, "UNPK", idSTPROC, stUNPK); - EnterProc(unit, "DISPOSE", idSTPROC, stDISPOSE); - EnterProc(unit, "COPY", idSTPROC, stCOPY); + PROCEDURE EnterFunc (unit: UNIT; name: SCAN.LEXSTR; func: INTEGER); + VAR + ident: IDENT; + BEGIN + ident := addIdent(unit, SCAN.enterid(name), idSTFUNC); + ident.stproc := func + END EnterFunc; + + +BEGIN + EnterProc(unit, "ASSERT", stASSERT); + EnterProc(unit, "DEC", stDEC); + EnterProc(unit, "EXCL", stEXCL); + EnterProc(unit, "INC", stINC); + EnterProc(unit, "INCL", stINCL); + EnterProc(unit, "NEW", stNEW); + EnterProc(unit, "COPY", stCOPY); + + EnterFunc(unit, "ABS", stABS); + EnterFunc(unit, "ASR", stASR); + EnterFunc(unit, "CHR", stCHR); + EnterFunc(unit, "LEN", stLEN); + EnterFunc(unit, "LSL", stLSL); + EnterFunc(unit, "ODD", stODD); + EnterFunc(unit, "ORD", stORD); + EnterFunc(unit, "ROR", stROR); + EnterFunc(unit, "BITS", stBITS); + EnterFunc(unit, "LSR", stLSR); + EnterFunc(unit, "LENGTH", stLENGTH); + EnterFunc(unit, "MIN", stMIN); + EnterFunc(unit, "MAX", stMAX); + + IF unit.program.target.sys # mConst.Target_iMSP430 THEN + EnterProc(unit, "PACK", stPACK); + EnterProc(unit, "UNPK", stUNPK); + EnterProc(unit, "DISPOSE", stDISPOSE); + + EnterFunc(unit, "WCHR", stWCHR); + EnterFunc(unit, "FLOOR", stFLOOR); + EnterFunc(unit, "FLT", stFLT) + END - EnterProc(unit, "ABS", idSTFUNC, stABS); - EnterProc(unit, "ASR", idSTFUNC, stASR); - EnterProc(unit, "CHR", idSTFUNC, stCHR); - EnterProc(unit, "WCHR", idSTFUNC, stWCHR); - EnterProc(unit, "FLOOR", idSTFUNC, stFLOOR); - EnterProc(unit, "FLT", idSTFUNC, stFLT); - EnterProc(unit, "LEN", idSTFUNC, stLEN); - EnterProc(unit, "LSL", idSTFUNC, stLSL); - EnterProc(unit, "ODD", idSTFUNC, stODD); - EnterProc(unit, "ORD", idSTFUNC, stORD); - EnterProc(unit, "ROR", idSTFUNC, stROR); - EnterProc(unit, "BITS", idSTFUNC, stBITS); - EnterProc(unit, "LSR", idSTFUNC, stLSR); - EnterProc(unit, "LENGTH", idSTFUNC, stLENGTH); - EnterProc(unit, "MIN", idSTFUNC, stMIN); - EnterProc(unit, "MAX", idSTFUNC, stMAX); END enterStProcs; -PROCEDURE newunit (units: UNITS; name: SCAN.IDENT): UNIT; +PROCEDURE newUnit* (program: PROGRAM; name: SCAN.IDENT): UNIT; VAR - unit: UNIT; - idents: IDENTS; + unit: UNIT; BEGIN - ASSERT(units # NIL); + ASSERT(program # NIL); ASSERT(name # NIL); NEW(unit); - NEW(idents); - ASSERT(LISTS.create(idents) = idents); - - idents.add := addIdent; - idents.get := getIdent; - - unit.program := units.program; + unit.program := program; unit.name := name; unit.closed := FALSE; - unit.idents := idents; + unit.idents := LISTS.create(NIL); unit.frwPointers := LISTS.create(NIL); - unit.scope.open := openScope; - unit.scope.close := closeScope; - unit.close := close; - unit.setvars := setvars; - unit.pointers.add := frwptr; - unit.pointers.link := linkptr; + ASSERT(openScope(unit, NIL)); - ASSERT(unit.scope.open(unit, NIL)); - - enterStTypes(unit, units.program); + enterStTypes(unit, program); enterStProcs(unit); - ASSERT(unit.scope.open(unit, NIL)); + ASSERT(openScope(unit, NIL)); unit.gscope := unit.idents.last(IDENT); - LISTS.push(units, unit); + LISTS.push(program.units, unit); unit.scopeLvl := 0; unit.scopes[0] := NIL; @@ -812,16 +773,16 @@ BEGIN unit.sysimport := FALSE; IF unit.name.s = mConst.RTL_NAME THEN - unit.program.rtl := unit + program.rtl := unit END RETURN unit -END newunit; +END newUnit; -PROCEDURE getField (self: TYPE_; name: SCAN.IDENT; unit: UNIT): FIELD; +PROCEDURE getField* (self: TYPE_; name: SCAN.IDENT; unit: UNIT): FIELD; VAR - field: FIELD; + field: FIELD; BEGIN ASSERT(self # NIL); @@ -851,10 +812,10 @@ BEGIN END getField; -PROCEDURE addField (self: TYPE_; name: SCAN.IDENT; export: BOOLEAN): BOOLEAN; +PROCEDURE addField* (self: TYPE_; name: SCAN.IDENT; export: BOOLEAN): BOOLEAN; VAR - field: FIELD; - res: BOOLEAN; + field: FIELD; + res: BOOLEAN; BEGIN ASSERT(name # NIL); @@ -876,7 +837,7 @@ BEGIN END addField; -PROCEDURE setFields (self: TYPE_; type: TYPE_): BOOLEAN; +PROCEDURE setFields* (self: TYPE_; type: TYPE_): BOOLEAN; VAR item: FIELD; res: BOOLEAN; @@ -895,7 +856,7 @@ BEGIN WHILE res & (item # NIL) & (item.type = NIL) DO item.type := type; IF ~self.noalign THEN - res := MACHINE.Align(self.size, type.align) + res := UTILS.Align(self.size, type.align) ELSE res := TRUE END; @@ -911,9 +872,9 @@ BEGIN END setFields; -PROCEDURE getParam (self: TYPE_; name: SCAN.IDENT): PARAM; +PROCEDURE getParam* (self: TYPE_; name: SCAN.IDENT): PARAM; VAR - item: PARAM; + item: PARAM; BEGIN ASSERT(name # NIL); @@ -928,15 +889,15 @@ BEGIN END getParam; -PROCEDURE addParam (self: TYPE_; name: SCAN.IDENT; vPar: BOOLEAN): BOOLEAN; +PROCEDURE addParam* (self: TYPE_; name: SCAN.IDENT; vPar: BOOLEAN): BOOLEAN; VAR - param: PARAM; - res: BOOLEAN; + param: PARAM; + res: BOOLEAN; BEGIN ASSERT(name # NIL); - res := self.params.get(self, name) = NIL; + res := getParam(self, name) = NIL; IF res THEN NEW(param); @@ -973,7 +934,7 @@ BEGIN END OpenBase; -PROCEDURE getFloatParamsPos (self: TYPE_; maxoffs: INTEGER; VAR int, flt: INTEGER): SET; +PROCEDURE getFloatParamsPos* (self: TYPE_; maxoffs: INTEGER; VAR int, flt: INTEGER): SET; VAR res: SET; param: PARAM; @@ -991,13 +952,13 @@ BEGIN param := param.next(PARAM) END; - int := self.params.size - flt + int := self.parSize - flt RETURN res END getFloatParamsPos; -PROCEDURE setParams (self: TYPE_; type: TYPE_); +PROCEDURE setParams* (self: TYPE_; type: TYPE_); VAR item: LISTS.ITEM; param: PARAM; @@ -1006,7 +967,7 @@ VAR BEGIN ASSERT(type # NIL); - word := MACHINE.target.bit_depth DIV 8; + word := UTILS.target.bit_depth DIV 8; item := self.params.first; @@ -1025,8 +986,8 @@ BEGIN ELSE size := 1 END; - param.offset := self.params.size + ORD(type.typ = tRECORD) + Dim(type) + STACK_FRAME; - INC(self.params.size, size) + 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 @@ -1036,11 +997,11 @@ BEGIN END ELSE size := type.size; - ASSERT(MACHINE.Align(size, word)); + ASSERT(UTILS.Align(size, word)); size := size DIV word END; - param.offset := self.params.size + Dim(type) + STACK_FRAME; - INC(self.params.size, size) + param.offset := self.parSize + Dim(type) + STACK_FRAME; + INC(self.parSize, size) END; item := item.next @@ -1049,47 +1010,32 @@ BEGIN END setParams; -PROCEDURE enterType (program: PROGRAM; typ, size, length: INTEGER; unit: UNIT): TYPE_; +PROCEDURE enterType* (program: PROGRAM; typ, size, length: INTEGER; unit: UNIT): TYPE_; VAR - t: TYPE_; - fields: FIELDS; - params: PARAMS; + t: TYPE_; BEGIN NEW(t); - NEW(fields); - ASSERT(LISTS.create(fields) = fields); - - NEW(params); - ASSERT(LISTS.create(params) = params); - t.typ := typ; t.size := size; t.length := length; t.align := 0; t.base := NIL; - t.fields := fields; - t.params := params; + t.fields := LISTS.create(NIL); + t.params := LISTS.create(NIL); t.unit := unit; t.num := 0; - IF program.target.bit_depth = 32 THEN - t.call := default - ELSIF program.target.bit_depth = 64 THEN - t.call := default64 + + CASE program.target.bit_depth OF + |16: t.call := default16 + |32: t.call := default32 + |64: t.call := default64 END; + t.import := FALSE; t.noalign := FALSE; - - t.fields.add := addField; - t.fields.get := getField; - t.fields.set := setFields; - - t.params.add := addParam; - t.params.get := getParam; - t.params.getfparams := getFloatParamsPos; - t.params.set := setParams; - t.params.size := 0; + t.parSize := 0; IF typ IN {tARRAY, tRECORD} THEN t.closed := FALSE; @@ -1107,7 +1053,7 @@ BEGIN END enterType; -PROCEDURE getType (program: PROGRAM; typ: INTEGER): TYPE_; +PROCEDURE getType* (program: PROGRAM; typ: INTEGER): TYPE_; VAR res: TYPE_; @@ -1154,33 +1100,42 @@ VAR BEGIN - unit := program.units.create(program.units, SCAN.enterid("$SYSTEM")); + unit := newUnit(program, SCAN.enterid("$SYSTEM")); EnterProc(unit, "ADR", idSYSFUNC, sysADR); EnterProc(unit, "SIZE", idSYSFUNC, sysSIZE); EnterProc(unit, "SADR", idSYSFUNC, sysSADR); - EnterProc(unit, "WSADR", idSYSFUNC, sysWSADR); EnterProc(unit, "TYPEID", idSYSFUNC, sysTYPEID); - EnterProc(unit, "INF", idSYSFUNC, sysINF); EnterProc(unit, "GET", idSYSPROC, sysGET); - EnterProc(unit, "PUT", idSYSPROC, sysPUT); EnterProc(unit, "PUT8", idSYSPROC, sysPUT8); - EnterProc(unit, "PUT16", idSYSPROC, sysPUT16); - EnterProc(unit, "PUT32", idSYSPROC, sysPUT32); + EnterProc(unit, "PUT", idSYSPROC, sysPUT); EnterProc(unit, "CODE", idSYSPROC, sysCODE); EnterProc(unit, "MOVE", idSYSPROC, sysMOVE); - EnterProc(unit, "COPY", idSYSPROC, sysCOPY); + (* + 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 program.target.sys # mConst.Target_iMSP430 THEN + EnterProc(unit, "WSADR", idSYSFUNC, sysWSADR); + EnterProc(unit, "INF", idSYSFUNC, sysINF); + EnterProc(unit, "PUT32", idSYSPROC, sysPUT32); + EnterProc(unit, "PUT16", idSYSPROC, sysPUT16); + EnterProc(unit, "COPY", idSYSPROC, sysCOPY); - ident := addIdent(unit, SCAN.enterid("CARD16"), idTYPE); - ident.type := program.stTypes.tCARD16; - ident.export := TRUE; + ident := addIdent(unit, SCAN.enterid("CARD16"), idTYPE); + ident.type := program.stTypes.tCARD16; + ident.export := TRUE; - ident := addIdent(unit, SCAN.enterid("CARD32"), idTYPE); - ident.type := program.stTypes.tCARD32; - ident.export := TRUE; + ident := addIdent(unit, SCAN.enterid("CARD32"), idTYPE); + ident.type := program.stTypes.tCARD32; + ident.export := TRUE + END; - unit.close(unit); + closeUnit(unit); program.sysunit := unit END createSysUnit; @@ -1188,8 +1143,8 @@ END createSysUnit; PROCEDURE DelUnused* (program: PROGRAM; DelImport: DELIMPORT); VAR - proc: PROC; - flag: BOOLEAN; + proc: PROC; + flag: BOOLEAN; PROCEDURE process (proc: PROC); @@ -1211,7 +1166,6 @@ VAR BEGIN REPEAT - flag := FALSE; proc := program.procs.first(PROC); @@ -1230,7 +1184,7 @@ BEGIN WHILE proc # NIL DO IF ~proc.used THEN IF proc.import = NIL THEN - CODE.delete2(proc.enter, proc.leave) + IL.delete2(proc.enter, proc.leave) ELSE DelImport(proc.import) END @@ -1241,63 +1195,81 @@ BEGIN END DelUnused; -PROCEDURE create* (bit_depth, sys: INTEGER): PROGRAM; +PROCEDURE create* (bit_depth, target: INTEGER; options: OPTIONS): PROGRAM; VAR program: PROGRAM; - units: UNITS; BEGIN idents := C.create(); - MACHINE.SetBitDepth(bit_depth); + UTILS.SetBitDepth(bit_depth); NEW(program); - NEW(units); - ASSERT(LISTS.create(units) = units); program.target.bit_depth := bit_depth; program.target.word := bit_depth DIV 8; program.target.adr := bit_depth DIV 8; - program.target.sys := sys; + program.target.sys := target; + program.target.options := options; + + CASE target OF + |mConst.Target_iConsole, + mConst.Target_iGUI, + mConst.Target_iDLL: program.target.sysflags := {sf_windows, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} + + |mConst.Target_iELF32, + mConst.Target_iELFSO32: program.target.sysflags := {sf_linux, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} + + |mConst.Target_iKolibri, + mConst.Target_iObject: program.target.sysflags := {sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} + + |mConst.Target_iConsole64, + mConst.Target_iGUI64, + mConst.Target_iDLL64: program.target.sysflags := {sf_windows, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} + + |mConst.Target_iELF64, + mConst.Target_iELFSO64: program.target.sysflags := {sf_linux, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} + + |mConst.Target_iMSP430: program.target.sysflags := {sf_code} + END; program.recCount := -1; program.bss := 0; - program.units := units; + program.units := LISTS.create(NIL); program.types := LISTS.create(NIL); - program.procs := LISTS.create(NIL); - program.enterType := enterType; - program.getType := getType; - program.stTypes.tINTEGER := enterType(program, tINTEGER, program.target.word, 0, NIL); program.stTypes.tBYTE := enterType(program, tBYTE, 1, 0, NIL); program.stTypes.tCHAR := enterType(program, tCHAR, 1, 0, NIL); - program.stTypes.tWCHAR := enterType(program, tWCHAR, 2, 0, NIL); program.stTypes.tSET := enterType(program, tSET, program.target.word, 0, NIL); program.stTypes.tBOOLEAN := enterType(program, tBOOLEAN, 1, 0, NIL); - program.stTypes.tREAL := enterType(program, tREAL, 8, 0, NIL); - program.stTypes.tSTRING := enterType(program, tSTRING, program.target.word, 0, NIL); - program.stTypes.tNIL := enterType(program, tNIL, program.target.word, 0, NIL); - program.stTypes.tCARD16 := enterType(program, tCARD16, 2, 0, NIL); - program.stTypes.tCARD32 := enterType(program, tCARD32, 4, 0, NIL); - program.stTypes.tANYREC := enterType(program, tRECORD, 0, 0, NIL); + + IF target # mConst.Target_iMSP430 THEN + program.stTypes.tWCHAR := enterType(program, tWCHAR, 2, 0, NIL); + program.stTypes.tREAL := enterType(program, tREAL, 8, 0, NIL); + program.stTypes.tCARD16 := enterType(program, tCARD16, 2, 0, NIL); + program.stTypes.tCARD32 := enterType(program, tCARD32, 4, 0, NIL) + END; + + program.stTypes.tSTRING := enterType(program, tSTRING, program.target.word, 0, NIL); + program.stTypes.tNIL := enterType(program, tNIL, program.target.word, 0, NIL); + + program.stTypes.tANYREC := enterType(program, tRECORD, 0, 0, NIL); program.stTypes.tANYREC.closed := TRUE; program.stTypes.tINTEGER.align := program.stTypes.tINTEGER.size; program.stTypes.tBYTE.align := 1; program.stTypes.tCHAR.align := program.stTypes.tCHAR.size; - program.stTypes.tWCHAR.align := program.stTypes.tWCHAR.size; program.stTypes.tSET.align := program.stTypes.tSET.size; program.stTypes.tBOOLEAN.align := program.stTypes.tBOOLEAN.size; - program.stTypes.tREAL.align := program.stTypes.tREAL.size; - program.stTypes.tCARD16.align := program.stTypes.tCARD16.size; - program.stTypes.tCARD32.align := program.stTypes.tCARD32.size; - units.program := program; - - units.create := newunit; - units.get := getunit; + IF target # mConst.Target_iMSP430 THEN + program.stTypes.tWCHAR.align := program.stTypes.tWCHAR.size; + program.stTypes.tREAL.align := program.stTypes.tREAL.size; + program.stTypes.tCARD16.align := program.stTypes.tCARD16.size; + program.stTypes.tCARD32.align := program.stTypes.tCARD32.size + END; program.dll := FALSE; program.obj := FALSE; diff --git a/programs/develop/oberon07/Source/REG.ob07 b/programs/develop/oberon07/Source/REG.ob07 index 1f448d833b..b77aebf4e2 100644 --- a/programs/develop/oberon07/Source/REG.ob07 +++ b/programs/develop/oberon07/Source/REG.ob07 @@ -12,8 +12,10 @@ CONST N = 16; - R0* = 0; R1* = 1; R2* = 2; - R8* = 8; R9* = 9; R10* = 10; R11* = 11; + 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; NVR = 32; @@ -24,7 +26,7 @@ TYPE OP2 = PROCEDURE (arg1, arg2: INTEGER); OP3 = PROCEDURE (arg1, arg2, arg3: INTEGER); - REGS* = POINTER TO RECORD + REGS* = RECORD regs*: SET; stk*: ARRAY N OF INTEGER; @@ -42,7 +44,7 @@ TYPE END; -PROCEDURE push (R: REGS); +PROCEDURE push (VAR R: REGS); VAR i, reg: INTEGER; @@ -58,7 +60,7 @@ BEGIN END push; -PROCEDURE pop (R: REGS; reg: INTEGER); +PROCEDURE pop (VAR R: REGS; reg: INTEGER); VAR i: INTEGER; @@ -111,7 +113,7 @@ BEGIN END GetFreeReg; -PROCEDURE Put (R: REGS; reg: INTEGER); +PROCEDURE Put (VAR R: REGS; reg: INTEGER); BEGIN EXCL(R.regs, reg); INC(R.top); @@ -119,7 +121,7 @@ BEGIN END Put; -PROCEDURE PopAnyReg (R: REGS): INTEGER; +PROCEDURE PopAnyReg (VAR R: REGS): INTEGER; VAR reg: INTEGER; @@ -134,7 +136,7 @@ BEGIN END PopAnyReg; -PROCEDURE GetAnyReg* (R: REGS): INTEGER; +PROCEDURE GetAnyReg* (VAR R: REGS): INTEGER; VAR reg: INTEGER; @@ -152,13 +154,13 @@ BEGIN END GetAnyReg; -PROCEDURE GetReg* (R: REGS; reg: INTEGER): BOOLEAN; +PROCEDURE GetReg* (VAR R: REGS; reg: INTEGER): BOOLEAN; VAR free, n: INTEGER; res: BOOLEAN; - PROCEDURE exch (R: REGS; reg1, reg2: INTEGER); + PROCEDURE exch (VAR R: REGS; reg1, reg2: INTEGER); VAR n1, n2: INTEGER; @@ -201,7 +203,7 @@ BEGIN END GetReg; -PROCEDURE Exchange* (R: REGS; reg1, reg2: INTEGER): BOOLEAN; +PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN; VAR n1, n2: INTEGER; res: BOOLEAN; @@ -239,14 +241,14 @@ BEGIN END Exchange; -PROCEDURE Drop* (R: REGS); +PROCEDURE Drop* (VAR R: REGS); BEGIN INCL(R.regs, R.stk[R.top]); DEC(R.top) END Drop; -PROCEDURE BinOp* (R: REGS; VAR reg1, reg2: INTEGER); +PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER); BEGIN IF R.top > 0 THEN reg1 := R.stk[R.top - 1]; @@ -261,7 +263,7 @@ BEGIN END BinOp; -PROCEDURE UnOp* (R: REGS; VAR reg: INTEGER); +PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER); BEGIN IF R.top >= 0 THEN reg := R.stk[R.top] @@ -271,7 +273,7 @@ BEGIN END UnOp; -PROCEDURE PushAll* (R: REGS); +PROCEDURE PushAll* (VAR R: REGS); BEGIN WHILE R.top >= 0 DO push(R) @@ -279,7 +281,15 @@ BEGIN END PushAll; -PROCEDURE Lock* (R: REGS; reg, offs, size: INTEGER); +PROCEDURE PushAll_1* (VAR R: REGS); +BEGIN + WHILE R.top >= 1 DO + push(R) + END +END PushAll_1; + + +PROCEDURE Lock* (VAR R: REGS; reg, offs, size: INTEGER); BEGIN ASSERT(reg IN R.vregs); ASSERT(offs # 0); @@ -291,7 +301,7 @@ BEGIN END Lock; -PROCEDURE Release* (R: REGS; reg: INTEGER); +PROCEDURE Release* (VAR R: REGS; reg: INTEGER); BEGIN ASSERT(reg IN R.vregs); R.offs[reg] := 0 @@ -350,7 +360,7 @@ BEGIN END Restore; -PROCEDURE Reset* (R: REGS); +PROCEDURE Reset* (VAR R: REGS); VAR i: INTEGER; @@ -401,14 +411,11 @@ BEGIN END GetAnyVarReg; -PROCEDURE Create* (push, pop: OP1; mov, xch: OP2; load, save: OP3; regs, vregs: SET): REGS; +PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; load, save: OP3; regs, vregs: SET); VAR - R: REGS; i: INTEGER; BEGIN - NEW(R); - R.regs := regs; R.pushed := 0; R.top := -1; @@ -427,8 +434,7 @@ BEGIN R.size[i] := 0 END - RETURN R -END Create; +END Init; END REG. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/SCAN.ob07 b/programs/develop/oberon07/Source/SCAN.ob07 index ab771009a3..91de0575a9 100644 --- a/programs/develop/oberon07/Source/SCAN.ob07 +++ b/programs/develop/oberon07/Source/SCAN.ob07 @@ -1,46 +1,47 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) MODULE SCAN; -IMPORT TEXTDRV, AVL := AVLTREES, ARITH, S := STRINGS, C := COLLECTIONS; +IMPORT TXT := TEXTDRV, AVL := AVLTREES, ARITH, S := STRINGS; CONST LEXLEN = 1024; - lxUNDEF* = 0; lxIDENT* = 1; lxINTEGER* = 2; lxHEX* = 3; - lxCHAR* = 4; lxFLOAT* = 5; lxSTRING* = 6; lxCOMMENT* = 7; - lxEOF* = 8; + lxUNDEF* = 0; lxIDENT* = 1; lxINTEGER* = 2; lxHEX* = 3; + lxCHAR* = 4; lxFLOAT* = 5; lxSTRING* = 6; lxCOMMENT* = 7; + lxEOF* = 8; - lxKW = 101; + 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; - lxARRAY* = 101; lxBEGIN* = 102; lxBY* = 103; lxCASE* = 104; - lxCONST* = 105; lxDIV* = 106; lxDO* = 107; lxELSE* = 108; - lxELSIF* = 109; lxEND* = 110; lxFALSE* = 111; lxFOR* = 112; - lxIF* = 113; lxIMPORT* = 114; lxIN* = 115; lxIS* = 116; - lxMOD* = 117; lxMODULE* = 118; lxNIL* = 119; lxOF* = 120; - lxOR* = 121; lxPOINTER* = 122; lxPROCEDURE* = 123; lxRECORD* = 124; - lxREPEAT* = 125; lxRETURN* = 126; lxTHEN* = 127; lxTO* = 128; - lxTRUE* = 129; lxTYPE* = 130; lxUNTIL* = 131; lxVAR* = 132; - lxWHILE* = 133; + lxKW = 51; - lxPLUS* = 201; lxMINUS* = 202; lxMUL* = 203; lxSLASH* = 204; - lxNOT* = 205; lxAND* = 206; lxPOINT* = 207; lxCOMMA* = 208; - lxSEMI* = 209; lxBAR* = 210; lxLROUND* = 211; lxLSQUARE* = 212; - lxLCURLY* = 213; lxCARET* = 214; lxEQ* = 215; lxNE* = 216; - lxLT* = 217; lxGT* = 218; lxCOLON* = 219; lxRROUND* = 220; - lxRSQUARE* = 221; lxRCURLY* = 222; lxLE* = 223; lxGE* = 224; - lxASSIGN* = 225; lxRANGE* = 226; + 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; + 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 @@ -62,25 +63,20 @@ TYPE LEX* = RECORD - s*: LEXSTR; - length*: INTEGER; - sym*: INTEGER; - pos*: POSITION; - ident*: IDENT; - string*: IDENT; - value*: ARITH.VALUE; - error*: INTEGER; + s*: LEXSTR; + length*: INTEGER; + sym*: INTEGER; + pos*: POSITION; + ident*: IDENT; + string*: IDENT; + value*: ARITH.VALUE; + error*: INTEGER; - over: BOOLEAN + over: BOOLEAN END; - SCANNER* = POINTER TO RECORD (C.ITEM) - - text: TEXTDRV.TEXT; - range: BOOLEAN - - END; + SCANNER* = TXT.TEXT; KEYWORD = ARRAY 10 OF CHAR; @@ -89,16 +85,14 @@ VAR vocabulary: RECORD - KW: ARRAY 33 OF KEYWORD; - - delimiters: ARRAY 256 OF BOOLEAN; - - idents: AVL.NODE; - ident: IDENT + KW: ARRAY 33 OF KEYWORD; + delimiters: ARRAY 256 OF BOOLEAN; + idents: AVL.NODE; + ident: IDENT END; - scanners: C.COLLECTION; + upto: BOOLEAN; PROCEDURE nodecmp (a, b: AVL.DATA): INTEGER; @@ -109,36 +103,27 @@ END nodecmp; PROCEDURE key (VAR lex: LEX); VAR L, R, M: INTEGER; + found: BOOLEAN; BEGIN L := 0; R := LEN(vocabulary.KW) - 1; - M := (L + R) DIV 2; + found := FALSE; - WHILE L # M DO - IF lex.s > vocabulary.KW[M] THEN - L := M; - M := (L + R) DIV 2 - ELSIF lex.s < vocabulary.KW[M] THEN - R := M; - M := (L + R) DIV 2 + REPEAT + M := (L + R) DIV 2; + + IF lex.s # vocabulary.KW[M] THEN + IF lex.s > vocabulary.KW[M] THEN + L := M + 1 + ELSE + R := M - 1 + END ELSE - lex.sym := lxKW + M; - L := M; - R := M + found := TRUE; + lex.sym := lxKW + M END - END; - - IF L # R THEN - IF lex.s = vocabulary.KW[L] THEN - lex.sym := lxKW + L - END; - - IF lex.s = vocabulary.KW[R] THEN - lex.sym := lxKW + R - END - END - + UNTIL found OR (L > R) END key; @@ -173,18 +158,24 @@ BEGIN END putchar; -PROCEDURE ident (text: TEXTDRV.TEXT; VAR lex: LEX); +PROCEDURE nextc (text: TXT.TEXT): CHAR; +BEGIN + TXT.next(text) + RETURN text.peak +END nextc; + + +PROCEDURE ident (text: TXT.TEXT; VAR lex: LEX); VAR c: CHAR; BEGIN - c := text.peak(text); + c := text.peak; ASSERT(S.letter(c)); WHILE S.letter(c) OR S.digit(c) DO putchar(lex, c); - text.nextc(text); - c := text.peak(text) + c := nextc(text) END; IF lex.over THEN @@ -201,44 +192,40 @@ BEGIN END ident; -PROCEDURE number (text: TEXTDRV.TEXT; VAR lex: LEX; VAR range: BOOLEAN); +PROCEDURE number (text: TXT.TEXT; VAR lex: LEX); VAR c: CHAR; hex: BOOLEAN; error: INTEGER; BEGIN - c := text.peak(text); + c := text.peak; ASSERT(S.digit(c)); error := 0; - range := FALSE; - lex.sym := lxINTEGER; hex := FALSE; WHILE S.digit(c) DO putchar(lex, c); - text.nextc(text); - c := text.peak(text) + c := nextc(text) END; WHILE S.hexdigit(c) DO putchar(lex, c); - text.nextc(text); - c := text.peak(text); + c := nextc(text); hex := TRUE END; IF c = "H" THEN putchar(lex, c); - text.nextc(text); + TXT.next(text); lex.sym := lxHEX ELSIF c = "X" THEN putchar(lex, c); - text.nextc(text); + TXT.next(text); lex.sym := lxCHAR ELSIF c = "." THEN @@ -247,39 +234,35 @@ BEGIN lex.sym := lxERROR01 ELSE - text.nextc(text); - c := text.peak(text); + c := nextc(text); IF c # "." THEN putchar(lex, "."); lex.sym := lxFLOAT ELSE lex.sym := lxINTEGER; - range := TRUE + text.peak := 7FX; + upto := TRUE END; WHILE S.digit(c) DO putchar(lex, c); - text.nextc(text); - c := text.peak(text) + c := nextc(text) END; IF c = "E" THEN putchar(lex, c); - text.nextc(text); - c := text.peak(text); + c := nextc(text); IF (c = "+") OR (c = "-") THEN putchar(lex, c); - text.nextc(text); - c := text.peak(text) + c := nextc(text) END; IF S.digit(c) THEN WHILE S.digit(c) DO putchar(lex, c); - text.nextc(text); - c := text.peak(text) + c := nextc(text) END ELSE lex.sym := lxERROR02 @@ -289,11 +272,8 @@ BEGIN END - ELSE - - IF hex THEN - lex.sym := lxERROR01 - END + ELSIF hex THEN + lex.sym := lxERROR01 END; @@ -321,31 +301,23 @@ BEGIN END number; -PROCEDURE string (text: TEXTDRV.TEXT; VAR lex: LEX); +PROCEDURE string (text: TXT.TEXT; VAR lex: LEX; quot: CHAR); VAR - c, c1: CHAR; - n: INTEGER; - quot: CHAR; + c: CHAR; + n: INTEGER; BEGIN - quot := text.peak(text); - - ASSERT((quot = '"') OR (quot = "'")); - - text.nextc(text); - c := text.peak(text); - c1 := c; - n := 0; + c := nextc(text); + n := 0; WHILE (c # quot) & (c # 0X) & ~text.eol & ~text.eof DO putchar(lex, c); - text.nextc(text); - c := text.peak(text); + c := nextc(text); INC(n) END; IF c = quot THEN - text.nextc(text); + TXT.next(text); IF lex.over THEN lex.sym := lxERROR05 ELSE @@ -353,7 +325,7 @@ BEGIN lex.sym := lxSTRING ELSE lex.sym := lxCHAR; - ARITH.setChar(lex.value, ORD(c1)) + ARITH.setChar(lex.value, ORD(lex.s[0])) END END ELSE @@ -369,19 +341,19 @@ BEGIN END string; -PROCEDURE comment (text: TEXTDRV.TEXT); +PROCEDURE comment (text: TXT.TEXT); VAR c: CHAR; cond, depth: INTEGER; BEGIN - cond := 0; + cond := 0; depth := 1; REPEAT - c := text.peak(text); - text.nextc(text); + c := text.peak; + TXT.next(text); IF c = "*" THEN IF cond = 1 THEN @@ -406,21 +378,12 @@ BEGIN END comment; -PROCEDURE delimiter (text: TEXTDRV.TEXT; VAR lex: LEX; VAR range: BOOLEAN); -VAR - c: CHAR; - +PROCEDURE delimiter (text: TXT.TEXT; VAR lex: LEX; c: CHAR); BEGIN - c := text.peak(text); - - IF range THEN - ASSERT(c = ".") - END; - putchar(lex, c); - text.nextc(text); + c := nextc(text); - CASE c OF + CASE lex.s[0] OF |"+": lex.sym := lxPLUS @@ -433,10 +396,10 @@ BEGIN |"/": lex.sym := lxSLASH; - IF text.peak(text) = "/" THEN + IF c = "/" THEN lex.sym := lxCOMMENT; REPEAT - text.nextc(text) + TXT.next(text) UNTIL text.eol OR text.eof END @@ -447,24 +410,12 @@ BEGIN lex.sym := lxAND |".": - IF range THEN + lex.sym := lxPOINT; - putchar(lex, "."); + IF c = "." THEN lex.sym := lxRANGE; - range := FALSE; - DEC(lex.pos.col) - - ELSE - - lex.sym := lxPOINT; - c := text.peak(text); - - IF c = "." THEN - lex.sym := lxRANGE; - putchar(lex, c); - text.nextc(text) - END - + putchar(lex, c); + TXT.next(text) END |",": @@ -478,12 +429,10 @@ BEGIN |"(": lex.sym := lxLROUND; - c := text.peak(text); IF c = "*" THEN lex.sym := lxCOMMENT; - putchar(lex, c); - text.nextc(text); + TXT.next(text); comment(text) END @@ -504,32 +453,29 @@ BEGIN |"<": lex.sym := lxLT; - c := text.peak(text); IF c = "=" THEN lex.sym := lxLE; putchar(lex, c); - text.nextc(text) + TXT.next(text) END |">": lex.sym := lxGT; - c := text.peak(text); IF c = "=" THEN lex.sym := lxGE; putchar(lex, c); - text.nextc(text) + TXT.next(text) END |":": lex.sym := lxCOLON; - c := text.peak(text); IF c = "=" THEN lex.sym := lxASSIGN; putchar(lex, c); - text.nextc(text) + TXT.next(text) END |")": @@ -546,26 +492,21 @@ BEGIN END delimiter; -PROCEDURE Next* (scanner: SCANNER; VAR lex: LEX); +PROCEDURE Next* (text: SCANNER; VAR lex: LEX); VAR c: CHAR; - text: TEXTDRV.TEXT; BEGIN - text := scanner.text; REPEAT - - c := text.peak(text); + c := text.peak; WHILE S.space(c) DO - text.nextc(text); - c := text.peak(text) + c := nextc(text) END; lex.s[0] := 0X; lex.length := 0; - lex.sym := lxUNDEF; lex.pos.line := text.line; lex.pos.col := text.col; lex.ident := NIL; @@ -574,19 +515,26 @@ BEGIN IF S.letter(c) THEN ident(text, lex) ELSIF S.digit(c) THEN - number(text, lex, scanner.range) + number(text, lex) ELSIF (c = '"') OR (c = "'") THEN - string(text, lex) + string(text, lex, c) ELSIF vocabulary.delimiters[ORD(c)] THEN - delimiter(text, lex, scanner.range) + delimiter(text, lex, c) ELSIF c = 0X THEN lex.sym := lxEOF; IF text.eof THEN INC(lex.pos.col) END + ELSIF (c = 7FX) & upto THEN + upto := FALSE; + lex.sym := lxRANGE; + putchar(lex, "."); + putchar(lex, "."); + DEC(lex.pos.col); + TXT.next(text) ELSE putchar(lex, c); - text.nextc(text); + TXT.next(text); lex.sym := lxERROR04 END; @@ -601,53 +549,14 @@ BEGIN END Next; -PROCEDURE NewScanner (): SCANNER; -VAR - scan: SCANNER; - citem: C.ITEM; - -BEGIN - citem := C.pop(scanners); - IF citem = NIL THEN - NEW(scan) - ELSE - scan := citem(SCANNER) - END - - RETURN scan -END NewScanner; - - PROCEDURE open* (name: ARRAY OF CHAR): SCANNER; -VAR - scanner: SCANNER; - text: TEXTDRV.TEXT; - -BEGIN - text := TEXTDRV.create(); - IF text.open(text, name) THEN - scanner := NewScanner(); - scanner.text := text; - scanner.range := FALSE - ELSE - scanner := NIL; - TEXTDRV.destroy(text) - END - - RETURN scanner + RETURN TXT.open(name) END open; PROCEDURE close* (VAR scanner: SCANNER); BEGIN - IF scanner # NIL THEN - IF scanner.text # NIL THEN - TEXTDRV.destroy(scanner.text) - END; - - C.push(scanners, scanner); - scanner := NIL - END + TXT.close(scanner) END close; @@ -656,14 +565,16 @@ VAR i: INTEGER; delim: ARRAY 23 OF CHAR; + PROCEDURE enterkw (VAR i: INTEGER; kw: KEYWORD); BEGIN vocabulary.KW[i] := kw; INC(i) END enterkw; + BEGIN - scanners := C.create(); + upto := FALSE; FOR i := 0 TO 255 DO vocabulary.delimiters[i] := FALSE @@ -714,7 +625,7 @@ BEGIN vocabulary.ident.s := ""; vocabulary.ident.offset := -1; vocabulary.ident.offsetW := -1; - vocabulary.idents := NIL + vocabulary.idents := NIL END init; diff --git a/programs/develop/oberon07/Source/STATEMENTS.ob07 b/programs/develop/oberon07/Source/STATEMENTS.ob07 index ef9886c11a..8f53dd80c4 100644 --- a/programs/develop/oberon07/Source/STATEMENTS.ob07 +++ b/programs/develop/oberon07/Source/STATEMENTS.ob07 @@ -9,8 +9,8 @@ MODULE STATEMENTS; IMPORT - PARS, PROG, SCAN, ARITH, STRINGS, LISTS, CODE, X86, AMD64, - ERRORS, MACHINE, AVL := AVLTREES, CONSOLE, C := COLLECTIONS, mConst := CONSTANTS; + PARS, PROG, SCAN, ARITH, STRINGS, LISTS, IL, X86, AMD64, MSP430, + ERRORS, UTILS, AVL := AVLTREES, CONSOLE, C := COLLECTIONS, mConst := CONSTANTS; CONST @@ -21,14 +21,16 @@ CONST 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; + 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; chkALL* = {chkIDX, chkGUARD, chkPTR, chkCHR, chkWCHR, chkBYTE}; + cpuX86 = 1; cpuAMD64 = 2; cpuMSP430 = 3; + TYPE @@ -56,23 +58,27 @@ TYPE CASE_VARIANT = POINTER TO RECORD (LISTS.ITEM) - label: INTEGER; - cmd: CODE.COMMAND; - processed: BOOLEAN + label: INTEGER; + cmd: IL.COMMAND; + processed: BOOLEAN END; VAR - begcall, endcall: CODE.COMMAND; + Options: PROG.OPTIONS; - checking: SET; + 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} @@ -85,17 +91,17 @@ END isVar; PROCEDURE isBoolean (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tBOOLEAN) + RETURN isExpr(e) & (e.type = tBOOLEAN) END isBoolean; PROCEDURE isInteger (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tINTEGER) + RETURN isExpr(e) & (e.type = tINTEGER) END isInteger; PROCEDURE isByte (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tBYTE) + RETURN isExpr(e) & (e.type = tBYTE) END isByte; @@ -105,12 +111,12 @@ END isInt; PROCEDURE isReal (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tREAL) + RETURN isExpr(e) & (e.type = tREAL) END isReal; PROCEDURE isSet (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tSET) + RETURN isExpr(e) & (e.type = tSET) END isSet; @@ -125,30 +131,15 @@ END isStringW; PROCEDURE isChar (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tCHAR) + RETURN isExpr(e) & (e.type = tCHAR) END isChar; -PROCEDURE isCharArray (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tARRAY) & (e.type.base.typ = PROG.tCHAR) -END isCharArray; - - PROCEDURE isCharW (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tWCHAR) + RETURN isExpr(e) & (e.type = tWCHAR) END isCharW; -PROCEDURE isCharArrayW (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tARRAY) & (e.type.base.typ = PROG.tWCHAR) -END isCharArrayW; - - -PROCEDURE isCharArrayX (e: PARS.EXPR): BOOLEAN; - RETURN isExpr(e) & (e.type.typ = PROG.tARRAY) & (e.type.base.typ IN {PROG.tCHAR, PROG.tWCHAR}) -END isCharArrayX; - - PROCEDURE isPtr (e: PARS.EXPR): BOOLEAN; RETURN isExpr(e) & (e.type.typ = PROG.tPOINTER) END isPtr; @@ -159,6 +150,11 @@ PROCEDURE isRec (e: PARS.EXPR): BOOLEAN; 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; @@ -174,15 +170,33 @@ PROCEDURE isNil (e: PARS.EXPR): BOOLEAN; END isNil; -PROCEDURE getpos (parser: PARS.PARSER; VAR pos: SCAN.POSITION); +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 := parser.lex.pos + pos.line := parser.lex.pos.line; + pos.col := parser.lex.pos.col; + pos.parser := parser END getpos; -PROCEDURE NextPos (parser: PARS.PARSER; VAR pos: SCAN.POSITION); +PROCEDURE NextPos (parser: PARS.PARSER; VAR pos: PARS.POSITION); BEGIN - PARS.NextPos(parser, pos) + PARS.Next(parser); + getpos(parser, pos) END NextPos; @@ -192,7 +206,7 @@ VAR BEGIN ASSERT(isString(e)); - IF e.type.typ = PROG.tCHAR THEN + IF e.type = tCHAR THEN res := 1 ELSE res := LENGTH(e.value.string(SCAN.IDENT).s) @@ -266,24 +280,24 @@ BEGIN IF arrcomp(e.type, t) THEN res := TRUE ELSIF isInt(e) & (t.typ IN {PROG.tBYTE, PROG.tINTEGER}) THEN - IF (e.obj = eCONST) & (t.typ = PROG.tBYTE) THEN + IF (e.obj = eCONST) & (t = tBYTE) THEN res := ARITH.range(e.value, 0, 255) ELSE res := TRUE END - ELSIF isSet(e) & (t.typ = PROG.tSET) THEN + ELSIF isSet(e) & (t = tSET) THEN res := TRUE - ELSIF isBoolean(e) & (t.typ = PROG.tBOOLEAN) THEN + ELSIF isBoolean(e) & (t = tBOOLEAN) THEN res := TRUE - ELSIF isReal(e) & (t.typ = PROG.tREAL) THEN + ELSIF isReal(e) & (t = tREAL) THEN res := TRUE - ELSIF isChar(e) & (t.typ = PROG.tCHAR) THEN + ELSIF isChar(e) & (t = tCHAR) THEN res := TRUE - ELSIF (e.obj = eCONST) & isChar(e) & (t.typ = PROG.tWCHAR) THEN + ELSIF (e.obj = eCONST) & isChar(e) & (t = tWCHAR) THEN res := TRUE - ELSIF isStringW1(e) & (t.typ = PROG.tWCHAR) THEN + ELSIF isStringW1(e) & (t = tWCHAR) THEN res := TRUE - ELSIF isCharW(e) & (t.typ = PROG.tWCHAR) THEN + ELSIF isCharW(e) & (t = tWCHAR) THEN res := TRUE ELSIF PROG.isBaseOf(t, e.type) THEN res := TRUE @@ -291,9 +305,9 @@ BEGIN res := TRUE ELSIF isNil(e) & (t.typ IN {PROG.tPOINTER, PROG.tPROCEDURE}) THEN res := TRUE - ELSIF isString(e) & ((t.typ = PROG.tARRAY) & (t.base.typ = PROG.tCHAR) & (t.length > strlen(e))) THEN + ELSIF isString(e) & ((t.typ = PROG.tARRAY) & (t.base = tCHAR) & (t.length > strlen(e))) THEN res := TRUE - ELSIF isStringW(e) & ((t.typ = PROG.tARRAY) & (t.base.typ = PROG.tWCHAR) & (t.length > utf8strlen(e))) THEN + ELSIF isStringW(e) & ((t.typ = PROG.tARRAY) & (t.base = tWCHAR) & (t.length > utf8strlen(e))) THEN res := TRUE ELSE res := FALSE @@ -314,11 +328,11 @@ BEGIN IF strlen(e) # 1 THEN string := e.value.string(SCAN.IDENT); IF string.offset = -1 THEN - string.offset := CODE.putstr(string.s); + string.offset := IL.putstr(string.s); END; offset := string.offset ELSE - offset := CODE.putstr1(ARITH.Int(e.value)) + offset := IL.putstr1(ARITH.Int(e.value)) END RETURN offset @@ -334,16 +348,16 @@ BEGIN IF utf8strlen(e) # 1 THEN string := e.value.string(SCAN.IDENT); IF string.offsetW = -1 THEN - string.offsetW := CODE.putstrW(string.s); + string.offsetW := IL.putstrW(string.s); END; offset := string.offsetW ELSE IF e.type.typ IN {PROG.tWCHAR, PROG.tCHAR} THEN - offset := CODE.putstrW1(ARITH.Int(e.value)) + offset := IL.putstrW1(ARITH.Int(e.value)) ELSE (* e.type.typ = PROG.tSTRING *) string := e.value.string(SCAN.IDENT); IF string.offsetW = -1 THEN - string.offsetW := CODE.putstrW(string.s); + string.offsetW := IL.putstrW(string.s); END; offset := string.offsetW END @@ -358,10 +372,10 @@ VAR label: INTEGER; BEGIN - label := CODE.NewLabel(); - CODE.AddCmd2(CODE.opCHKIDX, label, range); - CODE.OnError(line, errno); - CODE.SetLabel(label) + label := IL.NewLabel(); + IL.AddCmd2(IL.opCHKIDX, label, range); + IL.OnError(line, errno); + IL.SetLabel(label) END CheckRange; @@ -384,98 +398,98 @@ BEGIN IF arrcomp(e.type, VarType) THEN IF ~PROG.isOpenArray(VarType) THEN - CODE.AddCmd(CODE.opCONST, VarType.length) + IL.Const(VarType.length) END; - CODE.AddCmd(CODE.opCOPYA, VarType.base.size); - label := CODE.NewLabel(); - CODE.AddJmpCmd(CODE.opJE, label); - CODE.OnError(line, errCOPY); - CODE.SetLabel(label) + IL.AddCmd(IL.opCOPYA, VarType.base.size); + label := IL.NewLabel(); + IL.AddJmpCmd(IL.opJE, label); + IL.OnError(line, errCOPY); + IL.SetLabel(label) ELSIF isInt(e) & (VarType.typ IN {PROG.tBYTE, PROG.tINTEGER}) THEN - IF VarType.typ = PROG.tINTEGER THEN + IF VarType = tINTEGER THEN IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opSAVEC, ARITH.Int(e.value)) + IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) ELSE - CODE.AddCmd0(CODE.opSAVE) + IL.AddCmd0(IL.opSAVE) END ELSE IF e.obj = eCONST THEN res := ARITH.range(e.value, 0, 255); IF res THEN - CODE.AddCmd(CODE.opSAVE8C, ARITH.Int(e.value)) + IL.AddCmd(IL.opSAVE8C, ARITH.Int(e.value)) END ELSE - IF chkBYTE IN checking THEN - label := CODE.NewLabel(); - CODE.AddCmd2(CODE.opCHKBYTE, label, 0); - CODE.OnError(line, errBYTE); - CODE.SetLabel(label) + IF chkBYTE IN Options.checking THEN + label := IL.NewLabel(); + IL.AddCmd2(IL.opCHKBYTE, label, 0); + IL.OnError(line, errBYTE); + IL.SetLabel(label) END; - CODE.AddCmd0(CODE.opSAVE8) + IL.AddCmd0(IL.opSAVE8) END END - ELSIF isSet(e) & (VarType.typ = PROG.tSET) THEN + ELSIF isSet(e) & (VarType = tSET) THEN IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opSAVEC, ARITH.Int(e.value)) + IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) ELSE - CODE.AddCmd0(CODE.opSAVE) + IL.AddCmd0(IL.opSAVE) END - ELSIF isBoolean(e) & (VarType.typ = PROG.tBOOLEAN) THEN + ELSIF isBoolean(e) & (VarType = tBOOLEAN) THEN IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opSBOOLC, ARITH.Int(e.value)) + IL.AddCmd(IL.opSBOOLC, ARITH.Int(e.value)) ELSE - CODE.AddCmd0(CODE.opSBOOL) + IL.AddCmd0(IL.opSBOOL) END - ELSIF isReal(e) & (VarType.typ = PROG.tREAL) THEN + ELSIF isReal(e) & (VarType = tREAL) THEN IF e.obj = eCONST THEN - CODE.Float(ARITH.Float(e.value)) + IL.Float(ARITH.Float(e.value)) END; - CODE.savef - ELSIF isChar(e) & (VarType.typ = PROG.tCHAR) THEN + IL.savef + ELSIF isChar(e) & (VarType = tCHAR) THEN IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opSAVE8C, ARITH.Int(e.value)) + IL.AddCmd(IL.opSAVE8C, ARITH.Int(e.value)) ELSE - CODE.AddCmd0(CODE.opSAVE8) + IL.AddCmd0(IL.opSAVE8) END - ELSIF (e.obj = eCONST) & isChar(e) & (VarType.typ = PROG.tWCHAR) THEN - CODE.AddCmd(CODE.opSAVE16C, ARITH.Int(e.value)) - ELSIF isStringW1(e) & (VarType.typ = PROG.tWCHAR) THEN - CODE.AddCmd(CODE.opSAVE16C, StrToWChar(e.value.string(SCAN.IDENT).s)) - ELSIF isCharW(e) & (VarType.typ = PROG.tWCHAR) THEN + 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.IDENT).s)) + ELSIF isCharW(e) & (VarType = tWCHAR) THEN IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opSAVE16C, ARITH.Int(e.value)) + IL.AddCmd(IL.opSAVE16C, ARITH.Int(e.value)) ELSE - CODE.AddCmd0(CODE.opSAVE16) + IL.AddCmd0(IL.opSAVE16) END ELSIF PROG.isBaseOf(VarType, e.type) THEN IF VarType.typ = PROG.tPOINTER THEN - CODE.AddCmd0(CODE.opSAVE) + IL.AddCmd0(IL.opSAVE) ELSE - CODE.AddCmd(CODE.opCOPY, VarType.size) + IL.AddCmd(IL.opCOPY, VarType.size) END ELSIF (e.type.typ = PROG.tCARD32) & (VarType.typ = PROG.tCARD32) THEN - CODE.AddCmd0(CODE.opSAVE32) + IL.AddCmd0(IL.opSAVE32) ELSIF (e.type.typ = PROG.tCARD16) & (VarType.typ = PROG.tCARD16) THEN - CODE.AddCmd0(CODE.opSAVE16) + IL.AddCmd0(IL.opSAVE16) ELSIF ~PROG.isOpenArray(VarType) & ~PROG.isOpenArray(e.type) & PROG.isTypeEq(VarType, e.type) THEN IF e.obj = ePROC THEN - CODE.AssignProc(e.ident.proc.label) + IL.AssignProc(e.ident.proc.label) ELSIF e.obj = eIMP THEN - CODE.AssignImpProc(e.ident.import) + IL.AssignImpProc(e.ident.import) ELSE IF VarType.typ = PROG.tPROCEDURE THEN - CODE.AddCmd0(CODE.opSAVE) + IL.AddCmd0(IL.opSAVE) ELSE - CODE.AddCmd(CODE.opCOPY, VarType.size) + IL.AddCmd(IL.opCOPY, VarType.size) END END ELSIF isNil(e) & (VarType.typ IN {PROG.tPOINTER, PROG.tPROCEDURE}) THEN - CODE.AddCmd(CODE.opSAVEC, 0) - ELSIF isString(e) & ((VarType.typ = PROG.tARRAY) & (VarType.base.typ = PROG.tCHAR) & (VarType.length > strlen(e))) THEN - CODE.saves(String(e), strlen(e) + 1) - ELSIF isStringW(e) & ((VarType.typ = PROG.tARRAY) & (VarType.base.typ = PROG.tWCHAR) & (VarType.length > utf8strlen(e))) THEN - CODE.saves(StringW(e), (utf8strlen(e) + 1) * 2) + 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 @@ -488,11 +502,13 @@ END assign; PROCEDURE LoadConst (e: PARS.EXPR); BEGIN - CODE.AddCmd(CODE.opCONST, ARITH.Int(e.value)) + IL.Const(ARITH.Int(e.value)) END LoadConst; -PROCEDURE paramcomp (parser: PARS.PARSER; pos: SCAN.POSITION; e: PARS.EXPR; p: PROG.PARAM); +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 @@ -530,11 +546,11 @@ PROCEDURE paramcomp (parser: PARS.PARSER; pos: SCAN.POSITION; e: PARS.EXPR; p: P d1, d2: INTEGER; BEGIN IF t.length # 0 THEN - CODE.AddCmd(CODE.opPARAM, 1); + IL.Param1; n := PROG.Dim(t2) - 1; WHILE n >= 0 DO - CODE.AddCmd(CODE.opCONST, ArrLen(t, n)); - CODE.AddCmd(CODE.opPARAM, 1); + IL.Const(ArrLen(t, n)); + IL.Param1; DEC(n) END ELSE @@ -543,16 +559,16 @@ PROCEDURE paramcomp (parser: PARS.PARSER; pos: SCAN.POSITION; e: PARS.EXPR; p: P IF d1 # d2 THEN n := d2 - d1; WHILE d2 > d1 DO - CODE.AddCmd(CODE.opCONST, ArrLen(t, d2 - 1)); + IL.Const(ArrLen(t, d2 - 1)); DEC(d2) END; d2 := PROG.Dim(t2); WHILE n > 0 DO - CODE.AddCmd(CODE.opROT, d2); + IL.AddCmd(IL.opROT, d2); DEC(n) END END; - CODE.AddCmd(CODE.opPARAM, PROG.Dim(t2) + 1) + IL.AddCmd(IL.opPARAM, PROG.Dim(t2) + 1) END END OpenArray; @@ -560,87 +576,92 @@ PROCEDURE paramcomp (parser: PARS.PARSER; pos: SCAN.POSITION; e: PARS.EXPR; p: P BEGIN IF p.vPar THEN - PARS.check(isVar(e), parser, pos, 93); + PARS.check(isVar(e), pos, 93); IF p.type.typ = PROG.tRECORD THEN - PARS.check(PROG.isBaseOf(p.type, e.type), parser, pos, 66); + PARS.check(PROG.isBaseOf(p.type, e.type), pos, 66); IF e.obj = eVREC THEN IF e.ident # NIL THEN - CODE.AddCmd(CODE.opVADR, e.ident.offset - 1) + IL.AddCmd(IL.opVADR, e.ident.offset - 1) ELSE - CODE.AddCmd0(CODE.opPUSHT) + IL.AddCmd0(IL.opPUSHT) END ELSE - CODE.AddCmd(CODE.opCONST, e.type.num) + IL.Const(e.type.num) END; - CODE.AddCmd(CODE.opPARAM, 2) + IL.AddCmd(IL.opPARAM, 2) ELSIF PROG.isOpenArray(p.type) THEN - PARS.check(arrcomp(e, p), parser, pos, 66); + PARS.check(arrcomp(e, p), pos, 66); OpenArray(e.type, p.type) ELSE - PARS.check(PROG.isTypeEq(e.type, p.type), parser, pos, 66); - CODE.AddCmd(CODE.opPARAM, 1) + PARS.check(PROG.isTypeEq(e.type, p.type), pos, 66); + IL.Param1 END; - PARS.check(~e.readOnly, parser, pos, 94) + PARS.check(~e.readOnly, pos, 94) ELSE - PARS.check(isExpr(e) OR isProc(e), parser, pos, 66); + 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), parser, pos, 66); + PARS.check(arrcomp(e, p), pos, 66); OpenArray(e.type, p.type) - ELSIF isString(e) & (p.type.typ = PROG.tARRAY) & (p.type.base.typ = PROG.tCHAR) THEN - CODE.AddCmd(CODE.opSADR, String(e)); - CODE.AddCmd(CODE.opPARAM, 1); - CODE.AddCmd(CODE.opCONST, strlen(e) + 1); - CODE.AddCmd(CODE.opPARAM, 1) - ELSIF isStringW(e) & (p.type.typ = PROG.tARRAY) & (p.type.base.typ = PROG.tWCHAR) THEN - CODE.AddCmd(CODE.opSADR, StringW(e)); - CODE.AddCmd(CODE.opPARAM, 1); - CODE.AddCmd(CODE.opCONST, utf8strlen(e) + 1); - CODE.AddCmd(CODE.opPARAM, 1) + 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(parser, pos, 66) + PARS.error(pos, 66) END ELSE - PARS.check(~PROG.isOpenArray(e.type), parser, pos, 66); - PARS.check(assigncomp(e, p.type), parser, pos, 66); + PARS.check(~PROG.isOpenArray(e.type), pos, 66); + PARS.check(assigncomp(e, p.type), pos, 66); IF e.obj = eCONST THEN - IF e.type.typ = PROG.tREAL THEN - CODE.Float(ARITH.Float(e.value)); - CODE.pushf + IF e.type = tREAL THEN + IL.Float(ARITH.Float(e.value)); + IL.pushf ELSIF e.type.typ = PROG.tNIL THEN - CODE.AddCmd(CODE.opCONST, 0); - CODE.AddCmd(CODE.opPARAM, 1) - ELSIF isStringW1(e) & (p.type.typ = PROG.tWCHAR) THEN - CODE.AddCmd(CODE.opCONST, StrToWChar(e.value.string(SCAN.IDENT).s)); - CODE.AddCmd(CODE.opPARAM, 1) + IL.Const(0); + IL.Param1 + ELSIF isStringW1(e) & (p.type = tWCHAR) THEN + IL.Const(StrToWChar(e.value.string(SCAN.IDENT).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 - CODE.SetMinDataSize(p.type.size); - IF p.type.base.typ = PROG.tCHAR THEN - CODE.AddCmd(CODE.opSADR, String(e)) + IF p.type.base = tCHAR THEN + stroffs := String(e); + IL.StrAdr(stroffs); + IF (CPU = cpuMSP430) & (p.type.size - strlen(e) - 1 > MSP430.IntVectorSize) THEN + ERRORS.WarningMsg(pos.line, pos.col, 0) + END ELSE (* WCHAR *) - CODE.AddCmd(CODE.opSADR, StringW(e)) + stroffs := StringW(e); + IL.StrAdr(stroffs) END; - CODE.AddCmd(CODE.opPARAM, 1) + IL.codes.dmin := stroffs + p.type.size; + IL.Param1 ELSE LoadConst(e); - CODE.AddCmd(CODE.opPARAM, 1) + IL.Param1 END ELSIF e.obj = ePROC THEN - PARS.check(e.ident.global, parser, pos, 85); - CODE.PushProc(e.ident.proc.label); - CODE.AddCmd(CODE.opPARAM, 1) + PARS.check(e.ident.global, pos, 85); + IL.PushProc(e.ident.proc.label); + IL.Param1 ELSIF e.obj = eIMP THEN - CODE.PushImpProc(e.ident.import); - CODE.AddCmd(CODE.opPARAM, 1) - ELSIF isExpr(e) & (e.type.typ = PROG.tREAL) THEN - CODE.pushf + IL.PushImpProc(e.ident.import); + IL.Param1 + ELSIF isExpr(e) & (e.type = tREAL) THEN + IL.pushf ELSE - IF (p.type.typ = PROG.tBYTE) & (e.type.typ = PROG.tINTEGER) & (chkBYTE IN checking) THEN + IF (p.type = tBYTE) & (e.type = tINTEGER) & (chkBYTE IN Options.checking) THEN CheckRange(256, pos.line, errBYTE) END; - CODE.AddCmd(CODE.opPARAM, 1) + IL.Param1 END END @@ -648,10 +669,16 @@ BEGIN 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 e2: PARS.EXPR; - pos: SCAN.POSITION; + pos: PARS.POSITION; proc: INTEGER; label: INTEGER; n, i: INTEGER; @@ -659,16 +686,17 @@ VAR e1: PARS.EXPR; wchar: BOOLEAN; cmd1, - cmd2: CODE.COMMAND; + cmd2: IL.COMMAND; + comma: BOOLEAN; - PROCEDURE varparam (parser: PARS.PARSER; pos: SCAN.POSITION; isfunc: isXXX; readOnly: BOOLEAN; VAR e: PARS.EXPR); + 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), parser, pos, 93); - PARS.check(isfunc(e), parser, pos, 66); + PARS.check(isVar(e), pos, 93); + PARS.check(isfunc(e), pos, 66); IF readOnly THEN - PARS.check(~e.readOnly, parser, pos, 94) + PARS.check(~e.readOnly, pos, 94) END END varparam; @@ -691,13 +719,18 @@ VAR 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); - proc := e.stproc; IF e.obj IN {eSYSPROC, eSYSFUNC} THEN IF parser.unit.scopeLvl > 0 THEN - parser.unit.scopes[parser.unit.scopeLvl].enter(CODE.COMMAND).allocReg := FALSE + parser.unit.scopes[parser.unit.scopeLvl].enter(IL.COMMAND).allocReg := FALSE END END; @@ -705,90 +738,93 @@ BEGIN CASE proc OF |PROG.stASSERT: - parser.expression(parser, e); - PARS.check(isBoolean(e), parser, pos, 66); + PExpression(parser, e); + PARS.check(isBoolean(e), pos, 66); IF e.obj = eCONST THEN IF ~ARITH.getBool(e.value) THEN - CODE.OnError(pos.line, errASSERT) + IL.OnError(pos.line, errASSERT) END ELSE - label := CODE.NewLabel(); - CODE.AddJmpCmd(CODE.opJE, label); - CODE.OnError(pos.line, errASSERT); - CODE.SetLabel(label) + label := IL.NewLabel(); + IL.AddJmpCmd(IL.opJE, label); + IL.OnError(pos.line, errASSERT); + IL.SetLabel(label) END |PROG.stINC, PROG.stDEC: - CODE.pushBegEnd(begcall, endcall); + IL.pushBegEnd(begcall, endcall); varparam(parser, pos, isInt, TRUE, e); - IF e.type.typ = PROG.tINTEGER THEN + IF e.type = tINTEGER THEN IF parser.sym = SCAN.lxCOMMA THEN NextPos(parser, pos); - CODE.setlast(begcall); - parser.expression(parser, e2); - CODE.setlast(endcall.prev(CODE.COMMAND)); - PARS.check(isInt(e2), parser, pos, 66); + IL.setlast(begcall); + PExpression(parser, e2); + IL.setlast(endcall.prev(IL.COMMAND)); + PARS.check(isInt(e2), pos, 66); IF e2.obj = eCONST THEN - CODE.AddCmd(CODE.opINCC + ORD(proc = PROG.stDEC), ARITH.Int(e2.value)) + IL.AddCmd(IL.opINCC, ARITH.Int(e2.value) * (ORD(proc = PROG.stINC) * 2 - 1)) ELSE - CODE.AddCmd0(CODE.opINC + ORD(proc = PROG.stDEC)) + IL.AddCmd0(IL.opINC + ORD(proc = PROG.stDEC)) END ELSE - CODE.AddCmd0(CODE.opINC1 + ORD(proc = PROG.stDEC)) + IL.AddCmd(IL.opINCC, ORD(proc = PROG.stINC) * 2 - 1) END - ELSE (* e.type.typ = PROG.tBYTE *) + ELSE (* e.type = tBYTE *) IF parser.sym = SCAN.lxCOMMA THEN NextPos(parser, pos); - CODE.setlast(begcall); - parser.expression(parser, e2); - CODE.setlast(endcall.prev(CODE.COMMAND)); - PARS.check(isInt(e2), parser, pos, 66); + IL.setlast(begcall); + PExpression(parser, e2); + IL.setlast(endcall.prev(IL.COMMAND)); + PARS.check(isInt(e2), pos, 66); IF e2.obj = eCONST THEN - CODE.AddCmd(CODE.opINCCB + ORD(proc = PROG.stDEC), ARITH.Int(e2.value)) + IL.AddCmd(IL.opINCCB + ORD(proc = PROG.stDEC), ARITH.Int(e2.value)) ELSE - CODE.AddCmd0(CODE.opINCB + ORD(proc = PROG.stDEC)) + IL.AddCmd0(IL.opINCB + ORD(proc = PROG.stDEC)) END ELSE - CODE.AddCmd0(CODE.opINC1B + ORD(proc = PROG.stDEC)) + IL.AddCmd(IL.opINCCB + ORD(proc = PROG.stDEC), 1) END END; - CODE.popBegEnd(begcall, endcall) + IL.popBegEnd(begcall, endcall) |PROG.stINCL, PROG.stEXCL: - CODE.pushBegEnd(begcall, endcall); + IL.pushBegEnd(begcall, endcall); varparam(parser, pos, isSet, TRUE, e); PARS.checklex(parser, SCAN.lxCOMMA); NextPos(parser, pos); - CODE.setlast(begcall); - parser.expression(parser, e2); - CODE.setlast(endcall.prev(CODE.COMMAND)); - PARS.check(isInt(e2), parser, pos, 66); + 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, MACHINE.target.maxSet), parser, pos, 56); - CODE.AddCmd(CODE.opINCLC + ORD(proc = PROG.stEXCL), ARITH.Int(e2.value)) + 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 - CODE.AddCmd0(CODE.opINCL + ORD(proc = PROG.stEXCL)) + IL.AddCmd0(IL.opINCL + ORD(proc = PROG.stEXCL)) END; - CODE.popBegEnd(begcall, endcall) + IL.popBegEnd(begcall, endcall) |PROG.stNEW: varparam(parser, pos, isPtr, TRUE, e); - CODE.New(e.type.base.size, e.type.base.num) + IF CPU = 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); - CODE.AddCmd0(CODE.opDISP) + IL.AddCmd0(IL.opDISP) |PROG.stPACK: varparam(parser, pos, isReal, TRUE, e); PARS.checklex(parser, SCAN.lxCOMMA); NextPos(parser, pos); - parser.expression(parser, e2); - PARS.check(isInt(e2), parser, pos, 66); + PExpression(parser, e2); + PARS.check(isInt(e2), pos, 66); IF e2.obj = eCONST THEN - CODE.AddCmd(CODE.opPACKC, ARITH.Int(e2.value)) + IL.AddCmd(IL.opPACKC, ARITH.Int(e2.value)) ELSE - CODE.AddCmd0(CODE.opPACK) + IL.AddCmd0(IL.opPACK) END |PROG.stUNPK: @@ -796,24 +832,26 @@ BEGIN PARS.checklex(parser, SCAN.lxCOMMA); NextPos(parser, pos); varparam(parser, pos, isInteger, TRUE, e2); - CODE.AddCmd0(CODE.opUNPK) + IL.AddCmd0(IL.opUNPK) |PROG.stCOPY: - parser.expression(parser, e); + 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.check(FALSE, parser, pos, 66) + PARS.error(pos, 66) END; IF isCharArrayX(e) & ~PROG.isOpenArray(e.type) THEN - CODE.AddCmd(CODE.opCONST, e.type.length) + 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) @@ -824,96 +862,96 @@ BEGIN varparam(parser, pos, isCharArray, TRUE, e1) END; - wchar := e1.type.base.typ = PROG.tWCHAR + wchar := e1.type.base = tWCHAR END; IF ~PROG.isOpenArray(e1.type) THEN - CODE.AddCmd(CODE.opCONST, e1.type.length) + IL.Const(e1.type.length) END; + IL.setlast(endcall.prev(IL.COMMAND)); + IF e.obj = eCONST THEN IF wchar THEN - CODE.AddCmd(CODE.opSADR, StringW(e)); - CODE.AddCmd(CODE.opCONST, utf8strlen(e) + 1) + IL.StrAdr(StringW(e)); + IL.Const(utf8strlen(e) + 1) ELSE - CODE.AddCmd(CODE.opSADR, String(e)); - CODE.AddCmd(CODE.opCONST, strlen(e) + 1) - END; - CODE.AddCmd(CODE.opCOPYS2, e1.type.base.size) - ELSE - CODE.AddCmd(CODE.opCOPYS, e1.type.base.size) - END + 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: - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); - IF e.obj = eCONST THEN - LoadConst(e) - END; + 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), parser, pos, 93); - PARS.check((e2.type.typ IN PROG.BASICTYPES) OR (e2.type.typ = PROG.tPOINTER) OR (e2.type.typ = PROG.tPROCEDURE), parser, pos, 66); - CODE.SysGet(e2.type.size) + PARS.check(isVar(e2), pos, 93); + PARS.check(e2.type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66); + IF e.obj = eCONST THEN + IL.AddCmd2(IL.opGETC, ARITH.Int(e.value), e2.type.size) + ELSE + IL.AddCmd(IL.opGET, e2.type.size) + END |PROG.sysPUT, PROG.sysPUT8, PROG.sysPUT16, PROG.sysPUT32: - CODE.pushBegEnd(begcall, endcall); - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); + 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); - CODE.setlast(begcall); - parser.expression(parser, e2); - PARS.check(isExpr(e2), parser, pos, 66); + 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) OR (e2.type.typ = PROG.tPOINTER) OR (e2.type.typ = PROG.tPROCEDURE), parser, pos, 66); + PARS.check(e2.type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66); IF e2.obj = eCONST THEN - IF e2.type.typ = PROG.tREAL THEN - CODE.setlast(endcall.prev(CODE.COMMAND)); - CODE.Float(ARITH.Float(e2.value)); - CODE.savef + IF e2.type = tREAL THEN + IL.setlast(endcall.prev(IL.COMMAND)); + IL.Float(ARITH.Float(e2.value)); + IL.savef ELSE LoadConst(e2); - CODE.setlast(endcall.prev(CODE.COMMAND)); - CODE.SysPut(e2.type.size) + IL.setlast(endcall.prev(IL.COMMAND)); + IL.SysPut(e2.type.size) END ELSE - CODE.setlast(endcall.prev(CODE.COMMAND)); - IF e2.type.typ = PROG.tREAL THEN - CODE.savef - ELSIF e2.type.typ = PROG.tBYTE THEN - CODE.SysPut(PARS.program.stTypes.tINTEGER.size) + IL.setlast(endcall.prev(IL.COMMAND)); + IF e2.type = tREAL THEN + IL.savef + ELSIF e2.type = tBYTE THEN + IL.SysPut(tINTEGER.size) ELSE - CODE.SysPut(e2.type.size) + 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.tWCHAR, PROG.tCARD16, PROG.tCARD32}, parser, pos, 66); + PARS.check(e2.type.typ IN {PROG.tINTEGER, PROG.tBYTE, PROG.tCHAR, PROG.tSET, PROG.tWCHAR, PROG.tCARD16, PROG.tCARD32}, pos, 66); IF e2.obj = eCONST THEN LoadConst(e2) END; - CODE.setlast(endcall.prev(CODE.COMMAND)); - IF proc = PROG.sysPUT8 THEN - CODE.SysPut(1) - ELSIF proc = PROG.sysPUT16 THEN - CODE.SysPut(2) - ELSIF proc = PROG.sysPUT32 THEN - CODE.SysPut(4) + IL.setlast(endcall.prev(IL.COMMAND)); + CASE proc OF + |PROG.sysPUT8: IL.SysPut(1) + |PROG.sysPUT16: IL.SysPut(2) + |PROG.sysPUT32: IL.SysPut(4) END END; - CODE.popBegEnd(begcall, endcall) + IL.popBegEnd(begcall, endcall) |PROG.sysMOVE: FOR i := 1 TO 2 DO - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); + PExpression(parser, e); + PARS.check(isInt(e), pos, 66); IF e.obj = eCONST THEN LoadConst(e) END; @@ -921,47 +959,63 @@ BEGIN NextPos(parser, pos) END; - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); + PExpression(parser, e); + PARS.check(isInt(e), pos, 66); IF e.obj = eCONST THEN LoadConst(e) END; - CODE.AddCmd0(CODE.opMOVE) + IL.AddCmd0(IL.opMOVE) |PROG.sysCOPY: FOR i := 1 TO 2 DO parser.designator(parser, e); - PARS.check(isVar(e), parser, pos, 93); + PARS.check(isVar(e), pos, 93); n := PROG.Dim(e.type); WHILE n > 0 DO - CODE.drop; + IL.drop; DEC(n) END; PARS.checklex(parser, SCAN.lxCOMMA); NextPos(parser, pos) END; - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); + PExpression(parser, e); + PARS.check(isInt(e), pos, 66); IF e.obj = eCONST THEN LoadConst(e) END; - CODE.AddCmd0(CODE.opMOVE) + IL.AddCmd0(IL.opMOVE) |PROG.sysCODE: REPEAT getpos(parser, pos); PARS.ConstExpression(parser, code); - PARS.check(code.typ = ARITH.tINTEGER, parser, pos, 43); - PARS.check(ARITH.range(code, 0, 255), parser, pos, 42); - IF parser.sym = SCAN.lxCOMMA THEN + PARS.check(code.typ = ARITH.tINTEGER, pos, 43); + IF CPU # cpuMSP430 THEN + PARS.check(ARITH.range(code, 0, 255), pos, 42) + 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; - CODE.AddCmd(CODE.opCODE, ARITH.getInt(code)) - UNTIL parser.sym = 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; @@ -971,129 +1025,129 @@ BEGIN CASE e.stproc OF |PROG.stABS: - parser.expression(parser, e); - PARS.check(isInt(e) OR isReal(e), parser, pos, 66); + PExpression(parser, e); + PARS.check(isInt(e) OR isReal(e), pos, 66); IF e.obj = eCONST THEN - PARS.check(ARITH.abs(e.value), parser, pos, 39) + PARS.check(ARITH.abs(e.value), pos, 39) ELSE - CODE.abs(isReal(e)) + IL.abs(isReal(e)) END |PROG.stASR, PROG.stLSL, PROG.stROR, PROG.stLSR, PROG.stMIN, PROG.stMAX: - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); + PExpression(parser, e); + PARS.check(isInt(e), pos, 66); PARS.checklex(parser, SCAN.lxCOMMA); NextPos(parser, pos); - parser.expression(parser, e2); - PARS.check(isInt(e2), parser, pos, 66); - e.type := PARS.program.stTypes.tINTEGER; + 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 - CODE.shift_minmax1(shift_minmax(proc), ARITH.Int(e.value)) + IL.shift_minmax1(shift_minmax(proc), ARITH.Int(e.value)) ELSIF e2.obj = eCONST THEN - CODE.shift_minmax2(shift_minmax(proc), ARITH.Int(e2.value)) + IL.shift_minmax2(shift_minmax(proc), ARITH.Int(e2.value)) ELSE - CODE.shift_minmax(shift_minmax(proc)) + IL.shift_minmax(shift_minmax(proc)) END; e.obj := eEXPR END |PROG.stCHR: - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); - e.type := PARS.program.stTypes.tCHAR; + 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), parser, pos, 107) + PARS.check(ARITH.check(e.value), pos, 107) ELSE - IF chkCHR IN checking THEN + IF chkCHR IN Options.checking THEN CheckRange(256, pos.line, errCHR) ELSE - CODE.AddCmd0(CODE.opCHR) + IL.AddCmd0(IL.opCHR) END END |PROG.stWCHR: - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); - e.type := PARS.program.stTypes.tWCHAR; + 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), parser, pos, 101) + PARS.check(ARITH.check(e.value), pos, 101) ELSE - IF chkWCHR IN checking THEN + IF chkWCHR IN Options.checking THEN CheckRange(65536, pos.line, errWCHR) ELSE - CODE.AddCmd0(CODE.opWCHR) + IL.AddCmd0(IL.opWCHR) END END |PROG.stFLOOR: - parser.expression(parser, e); - PARS.check(isReal(e), parser, pos, 66); - e.type := PARS.program.stTypes.tINTEGER; + PExpression(parser, e); + PARS.check(isReal(e), pos, 66); + e.type := tINTEGER; IF e.obj = eCONST THEN - PARS.check(ARITH.floor(e.value), parser, pos, 39) + PARS.check(ARITH.floor(e.value), pos, 39) ELSE - CODE.floor + IL.floor END |PROG.stFLT: - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); - e.type := PARS.program.stTypes.tREAL; + PExpression(parser, e); + PARS.check(isInt(e), pos, 66); + e.type := tREAL; IF e.obj = eCONST THEN ARITH.flt(e.value) ELSE - PARS.check(CODE.flt(), parser, pos, 41) + PARS.check(IL.flt(), pos, 41) END |PROG.stLEN: - cmd1 := CODE.getlast(); + cmd1 := IL.getlast(); varparam(parser, pos, isArr, FALSE, e); IF e.type.length > 0 THEN - cmd2 := CODE.getlast(); - CODE.delete2(cmd1.next, cmd2); - CODE.setlast(cmd1); + cmd2 := IL.getlast(); + IL.delete2(cmd1.next, cmd2); + IL.setlast(cmd1); ASSERT(ARITH.setInt(e.value, e.type.length)); e.obj := eCONST ELSE - CODE.len(PROG.Dim(e.type)) + IL.len(PROG.Dim(e.type)) END; - e.type := PARS.program.stTypes.tINTEGER + e.type := tINTEGER |PROG.stLENGTH: - parser.expression(parser, e); + PExpression(parser, e); IF isCharArray(e) THEN IF e.type.length > 0 THEN - CODE.AddCmd(CODE.opCONST, e.type.length) + IL.Const(e.type.length) END; - CODE.AddCmd0(CODE.opLENGTH) + IL.AddCmd0(IL.opLENGTH) ELSIF isCharArrayW(e) THEN IF e.type.length > 0 THEN - CODE.AddCmd(CODE.opCONST, e.type.length) + IL.Const(e.type.length) END; - CODE.AddCmd0(CODE.opLENGTHW) + IL.AddCmd0(IL.opLENGTHW) ELSE - PARS.check(FALSE, parser, pos, 66); + PARS.error(pos, 66); END; - e.type := PARS.program.stTypes.tINTEGER + e.type := tINTEGER |PROG.stODD: - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); - e.type := PARS.program.stTypes.tBOOLEAN; + PExpression(parser, e); + PARS.check(isInt(e), pos, 66); + e.type := tBOOLEAN; IF e.obj = eCONST THEN ARITH.odd(e.value) ELSE - CODE.odd + IL.odd END |PROG.stORD: - parser.expression(parser, e); - PARS.check(isChar(e) OR isBoolean(e) OR isSet(e) OR isCharW(e) OR isStringW1(e), parser, pos, 66); + 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.IDENT).s))) @@ -1102,81 +1156,83 @@ BEGIN END ELSE IF isBoolean(e) THEN - CODE.ord + IL.ord END END; - e.type := PARS.program.stTypes.tINTEGER + e.type := tINTEGER |PROG.stBITS: - parser.expression(parser, e); - PARS.check(isInt(e), parser, pos, 66); + PExpression(parser, e); + PARS.check(isInt(e), pos, 66); IF e.obj = eCONST THEN ARITH.bits(e.value) END; - e.type := PARS.program.stTypes.tSET + e.type := tSET |PROG.sysADR: parser.designator(parser, e); IF isVar(e) THEN n := PROG.Dim(e.type); WHILE n > 0 DO - CODE.drop; + IL.drop; DEC(n) END ELSIF e.obj = ePROC THEN - CODE.PushProc(e.ident.proc.label) + IL.PushProc(e.ident.proc.label) ELSIF e.obj = eIMP THEN - CODE.PushImpProc(e.ident.import) + IL.PushImpProc(e.ident.import) ELSE - PARS.check(FALSE, parser, pos, 108) + PARS.error(pos, 108) END; - e.type := PARS.program.stTypes.tINTEGER + e.type := tINTEGER |PROG.sysSADR: - parser.expression(parser, e); - PARS.check(isString(e), parser, pos, 66); - CODE.AddCmd(CODE.opSADR, String(e)); - e.type := PARS.program.stTypes.tINTEGER; + PExpression(parser, e); + PARS.check(isString(e), pos, 66); + IL.StrAdr(String(e)); + e.type := tINTEGER; e.obj := eEXPR |PROG.sysWSADR: - parser.expression(parser, e); - PARS.check(isStringW(e), parser, pos, 66); - CODE.AddCmd(CODE.opSADR, StringW(e)); - e.type := PARS.program.stTypes.tINTEGER; + PExpression(parser, e); + PARS.check(isStringW(e), pos, 66); + IL.StrAdr(StringW(e)); + e.type := tINTEGER; e.obj := eEXPR |PROG.sysTYPEID: - parser.expression(parser, e); - PARS.check(e.obj = eTYPE, parser, pos, 68); + 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 + ELSIF e.type.typ = PROG.tPOINTER THEN ASSERT(ARITH.setInt(e.value, e.type.base.num)) ELSE - PARS.check(FALSE, parser, pos, 52) + PARS.error(pos, 52) END; e.obj := eCONST; - e.type := PARS.program.stTypes.tINTEGER + e.type := tINTEGER |PROG.sysINF: - PARS.check(CODE.inf(), parser, pos, 41); + PARS.check(IL.inf(), pos, 41); e.obj := eEXPR; - e.type := PARS.program.stTypes.tREAL + e.type := tREAL |PROG.sysSIZE: - parser.expression(parser, e); - PARS.check(e.obj = eTYPE, parser, pos, 68); + PExpression(parser, e); + PARS.check(e.obj = eTYPE, pos, 68); ASSERT(ARITH.setInt(e.value, e.type.size)); e.obj := eCONST; - e.type := PARS.program.stTypes.tINTEGER + e.type := tINTEGER END END; - PARS.checklex(parser, SCAN.lxRROUND); - PARS.Next(parser); +(* 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 @@ -1190,7 +1246,7 @@ VAR proc: PROG.TYPE_; param: LISTS.ITEM; e1: PARS.EXPR; - pos: SCAN.POSITION; + pos: PARS.POSITION; BEGIN ASSERT(parser.sym = SCAN.lxLROUND); @@ -1204,12 +1260,12 @@ BEGIN WHILE param # NIL DO getpos(parser, pos); - CODE.setlast(begcall); + IL.setlast(begcall); IF param(PROG.PARAM).vPar THEN parser.designator(parser, e1) ELSE - parser.expression(parser, e1) + PExpression(parser, e1) END; paramcomp(parser, pos, e1, param(PROG.PARAM)); param := param.next; @@ -1226,7 +1282,6 @@ BEGIN e.type := proc.base ELSIF e.obj IN {eSTPROC, eSTFUNC, eSYSPROC, eSYSFUNC} THEN - PARS.Next(parser); stProc(parser, e) ELSE PARS.check1(FALSE, parser, 86) @@ -1239,18 +1294,18 @@ PROCEDURE qualident (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR ident: PROG.IDENT; import: BOOLEAN; - pos: SCAN.POSITION; + pos: PARS.POSITION; BEGIN PARS.checklex(parser, SCAN.lxIDENT); getpos(parser, pos); import := FALSE; - ident := parser.unit.idents.get(parser.unit, parser.lex.ident, 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 := ident.unit.idents.get(ident.unit, parser.lex.ident, FALSE); + ident := PROG.getIdent(ident.unit, parser.lex.ident, FALSE); PARS.check1((ident # NIL) & ident.export, parser, 48); import := TRUE END; @@ -1298,34 +1353,34 @@ BEGIN e.obj := eSYSPROC; e.stproc := ident.stproc |PROG.idSYSFUNC: - PARS.check(~parser.constexp, parser, pos, 109); + PARS.check(~parser.constexp, pos, 109); e.obj := eSYSFUNC; e.stproc := ident.stproc |PROG.idNONE: - PARS.check(FALSE, parser, pos, 115) + PARS.error(pos, 115) END; IF isVar(e) THEN - PARS.check(e.ident.global OR (e.ident.scopeLvl = parser.unit.scopeLvl), parser, pos, 105) + PARS.check(e.ident.global OR (e.ident.scopeLvl = parser.unit.scopeLvl), pos, 105) END END qualident; -PROCEDURE deref (pos: SCAN.POSITION; e: PARS.EXPR; load: BOOLEAN; error: INTEGER); +PROCEDURE deref (pos: PARS.POSITION; e: PARS.EXPR; load: BOOLEAN; error: INTEGER); VAR label: INTEGER; BEGIN IF load THEN - CODE.load(e.type.size) + IL.load(e.type.size) END; - IF chkPTR IN checking THEN - label := CODE.NewLabel(); - CODE.AddJmpCmd(CODE.opJNZ, label); - CODE.OnError(pos.line, error); - CODE.SetLabel(label) + IF chkPTR IN Options.checking THEN + label := IL.NewLabel(); + IL.AddJmpCmd(IL.opJNZ, label); + IL.OnError(pos.line, error); + IL.SetLabel(label) END END deref; @@ -1333,7 +1388,7 @@ END deref; PROCEDURE designator (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR field: PROG.FIELD; - pos: SCAN.POSITION; + pos: PARS.POSITION; t, idx: PARS.EXPR; @@ -1348,7 +1403,7 @@ VAR offset := e.ident.offset; n := PROG.Dim(e.type); WHILE n >= 0 DO - CODE.AddCmd(CODE.opVADR, offset); + IL.AddCmd(IL.opVADR, offset); DEC(offset); DEC(n) END @@ -1359,29 +1414,29 @@ VAR IF e.obj = eVAR THEN offset := PROG.getOffset(PARS.program, e.ident); IF e.ident.global THEN - CODE.AddCmd(CODE.opGADR, offset) + IL.AddCmd(IL.opGADR, offset) ELSE - CODE.AddCmd(CODE.opLADR, -offset) + 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 - CODE.AddCmd(CODE.opVADR, e.ident.offset) + IL.AddCmd(IL.opVADR, e.ident.offset) ELSIF PROG.isOpenArray(e.type) THEN OpenArray(e) ELSE - CODE.AddCmd(CODE.opLADR, e.ident.offset) + IL.AddCmd(IL.opLADR, e.ident.offset) END ELSIF e.obj IN {eVPAR, eVREC} THEN IF PROG.isOpenArray(e.type) THEN OpenArray(e) ELSE - CODE.AddCmd(CODE.opVADR, e.ident.offset) + IL.AddCmd(IL.opVADR, e.ident.offset) END END END LoadAdr; - PROCEDURE OpenIdx (parser: PARS.PARSER; pos: SCAN.POSITION; e: PARS.EXPR); + PROCEDURE OpenIdx (parser: PARS.PARSER; pos: PARS.POSITION; e: PARS.EXPR); VAR label: INTEGER; type: PROG.TYPE_; @@ -1389,30 +1444,30 @@ VAR BEGIN - IF chkIDX IN checking THEN - label := CODE.NewLabel(); - CODE.AddCmd2(CODE.opCHKIDX2, label, 0); - CODE.OnError(pos.line, errIDX); - CODE.SetLabel(label) + IF chkIDX IN Options.checking THEN + label := IL.NewLabel(); + IL.AddCmd2(IL.opCHKIDX2, label, 0); + IL.OnError(pos.line, errIDX); + IL.SetLabel(label) ELSE - CODE.AddCmd(CODE.opCHKIDX2, -1) + IL.AddCmd(IL.opCHKIDX2, -1) END; type := PROG.OpenBase(e.type); IF type.size # 1 THEN - CODE.AddCmd(CODE.opMULC, type.size) + IL.AddCmd(IL.opMULC, type.size) END; n := PROG.Dim(e.type) - 1; k := n; WHILE n > 0 DO - CODE.AddCmd0(CODE.opMUL); + IL.AddCmd0(IL.opMUL); DEC(n) END; - CODE.AddCmd0(CODE.opADD); + IL.AddCmd0(IL.opADD); offset := e.ident.offset - 1; n := k; WHILE n > 0 DO - CODE.AddCmd(CODE.opVADR, offset); + IL.AddCmd(IL.opVADR, offset); DEC(offset); DEC(n) END @@ -1441,14 +1496,14 @@ BEGIN e.type := e.type.base; e.readOnly := FALSE END; - field := e.type.fields.get(e.type, parser.lex.ident, parser.unit); + 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 - CODE.AddCmd(CODE.opADDR, field.offset) + IL.AddCmd(IL.opADDR, field.offset) END; PARS.Next(parser); e.ident := NIL @@ -1459,29 +1514,29 @@ BEGIN PARS.check1(isArr(e), parser, 75); NextPos(parser, pos); - parser.expression(parser, idx); - PARS.check(isInt(idx), parser, pos, 76); + 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), parser, pos, 83); + PARS.check(ARITH.range(idx.value, 0, e.type.length - 1), pos, 83); IF ARITH.Int(idx.value) > 0 THEN - CODE.AddCmd(CODE.opADDR, ARITH.Int(idx.value) * e.type.base.size) + IL.AddCmd(IL.opADDR, ARITH.Int(idx.value) * e.type.base.size) END ELSE - PARS.check(ARITH.range(idx.value, 0, MACHINE.target.maxInt), parser, pos, 83); + 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 checking THEN + IF chkIDX IN Options.checking THEN CheckRange(e.type.length, pos.line, errIDX) END; IF e.type.base.size # 1 THEN - CODE.AddCmd(CODE.opMULC, e.type.base.size) + IL.AddCmd(IL.opMULC, e.type.base.size) END; - CODE.AddCmd0(CODE.opADD) + IL.AddCmd0(IL.opADD) ELSE OpenIdx(parser, pos, e) END @@ -1512,26 +1567,26 @@ BEGIN END; NextPos(parser, pos); qualident(parser, t); - PARS.check(t.obj = eTYPE, parser, pos, 79); + PARS.check(t.obj = eTYPE, pos, 79); IF e.type.typ = PROG.tRECORD THEN - PARS.check(t.type.typ = PROG.tRECORD, parser, pos, 80); - IF chkGUARD IN checking THEN + PARS.check(t.type.typ = PROG.tRECORD, pos, 80); + IF chkGUARD IN Options.checking THEN IF e.ident = NIL THEN - CODE.TypeGuard(CODE.opTYPEGD, t.type.num, pos.line, errGUARD) + IL.TypeGuard(IL.opTYPEGD, t.type.num, pos.line, errGUARD) ELSE - CODE.AddCmd(CODE.opVADR, e.ident.offset - 1); - CODE.TypeGuard(CODE.opTYPEGR, t.type.num, pos.line, errGUARD) + 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, parser, pos, 81); - IF chkGUARD IN checking THEN - CODE.TypeGuard(CODE.opTYPEGP, t.type.base.num, pos.line, errGUARD) + 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), parser, pos, 82); + PARS.check(PROG.isBaseOf(e.type, t.type), pos, 82); e.type := t.type; @@ -1543,69 +1598,69 @@ BEGIN END designator; -PROCEDURE ProcCall (e: PARS.EXPR; procType: PROG.TYPE_; isfloat: BOOLEAN; VAR fregs: INTEGER; parser: PARS.PARSER; pos: SCAN.POSITION; CallStat: BOOLEAN); +PROCEDURE ProcCall (e: PARS.EXPR; procType: PROG.TYPE_; isfloat: BOOLEAN; VAR fregs: INTEGER; parser: PARS.PARSER; pos: PARS.POSITION; CallStat: BOOLEAN); VAR - cconv: INTEGER; - params: INTEGER; - callconv: INTEGER; - fparams: INTEGER; - int, flt: INTEGER; - stk_par: INTEGER; + cconv: INTEGER; + parSize: INTEGER; + callconv: INTEGER; + fparSize: INTEGER; + int, flt: INTEGER; + stk_par: INTEGER; BEGIN cconv := procType.call; - params := procType.params.size; + parSize := procType.parSize; IF cconv IN {PROG._win64, PROG.win64} THEN - callconv := CODE.call_win64; - fparams := LSL(ORD(procType.params.getfparams(procType, 3, int, flt)), 5) + MIN(params, 4) + 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 := CODE.call_sysv; - fparams := LSL(ORD(procType.params.getfparams(procType, PROG.MAXSYSVPARAM - 1, int, flt)), 5) + params; + 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) ELSE - callconv := CODE.call_stack; - fparams := 0 + callconv := IL.call_stack; + fparSize := 0 END; - CODE.setlast(begcall); - fregs := CODE.precall(isfloat); + IL.setlast(begcall); + fregs := IL.precall(isfloat); IF cconv IN {PROG._ccall16, PROG.ccall16} THEN - CODE.AddCmd(CODE.opALIGN16, params) + IL.AddCmd(IL.opALIGN16, parSize) ELSIF cconv IN {PROG._win64, PROG.win64} THEN - CODE.AddCmd(CODE.opWIN64ALIGN16, params) + IL.AddCmd(IL.opWIN64ALIGN16, parSize) ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN - CODE.AddCmd(CODE.opSYSVALIGN16, params + stk_par) + IL.AddCmd(IL.opSYSVALIGN16, parSize + stk_par) END; - CODE.setlast(endcall.prev(CODE.COMMAND)); + IL.setlast(endcall.prev(IL.COMMAND)); IF e.obj = eIMP THEN - CODE.CallImp(e.ident.import, callconv, fparams) + IL.CallImp(e.ident.import, callconv, fparSize) ELSIF e.obj = ePROC THEN - CODE.Call(e.ident.proc.label, callconv, fparams) + IL.Call(e.ident.proc.label, callconv, fparSize) ELSIF isExpr(e) THEN deref(pos, e, CallStat, errPROC); - CODE.CallP(callconv, fparams) + IL.CallP(callconv, fparSize) END; IF cconv IN {PROG._ccall16, PROG.ccall16} THEN - CODE.AddCmd(CODE.opCLEANUP, params); - CODE.AddCmd0(CODE.opPOPSP) + IL.AddCmd(IL.opCLEANUP, parSize); + IL.AddCmd0(IL.opPOPSP) ELSIF cconv IN {PROG._win64, PROG.win64} THEN - CODE.AddCmd(CODE.opCLEANUP, MAX(params + params MOD 2, 4) + 1); - CODE.AddCmd0(CODE.opPOPSP) + IL.AddCmd(IL.opCLEANUP, MAX(parSize + parSize MOD 2, 4) + 1); + IL.AddCmd0(IL.opPOPSP) ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN - CODE.AddCmd(CODE.opCLEANUP, params + stk_par); - CODE.AddCmd0(CODE.opPOPSP) - ELSIF cconv IN {PROG._ccall, PROG.ccall} THEN - CODE.AddCmd(CODE.opCLEANUP, params) + IL.AddCmd(IL.opCLEANUP, parSize + stk_par); + IL.AddCmd0(IL.opPOPSP) + ELSIF cconv IN {PROG._ccall, PROG.ccall, PROG.default16, PROG.code, PROG._code} THEN + IL.AddCmd(IL.opCLEANUP, parSize) END; IF ~CallStat THEN IF isfloat THEN - PARS.check(CODE.resf(fregs), parser, pos, 41) + PARS.check(IL.resf(fregs), pos, 41) ELSE - CODE.res(fregs) + IL.res(fregs) END END END ProcCall; @@ -1613,7 +1668,7 @@ END ProcCall; PROCEDURE expression (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR - pos, pos0, pos1: SCAN.POSITION; + pos, pos0, pos1: PARS.POSITION; op: INTEGER; e1: PARS.EXPR; @@ -1646,17 +1701,17 @@ VAR PROCEDURE element (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR e1, e2: PARS.EXPR; - pos: SCAN.POSITION; + pos: PARS.POSITION; range: BOOLEAN; BEGIN range := FALSE; getpos(parser, pos); expression(parser, e1); - PARS.check(isInt(e1), parser, pos, 76); + PARS.check(isInt(e1), pos, 76); IF e1.obj = eCONST THEN - PARS.check(ARITH.range(e1.value, 0, MACHINE.target.maxSet), parser, pos, 44) + PARS.check(ARITH.range(e1.value, 0, UTILS.target.maxSet), pos, 44) END; range := parser.sym = SCAN.lxRANGE; @@ -1664,10 +1719,10 @@ VAR IF range THEN NextPos(parser, pos); expression(parser, e2); - PARS.check(isInt(e2), parser, pos, 76); + PARS.check(isInt(e2), pos, 76); IF e2.obj = eCONST THEN - PARS.check(ARITH.range(e2.value, 0, MACHINE.target.maxSet), parser, pos, 44) + PARS.check(ARITH.range(e2.value, 0, UTILS.target.maxSet), pos, 44) END ELSE IF e1.obj = eCONST THEN @@ -1675,7 +1730,7 @@ VAR END END; - e.type := PARS.program.stTypes.tSET; + e.type := tSET; IF (e1.obj = eCONST) & (e2.obj = eCONST) THEN ARITH.constrSet(e.value, e1.value, e2.value); @@ -1683,14 +1738,14 @@ VAR ELSE IF range THEN IF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opRSETL, ARITH.Int(e1.value)) + IL.AddCmd(IL.opRSETL, ARITH.Int(e1.value)) ELSIF e2.obj = eCONST THEN - CODE.AddCmd(CODE.opRSETR, ARITH.Int(e2.value)) + IL.AddCmd(IL.opRSETR, ARITH.Int(e2.value)) ELSE - CODE.AddCmd0(CODE.opRSET) + IL.AddCmd0(IL.opRSET) END ELSE - CODE.AddCmd0(CODE.opRSET1) + IL.AddCmd0(IL.opRSET1) END; e.obj := eEXPR END @@ -1706,7 +1761,7 @@ VAR ASSERT(parser.sym = SCAN.lxLCURLY); e.obj := eCONST; - e.type := PARS.program.stTypes.tSET; + e.type := tSET; ARITH.emptySet(e.value); PARS.Next(parser); @@ -1726,11 +1781,11 @@ VAR ARITH.opSet(e.value, e1.value, "+") ELSE IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opADDSL, ARITH.Int(e.value)) + IL.AddCmd(IL.opADDSL, ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opADDSR, ARITH.Int(e1.value)) + IL.AddCmd(IL.opADDSR, ARITH.Int(e1.value)) ELSE - CODE.AddCmd0(CODE.opADDS) + IL.AddCmd0(IL.opADDS) END; e.obj := eEXPR END @@ -1744,19 +1799,19 @@ VAR PROCEDURE factor (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR sym: INTEGER; - pos: SCAN.POSITION; + pos: PARS.POSITION; e1: PARS.EXPR; isfloat: BOOLEAN; fregs: INTEGER; - PROCEDURE LoadVar (e: PARS.EXPR; parser: PARS.PARSER; pos: SCAN.POSITION); + 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.typ = PROG.tREAL THEN - PARS.check(CODE.loadf(), parser, pos, 41) + IF e.type = tREAL THEN + PARS.check(IL.loadf(), pos, 41) ELSE - CODE.load(e.type.size) + IL.load(e.type.size) END END END LoadVar; @@ -1768,18 +1823,18 @@ VAR 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 := PARS.program.getType(PARS.program, e.value.typ); + e.type := PROG.getType(PARS.program, e.value.typ); PARS.Next(parser) ELSIF sym = SCAN.lxNIL THEN - e.obj := eCONST; - e.type := PARS.program.stTypes.tNIL; + e.obj := eCONST; + e.type := PARS.program.stTypes.tNIL; PARS.Next(parser) ELSIF (sym = SCAN.lxTRUE) OR (sym = SCAN.lxFALSE) THEN - e.obj := eCONST; + e.obj := eCONST; ARITH.setbool(e.value, sym = SCAN.lxTRUE); - e.type := PARS.program.stTypes.tBOOLEAN; + e.type := tBOOLEAN; PARS.Next(parser) ELSIF sym = SCAN.lxLCURLY THEN @@ -1788,7 +1843,7 @@ VAR ELSIF sym = SCAN.lxIDENT THEN getpos(parser, pos); - CODE.pushBegEnd(begcall, endcall); + IL.pushBegEnd(begcall, endcall); designator(parser, e); IF isVar(e) THEN @@ -1797,15 +1852,15 @@ VAR IF parser.sym = SCAN.lxLROUND THEN e1 := e; ActualParameters(parser, e); - PARS.check(e.type # NIL, parser, pos, 59); - isfloat := e.type.typ = PROG.tREAL; + PARS.check(e.type # NIL, pos, 59); + isfloat := e.type = tREAL; IF e1.obj IN {ePROC, eIMP} THEN ProcCall(e1, e1.ident.type, isfloat, fregs, parser, pos, FALSE) ELSIF isExpr(e1) THEN ProcCall(e1, e1.type, isfloat, fregs, parser, pos, FALSE) END END; - CODE.popBegEnd(begcall, endcall) + IL.popBegEnd(begcall, endcall) ELSIF sym = SCAN.lxLROUND THEN PARS.Next(parser); @@ -1819,9 +1874,9 @@ VAR ELSIF sym = SCAN.lxNOT THEN NextPos(parser, pos); factor(parser, e); - PARS.check(isBoolean(e), parser, pos, 72); + PARS.check(isBoolean(e), pos, 72); IF e.obj # eCONST THEN - CODE.not; + IL.not; e.obj := eEXPR ELSE ASSERT(ARITH.neg(e.value)) @@ -1835,7 +1890,7 @@ VAR PROCEDURE term (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR - pos: SCAN.POSITION; + pos: PARS.POSITION; op: INTEGER; e1: PARS.EXPR; @@ -1855,15 +1910,15 @@ VAR IF ~parser.constexp THEN IF label = -1 THEN - label := CODE.NewLabel() + label := IL.NewLabel() END; IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opCONST, ORD(ARITH.getBool(e.value))) - END; - CODE.AddCmd0(CODE.opACC); - CODE.AddJmpCmd(CODE.opJZ, label); - CODE.drop + IL.Const(ORD(ARITH.getBool(e.value))) + END; + IL.AddCmd0(IL.opACC); + IL.AddJmpCmd(IL.opJZ, label); + IL.drop END END; @@ -1871,135 +1926,142 @@ VAR CASE op OF |SCAN.lxMUL: - PARS.check(isInt(e) & isInt(e1) OR isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), parser, pos, 37); + 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, "*"), parser, pos, 39) - |ARITH.tREAL: PARS.check(ARITH.opFloat(e.value, e1.value, "*"), parser, pos, 40) + |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 - CODE.AddCmd(CODE.opMULC, ARITH.Int(e.value)) + IL.AddCmd(IL.opMULC, ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opMULC, ARITH.Int(e1.value)) + IL.AddCmd(IL.opMULC, ARITH.Int(e1.value)) ELSE - CODE.AddCmd0(CODE.opMUL) + IL.AddCmd0(IL.opMUL) END ELSIF isReal(e) THEN IF e.obj = eCONST THEN - CODE.Float(ARITH.Float(e.value)) + IL.Float(ARITH.Float(e.value)) ELSIF e1.obj = eCONST THEN - CODE.Float(ARITH.Float(e1.value)) + IL.Float(ARITH.Float(e1.value)) END; - CODE.fbinop(CODE.opMULF) + IL.fbinop(IL.opMULF) ELSIF isSet(e) THEN IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opMULSC, ARITH.Int(e.value)) + IL.AddCmd(IL.opMULSC, ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opMULSC, ARITH.Int(e1.value)) + IL.AddCmd(IL.opMULSC, ARITH.Int(e1.value)) ELSE - CODE.AddCmd0(CODE.opMULS) + IL.AddCmd0(IL.opMULS) END END; e.obj := eEXPR END |SCAN.lxSLASH: - PARS.check(isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), parser, pos, 37); + 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), parser, pos, 45) + 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, "/"), parser, pos, 40) + |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 - CODE.Float(ARITH.Float(e.value)); - CODE.fbinop(CODE.opDIVFI) + IL.Float(ARITH.Float(e.value)); + IL.fbinop(IL.opDIVFI) ELSIF e1.obj = eCONST THEN - CODE.Float(ARITH.Float(e1.value)); - CODE.fbinop(CODE.opDIVF) + IL.Float(ARITH.Float(e1.value)); + IL.fbinop(IL.opDIVF) ELSE - CODE.fbinop(CODE.opDIVF) + IL.fbinop(IL.opDIVF) END ELSIF isSet(e) THEN IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opDIVSC, ARITH.Int(e.value)) + IL.AddCmd(IL.opDIVSC, ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opDIVSC, ARITH.Int(e1.value)) + IL.AddCmd(IL.opDIVSC, ARITH.Int(e1.value)) ELSE - CODE.AddCmd0(CODE.opDIVS) + IL.AddCmd0(IL.opDIVS) END END; e.obj := eEXPR END |SCAN.lxDIV, SCAN.lxMOD: - PARS.check(isInt(e) & isInt(e1), parser, pos, 37); + PARS.check(isInt(e) & isInt(e1), pos, 37); IF e1.obj = eCONST THEN - PARS.check(~ARITH.isZero(e1.value), parser, pos, 46) + PARS.check(~ARITH.isZero(e1.value), pos, 46); + IF CPU = cpuMSP430 THEN + PARS.check(ARITH.Int(e1.value) > 0, pos, 122) + END END; IF (e.obj = eCONST) & (e1.obj = eCONST) THEN IF op = SCAN.lxDIV THEN - PARS.check(ARITH.opInt(e.value, e1.value, "D"), parser, pos, 39) + 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 := CODE.NewLabel(); - CODE.AddJmpCmd(CODE.opJNZ, label1) + label1 := IL.NewLabel(); + IF CPU = cpuMSP430 THEN + IL.AddJmpCmd(IL.opJG, label1) + ELSE + IL.AddJmpCmd(IL.opJNZ, label1) + END END; IF e.obj = eCONST THEN - CODE.OnError(pos.line, errDIV); - CODE.SetLabel(label1); - CODE.AddCmd(CODE.opDIVL + ORD(op = SCAN.lxMOD), ARITH.Int(e.value)) + 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 - CODE.AddCmd(CODE.opDIVR + ORD(op = SCAN.lxMOD), ARITH.Int(e1.value)) + IL.AddCmd(IL.opDIVR + ORD(op = SCAN.lxMOD), ARITH.Int(e1.value)) ELSE - CODE.OnError(pos.line, errDIV); - CODE.SetLabel(label1); - CODE.AddCmd0(CODE.opDIV + ORD(op = SCAN.lxMOD)) + 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), parser, pos, 37); + PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); IF (e.obj = eCONST) & (e1.obj = eCONST) THEN ARITH.opBoolean(e.value, e1.value, "&") ELSE e.obj := eEXPR; IF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opCONST, ORD(ARITH.getBool(e1.value))) + IL.Const(ORD(ARITH.getBool(e1.value))) END; - CODE.AddCmd0(CODE.opACC) + IL.AddCmd0(IL.opACC) END END END; IF label # -1 THEN - CODE.SetLabel(label) + IL.SetLabel(label) END END term; PROCEDURE SimpleExpression (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR - pos: SCAN.POSITION; + pos: PARS.POSITION; op: INTEGER; e1: PARS.EXPR; @@ -2019,20 +2081,20 @@ VAR term(parser, e); IF plus OR minus THEN - PARS.check(isInt(e) OR isReal(e) OR isSet(e), parser, pos, 36); + PARS.check(isInt(e) OR isReal(e) OR isSet(e), pos, 36); IF minus & (e.obj = eCONST) THEN - PARS.check(ARITH.neg(e.value), parser, pos, 39) + PARS.check(ARITH.neg(e.value), pos, 39) END; IF e.obj # eCONST THEN IF minus THEN IF isInt(e) THEN - CODE.AddCmd0(CODE.opUMINUS) + IL.AddCmd0(IL.opUMINUS) ELSIF isReal(e) THEN - CODE.AddCmd0(CODE.opUMINF) + IL.AddCmd0(IL.opUMINF) ELSIF isSet(e) THEN - CODE.AddCmd0(CODE.opUMINS) + IL.AddCmd0(IL.opUMINS) END END; e.obj := eEXPR @@ -2052,15 +2114,15 @@ VAR IF ~parser.constexp THEN IF label = -1 THEN - label := CODE.NewLabel() + label := IL.NewLabel() END; IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opCONST, ORD(ARITH.getBool(e.value))) - END; - CODE.AddCmd0(CODE.opACC); - CODE.AddJmpCmd(CODE.opJNZ, label); - CODE.drop + IL.Const(ORD(ARITH.getBool(e.value))) + END; + IL.AddCmd0(IL.opACC); + IL.AddJmpCmd(IL.opJNZ, label); + IL.drop END END; @@ -2076,64 +2138,64 @@ VAR op := ORD("-") END; - PARS.check(isInt(e) & isInt(e1) OR isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), parser, pos, 37); + 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, CHR(op)), parser, pos, 39) - |ARITH.tREAL: PARS.check(ARITH.opFloat(e.value, e1.value, CHR(op)), parser, pos, 40) + |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)) END ELSE IF isInt(e) THEN IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opADDL + ORD(op = ORD("-")), ARITH.Int(e.value)) + IL.AddCmd(IL.opADDL + ORD(op = ORD("-")), ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opADDR + ORD(op = ORD("-")), ARITH.Int(e1.value)) + IL.AddCmd(IL.opADDR + ORD(op = ORD("-")), ARITH.Int(e1.value)) ELSE - CODE.AddCmd0(CODE.opADD + ORD(op = ORD("-"))) + IL.AddCmd0(IL.opADD + ORD(op = ORD("-"))) END ELSIF isReal(e) THEN IF e.obj = eCONST THEN - CODE.Float(ARITH.Float(e.value)); - CODE.fbinop(CODE.opADDFI + ORD(op = ORD("-"))) + IL.Float(ARITH.Float(e.value)); + IL.fbinop(IL.opADDFI + ORD(op = ORD("-"))) ELSIF e1.obj = eCONST THEN - CODE.Float(ARITH.Float(e1.value)); - CODE.fbinop(CODE.opADDF + ORD(op = ORD("-"))) + IL.Float(ARITH.Float(e1.value)); + IL.fbinop(IL.opADDF + ORD(op = ORD("-"))) ELSE - CODE.fbinop(CODE.opADDF + ORD(op = ORD("-"))) + IL.fbinop(IL.opADDF + ORD(op = ORD("-"))) END ELSIF isSet(e) THEN IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opADDSL + ORD(op = ORD("-")), ARITH.Int(e.value)) + IL.AddCmd(IL.opADDSL + ORD(op = ORD("-")), ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opADDSR + ORD(op = ORD("-")), ARITH.Int(e1.value)) + IL.AddCmd(IL.opADDSR + ORD(op = ORD("-")), ARITH.Int(e1.value)) ELSE - CODE.AddCmd0(CODE.opADDS + ORD(op = ORD("-"))) + IL.AddCmd0(IL.opADDS + ORD(op = ORD("-"))) END END; e.obj := eEXPR END |SCAN.lxOR: - PARS.check(isBoolean(e) & isBoolean(e1), parser, pos, 37); + PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); IF (e.obj = eCONST) & (e1.obj = eCONST) THEN ARITH.opBoolean(e.value, e1.value, "|") ELSE e.obj := eEXPR; IF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opCONST, ORD(ARITH.getBool(e1.value))) + IL.Const(ORD(ARITH.getBool(e1.value))) END; - CODE.AddCmd0(CODE.opACC) + IL.AddCmd0(IL.opACC) END END END; IF label # -1 THEN - CODE.SetLabel(label) + IL.SetLabel(label) END END SimpleExpression; @@ -2142,6 +2204,7 @@ VAR PROCEDURE cmpcode (op: INTEGER): INTEGER; VAR res: INTEGER; + BEGIN CASE op OF |SCAN.lxEQ: res := 0 @@ -2156,12 +2219,30 @@ VAR END cmpcode; + PROCEDURE invcmpcode (op: INTEGER): INTEGER; + VAR + res: INTEGER; + + BEGIN + CASE op OF + |SCAN.lxEQ: res := 0 + |SCAN.lxNE: res := 1 + |SCAN.lxLT: res := 4 + |SCAN.lxLE: res := 5 + |SCAN.lxGT: res := 2 + |SCAN.lxGE: res := 3 + END + + RETURN res + END invcmpcode; + + PROCEDURE BoolCmp (eq, val: BOOLEAN); BEGIN IF eq = val THEN - CODE.AddCmd0(CODE.opNER) + IL.AddCmd0(IL.opNEC) ELSE - CODE.AddCmd0(CODE.opEQR) + IL.AddCmd0(IL.opEQC) END END BoolCmp; @@ -2175,40 +2256,40 @@ VAR res := TRUE; IF isString(e) & isCharArray(e1) THEN - CODE.AddCmd(CODE.opSADR, String(e)); - CODE.AddCmd(CODE.opCONST, strlen(e) + 1); - CODE.AddCmd0(CODE.opEQS2 + cmpcode(op)) + IL.StrAdr(String(e)); + IL.Const(strlen(e) + 1); + IL.AddCmd0(IL.opEQS + invcmpcode(op)) ELSIF isString(e) & isCharArrayW(e1) THEN - CODE.AddCmd(CODE.opSADR, StringW(e)); - CODE.AddCmd(CODE.opCONST, utf8strlen(e) + 1); - CODE.AddCmd0(CODE.opEQSW2 + cmpcode(op)) + IL.StrAdr(StringW(e)); + IL.Const(utf8strlen(e) + 1); + IL.AddCmd0(IL.opEQSW + invcmpcode(op)) ELSIF isStringW(e) & isCharArrayW(e1) THEN - CODE.AddCmd(CODE.opSADR, StringW(e)); - CODE.AddCmd(CODE.opCONST, utf8strlen(e) + 1); - CODE.AddCmd0(CODE.opEQSW2 + cmpcode(op)) + IL.StrAdr(StringW(e)); + IL.Const(utf8strlen(e) + 1); + IL.AddCmd0(IL.opEQSW + invcmpcode(op)) ELSIF isCharArray(e) & isString(e1) THEN - CODE.AddCmd(CODE.opSADR, String(e1)); - CODE.AddCmd(CODE.opCONST, strlen(e1) + 1); - CODE.AddCmd0(CODE.opEQS + cmpcode(op)) + IL.StrAdr(String(e1)); + IL.Const(strlen(e1) + 1); + IL.AddCmd0(IL.opEQS + cmpcode(op)) ELSIF isCharArrayW(e) & isString(e1) THEN - CODE.AddCmd(CODE.opSADR, StringW(e1)); - CODE.AddCmd(CODE.opCONST, utf8strlen(e1) + 1); - CODE.AddCmd0(CODE.opEQSW + cmpcode(op)) + IL.StrAdr(StringW(e1)); + IL.Const(utf8strlen(e1) + 1); + IL.AddCmd0(IL.opEQSW + cmpcode(op)) ELSIF isCharArrayW(e) & isStringW(e1) THEN - CODE.AddCmd(CODE.opSADR, StringW(e1)); - CODE.AddCmd(CODE.opCONST, utf8strlen(e1) + 1); - CODE.AddCmd0(CODE.opEQSW + cmpcode(op)) + IL.StrAdr(StringW(e1)); + IL.Const(utf8strlen(e1) + 1); + IL.AddCmd0(IL.opEQSW + cmpcode(op)) ELSIF isCharArrayW(e) & isCharArrayW(e1) THEN - CODE.AddCmd0(CODE.opEQSW + cmpcode(op)) + IL.AddCmd0(IL.opEQSW + cmpcode(op)) ELSIF isCharArray(e) & isCharArray(e1) THEN - CODE.AddCmd0(CODE.opEQS + cmpcode(op)) + IL.AddCmd0(IL.opEQS + cmpcode(op)) ELSIF isString(e) & isString(e1) THEN PARS.strcmp(e.value, e1.value, op) @@ -2227,17 +2308,17 @@ BEGIN SimpleExpression(parser, e); IF relation(parser.sym) THEN IF (isCharArray(e) OR isCharArrayW(e)) & (e.type.length # 0) THEN - CODE.AddCmd(CODE.opCONST, e.type.length) + IL.Const(e.type.length) END; op := parser.sym; getpos(parser, pos); PARS.Next(parser); - pos1 := parser.lex.pos; + getpos(parser, pos1); SimpleExpression(parser, e1); IF (isCharArray(e1) OR isCharArrayW(e1)) & (e1.type.length # 0) THEN - CODE.AddCmd(CODE.opCONST, e1.type.length) + IL.Const(e1.type.length) END; constant := (e.obj = eCONST) & (e1.obj = eCONST); @@ -2267,19 +2348,19 @@ BEGIN ARITH.relation(e.value, e1.value, operator, error) ELSE IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opEQ + cmpcode(op) + 6, ARITH.Int(e.value)) + IL.AddCmd(IL.opEQC + cmpcode(op), ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opEQ + cmpcode(op) + 12, ARITH.Int(e1.value)) + IL.AddCmd(IL.opEQC + cmpcode(op), ARITH.Int(e1.value)) ELSE - CODE.AddCmd0(CODE.opEQ + cmpcode(op)) + IL.AddCmd0(IL.opEQ + cmpcode(op)) END END ELSIF isStringW1(e) & isCharW(e1) THEN - CODE.AddCmd(CODE.opEQ + cmpcode(op) + 6, StrToWChar(e.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + cmpcode(op), StrToWChar(e.value.string(SCAN.IDENT).s)) ELSIF isStringW1(e1) & isCharW(e) THEN - CODE.AddCmd(CODE.opEQ + cmpcode(op) + 12, StrToWChar(e1.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + cmpcode(op), StrToWChar(e1.value.string(SCAN.IDENT).s)) ELSIF isBoolean(e) & isBoolean(e1) THEN IF constant THEN @@ -2291,9 +2372,9 @@ BEGIN BoolCmp(op = SCAN.lxEQ, ARITH.Int(e1.value) # 0) ELSE IF op = SCAN.lxEQ THEN - CODE.AddCmd0(CODE.opEQB) + IL.AddCmd0(IL.opEQB) ELSE - CODE.AddCmd0(CODE.opNEB) + IL.AddCmd0(IL.opNEB) END END END @@ -2303,50 +2384,47 @@ BEGIN ARITH.relation(e.value, e1.value, operator, error) ELSE IF e.obj = eCONST THEN - CODE.Float(ARITH.Float(e.value)); - CODE.fcmp(CODE.opEQF + cmpcode(op) + 6) + IL.Float(ARITH.Float(e.value)) ELSIF e1.obj = eCONST THEN - CODE.Float(ARITH.Float(e1.value)); - CODE.fcmp(CODE.opEQF + cmpcode(op)) - ELSE - CODE.fcmp(CODE.opEQF + cmpcode(op)) - END + IL.Float(ARITH.Float(e1.value)) + END; + IL.fcmp(IL.opEQF + cmpcode(op)) END ELSIF (isStringW(e) OR isCharArrayX(e)) & (isStringW(e1) OR isCharArrayX(e1)) THEN IF ~strcmp(e, e1, op) THEN - PARS.error(parser, pos, 37) + PARS.error(pos, 37) END ELSIF isPtr(e) & isNil(e1) OR isNil(e) & isPtr(e1) THEN - CODE.AddCmd0(CODE.opEQ + cmpcode(op) + 6) + IL.AddCmd0(IL.opEQC + cmpcode(op)) ELSIF isProc(e) & isNil(e1) THEN IF e.obj IN {ePROC, eIMP} THEN - PARS.check(e.ident.global, parser, pos0, 85); + PARS.check(e.ident.global, pos0, 85); constant := TRUE; e.obj := eCONST; ARITH.setbool(e.value, op = SCAN.lxNE) ELSE - CODE.AddCmd0(CODE.opEQ + cmpcode(op) + 6) + IL.AddCmd0(IL.opEQC + cmpcode(op)) END ELSIF isNil(e) & isProc(e1) THEN IF e1.obj IN {ePROC, eIMP} THEN - PARS.check(e1.ident.global, parser, pos1, 85); + PARS.check(e1.ident.global, pos1, 85); constant := TRUE; e.obj := eCONST; ARITH.setbool(e.value, op = SCAN.lxNE) ELSE - CODE.AddCmd0(CODE.opEQ + cmpcode(op) + 6) + IL.AddCmd0(IL.opEQC + cmpcode(op)) END ELSIF isProc(e) & isProc(e1) & PROG.isTypeEq(e.type, e1.type) THEN IF e.obj = ePROC THEN - PARS.check(e.ident.global, parser, pos0, 85) + PARS.check(e.ident.global, pos0, 85) END; IF e1.obj = ePROC THEN - PARS.check(e1.ident.global, parser, pos1, 85) + PARS.check(e1.ident.global, pos1, 85) END; IF (e.obj IN {ePROC, eIMP}) & (e1.obj IN {ePROC, eIMP}) THEN constant := TRUE; @@ -2357,15 +2435,15 @@ BEGIN ARITH.setbool(e.value, e.ident # e1.ident) END ELSIF e.obj = ePROC THEN - CODE.ProcCmp(e.ident.proc.label, cmpcode(op) = 0) + IL.ProcCmp(e.ident.proc.label, op = SCAN.lxEQ) ELSIF e1.obj = ePROC THEN - CODE.ProcCmp(e1.ident.proc.label, cmpcode(op) = 0) + IL.ProcCmp(e1.ident.proc.label, op = SCAN.lxEQ) ELSIF e.obj = eIMP THEN - CODE.ProcImpCmp(e.ident.import, cmpcode(op) = 0) + IL.ProcImpCmp(e.ident.import, op = SCAN.lxEQ) ELSIF e1.obj = eIMP THEN - CODE.ProcImpCmp(e1.ident.import, cmpcode(op) = 0) + IL.ProcImpCmp(e1.ident.import, op = SCAN.lxEQ) ELSE - CODE.AddCmd0(CODE.opEQ + cmpcode(op)) + IL.AddCmd0(IL.opEQ + cmpcode(op)) END ELSIF isNil(e) & isNil(e1) THEN @@ -2374,7 +2452,7 @@ BEGIN ARITH.setbool(e.value, op = SCAN.lxEQ) ELSE - PARS.error(parser, pos, 37) + PARS.error(pos, 37) END |SCAN.lxLT, SCAN.lxLE, SCAN.lxGT, SCAN.lxGE: @@ -2387,88 +2465,86 @@ BEGIN ARITH.relation(e.value, e1.value, operator, error) ELSE IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opEQ + cmpcode(op) + 6, ARITH.Int(e.value)) + IL.AddCmd(IL.opEQC + invcmpcode(op), ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opEQ + cmpcode(op) + 12, ARITH.Int(e1.value)) + IL.AddCmd(IL.opEQC + cmpcode(op), ARITH.Int(e1.value)) ELSE - CODE.AddCmd0(CODE.opEQ + cmpcode(op)) + IL.AddCmd0(IL.opEQ + cmpcode(op)) END END ELSIF isStringW1(e) & isCharW(e1) THEN - CODE.AddCmd(CODE.opEQ + cmpcode(op) + 6, StrToWChar(e.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + invcmpcode(op), StrToWChar(e.value.string(SCAN.IDENT).s)) ELSIF isStringW1(e1) & isCharW(e) THEN - CODE.AddCmd(CODE.opEQ + cmpcode(op) + 12, StrToWChar(e1.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + cmpcode(op), StrToWChar(e1.value.string(SCAN.IDENT).s)) ELSIF isReal(e) & isReal(e1) THEN IF constant THEN ARITH.relation(e.value, e1.value, operator, error) ELSE IF e.obj = eCONST THEN - CODE.Float(ARITH.Float(e.value)); - CODE.fcmp(CODE.opEQF + cmpcode(op) + 6) + IL.Float(ARITH.Float(e.value)); + IL.fcmp(IL.opEQF + invcmpcode(op)) ELSIF e1.obj = eCONST THEN - CODE.Float(ARITH.Float(e1.value)); - CODE.fcmp(CODE.opEQF + cmpcode(op)) + IL.Float(ARITH.Float(e1.value)); + IL.fcmp(IL.opEQF + cmpcode(op)) ELSE - CODE.fcmp(CODE.opEQF + cmpcode(op)) + IL.fcmp(IL.opEQF + cmpcode(op)) END END ELSIF (isStringW(e) OR isCharArrayX(e)) & (isStringW(e1) OR isCharArrayX(e1)) THEN IF ~strcmp(e, e1, op) THEN - PARS.error(parser, pos, 37) + PARS.error(pos, 37) END ELSE - PARS.error(parser, pos, 37) + PARS.error(pos, 37) END |SCAN.lxIN: - PARS.check(isInt(e) & isSet(e1), parser, pos, 37); + PARS.check(isInt(e) & isSet(e1), pos, 37); IF e.obj = eCONST THEN - PARS.check(ARITH.range(e.value, 0, MACHINE.target.maxSet), parser, pos0, 56) + PARS.check(ARITH.range(e.value, 0, UTILS.target.maxSet), pos0, 56) END; IF constant THEN ARITH.relation(e.value, e1.value, operator, error) ELSE IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opINL, ARITH.Int(e.value)) + IL.AddCmd(IL.opINL, ARITH.Int(e.value)) ELSIF e1.obj = eCONST THEN - CODE.AddCmd(CODE.opINR, ARITH.Int(e1.value)) + IL.AddCmd(IL.opINR, ARITH.Int(e1.value)) ELSE - CODE.AddCmd0(CODE.opIN) + IL.AddCmd0(IL.opIN) END END |SCAN.lxIS: - PARS.check(isExpr(e) & (e.type.typ IN {PROG.tRECORD, PROG.tPOINTER}), parser, pos, 73); - IF e.type.typ = PROG.tRECORD THEN - PARS.check(e.obj = eVREC, parser, pos0, 78) - END; - PARS.check(e1.obj = eTYPE, parser, pos1, 79); + PARS.check(isRecPtr(e), pos, 73); + PARS.check(e1.obj = eTYPE, pos1, 79); - IF e.type.typ = PROG.tRECORD THEN - PARS.check(e1.type.typ = PROG.tRECORD, parser, pos1, 80); + 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 - CODE.TypeCheck(e1.type.num) + IL.TypeCheck(e1.type.num) ELSE - CODE.AddCmd(CODE.opVADR, e.ident.offset - 1); - CODE.TypeCheckRec(e1.type.num) + IL.AddCmd(IL.opVADR, e.ident.offset - 1); + IL.TypeCheckRec(e1.type.num) END ELSE - PARS.check(e1.type.typ = PROG.tPOINTER, parser, pos1, 81); - CODE.TypeCheck(e1.type.base.num) + PARS.check(e1.type.typ = PROG.tPOINTER, pos1, 81); + IL.TypeCheck(e1.type.base.num) END; - PARS.check(PROG.isBaseOf(e.type, e1.type), parser, pos1, 82) + PARS.check(PROG.isBaseOf(e.type, e1.type), pos1, 82) END; ASSERT(error = 0); - e.type := PARS.program.stTypes.tBOOLEAN; + e.type := tBOOLEAN; IF ~constant THEN e.obj := eEXPR @@ -2481,7 +2557,7 @@ END expression; PROCEDURE ElementaryStatement (parser: PARS.PARSER); VAR e, e1: PARS.EXPR; - pos: SCAN.POSITION; + pos: PARS.POSITION; line: INTEGER; call: BOOLEAN; fregs: INTEGER; @@ -2489,25 +2565,25 @@ VAR BEGIN getpos(parser, pos); - CODE.pushBegEnd(begcall, endcall); + IL.pushBegEnd(begcall, endcall); designator(parser, e); IF parser.sym = SCAN.lxASSIGN THEN line := parser.lex.pos.line; - PARS.check(isVar(e), parser, pos, 93); - PARS.check(~e.readOnly, parser, pos, 94); + PARS.check(isVar(e), pos, 93); + PARS.check(~e.readOnly, pos, 94); - CODE.setlast(begcall); + IL.setlast(begcall); NextPos(parser, pos); expression(parser, e1); - CODE.setlast(endcall.prev(CODE.COMMAND)); + IL.setlast(endcall.prev(IL.COMMAND)); - PARS.check(assign(e1, e.type, line), parser, pos, 91); + PARS.check(assign(e1, e.type, line), pos, 91); IF e1.obj = ePROC THEN - PARS.check(e1.ident.global, parser, pos, 85) + PARS.check(e1.ident.global, pos, 85) END; call := FALSE ELSIF parser.sym = SCAN.lxEQ THEN @@ -2515,13 +2591,18 @@ BEGIN ELSIF parser.sym = SCAN.lxLROUND THEN e1 := e; ActualParameters(parser, e1); - PARS.check((e1.type = NIL) OR ODD(e.type.call), parser, pos, 92); + PARS.check((e1.type = NIL) OR ODD(e.type.call), pos, 92); call := TRUE ELSE - PARS.check(isProc(e), parser, pos, 86); - PARS.check((e.type.base = NIL) OR ODD(e.type.call), parser, pos, 92); - PARS.check1(e.type.params.first = NIL, parser, 64); - call := TRUE + 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 @@ -2532,39 +2613,39 @@ BEGIN END END; - CODE.popBegEnd(begcall, endcall) + IL.popBegEnd(begcall, endcall) END ElementaryStatement; PROCEDURE IfStatement (parser: PARS.PARSER; if: BOOLEAN); VAR e: PARS.EXPR; - pos: SCAN.POSITION; + pos: PARS.POSITION; label, L: INTEGER; BEGIN - L := CODE.NewLabel(); + L := IL.NewLabel(); IF ~if THEN - CODE.AddCmd0(CODE.opLOOP); - CODE.SetLabel(L) + IL.AddCmd0(IL.opLOOP); + IL.SetLabel(L) END; REPEAT NextPos(parser, pos); - label := CODE.NewLabel(); + label := IL.NewLabel(); expression(parser, e); - PARS.check(isBoolean(e), parser, pos, 72); + PARS.check(isBoolean(e), pos, 72); IF e.obj = eCONST THEN IF ~ARITH.getBool(e.value) THEN - CODE.AddJmpCmd(CODE.opJMP, label) + IL.AddJmpCmd(IL.opJMP, label) END ELSE - CODE.AddJmpCmd(CODE.opJNE, label) + IL.AddJmpCmd(IL.opJNE, label) END; IF if THEN @@ -2576,8 +2657,8 @@ BEGIN PARS.Next(parser); parser.StatSeq(parser); - CODE.AddJmpCmd(CODE.opJMP, L); - CODE.SetLabel(label) + IL.AddJmpCmd(IL.opJMP, L); + IL.SetLabel(label) UNTIL parser.sym # SCAN.lxELSIF; @@ -2586,13 +2667,13 @@ BEGIN PARS.Next(parser); parser.StatSeq(parser) END; - CODE.SetLabel(L) + IL.SetLabel(L) END; PARS.checklex(parser, SCAN.lxEND); IF ~if THEN - CODE.AddCmd0(CODE.opENDLOOP) + IL.AddCmd0(IL.opENDLOOP) END; PARS.Next(parser) @@ -2602,31 +2683,31 @@ END IfStatement; PROCEDURE RepeatStatement (parser: PARS.PARSER); VAR e: PARS.EXPR; - pos: SCAN.POSITION; + pos: PARS.POSITION; label: INTEGER; BEGIN - CODE.AddCmd0(CODE.opLOOP); + IL.AddCmd0(IL.opLOOP); - label := CODE.NewLabel(); - CODE.SetLabel(label); + label := IL.NewLabel(); + IL.SetLabel(label); PARS.Next(parser); parser.StatSeq(parser); PARS.checklex(parser, SCAN.lxUNTIL); NextPos(parser, pos); expression(parser, e); - PARS.check(isBoolean(e), parser, pos, 72); + PARS.check(isBoolean(e), pos, 72); IF e.obj = eCONST THEN IF ~ARITH.getBool(e.value) THEN - CODE.AddJmpCmd(CODE.opJMP, label) + IL.AddJmpCmd(IL.opJMP, label) END ELSE - CODE.AddJmpCmd(CODE.opJNE, label) + IL.AddJmpCmd(IL.opJNE, label) END; - CODE.AddCmd0(CODE.opENDLOOP) + IL.AddCmd0(IL.opENDLOOP) END RepeatStatement; @@ -2656,7 +2737,7 @@ BEGIN END DestroyLabel; -PROCEDURE NewVariant (label: INTEGER; cmd: CODE.COMMAND): CASE_VARIANT; +PROCEDURE NewVariant (label: INTEGER; cmd: IL.COMMAND): CASE_VARIANT; VAR res: CASE_VARIANT; citem: C.ITEM; @@ -2680,19 +2761,14 @@ END NewVariant; PROCEDURE CaseStatement (parser: PARS.PARSER); VAR e: PARS.EXPR; - pos: SCAN.POSITION; - - - PROCEDURE isRecPtr (caseExpr: PARS.EXPR): BOOLEAN; - RETURN isRec(caseExpr) OR isPtr(caseExpr) - END isRecPtr; + pos: PARS.POSITION; PROCEDURE Label (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR type: PROG.TYPE_): INTEGER; VAR a: INTEGER; label: PARS.EXPR; - pos: SCAN.POSITION; + pos: PARS.POSITION; value: ARITH.VALUE; BEGIN @@ -2701,24 +2777,24 @@ VAR IF isChar(caseExpr) THEN PARS.ConstExpression(parser, value); - PARS.check(value.typ = ARITH.tCHAR, parser, pos, 99); + 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.IDENT).s) = 1) & (LENGTH(value.string(SCAN.IDENT).s) > 1) THEN ASSERT(ARITH.setInt(value, StrToWChar(value.string(SCAN.IDENT).s))) ELSE - PARS.check(value.typ IN {ARITH.tWCHAR, ARITH.tCHAR}, parser, pos, 99) + 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, parser, pos, 99); + PARS.check(value.typ = ARITH.tINTEGER, pos, 99); a := ARITH.getInt(value) ELSIF isRecPtr(caseExpr) THEN qualident(parser, label); - PARS.check(label.obj = eTYPE, parser, pos, 79); - PARS.check(PROG.isBaseOf(caseExpr.type, label.type), parser, pos, 99); + 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 @@ -2731,10 +2807,10 @@ VAR END Label; - PROCEDURE CheckType (node: AVL.NODE; type: PROG.TYPE_; parser: PARS.PARSER; pos: SCAN.POSITION); + 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)), parser, pos, 100); + 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 @@ -2745,7 +2821,7 @@ VAR VAR label: CASE_LABEL; citem: C.ITEM; - pos, pos1: SCAN.POSITION; + pos, pos1: PARS.POSITION; node: AVL.NODE; newnode: BOOLEAN; range: RANGE; @@ -2759,7 +2835,7 @@ VAR END; label.variant := variant; - label.self := CODE.NewLabel(); + label.self := IL.NewLabel(); getpos(parser, pos1); range.a := Label(parser, caseExpr, label.type); @@ -2768,7 +2844,7 @@ VAR PARS.check1(~isRecPtr(caseExpr), parser, 53); NextPos(parser, pos); range.b := Label(parser, caseExpr, label.type); - PARS.check(range.a <= range.b, parser, pos, 103) + PARS.check(range.a <= range.b, pos, 103) ELSE range.b := range.a END; @@ -2779,7 +2855,7 @@ VAR CheckType(tree, label.type, parser, pos1) END; tree := AVL.insert(tree, label, LabelCmp, newnode, node); - PARS.check(newnode, parser, pos1, 100) + PARS.check(newnode, pos1, 100) RETURN node @@ -2813,12 +2889,12 @@ VAR t: PROG.TYPE_; variant: INTEGER; node: AVL.NODE; - last: CODE.COMMAND; + last: IL.COMMAND; BEGIN sym := parser.sym; IF sym # SCAN.lxBAR THEN - variant := CODE.NewLabel(); + variant := IL.NewLabel(); node := CaseLabelList(parser, caseExpr, tree, variant); PARS.checklex(parser, SCAN.lxCOLON); PARS.Next(parser); @@ -2827,15 +2903,15 @@ VAR caseExpr.ident.type := node.data(CASE_LABEL).type END; - last := CODE.getlast(); - CODE.SetLabel(variant); + last := IL.getlast(); + IL.SetLabel(variant); IF ~isRecPtr(caseExpr) THEN LISTS.push(CaseVariants, NewVariant(variant, last)) END; parser.StatSeq(parser); - CODE.AddJmpCmd(CODE.opJMP, end); + IL.AddJmpCmd(IL.opJMP, end); IF isRecPtr(caseExpr) THEN caseExpr.ident.type := t @@ -2849,7 +2925,7 @@ VAR L, R: INTEGER; range: RANGE; left, right: AVL.NODE; - last: CODE.COMMAND; + last: IL.COMMAND; v: CASE_VARIANT; BEGIN @@ -2871,7 +2947,7 @@ VAR R := else END; - last := CODE.getlast(); + last := IL.getlast(); v := CaseVariants.last(CASE_VARIANT); WHILE (v # NIL) & (v.label # 0) & (v.label # node.data(CASE_LABEL).variant) DO @@ -2879,16 +2955,16 @@ VAR END; ASSERT((v # NIL) & (v.label # 0)); - CODE.setlast(v.cmd); + IL.setlast(v.cmd); - CODE.SetLabel(node.data(CASE_LABEL).self); - CODE.case(range.a, range.b, L, R); + IL.SetLabel(node.data(CASE_LABEL).self); + IL.case(range.a, range.b, L, R); IF v.processed THEN - CODE.AddJmpCmd(CODE.opJMP, node.data(CASE_LABEL).variant) + IL.AddJmpCmd(IL.opJMP, node.data(CASE_LABEL).variant) END; v.processed := TRUE; - CODE.setlast(last); + IL.setlast(last); Table(left, else); Table(right, else) @@ -2899,7 +2975,7 @@ VAR PROCEDURE TableT (node: AVL.NODE); BEGIN IF node # NIL THEN - CODE.caset(node.data(CASE_LABEL).range.a, node.data(CASE_LABEL).variant); + IL.caset(node.data(CASE_LABEL).range.a, node.data(CASE_LABEL).variant); TableT(node.left); TableT(node.right) @@ -2907,7 +2983,7 @@ VAR END TableT; - PROCEDURE ParseCase (parser: PARS.PARSER; e: PARS.EXPR; pos: SCAN.POSITION); + PROCEDURE ParseCase (parser: PARS.PARSER; e: PARS.EXPR; pos: PARS.POSITION); VAR table, end, else: INTEGER; tree: AVL.NODE; @@ -2915,11 +2991,11 @@ VAR BEGIN LISTS.push(CaseVariants, NewVariant(0, NIL)); - end := CODE.NewLabel(); - else := CODE.NewLabel(); - table := CODE.NewLabel(); - CODE.AddCmd(CODE.opSWITCH, ORD(isRecPtr(e))); - CODE.AddJmpCmd(CODE.opJMP, table); + end := IL.NewLabel(); + else := IL.NewLabel(); + table := IL.NewLabel(); + IL.AddCmd(IL.opSWITCH, ORD(isRecPtr(e))); + IL.AddJmpCmd(IL.opJMP, table); tree := NIL; @@ -2929,30 +3005,30 @@ VAR case(parser, e, tree, end) END; - CODE.SetLabel(else); + IL.SetLabel(else); IF parser.sym = SCAN.lxELSE THEN PARS.Next(parser); parser.StatSeq(parser); - CODE.AddJmpCmd(CODE.opJMP, end) + IL.AddJmpCmd(IL.opJMP, end) ELSE - CODE.OnError(pos.line, errCASE) + IL.OnError(pos.line, errCASE) END; PARS.checklex(parser, SCAN.lxEND); PARS.Next(parser); IF isRecPtr(e) THEN - CODE.SetLabel(table); + IL.SetLabel(table); TableT(tree); - CODE.AddJmpCmd(CODE.opJMP, else) + IL.AddJmpCmd(IL.opJMP, else) ELSE tree.data(CASE_LABEL).self := table; Table(tree, else) END; AVL.destroy(tree, DestroyLabel); - CODE.SetLabel(end); - CODE.AddCmd0(CODE.opENDSW); + IL.SetLabel(end); + IL.AddCmd0(IL.opENDSW); REPEAT item := LISTS.pop(CaseVariants); @@ -2965,25 +3041,25 @@ VAR BEGIN NextPos(parser, pos); expression(parser, e); - PARS.check(isInt(e) OR isChar(e) OR isCharW(e) OR isPtr(e) OR isRec(e), parser, pos, 95); + 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), parser, pos, 93); - PARS.check(e.ident # NIL, parser, pos, 106) + PARS.check(isVar(e), pos, 93); + PARS.check(e.ident # NIL, pos, 106) END; IF isRec(e) THEN - PARS.check(e.obj = eVREC, parser, pos, 78) + PARS.check(e.obj = eVREC, pos, 78) END; IF e.obj = eCONST THEN LoadConst(e) ELSIF isRec(e) THEN - CODE.drop; - CODE.AddCmd(CODE.opLADR, e.ident.offset - 1); - CODE.load(PARS.program.target.word) + IL.drop; + IL.AddCmd(IL.opLADR, e.ident.offset - 1); + IL.load(PARS.program.target.word) ELSIF isPtr(e) THEN deref(pos, e, FALSE, errPTR); - CODE.AddCmd(CODE.opSUBR, PARS.program.target.word); - CODE.load(PARS.program.target.word) + IL.AddCmd(IL.opSUBR, PARS.program.target.word); + IL.load(PARS.program.target.word) END; PARS.checklex(parser, SCAN.lxOF); @@ -2994,114 +3070,110 @@ END CaseStatement; PROCEDURE ForStatement (parser: PARS.PARSER); VAR - e: PARS.EXPR; - pos: SCAN.POSITION; - step: ARITH.VALUE; - st: INTEGER; - ident: PROG.IDENT; - offset: INTEGER; - L1, L2: INTEGER; + e: PARS.EXPR; + pos, pos2: PARS.POSITION; + step: ARITH.VALUE; + st: INTEGER; + ident: PROG.IDENT; + offset: INTEGER; + L1, L2: INTEGER; BEGIN - CODE.AddCmd0(CODE.opLOOP); + IL.AddCmd0(IL.opLOOP); - L1 := CODE.NewLabel(); - L2 := CODE.NewLabel(); + L1 := IL.NewLabel(); + L2 := IL.NewLabel(); PARS.ExpectSym(parser, SCAN.lxIDENT); - ident := parser.unit.idents.get(parser.unit, parser.lex.ident, TRUE); + 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.typ = PROG.tINTEGER, parser, 97); + PARS.check1(ident.type = tINTEGER, parser, 97); PARS.ExpectSym(parser, SCAN.lxASSIGN); NextPos(parser, pos); expression(parser, e); - PARS.check(isInt(e), parser, pos, 76); + PARS.check(isInt(e), pos, 76); offset := PROG.getOffset(PARS.program, ident); IF ident.global THEN - CODE.AddCmd(CODE.opGADR, offset) + IL.AddCmd(IL.opGADR, offset) ELSE - CODE.AddCmd(CODE.opLADR, -offset) + IL.AddCmd(IL.opLADR, -offset) END; IF e.obj = eCONST THEN - CODE.AddCmd(CODE.opSAVEC, ARITH.Int(e.value)) + IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) ELSE - CODE.AddCmd0(CODE.opSAVE) + IL.AddCmd0(IL.opSAVE) END; - CODE.SetLabel(L1); + IL.SetLabel(L1); IF ident.global THEN - CODE.AddCmd(CODE.opGADR, offset) + IL.AddCmd(IL.opGADR, offset) ELSE - CODE.AddCmd(CODE.opLADR, -offset) + IL.AddCmd(IL.opLADR, -offset) END; - CODE.load(ident.type.size); + IL.load(ident.type.size); PARS.checklex(parser, SCAN.lxTO); - NextPos(parser, pos); + NextPos(parser, pos2); expression(parser, e); - PARS.check(isInt(e), parser, pos, 76); + 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, parser, pos, 76); + PARS.check(step.typ = ARITH.tINTEGER, pos, 76); st := ARITH.getInt(step); - PARS.check(st # 0, parser, pos, 98) + PARS.check(st # 0, pos, 98) ELSE st := 1 END; IF e.obj = eCONST THEN IF st > 0 THEN - CODE.AddCmd(CODE.opLER, ARITH.Int(e.value)) + 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 - CODE.AddCmd(CODE.opGER, ARITH.Int(e.value)) + 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 - CODE.AddCmd0(CODE.opLE) + IL.AddCmd0(IL.opLE) ELSE - CODE.AddCmd0(CODE.opGE) + IL.AddCmd0(IL.opGE) END END; - CODE.AddJmpCmd(CODE.opJNE, L2); + IL.AddJmpCmd(IL.opJNE, L2); PARS.checklex(parser, SCAN.lxDO); PARS.Next(parser); parser.StatSeq(parser); IF ident.global THEN - CODE.AddCmd(CODE.opGADR, offset) + IL.AddCmd(IL.opGADR, offset) ELSE - CODE.AddCmd(CODE.opLADR, -offset) + IL.AddCmd(IL.opLADR, -offset) END; - IF st = 1 THEN - CODE.AddCmd0(CODE.opINC1) - ELSIF st = -1 THEN - CODE.AddCmd0(CODE.opDEC1) - ELSE - IF st > 0 THEN - CODE.AddCmd(CODE.opINCC, st) - ELSE - CODE.AddCmd(CODE.opDECC, -st) - END - END; + IL.AddCmd(IL.opINCC, st); - CODE.AddJmpCmd(CODE.opJMP, L1); + IL.AddJmpCmd(IL.opJMP, L1); PARS.checklex(parser, SCAN.lxEND); PARS.Next(parser); - CODE.SetLabel(L2); + IL.SetLabel(L2); - CODE.AddCmd0(CODE.opENDLOOP) + IL.AddCmd0(IL.opENDLOOP) END ForStatement; @@ -3139,7 +3211,7 @@ BEGIN END StatSeq; -PROCEDURE chkreturn (parser: PARS.PARSER; e: PARS.EXPR; t: PROG.TYPE_; pos: SCAN.POSITION): BOOLEAN; +PROCEDURE chkreturn (parser: PARS.PARSER; e: PARS.EXPR; t: PROG.TYPE_; pos: PARS.POSITION): BOOLEAN; VAR res: BOOLEAN; @@ -3147,24 +3219,24 @@ BEGIN res := assigncomp(e, t); IF res THEN IF e.obj = eCONST THEN - IF e.type.typ = PROG.tREAL THEN - CODE.Float(ARITH.Float(e.value)) + IF e.type = tREAL THEN + IL.Float(ARITH.Float(e.value)) ELSIF e.type.typ = PROG.tNIL THEN - CODE.AddCmd(CODE.opCONST, 0) + IL.Const(0) ELSE LoadConst(e) END - ELSIF (e.type.typ = PROG.tINTEGER) & (t.typ = PROG.tBYTE) & (chkBYTE IN checking) THEN + 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, parser, pos, 85); - CODE.PushProc(e.ident.proc.label) + PARS.check(e.ident.global, pos, 85); + IL.PushProc(e.ident.proc.label) ELSIF e.obj = eIMP THEN - CODE.PushImpProc(e.ident.import) + IL.PushImpProc(e.ident.import) END; - IF e.type.typ = PROG.tREAL THEN - CODE.retf + IF e.type = tREAL THEN + IL.retf END END @@ -3182,16 +3254,16 @@ VAR id: PROG.IDENT; BEGIN - id := rtl.idents.get(rtl, SCAN.enterid(name), FALSE); + id := PROG.getIdent(rtl, SCAN.enterid(name), FALSE); IF (id # NIL) & (id.import # NIL) THEN - CODE.codes.rtl[idx] := -id.import(CODE.IMPORT_PROC).label; + IL.codes.rtl[idx] := -id.import(IL.IMPORT_PROC).label; id.proc.used := TRUE ELSIF (id # NIL) & (id.proc # NIL) THEN - CODE.codes.rtl[idx] := id.proc.label; + IL.codes.rtl[idx] := id.proc.label; id.proc.used := TRUE ELSE - ERRORS.error5("procedure ", mConst.RTL_NAME, ".", name, " not found") + ERRORS.WrongRTL(name) END END getproc; @@ -3200,46 +3272,65 @@ BEGIN rtl := PARS.program.rtl; ASSERT(rtl # NIL); - getproc(rtl, "_move", CODE._move); - getproc(rtl, "_move2", CODE._move2); - getproc(rtl, "_set", CODE._set); - getproc(rtl, "_set2", CODE._set2); - getproc(rtl, "_div", CODE._div); - getproc(rtl, "_mod", CODE._mod); - getproc(rtl, "_div2", CODE._div2); - getproc(rtl, "_mod2", CODE._mod2); - getproc(rtl, "_arrcpy", CODE._arrcpy); - getproc(rtl, "_rot", CODE._rot); - getproc(rtl, "_new", CODE._new); - getproc(rtl, "_dispose", CODE._dispose); - getproc(rtl, "_strcmp", CODE._strcmp); - getproc(rtl, "_error", CODE._error); - getproc(rtl, "_is", CODE._is); - getproc(rtl, "_isrec", CODE._isrec); - getproc(rtl, "_guard", CODE._guard); - getproc(rtl, "_guardrec", CODE._guardrec); - getproc(rtl, "_length", CODE._length); - getproc(rtl, "_init", CODE._init); - getproc(rtl, "_dllentry", CODE._dllentry); - getproc(rtl, "_strcpy", CODE._strcpy); - getproc(rtl, "_exit", CODE._exit); - getproc(rtl, "_strcpy2", CODE._strcpy2); - getproc(rtl, "_lengthw", CODE._lengthw); - getproc(rtl, "_strcmp2", CODE._strcmp2); - getproc(rtl, "_strcmpw", CODE._strcmpw); - getproc(rtl, "_strcmpw2", CODE._strcmpw2); + IF CPU IN {cpuX86, cpuAMD64} THEN + getproc(rtl, "_strcmp", IL._strcmp); + getproc(rtl, "_length", IL._length); + getproc(rtl, "_arrcpy", IL._arrcpy); + getproc(rtl, "_move", IL._move); + getproc(rtl, "_is", IL._is); + getproc(rtl, "_guard", IL._guard); + getproc(rtl, "_guardrec", IL._guardrec); + getproc(rtl, "_error", IL._error); + getproc(rtl, "_new", IL._new); + getproc(rtl, "_rot", IL._rot); + getproc(rtl, "_strcpy", IL._strcpy); + getproc(rtl, "_move2", IL._move2); + getproc(rtl, "_div2", IL._div2); + getproc(rtl, "_mod2", IL._mod2); + getproc(rtl, "_div", IL._div); + getproc(rtl, "_mod", IL._mod); + getproc(rtl, "_set", IL._set); + getproc(rtl, "_set2", IL._set2); + getproc(rtl, "_isrec", IL._isrec); + getproc(rtl, "_lengthw", IL._lengthw); + getproc(rtl, "_strcmpw", IL._strcmpw); + getproc(rtl, "_dllentry", IL._dllentry); + getproc(rtl, "_dispose", IL._dispose); + getproc(rtl, "_exit", IL._exit); + getproc(rtl, "_init", IL._init); + getproc(rtl, "_sofinit", IL._sofinit) + END END setrtl; -PROCEDURE compile* (path, lib_path, modname, outname: PARS.PATH; target, version, stack, base: INTEGER; pic: BOOLEAN; chk: SET); +PROCEDURE compile* (path, lib_path, modname, outname: PARS.PATH; target: INTEGER; options: PROG.OPTIONS); VAR - parser: PARS.PARSER; + parser: PARS.PARSER; ext: PARS.PATH; - amd64: BOOLEAN; BEGIN - amd64 := target IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64, mConst.Target_iELF64}; + tINTEGER := PARS.program.stTypes.tINTEGER; + tBYTE := PARS.program.stTypes.tBYTE; + tCHAR := PARS.program.stTypes.tCHAR; + tSET := PARS.program.stTypes.tSET; + tBOOLEAN := PARS.program.stTypes.tBOOLEAN; + tWCHAR := PARS.program.stTypes.tWCHAR; + tREAL := PARS.program.stTypes.tREAL; + + Options := options; + + CASE target OF + |mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64, mConst.Target_iELF64, mConst.Target_iELFSO64: + CPU := cpuAMD64 + |mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, + mConst.Target_iKolibri, mConst.Target_iObject, mConst.Target_iELF32, + mConst.Target_iELFSO32: + CPU := cpuX86 + |mConst.Target_iMSP430: + CPU := cpuMSP430 + END; + ext := mConst.FILE_EXT; CaseLabels := C.create(); CaseVar := C.create(); @@ -3247,26 +3338,26 @@ BEGIN CaseVariants := LISTS.create(NIL); LISTS.push(CaseVariants, NewVariant(0, NIL)); - checking := chk; - - IF amd64 THEN - CODE.init(6, CODE.little_endian) - ELSE - CODE.init(8, CODE.little_endian) + CASE CPU OF + |cpuAMD64: IL.init(6, IL.little_endian) + |cpuX86: IL.init(8, IL.little_endian) + |cpuMSP430: IL.init(0, IL.little_endian) END; - parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); - IF parser.open(parser, mConst.RTL_NAME) THEN - parser.parse(parser); - PARS.destroy(parser) - ELSE - PARS.destroy(parser); - parser := PARS.create(lib_path, lib_path, StatSeq, expression, designator, chkreturn); + IF CPU # cpuMSP430 THEN + parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); IF parser.open(parser, mConst.RTL_NAME) THEN parser.parse(parser); PARS.destroy(parser) ELSE - ERRORS.error5("file ", lib_path, mConst.RTL_NAME, mConst.FILE_EXT, " not found") + PARS.destroy(parser); + parser := PARS.create(lib_path, lib_path, StatSeq, expression, designator, chkreturn); + IF parser.open(parser, mConst.RTL_NAME) THEN + parser.parse(parser); + PARS.destroy(parser) + ELSE + ERRORS.FileNotFound(lib_path, mConst.RTL_NAME, mConst.FILE_EXT) + END END END; @@ -3276,25 +3367,29 @@ BEGIN IF parser.open(parser, modname) THEN parser.parse(parser) ELSE - ERRORS.error5("file ", path, modname, mConst.FILE_EXT, " not found") + ERRORS.FileNotFound(path, modname, mConst.FILE_EXT) END; PARS.destroy(parser); IF PARS.program.bss > mConst.MAX_GLOBAL_SIZE THEN - ERRORS.error1("size of global variables is too large") + ERRORS.Error(204) END; - setrtl; + IF CPU # cpuMSP430 THEN + setrtl + END; - PROG.DelUnused(PARS.program, CODE.DelImport); + PROG.DelUnused(PARS.program, IL.DelImport); - CODE.codes.bss := PARS.program.bss; - IF amd64 THEN - AMD64.CodeGen(CODE.codes, outname, target, stack, base) - ELSE - X86.CodeGen(CODE.codes, outname, target, stack, base, version, pic) + IL.codes.bss := PARS.program.bss; + + CASE CPU OF + | cpuAMD64: AMD64.CodeGen(IL.codes, outname, target, options) + | cpuX86: X86.CodeGen(IL.codes, outname, target, options) + |cpuMSP430: MSP430.CodeGen(IL.codes, outname, target, options) END + END compile; diff --git a/programs/develop/oberon07/Source/STRINGS.ob07 b/programs/develop/oberon07/Source/STRINGS.ob07 index b33e4bbcdf..2905c08b81 100644 --- a/programs/develop/oberon07/Source/STRINGS.ob07 +++ b/programs/develop/oberon07/Source/STRINGS.ob07 @@ -92,6 +92,29 @@ BEGIN END IntToStr; +PROCEDURE hexdgt (n: BYTE): BYTE; +BEGIN + IF n < 10 THEN + n := n + ORD("0") + ELSE + n := n - 10 + ORD("A") + END + + RETURN n +END hexdgt; + + +PROCEDURE IntToHex* (x: INTEGER; VAR str: ARRAY OF CHAR; n: INTEGER); +BEGIN + str[n] := 0X; + WHILE n > 0 DO + str[n - 1] := CHR(hexdgt(x MOD 16)); + x := x DIV 16; + DEC(n) + END +END IntToHex; + + PROCEDURE copy* (src: ARRAY OF CHAR; VAR dst: ARRAY OF CHAR; spos, dpos, count: INTEGER); BEGIN WHILE count > 0 DO @@ -261,12 +284,12 @@ BEGIN |0E1X..0EFX: u := LSL(ORD(c) - 0E0H, 12); - IF i + 1 < srclen THEN + IF i + 1 < srclen THEN INC(i); INC(u, ORD(BITS(ORD(src[i])) * {0..5}) * 64) END; IF i + 1 < srclen THEN - INC(i); + INC(i); INC(u, ORD(BITS(ORD(src[i])) * {0..5})) END (* diff --git a/programs/develop/oberon07/Source/TEXTDRV.ob07 b/programs/develop/oberon07/Source/TEXTDRV.ob07 index 0e6a6369d6..5838782399 100644 --- a/programs/develop/oberon07/Source/TEXTDRV.ob07 +++ b/programs/develop/oberon07/Source/TEXTDRV.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) @@ -30,10 +30,7 @@ TYPE line*, col*: INTEGER; eof*: BOOLEAN; eol*: BOOLEAN; - - open*: PROCEDURE (text: TEXT; name: ARRAY OF CHAR): BOOLEAN; - peak*: PROCEDURE (text: TEXT): CHAR; - nextc*: PROCEDURE (text: TEXT) + peak*: CHAR END; @@ -43,26 +40,6 @@ VAR texts: C.COLLECTION; -PROCEDURE reset (text: TEXT); -BEGIN - text.chunk[0] := 0; - text.pos := 0; - text.size := 0; - text.file := NIL; - text.utf8 := FALSE; - text.CR := FALSE; - text.line := 1; - text.col := 1; - text.eof := FALSE; - text.eol := FALSE -END reset; - - -PROCEDURE peak (text: TEXT): CHAR; - RETURN CHR(text.chunk[text.pos]) -END peak; - - PROCEDURE load (text: TEXT); BEGIN IF ~text.eof THEN @@ -71,37 +48,40 @@ BEGIN IF text.size = 0 THEN text.eof := TRUE; text.chunk[0] := 0 - END + END; + text.peak := CHR(text.chunk[0]) END END load; -PROCEDURE next (text: TEXT); +PROCEDURE next* (text: TEXT); VAR c: CHAR; + BEGIN IF text.pos < text.size - 1 THEN - INC(text.pos) + INC(text.pos); + text.peak := CHR(text.chunk[text.pos]) ELSE load(text) END; IF ~text.eof THEN - c := peak(text); + c := text.peak; IF c = CR THEN INC(text.line); - text.col := 0; - text.eol := TRUE; - text.CR := TRUE + 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 + text.col := 0; + text.eol := TRUE ELSE - text.eol := FALSE + text.eol := FALSE END; text.CR := FALSE ELSE @@ -123,7 +103,6 @@ END next; PROCEDURE init (text: TEXT); BEGIN - IF (text.pos = 0) & (text.size >= 3) THEN IF (text.chunk[0] = 0EFH) & (text.chunk[1] = 0BBH) & @@ -140,58 +119,13 @@ BEGIN END; text.line := 1; - text.col := 1 + text.col := 1; + text.peak := CHR(text.chunk[text.pos]) END init; -PROCEDURE open (text: TEXT; name: ARRAY OF CHAR): BOOLEAN; -BEGIN - ASSERT(text # NIL); - - reset(text); - text.file := FILES.open(name); - IF text.file # NIL THEN - load(text); - init(text) - END - - RETURN text.file # NIL -END open; - - -PROCEDURE NewText (): TEXT; -VAR - text: TEXT; - citem: C.ITEM; - -BEGIN - citem := C.pop(texts); - IF citem = NIL THEN - NEW(text) - ELSE - text := citem(TEXT) - END - - RETURN text -END NewText; - - -PROCEDURE create* (): TEXT; -VAR - text: TEXT; -BEGIN - text := NewText(); - reset(text); - text.open := open; - text.peak := peak; - text.nextc := next - - RETURN text -END create; - - -PROCEDURE destroy* (VAR text: TEXT); +PROCEDURE close* (VAR text: TEXT); BEGIN IF text # NIL THEN IF text.file # NIL THEN @@ -201,7 +135,44 @@ BEGIN C.push(texts, text); text := NIL END -END destroy; +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] := 0; + 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.peak := 0X; + text.file := FILES.open(name); + IF text.file # NIL THEN + load(text); + init(text) + ELSE + close(text) + END + END + + RETURN text +END open; BEGIN diff --git a/programs/develop/oberon07/Source/UNIXTIME.ob07 b/programs/develop/oberon07/Source/UNIXTIME.ob07 index be1979b63b..e5f6ce39de 100644 --- a/programs/develop/oberon07/Source/UNIXTIME.ob07 +++ b/programs/develop/oberon07/Source/UNIXTIME.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) @@ -55,12 +55,7 @@ END init; PROCEDURE time* (year, month, day, hour, min, sec: INTEGER): INTEGER; -VAR - d, s: INTEGER; -BEGIN - d := (year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4; - s := d * 86400 + hour * 3600 + min * 60 + sec - RETURN s + 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; diff --git a/programs/develop/oberon07/Source/UTILS.ob07 b/programs/develop/oberon07/Source/UTILS.ob07 index 8f0766b766..c31ac8189e 100644 --- a/programs/develop/oberon07/Source/UTILS.ob07 +++ b/programs/develop/oberon07/Source/UTILS.ob07 @@ -17,9 +17,12 @@ CONST bit_depth* = HOST.bit_depth; maxint* = HOST.maxint; minint* = HOST.minint; - + OS = HOST.OS; + min32* = -2147483647-1; + max32* = 2147483647; + VAR @@ -29,6 +32,22 @@ VAR maxreal*: REAL; + target*: + + RECORD + + bit_depth*, + maxInt*, + minInt*, + maxSet*, + maxHex*: INTEGER; + + maxReal*: REAL + + END; + + bit_diff*: INTEGER; + PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; RETURN HOST.FileRead(F, Buffer, bytes) @@ -112,6 +131,76 @@ BEGIN END UnixTime; +PROCEDURE SetBitDepth* (BitDepth: INTEGER); +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); + target.maxReal := 1.9; + PACK(target.maxReal, 1023); +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; +VAR + res: BOOLEAN; + +BEGIN + IF bytes MOD align # 0 THEN + res := maxint - bytes >= align - (bytes MOD align); + IF res THEN + bytes := bytes + align - (bytes MOD align) + END + ELSE + res := TRUE + END + + RETURN res +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 + ASSERT(x > 0); + + n := 0; + WHILE ~ODD(x) DO + x := x DIV 2; + INC(n) + END; + + IF x # 1 THEN + n := -1 + END + + RETURN n +END Log2; + + BEGIN time := GetTickCount(); COPY(HOST.eol, eol); diff --git a/programs/develop/oberon07/Source/WRITER.ob07 b/programs/develop/oberon07/Source/WRITER.ob07 index 92f90fe513..4781013bd1 100644 --- a/programs/develop/oberon07/Source/WRITER.ob07 +++ b/programs/develop/oberon07/Source/WRITER.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2019, Anton Krotov All rights reserved. *) MODULE WRITER; -IMPORT FILES, ERRORS, MACHINE; +IMPORT FILES, ERRORS, UTILS; TYPE @@ -35,7 +35,7 @@ BEGIN IF FILES.WriteByte(file, n) THEN INC(counter) ELSE - ERRORS.error1("writing file error") + ERRORS.Error(201) END END WriteByte; @@ -47,7 +47,7 @@ VAR BEGIN n := FILES.write(file, chunk, bytes); IF n # bytes THEN - ERRORS.error1("writing file error") + ERRORS.Error(201) END; INC(counter, n) END Write; @@ -59,7 +59,7 @@ VAR BEGIN FOR i := 0 TO 7 DO - WriteByte(file, MACHINE.Byte(n, i)) + WriteByte(file, UTILS.Byte(n, i)) END END Write64LE; @@ -70,15 +70,15 @@ VAR BEGIN FOR i := 0 TO 3 DO - WriteByte(file, MACHINE.Byte(n, i)) + WriteByte(file, UTILS.Byte(n, i)) END END Write32LE; PROCEDURE Write16LE* (file: FILE; n: INTEGER); BEGIN - WriteByte(file, MACHINE.Byte(n, 0)); - WriteByte(file, MACHINE.Byte(n, 1)) + WriteByte(file, UTILS.Byte(n, 0)); + WriteByte(file, UTILS.Byte(n, 1)) END Write16LE; diff --git a/programs/develop/oberon07/Source/X86.ob07 b/programs/develop/oberon07/Source/X86.ob07 index 6dee89a4fc..fde3b94b47 100644 --- a/programs/develop/oberon07/Source/X86.ob07 +++ b/programs/develop/oberon07/Source/X86.ob07 @@ -7,7 +7,8 @@ MODULE X86; -IMPORT CODE, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, mConst := CONSTANTS, MACHINE, CHL := CHUNKLISTS, PATHS; +IMPORT IL, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, PROG, + mConst := CONSTANTS, CHL := CHUNKLISTS, PATHS; CONST @@ -31,7 +32,7 @@ CONST TYPE - COMMAND = CODE.COMMAND; + COMMAND = IL.COMMAND; ANYCODE = POINTER TO RECORD (LISTS.ITEM) @@ -40,7 +41,7 @@ TYPE END; - TCODE = POINTER TO RECORD (ANYCODE) + CODE = POINTER TO RECORD (ANYCODE) code: ARRAY CODECHUNK OF BYTE; length: INTEGER @@ -89,27 +90,29 @@ VAR CodeList: LISTS.LIST; + tcount: INTEGER; + PROCEDURE Byte (n: INTEGER): BYTE; - RETURN MACHINE.Byte(n, 0) + RETURN UTILS.Byte(n, 0) END Byte; PROCEDURE Word (n: INTEGER): INTEGER; - RETURN MACHINE.Byte(n, 0) + MACHINE.Byte(n, 1) * 256 + RETURN UTILS.Byte(n, 0) + UTILS.Byte(n, 1) * 256 END Word; PROCEDURE OutByte* (n: BYTE); VAR - c: TCODE; + c: CODE; last: ANYCODE; BEGIN last := CodeList.last(ANYCODE); - IF (last IS TCODE) & (last(TCODE).length < CODECHUNK) THEN - c := last(TCODE); + IF (last IS CODE) & (last(CODE).length < CODECHUNK) THEN + c := last(CODE); c.code[c.length] := n; INC(c.length) ELSE @@ -124,10 +127,10 @@ END OutByte; PROCEDURE OutInt (n: INTEGER); BEGIN - OutByte(MACHINE.Byte(n, 0)); - OutByte(MACHINE.Byte(n, 1)); - OutByte(MACHINE.Byte(n, 2)); - OutByte(MACHINE.Byte(n, 3)) + OutByte(UTILS.Byte(n, 0)); + OutByte(UTILS.Byte(n, 1)); + OutByte(UTILS.Byte(n, 2)); + OutByte(UTILS.Byte(n, 3)) END OutInt; @@ -181,10 +184,10 @@ END OutIntByte; PROCEDURE shift* (op, reg: INTEGER); BEGIN CASE op OF - |CODE.opASR, CODE.opASR1, CODE.opASR2: OutByte(0F8H + reg) - |CODE.opROR, CODE.opROR1, CODE.opROR2: OutByte(0C8H + reg) - |CODE.opLSL, CODE.opLSL1, CODE.opLSL2: OutByte(0E0H + reg) - |CODE.opLSR, CODE.opLSR1, CODE.opLSR2: OutByte(0E8H + reg) + |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; @@ -320,25 +323,9 @@ BEGIN END drop; -PROCEDURE log2* (x: INTEGER): INTEGER; -VAR - n: INTEGER; - -BEGIN - ASSERT(x > 0); - - 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 GetAnyReg (): INTEGER; + RETURN REG.GetAnyReg(R) +END GetAnyReg; PROCEDURE cond* (op: INTEGER): INTEGER; @@ -347,28 +334,21 @@ VAR BEGIN CASE op OF - |CODE.opGT, CODE.opGTR, CODE.opLTL: res := jg - |CODE.opGE, CODE.opGER, CODE.opLEL: res := jge - |CODE.opLT, CODE.opLTR, CODE.opGTL: res := jl - |CODE.opLE, CODE.opLER, CODE.opGEL: res := jle - |CODE.opEQ, CODE.opEQR, CODE.opEQL: res := je - |CODE.opNE, CODE.opNER, CODE.opNEL: res := jne + |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 inv1* (op: INTEGER): INTEGER; -BEGIN - IF ODD(op) THEN - DEC(op) - ELSE - INC(op) - END - - RETURN op -END inv1; +PROCEDURE inv0* (op: INTEGER): INTEGER; + RETURN ORD(BITS(op) / {0}) +END inv0; PROCEDURE Reloc* (op, value: INTEGER); @@ -436,12 +416,12 @@ VAR reg1: INTEGER; BEGIN - label := CODE.codes.rtl[proc]; + label := IL.codes.rtl[proc]; IF label < 0 THEN label := -label; IF pic THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Pic(reg1, BIN.PICIMP, label); OutByte2(0FFH, 010H + reg1); // call dword[reg1] drop @@ -485,7 +465,7 @@ BEGIN code.offset := count; CASE code OF - |TCODE: INC(count, code.length) + |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 @@ -518,7 +498,7 @@ BEGIN CASE code OF - |TCODE: + |CODE: FOR i := 0 TO code.length - 1 DO BIN.PutCode(program, code.code[i]) END @@ -576,14 +556,14 @@ END BinOp; PROCEDURE PushAll (NumberOfParameters: INTEGER); BEGIN REG.PushAll(R); - R.pushed := R.pushed - NumberOfParameters + DEC(R.pushed, NumberOfParameters) END PushAll; PROCEDURE NewLabel (): INTEGER; BEGIN BIN.NewLabel(program) - RETURN CODE.NewLabel() + RETURN IL.NewLabel() END NewLabel; @@ -593,7 +573,7 @@ BEGIN END GetRegA; -PROCEDURE translate (code: CODE.CODES; pic: BOOLEAN; stroffs: INTEGER); +PROCEDURE translate (code: IL.CODES; pic: BOOLEAN; stroffs: INTEGER); VAR cmd: COMMAND; @@ -601,7 +581,7 @@ VAR n, a, b, label, cc: INTEGER; - param1, param2: INTEGER; + opcode, param1, param2: INTEGER; float: REAL; @@ -613,17 +593,19 @@ BEGIN param1 := cmd.param1; param2 := cmd.param2; - CASE cmd.opcode OF + opcode := cmd.opcode; - |CODE.opJMP: + CASE opcode OF + + |IL.opJMP: jmp(param1) - |CODE.opCALL: + |IL.opCALL: call(param1) - |CODE.opCALLI: + |IL.opCALLI: IF pic THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Pic(reg1, BIN.PICIMP, param1); OutByte2(0FFH, 010H + reg1); // call dword[reg1] drop @@ -632,13 +614,13 @@ BEGIN Reloc(BIN.RIMP, param1) END - |CODE.opCALLP: + |IL.opCALLP: UnOp(reg1); OutByte2(0FFH, 0D0H + reg1); // call reg1 drop; ASSERT(R.top = -1) - |CODE.opPRECALL: + |IL.opPRECALL: n := param2; IF (param1 # 0) & (n # 0) THEN subrc(esp, 8) @@ -650,7 +632,7 @@ BEGIN END; PushAll(0) - |CODE.opALIGN16: + |IL.opALIGN16: ASSERT(eax IN R.regs); mov(eax, esp); andrc(esp, -16); @@ -660,7 +642,7 @@ BEGIN END; push(eax) - |CODE.opRES: + |IL.opRES: ASSERT(R.top = -1); GetRegA; n := param2; @@ -670,7 +652,7 @@ BEGIN DEC(n) END - |CODE.opRESF: + |IL.opRESF: n := param2; IF n > 0 THEN OutByte3(0DDH, 5CH + long(n * 8), 24H); @@ -684,7 +666,7 @@ BEGIN DEC(n) END - |CODE.opENTER: + |IL.opENTER: ASSERT(R.top = -1); SetLabel(param1); @@ -704,8 +686,8 @@ BEGIN END END - |CODE.opLEAVE, CODE.opLEAVER, CODE.opLEAVEF: - IF cmd.opcode = CODE.opLEAVER THEN + |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: + IF opcode = IL.opLEAVER THEN UnOp(reg1); IF reg1 # eax THEN GetRegA; @@ -717,7 +699,10 @@ BEGIN ASSERT(R.top = -1); - mov(esp, ebp); + IF param1 > 0 THEN + mov(esp, ebp) + END; + pop(ebp); n := param2; @@ -728,10 +713,10 @@ BEGIN OutByte(0C3H) // ret END - |CODE.opERRC: + |IL.opPUSHC: pushc(param2) - |CODE.opPARAM: + |IL.opPARAM: n := param2; IF n = 1 THEN UnOp(reg1); @@ -742,26 +727,25 @@ BEGIN PushAll(n) END - |CODE.opCLEANUP: + |IL.opCLEANUP: n := param2 * 4; IF n # 0 THEN addrc(esp, n) END - |CODE.opPOPSP: + |IL.opPOPSP: pop(esp) - |CODE.opCONST: - reg1 := REG.GetAnyReg(R); - movrc(reg1, param2) + |IL.opCONST: + movrc(GetAnyReg(), param2) - |CODE.opLABEL: - SetLabel(param2) // L: + |IL.opLABEL: + SetLabel(param1) // L: - |CODE.opNOP: + |IL.opNOP: - |CODE.opGADR: - reg1 := REG.GetAnyReg(R); + |IL.opGADR: + reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICBSS, param2) ELSE @@ -769,20 +753,18 @@ BEGIN Reloc(BIN.RBSS, param2) END - |CODE.opLADR: + |IL.opLADR: n := param2 * 4; - reg1 := REG.GetAnyReg(R); - OutByte2(8DH, 45H + reg1 * 8 + long(n)); // lea reg1, dword[ebp + n] + OutByte2(8DH, 45H + GetAnyReg() * 8 + long(n)); // lea reg1, dword[ebp + n] OutIntByte(n) - |CODE.opVADR: + |IL.opVADR: n := param2 * 4; - reg1 := REG.GetAnyReg(R); - OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] + OutByte2(8BH, 45H + GetAnyReg() * 8 + long(n)); // mov reg1, dword[ebp + n] OutIntByte(n) - |CODE.opSADR: - reg1 := REG.GetAnyReg(R); + |IL.opSADR: + reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICDATA, stroffs + param2); ELSE @@ -790,30 +772,30 @@ BEGIN Reloc(BIN.RDATA, stroffs + param2) END - |CODE.opSAVEC: + |IL.opSAVEC: UnOp(reg1); OutByte2(0C7H, reg1); OutInt(param2); // mov dword[reg1], param2 drop - |CODE.opSAVE8C: + |IL.opSAVE8C: UnOp(reg1); OutByte3(0C6H, reg1, Byte(param2)); // mov byte[reg1], param2 drop - |CODE.opSAVE16C: + |IL.opSAVE16C: UnOp(reg1); OutByte3(66H, 0C7H, reg1); OutWord(Word(param2)); // mov word[reg1], param2 drop - |CODE.opVLOAD32: + |IL.opVLOAD32: n := param2 * 4; - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] OutIntByte(n); OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] - |CODE.opGLOAD32: - reg1 := REG.GetAnyReg(R); + |IL.opGLOAD32: + reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICBSS, param2); OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] @@ -822,25 +804,24 @@ BEGIN Reloc(BIN.RBSS, param2) END - |CODE.opLLOAD32: + |IL.opLLOAD32: n := param2 * 4; - reg1 := REG.GetAnyReg(R); - OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] + OutByte2(8BH, 45H + GetAnyReg() * 8 + long(n)); // mov reg1, dword[ebp + n] OutIntByte(n) - |CODE.opLOAD32: + |IL.opLOAD32: UnOp(reg1); OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] - |CODE.opVLOAD8: + |IL.opVLOAD8: n := param2 * 4; - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] OutIntByte(n); OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] - |CODE.opGLOAD8: - reg1 := REG.GetAnyReg(R); + |IL.opGLOAD8: + reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICBSS, param2); OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] @@ -849,25 +830,24 @@ BEGIN Reloc(BIN.RBSS, param2) END - |CODE.opLLOAD8: + |IL.opLLOAD8: n := param2 * 4; - reg1 := REG.GetAnyReg(R); - OutByte3(0FH, 0B6H, 45H + reg1 * 8 + long(n)); // movzx reg1, byte[ebp + n] + OutByte3(0FH, 0B6H, 45H + GetAnyReg() * 8 + long(n)); // movzx reg1, byte[ebp + n] OutIntByte(n) - |CODE.opLOAD8: + |IL.opLOAD8: UnOp(reg1); OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] - |CODE.opVLOAD16: + |IL.opVLOAD16: n := param2 * 4; - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] OutIntByte(n); OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] - |CODE.opGLOAD16: - reg1 := REG.GetAnyReg(R); + |IL.opGLOAD16: + reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICBSS, param2); OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] @@ -876,26 +856,25 @@ BEGIN Reloc(BIN.RBSS, param2) END - |CODE.opLLOAD16: + |IL.opLLOAD16: n := param2 * 4; - reg1 := REG.GetAnyReg(R); - OutByte3(0FH, 0B7H, 45H + reg1 * 8 + long(n)); // movzx reg1, word[ebp + n] + OutByte3(0FH, 0B7H, 45H + GetAnyReg() * 8 + long(n)); // movzx reg1, word[ebp + n] OutIntByte(n) - |CODE.opLOAD16: + |IL.opLOAD16: UnOp(reg1); OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] - |CODE.opUMINUS: + |IL.opUMINUS: UnOp(reg1); neg(reg1) - |CODE.opADD: + |IL.opADD: BinOp(reg1, reg2); add(reg1, reg2); drop - |CODE.opADDL, CODE.opADDR: + |IL.opADDL, IL.opADDR: IF param2 # 0 THEN UnOp(reg1); IF param2 = 1 THEN @@ -907,12 +886,12 @@ BEGIN END END - |CODE.opSUB: + |IL.opSUB: BinOp(reg1, reg2); OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2 drop - |CODE.opSUBR, CODE.opSUBL: + |IL.opSUBR, IL.opSUBL: UnOp(reg1); n := param2; IF n = 1 THEN @@ -922,18 +901,18 @@ BEGIN ELSIF n # 0 THEN subrc(reg1, n) END; - IF cmd.opcode = CODE.opSUBL THEN + IF opcode = IL.opSUBL THEN neg(reg1) END - |CODE.opMULC: + |IL.opMULC: UnOp(reg1); a := param2; IF a > 1 THEN - n := log2(a) + n := UTILS.Log2(a) ELSIF a < -1 THEN - n := log2(-a) + n := UTILS.Log2(-a) ELSE n := -1 END; @@ -961,33 +940,33 @@ BEGIN END END - |CODE.opMUL: + |IL.opMUL: BinOp(reg1, reg2); OutByte3(0FH, 0AFH, 0C0H + reg1 * 8 + reg2); // imul reg1, reg2 drop - |CODE.opSAVE, CODE.opSAVE32: + |IL.opSAVE, IL.opSAVE32: BinOp(reg2, reg1); OutByte2(89H, reg2 * 8 + reg1); // mov dword[reg1], reg2 drop; drop - |CODE.opSAVE8: + |IL.opSAVE8: BinOp(reg2, reg1); OutByte2(88H, reg2 * 8 + reg1); // mov byte[reg1], reg2 drop; drop - |CODE.opSAVE16: + |IL.opSAVE16: BinOp(reg2, reg1); OutByte3(66H, 89H, reg2 * 8 + reg1); // mov word[reg1], reg2 drop; drop - |CODE.opSAVEP: + |IL.opSAVEP: UnOp(reg1); IF pic THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); Pic(reg2, BIN.PICCODE, param2); OutByte2(089H, reg2 * 8 + reg1); // mov dword[reg1], reg2 drop @@ -997,10 +976,10 @@ BEGIN END; drop - |CODE.opSAVEIP: + |IL.opSAVEIP: UnOp(reg1); IF pic THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); Pic(reg2, BIN.PICIMP, param2); OutByte2(0FFH, 30H + reg2); // push dword[reg2] OutByte2(08FH, reg1); // pop dword[reg1] @@ -1012,8 +991,8 @@ BEGIN END; drop - |CODE.opPUSHP: - reg1 := REG.GetAnyReg(R); + |IL.opPUSHP: + reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICCODE, param2) ELSE @@ -1021,8 +1000,8 @@ BEGIN Reloc(BIN.RCODE, param2) END - |CODE.opPUSHIP: - reg1 := REG.GetAnyReg(R); + |IL.opPUSHIP: + reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICIMP, param2); OutByte2(08BH, reg1 * 9) // mov reg1, dword[reg1] @@ -1031,90 +1010,71 @@ BEGIN Reloc(BIN.RIMP, param2) END - |CODE.opNOT: + |IL.opNOT: UnOp(reg1); test(reg1); setcc(sete, reg1); andrc(reg1, 1) - |CODE.opORD: + |IL.opORD: UnOp(reg1); test(reg1); setcc(setne, reg1); andrc(reg1, 1) - |CODE.opSBOOL: + |IL.opSBOOL: BinOp(reg2, reg1); test(reg2); - setcc(setne, reg2); - OutByte2(88H, reg2 * 8 + reg1); // mov byte[reg1], reg2 + OutByte3(0FH, 95H, reg1); // setne byte[reg1] drop; drop - |CODE.opSBOOLC: + |IL.opSBOOLC: UnOp(reg1); OutByte3(0C6H, reg1, ORD(param2 # 0)); // mov byte[reg1], 0/1 drop - |CODE.opODD: + |IL.opODD: UnOp(reg1); andrc(reg1, 1) - |CODE.opGTR, CODE.opLTL, CODE.opGER, CODE.opLEL, - CODE.opLER, CODE.opGEL, CODE.opLTR, CODE.opGTL, - CODE.opEQR, CODE.opEQL, CODE.opNER, CODE.opNEL: - UnOp(reg1); - IF param2 = 0 THEN - test(reg1) + |IL.opEQ..IL.opGE, + IL.opEQC..IL.opGEC: + + IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN + BinOp(reg1, reg2); + cmprr(reg1, reg2); + drop ELSE - cmprc(reg1, param2) + UnOp(reg1); + IF param2 = 0 THEN + test(reg1) + ELSE + cmprc(reg1, param2) + END END; - drop; - cc := cond(cmd.opcode); - IF cmd.next(COMMAND).opcode = CODE.opJE THEN + drop; + cc := cond(opcode); + + IF cmd.next(COMMAND).opcode = IL.opJE THEN label := cmd.next(COMMAND).param1; jcc(cc, label); cmd := cmd.next(COMMAND) - ELSIF cmd.next(COMMAND).opcode = CODE.opJNE THEN + ELSIF cmd.next(COMMAND).opcode = IL.opJNE THEN label := cmd.next(COMMAND).param1; - jcc(inv1(cc), label); + jcc(inv0(cc), label); cmd := cmd.next(COMMAND) ELSE - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); setcc(cc + 16, reg1); andrc(reg1, 1) END - |CODE.opGT, CODE.opGE, CODE.opLT, - CODE.opLE, CODE.opEQ, CODE.opNE: + |IL.opEQB, IL.opNEB: BinOp(reg1, reg2); - cmprr(reg1, reg2); - drop; - drop; - cc := cond(cmd.opcode); - - IF cmd.next(COMMAND).opcode = CODE.opJE THEN - label := cmd.next(COMMAND).param1; - jcc(cc, label); - cmd := cmd.next(COMMAND) - - ELSIF cmd.next(COMMAND).opcode = CODE.opJNE THEN - label := cmd.next(COMMAND).param1; - jcc(inv1(cc), label); - cmd := cmd.next(COMMAND) - - ELSE - reg1 := REG.GetAnyReg(R); - setcc(cc + 16, reg1); - andrc(reg1, 1) - END - - |CODE.opEQB, CODE.opNEB: - BinOp(reg1, reg2); - drop; drop; test(reg1); @@ -1127,15 +1087,14 @@ BEGIN // @@: cmprr(reg1, reg2); - reg1 := REG.GetAnyReg(R); - IF cmd.opcode = CODE.opEQB THEN + IF opcode = IL.opEQB THEN setcc(sete, reg1) ELSE setcc(setne, reg1) END; andrc(reg1, 1) - - |CODE.opACC: + + |IL.opACC: IF (R.top # 0) OR (R.stk[0] # eax) THEN PushAll(0); GetRegA; @@ -1143,33 +1102,33 @@ BEGIN DEC(R.pushed) END - |CODE.opDROP: + |IL.opDROP: UnOp(reg1); drop - |CODE.opJNZ: + |IL.opJNZ: UnOp(reg1); test(reg1); jcc(jne, param1) - |CODE.opJZ: + |IL.opJZ: UnOp(reg1); test(reg1); jcc(je, param1) - |CODE.opJE: + |IL.opJE: UnOp(reg1); test(reg1); jcc(jne, param1); - drop; + drop - |CODE.opJNE: + |IL.opJNE: UnOp(reg1); test(reg1); jcc(je, param1); - drop; + drop - |CODE.opSWITCH: + |IL.opSWITCH: UnOp(reg1); IF param2 = 0 THEN reg2 := eax @@ -1183,26 +1142,32 @@ BEGIN END; drop - |CODE.opENDSW: + |IL.opENDSW: - |CODE.opCASEL: + |IL.opCASEL: cmprc(eax, param1); jcc(jl, param2) - |CODE.opCASER: + |IL.opCASER: cmprc(eax, param1); jcc(jg, param2) - |CODE.opCASELR: + |IL.opCASELR: cmprc(eax, param1); jcc(jl, param2); jcc(jg, cmd.param3) - |CODE.opCODE: + |IL.opCODE: OutByte(param2) - |CODE.opGET: - BinOp(reg1, reg2); + |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; @@ -1224,11 +1189,11 @@ BEGIN push(reg2); push(reg1); pushc(8); - CallRTL(pic, CODE._move) + CallRTL(pic, IL._move) END - |CODE.opSAVES: + |IL.opSAVES: UnOp(reg1); drop; PushAll(0); @@ -1243,19 +1208,19 @@ BEGIN END; pushc(param1); - CallRTL(pic, CODE._move) + CallRTL(pic, IL._move) - |CODE.opCHKBYTE: + |IL.opCHKBYTE: BinOp(reg1, reg2); cmprc(reg1, 256); jcc(jb, param1) - |CODE.opCHKIDX: + |IL.opCHKIDX: UnOp(reg1); cmprc(reg1, param2); jcc(jb, param1) - |CODE.opCHKIDX2: + |IL.opCHKIDX2: BinOp(reg1, reg2); IF param2 # -1 THEN cmprr(reg2, reg1); @@ -1268,7 +1233,7 @@ BEGIN R.stk[R.top] := reg2 END - |CODE.opLEN: + |IL.opLEN: n := param2; UnOp(reg1); drop; @@ -1283,136 +1248,94 @@ BEGIN INCL(R.regs, reg1); ASSERT(REG.GetReg(R, reg1)) - |CODE.opINC1: + |IL.opINCC: UnOp(reg1); - OutByte2(0FFH, reg1); // inc dword[reg1] + OutByte2(81H + short(param2), reg1); OutIntByte(param2); // add dword[reg1], param2 drop - |CODE.opDEC1: - UnOp(reg1); - OutByte2(0FFH, 8 + reg1); // dec dword[reg1] - drop - - |CODE.opINCC: - UnOp(reg1); - n := param2; - OutByte2(81H + short(n), reg1); OutIntByte(n); // add dword[reg1], n - drop - - |CODE.opDECC: - UnOp(reg1); - n := param2; - OutByte2(81H + short(n), 28H + reg1); OutIntByte(n); // sub dword[reg1], n - drop - - |CODE.opINC: + |IL.opINC, IL.opDEC: BinOp(reg1, reg2); - OutByte2(01H, reg1 * 8 + reg2); // add dword[reg2], reg1 + OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); // add/sub dword[reg2], reg1 drop; drop - |CODE.opDEC: + |IL.opINCCB, IL.opDECCB: + UnOp(reg1); + OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, Byte(param2)); // add/sub byte[reg1], n + drop + + |IL.opINCB, IL.opDECB: BinOp(reg1, reg2); - OutByte2(29H, reg1 * 8 + reg2); // sub dword[reg2], reg1 + OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); // add/sub byte[reg2], reg1 drop; drop - |CODE.opINC1B: - UnOp(reg1); - OutByte2(0FEH, reg1); // inc byte[reg1] - drop - - |CODE.opDEC1B: - UnOp(reg1); - OutByte2(0FEH, 08H + reg1); // dec byte[reg1] - drop - - |CODE.opINCCB: - UnOp(reg1); - OutByte3(80H, reg1, Byte(param2)); // add byte[reg1], n - drop - - |CODE.opDECCB: - UnOp(reg1); - OutByte3(80H, 28H + reg1, Byte(param2)); // sub byte[reg1], n - drop - - |CODE.opINCB, CODE.opDECB: - BinOp(reg1, reg2); - IF cmd.opcode = CODE.opINCB THEN - OutByte2(00H, reg1 * 8 + reg2) // add byte[reg2], reg1 - ELSE - OutByte2(28H, reg1 * 8 + reg2) // sub byte[reg2], reg1 - END; - drop; - drop - - |CODE.opMULS: + |IL.opMULS: BinOp(reg1, reg2); OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 drop - |CODE.opMULSC: + |IL.opMULSC: UnOp(reg1); andrc(reg1, param2) - |CODE.opDIVS: + |IL.opDIVS: BinOp(reg1, reg2); xor(reg1, reg2); drop - |CODE.opDIVSC: + |IL.opDIVSC: UnOp(reg1); OutByte2(81H + short(param2), 0F0H + reg1); // xor reg1, n OutIntByte(param2) - |CODE.opADDS: + |IL.opADDS: BinOp(reg1, reg2); OutByte2(9H, 0C0H + reg2 * 8 + reg1); // or reg1, reg2 drop - |CODE.opSUBS: + |IL.opSUBS: BinOp(reg1, reg2); not(reg2); OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 drop - |CODE.opADDSL, CODE.opADDSR: + |IL.opADDSL, IL.opADDSR: UnOp(reg1); orrc(reg1, param2) - |CODE.opSUBSL: + |IL.opSUBSL: UnOp(reg1); not(reg1); andrc(reg1, param2) - |CODE.opSUBSR: + |IL.opSUBSR: UnOp(reg1); - andrc(reg1, ORD(-BITS(param2))); + andrc(reg1, ORD(-BITS(param2))) - |CODE.opUMINS: + |IL.opUMINS: UnOp(reg1); not(reg1) - |CODE.opLENGTH: + |IL.opLENGTH: PushAll(2); - CallRTL(pic, CODE._length); + CallRTL(pic, IL._length); GetRegA - |CODE.opLENGTHW: + |IL.opLENGTHW: PushAll(2); - CallRTL(pic, CODE._lengthw); + CallRTL(pic, IL._lengthw); GetRegA - |CODE.opCHR: + |IL.opCHR: UnOp(reg1); andrc(reg1, 255) - |CODE.opWCHR: + |IL.opWCHR: UnOp(reg1); andrc(reg1, 65535) - |CODE.opASR, CODE.opROR, CODE.opLSL, CODE.opLSR: + |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: UnOp(reg1); IF reg1 # ecx THEN ASSERT(REG.GetReg(R, ecx)); @@ -1423,10 +1346,10 @@ BEGIN BinOp(reg1, reg2); ASSERT(reg2 = ecx); OutByte(0D3H); - shift(cmd.opcode, reg1); // shift reg1, cl + shift(opcode, reg1); // shift reg1, cl drop - |CODE.opASR1, CODE.opROR1, CODE.opLSL1, CODE.opLSR1: + |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: UnOp(reg1); IF reg1 # ecx THEN ASSERT(REG.GetReg(R, ecx)); @@ -1434,30 +1357,30 @@ BEGIN drop END; - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); movrc(reg1, param2); BinOp(reg1, reg2); ASSERT(reg1 = ecx); OutByte(0D3H); - shift(cmd.opcode, reg2); // shift reg2, cl + shift(opcode, reg2); // shift reg2, cl drop; drop; ASSERT(REG.GetReg(R, reg2)) - |CODE.opASR2, CODE.opROR2, CODE.opLSL2, CODE.opLSR2: + |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: UnOp(reg1); - n := ORD(BITS(param2) * {0..4}); + n := param2 MOD 32; IF n # 1 THEN OutByte(0C1H) ELSE OutByte(0D1H) END; - shift(cmd.opcode, reg1); // shift reg1, n + shift(opcode, reg1); // shift reg1, n IF n # 1 THEN OutByte(n) END - |CODE.opMIN: + |IL.opMIN: BinOp(reg1, reg2); cmprr(reg1, reg2); OutByte2(07EH, 002H); // jle @f @@ -1465,7 +1388,7 @@ BEGIN // @@: drop - |CODE.opMAX: + |IL.opMAX: BinOp(reg1, reg2); cmprr(reg1, reg2); OutByte2(07DH, 002H); // jge @f @@ -1473,21 +1396,21 @@ BEGIN // @@: drop - |CODE.opMINC: + |IL.opMINC: UnOp(reg1); cmprc(reg1, param2); OutByte2(07EH, 005H); // jle @f - movrc(reg1, param2); // mov reg1, param2 + movrc(reg1, param2) // mov reg1, param2 // @@: - |CODE.opMAXC: + |IL.opMAXC: UnOp(reg1); cmprc(reg1, param2); OutByte2(07DH, 005H); // jge @f - movrc(reg1, param2); // mov reg1, param2 + movrc(reg1, param2) // mov reg1, param2 // @@: - |CODE.opIN: + |IL.opIN: label := NewLabel(); BinOp(reg1, reg2); cmprc(reg1, 32); @@ -1501,10 +1424,10 @@ BEGIN SetLabel(label); drop - |CODE.opINR: + |IL.opINR: label := NewLabel(); UnOp(reg1); - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); cmprc(reg1, 32); OutByte2(72H, 4); // jb L xor(reg1, reg1); @@ -1517,42 +1440,42 @@ BEGIN SetLabel(label); drop - |CODE.opINL: + |IL.opINL: UnOp(reg1); OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); // bt reg1, param2 setcc(setc, reg1); andrc(reg1, 1) - |CODE.opRSET: + |IL.opRSET: PushAll(2); - CallRTL(pic, CODE._set); + CallRTL(pic, IL._set); GetRegA - |CODE.opRSETR: + |IL.opRSETR: PushAll(1); pushc(param2); - CallRTL(pic, CODE._set); + CallRTL(pic, IL._set); GetRegA - |CODE.opRSETL: + |IL.opRSETL: PushAll(1); pushc(param2); - CallRTL(pic, CODE._set2); + CallRTL(pic, IL._set2); GetRegA - |CODE.opRSET1: + |IL.opRSET1: UnOp(reg1); PushAll(1); push(reg1); - CallRTL(pic, CODE._set); + CallRTL(pic, IL._set); GetRegA - |CODE.opINCL, CODE.opEXCL: + |IL.opINCL, IL.opEXCL: BinOp(reg1, reg2); cmprc(reg1, 32); OutByte2(73H, 03H); // jnb L OutByte(0FH); - IF cmd.opcode = CODE.opINCL THEN + IF opcode = IL.opINCL THEN OutByte(0ABH) // bts dword[reg2], reg1 ELSE OutByte(0B3H) // btr dword[reg2], reg1 @@ -1562,27 +1485,27 @@ BEGIN drop; drop - |CODE.opINCLC: + |IL.opINCLC: UnOp(reg1); OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); //bts dword[reg1],param2 drop - |CODE.opEXCLC: + |IL.opEXCLC: UnOp(reg1); OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); //btr dword[reg1],param2 drop - |CODE.opDIV: + |IL.opDIV: PushAll(2); - CallRTL(pic, CODE._div); + CallRTL(pic, IL._div); GetRegA - |CODE.opDIVR: + |IL.opDIVR: a := param2; IF a > 1 THEN - n := log2(a) + n := UTILS.Log2(a) ELSIF a < -1 THEN - n := log2(-a) + n := UTILS.Log2(-a) ELSE n := -1 END; @@ -1597,7 +1520,7 @@ BEGIN UnOp(reg1); IF a < 0 THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); mov(reg2, reg1); IF n # 1 THEN OutByte3(0C1H, 0F8H + reg1, n) // sar reg1, n @@ -1617,28 +1540,28 @@ BEGIN ELSE PushAll(1); pushc(param2); - CallRTL(pic, CODE._div); + CallRTL(pic, IL._div); GetRegA END END - |CODE.opDIVL: + |IL.opDIVL: PushAll(1); pushc(param2); - CallRTL(pic, CODE._div2); + CallRTL(pic, IL._div2); GetRegA - |CODE.opMOD: + |IL.opMOD: PushAll(2); - CallRTL(pic, CODE._mod); + CallRTL(pic, IL._mod); GetRegA - |CODE.opMODR: + |IL.opMODR: a := param2; IF a > 1 THEN - n := log2(a) + n := UTILS.Log2(a) ELSIF a < -1 THEN - n := log2(-a) + n := UTILS.Log2(-a) ELSE n := -1 END; @@ -1666,100 +1589,83 @@ BEGIN ELSE PushAll(1); pushc(param2); - CallRTL(pic, CODE._mod); + CallRTL(pic, IL._mod); GetRegA END END - |CODE.opMODL: + |IL.opMODL: PushAll(1); pushc(param2); - CallRTL(pic, CODE._mod2); + CallRTL(pic, IL._mod2); GetRegA - |CODE.opERR: - CallRTL(pic, CODE._error) + |IL.opERR: + CallRTL(pic, IL._error) - |CODE.opABS: + |IL.opABS: UnOp(reg1); test(reg1); OutByte2(07DH, 002H); // jge @f - neg(reg1); // neg reg1 + neg(reg1) // neg reg1 // @@: - |CODE.opCOPY: + |IL.opCOPY: PushAll(2); pushc(param2); - CallRTL(pic, CODE._move2) + CallRTL(pic, IL._move2) - |CODE.opMOVE: + |IL.opMOVE: PushAll(3); - CallRTL(pic, CODE._move2) + CallRTL(pic, IL._move2) - |CODE.opCOPYA: + |IL.opCOPYA: PushAll(4); pushc(param2); - CallRTL(pic, CODE._arrcpy); + CallRTL(pic, IL._arrcpy); GetRegA - |CODE.opCOPYS: + |IL.opCOPYS: PushAll(4); pushc(param2); - CallRTL(pic, CODE._strcpy) + CallRTL(pic, IL._strcpy) - |CODE.opCOPYS2: - PushAll(4); - pushc(param2); - CallRTL(pic, CODE._strcpy2) - - |CODE.opROT: + |IL.opROT: PushAll(0); push(esp); pushc(param2); - CallRTL(pic, CODE._rot) + CallRTL(pic, IL._rot) - |CODE.opNEW: + |IL.opNEW: PushAll(1); n := param2 + 8; - ASSERT(MACHINE.Align(n, 32)); + ASSERT(UTILS.Align(n, 32)); pushc(n); pushc(param1); - CallRTL(pic, CODE._new) + CallRTL(pic, IL._new) - |CODE.opDISP: + |IL.opDISP: PushAll(1); - CallRTL(pic, CODE._dispose) + CallRTL(pic, IL._dispose) - |CODE.opEQS .. CODE.opGES: + |IL.opEQS .. IL.opGES: PushAll(4); - pushc(cmd.opcode - CODE.opEQS); - CallRTL(pic, CODE._strcmp); + pushc(opcode - IL.opEQS); + CallRTL(pic, IL._strcmp); GetRegA - |CODE.opEQS2 .. CODE.opGES2: + |IL.opEQSW .. IL.opGESW: PushAll(4); - pushc(cmd.opcode - CODE.opEQS2); - CallRTL(pic, CODE._strcmp2); + pushc(opcode - IL.opEQSW); + CallRTL(pic, IL._strcmpw); GetRegA - |CODE.opEQSW .. CODE.opGESW: - PushAll(4); - pushc(cmd.opcode - CODE.opEQSW); - CallRTL(pic, CODE._strcmpw); - GetRegA - - |CODE.opEQSW2 .. CODE.opGESW2: - PushAll(4); - pushc(cmd.opcode - CODE.opEQSW2); - CallRTL(pic, CODE._strcmpw2); - GetRegA - - |CODE.opEQP, CODE.opNEP, CODE.opEQIP, CODE.opNEIP: + |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP: UnOp(reg1); - CASE cmd.opcode OF - |CODE.opEQP, CODE.opNEP: + CASE opcode OF + |IL.opEQP, IL.opNEP: IF pic THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); Pic(reg2, BIN.PICCODE, param1); cmprr(reg1, reg2); drop @@ -1768,9 +1674,9 @@ BEGIN Reloc(BIN.RCODE, param1) END - |CODE.opEQIP, CODE.opNEIP: + |IL.opEQIP, IL.opNEIP: IF pic THEN - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); Pic(reg2, BIN.PICIMP, param1); OutByte2(03BH, reg1 * 8 + reg2); //cmp reg1, dword [reg2] drop @@ -1781,64 +1687,64 @@ BEGIN END; drop; - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); - CASE cmd.opcode OF - |CODE.opEQP, CODE.opEQIP: setcc(sete, reg1) - |CODE.opNEP, CODE.opNEIP: setcc(setne, reg1) + CASE opcode OF + |IL.opEQP, IL.opEQIP: setcc(sete, reg1) + |IL.opNEP, IL.opNEIP: setcc(setne, reg1) END; andrc(reg1, 1) - |CODE.opPUSHT: + |IL.opPUSHT: UnOp(reg1); - reg2 := REG.GetAnyReg(R); + reg2 := GetAnyReg(); OutByte3(8BH, 40H + reg2 * 8 + reg1, 0FCH) // mov reg2, dword[reg1 - 4] - |CODE.opISREC: + |IL.opISREC: PushAll(2); - pushc(param2); - CallRTL(pic, CODE._isrec); + pushc(param2 * tcount); + CallRTL(pic, IL._isrec); GetRegA - |CODE.opIS: + |IL.opIS: PushAll(1); - pushc(param2); - CallRTL(pic, CODE._is); + pushc(param2 * tcount); + CallRTL(pic, IL._is); GetRegA - |CODE.opTYPEGR: + |IL.opTYPEGR: PushAll(1); - pushc(param2); - CallRTL(pic, CODE._guardrec); + pushc(param2 * tcount); + CallRTL(pic, IL._guardrec); GetRegA - |CODE.opTYPEGP: + |IL.opTYPEGP: UnOp(reg1); PushAll(0); push(reg1); - pushc(param2); - CallRTL(pic, CODE._guard); + pushc(param2 * tcount); + CallRTL(pic, IL._guard); GetRegA - |CODE.opTYPEGD: + |IL.opTYPEGD: UnOp(reg1); PushAll(0); OutByte3(0FFH, 070H + reg1, 0FCH); // push dword[reg1 - 4] - pushc(param2); - CallRTL(pic, CODE._guardrec); + pushc(param2 * tcount); + CallRTL(pic, IL._guardrec); GetRegA - |CODE.opCASET: + |IL.opCASET: push(ecx); push(ecx); - pushc(param2); - CallRTL(pic, CODE._guardrec); + pushc(param2 * tcount); + CallRTL(pic, IL._guardrec); pop(ecx); test(eax); jcc(jne, param1) - |CODE.opPACK: + |IL.opPACK: BinOp(reg1, reg2); push(reg2); OutByte3(0DBH, 004H, 024H); // fild dword[esp] @@ -1850,7 +1756,7 @@ BEGIN drop; drop - |CODE.opPACKC: + |IL.opPACKC: UnOp(reg1); pushc(param2); OutByte3(0DBH, 004H, 024H); // fild dword[esp] @@ -1861,7 +1767,7 @@ BEGIN pop(reg1); drop - |CODE.opUNPK: + |IL.opUNPK: BinOp(reg1, reg2); OutByte2(0DDH, reg1); // fld qword[reg1] OutByte2(0D9H, 0F4H); // fxtract @@ -1870,16 +1776,16 @@ BEGIN drop; drop - |CODE.opPUSHF: + |IL.opPUSHF: subrc(esp, 8); OutByte3(0DDH, 01CH, 024H) // fstp qword[esp] - |CODE.opLOADF: + |IL.opLOADF: UnOp(reg1); OutByte2(0DDH, reg1); // fld qword[reg1] drop - |CODE.opCONSTF: + |IL.opCONSTF: float := cmd.float; IF float = 0.0 THEN OutByte2(0D9H, 0EEH) // fldz @@ -1896,44 +1802,43 @@ BEGIN addrc(esp, 8) END - |CODE.opSAVEF: + |IL.opSAVEF: UnOp(reg1); OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] drop - |CODE.opADDF, CODE.opADDFI: + |IL.opADDF, IL.opADDFI: OutByte2(0DEH, 0C1H) // faddp st1, st - |CODE.opSUBF: + |IL.opSUBF: OutByte2(0DEH, 0E9H) // fsubp st1, st - |CODE.opSUBFI: + |IL.opSUBFI: OutByte2(0DEH, 0E1H) // fsubrp st1, st - |CODE.opMULF: + |IL.opMULF: OutByte2(0DEH, 0C9H) // fmulp st1, st - |CODE.opDIVF: + |IL.opDIVF: OutByte2(0DEH, 0F9H) // fdivp st1, st - |CODE.opDIVFI: + |IL.opDIVFI: OutByte2(0DEH, 0F1H) // fdivrp st1, st - |CODE.opUMINF: + |IL.opUMINF: OutByte2(0D9H, 0E0H) // fchs - |CODE.opFABS: + |IL.opFABS: OutByte2(0D9H, 0E1H) // fabs - |CODE.opFLT: + |IL.opFLT: UnOp(reg1); push(reg1); OutByte3(0DBH, 004H, 024H); // fild dword[esp] pop(reg1); drop - |CODE.opFLOOR: - reg1 := REG.GetAnyReg(R); + |IL.opFLOOR: 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] @@ -1942,11 +1847,11 @@ BEGIN OutByte2(0D9H, 06CH); OutByte2(024H, 004H); // fldcw word[esp+4] OutByte2(0D9H, 0FCH); // frndint OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] - pop(reg1); + pop(GetAnyReg()); OutByte2(0D9H, 06CH); OutByte2(024H, 002H); // fldcw word[esp+2] addrc(esp, 4) - |CODE.opEQF, CODE.opEQFI: + |IL.opEQF: GetRegA; OutByte2(0DAH, 0E9H); // fucompp OutByte3(09BH, 0DFH, 0E0H); // fstsw ax @@ -1956,7 +1861,7 @@ BEGIN setcc(sete, al) // L: - |CODE.opNEF, CODE.opNEFI: + |IL.opNEF: GetRegA; OutByte2(0DAH, 0E9H); // fucompp OutByte3(09BH, 0DFH, 0E0H); // fstsw ax @@ -1966,7 +1871,7 @@ BEGIN setcc(setne, al) // L: - |CODE.opLTF, CODE.opGTFI: + |IL.opLTF: GetRegA; OutByte2(0DAH, 0E9H); // fucompp OutByte3(09BH, 0DFH, 0E0H); // fstsw ax @@ -1980,7 +1885,7 @@ BEGIN andrc(eax, 1) // L: - |CODE.opGTF, CODE.opLTFI: + |IL.opGTF: GetRegA; OutByte2(0DAH, 0E9H); // fucompp OutByte3(09BH, 0DFH, 0E0H); // fstsw ax @@ -1994,7 +1899,7 @@ BEGIN andrc(eax, 1) // L: - |CODE.opLEF, CODE.opGEFI: + |IL.opLEF: GetRegA; OutByte2(0DAH, 0E9H); // fucompp OutByte3(09BH, 0DFH, 0E0H); // fstsw ax @@ -2004,7 +1909,7 @@ BEGIN setcc(setnc, al) // L: - |CODE.opGEF, CODE.opLEFI: + |IL.opGEF: GetRegA; OutByte2(0DAH, 0E9H); // fucompp OutByte3(09BH, 0DFH, 0E0H); // fstsw ax @@ -2019,15 +1924,15 @@ BEGIN andrc(eax, 1) // L: - |CODE.opINF: + |IL.opINF: pushc(7FF00000H); pushc(0); OutByte3(0DDH, 004H, 024H); // fld qword[esp] addrc(esp, 8) - |CODE.opLADR_UNPK: + |IL.opLADR_UNPK: n := param2 * 4; - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); OutByte2(8DH, 45H + reg1 * 8 + long(n)); // lea reg1, dword[ebp + n] OutIntByte(n); BinOp(reg1, reg2); @@ -2038,9 +1943,9 @@ BEGIN drop; drop - |CODE.opSADR_PARAM: + |IL.opSADR_PARAM: IF pic THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Pic(reg1, BIN.PICDATA, stroffs + param2); push(reg1); drop @@ -2049,17 +1954,17 @@ BEGIN Reloc(BIN.RDATA, stroffs + param2) END - |CODE.opVADR_PARAM: + |IL.opVADR_PARAM: n := param2 * 4; OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] OutIntByte(n) - |CODE.opCONST_PARAM: + |IL.opCONST_PARAM: pushc(param2) - |CODE.opGLOAD32_PARAM: + |IL.opGLOAD32_PARAM: IF pic THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Pic(reg1, BIN.PICBSS, param2); OutByte2(0FFH, 30H + reg1); // push dword[reg1] drop @@ -2068,132 +1973,96 @@ BEGIN Reloc(BIN.RBSS, param2) END - |CODE.opLLOAD32_PARAM: + |IL.opLLOAD32_PARAM: n := param2 * 4; OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] OutIntByte(n) - |CODE.opLOAD32_PARAM: + |IL.opLOAD32_PARAM: UnOp(reg1); OutByte2(0FFH, 30H + reg1); // push dword[reg1] drop - |CODE.opGADR_SAVEC: + |IL.opGADR_SAVEC: IF pic THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Pic(reg1, BIN.PICBSS, param1); OutByte2(0C7H, reg1); // mov dword[reg1], param2 OutInt(param2); drop ELSE - OutByte2(0C7H, 05H); // mov dword[_bss + param2], param2 + OutByte2(0C7H, 05H); // mov dword[_bss + param1], param2 Reloc(BIN.RBSS, param1); OutInt(param2) END - |CODE.opLADR_SAVEC: + |IL.opLADR_SAVEC: n := param1 * 4; OutByte2(0C7H, 45H + long(n)); // mov dword[ebp + n], param2 OutIntByte(n); OutInt(param2) - |CODE.opLADR_SAVE: + |IL.opLADR_SAVE: n := param2 * 4; UnOp(reg1); OutByte2(89H, 45H + reg1 * 8 + long(n)); // mov dword[ebp + n], reg1 OutIntByte(n); drop - |CODE.opLADR_INC1: - n := param2 * 4; - OutByte2(0FFH, 45H + long(n)); // inc dword[ebp + n] - OutIntByte(n) - - |CODE.opLADR_DEC1: - n := param2 * 4; - OutByte2(0FFH, 4DH + long(n)); // dec dword[ebp + n] - OutIntByte(n) - - |CODE.opLADR_INCC: + |IL.opLADR_INCC: n := param1 * 4; - OutByte2(81H + short(param2), 45H + long(n)); // add dword[ebp + n], param2 - OutIntByte(n); - OutIntByte(param2) + 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 - |CODE.opLADR_DECC: + |IL.opLADR_INCCB, IL.opLADR_DECCB: n := param1 * 4; - OutByte2(81H + short(param2), 6DH + long(n)); // sub dword[ebp + n], param2 - OutIntByte(n); - OutIntByte(param2) + 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 - |CODE.opLADR_INC1B: - n := param2 * 4; - OutByte2(0FEH, 45H + long(n)); // inc byte[ebp + n] - OutIntByte(n) - - |CODE.opLADR_DEC1B: - n := param2 * 4; - OutByte2(0FEH, 4DH + long(n)); // dec byte[ebp + n] - OutIntByte(n) - - |CODE.opLADR_INCCB: - n := param1 * 4; - OutByte2(80H, 45H + long(n)); // add byte[ebp + n], param2 - OutIntByte(n); - OutByte(param2 MOD 256) - - |CODE.opLADR_DECCB: - n := param1 * 4; - OutByte2(80H, 6DH + long(n)); // sub byte[ebp + n], param2 - OutIntByte(n); - OutByte(param2 MOD 256) - - |CODE.opLADR_INC: + |IL.opLADR_INC, IL.opLADR_DEC: n := param2 * 4; UnOp(reg1); - OutByte2(01H, 45H + long(n) + reg1 * 8); // add dword[ebp + n], reg1 + OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); // add/sub dword[ebp + n], reg1 OutIntByte(n); drop - |CODE.opLADR_DEC: + |IL.opLADR_INCB, IL.opLADR_DECB: n := param2 * 4; UnOp(reg1); - OutByte2(29H, 45H + long(n) + reg1 * 8); // sub dword[ebp + n], reg1 + OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); // add/sub byte[ebp + n], reg1 OutIntByte(n); drop - |CODE.opLADR_INCB: - n := param2 * 4; - UnOp(reg1); - OutByte2(00H, 45H + long(n) + reg1 * 8); // add byte[ebp + n], reg1 - OutIntByte(n); - drop - - |CODE.opLADR_DECB: - n := param2 * 4; - UnOp(reg1); - OutByte2(28H, 45H + long(n) + reg1 * 8); // sub byte[ebp + n], reg1 - OutIntByte(n); - drop - - |CODE.opLADR_INCL, CODE.opLADR_EXCL: + |IL.opLADR_INCL, IL.opLADR_EXCL: n := param2 * 4; UnOp(reg1); cmprc(reg1, 32); label := NewLabel(); jcc(jnb, label); - OutByte3(0FH, 0ABH + 8 * ORD(cmd.opcode = CODE.opLADR_EXCL), 45H + long(n) + reg1 * 8); // bts(r) dword[ebp + n], reg1 + 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 - |CODE.opLADR_INCLC, CODE.opLADR_EXCLC: + |IL.opLADR_INCLC, IL.opLADR_EXCLC: n := param1 * 4; - OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(cmd.opcode = CODE.opLADR_EXCLC)); // bts(r) dword[ebp + n], param2 + OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); // bts(r) dword[ebp + n], param2 OutIntByte(n); OutByte(param2) - |CODE.opLOOP, CODE.opENDLOOP: + |IL.opLOOP, IL.opENDLOOP: END; @@ -2206,9 +2075,9 @@ BEGIN END translate; -PROCEDURE prolog (code: CODE.CODES; pic: BOOLEAN; target, stack, dllinit, dllret: INTEGER); +PROCEDURE prolog (code: IL.CODES; pic: BOOLEAN; target, stack, dllinit, dllret: INTEGER); VAR - reg1, entry, tcount, dcount: INTEGER; + reg1, entry, dcount: INTEGER; BEGIN @@ -2221,7 +2090,7 @@ BEGIN OutByte3(0FFH, 75H, 16); // push dword[ebp+16] OutByte3(0FFH, 75H, 12); // push dword[ebp+12] OutByte3(0FFH, 75H, 8); // push dword[ebp+8] - CallRTL(pic, CODE._dllentry); + CallRTL(pic, IL._dllentry); test(eax); jcc(je, dllret) ELSIF target = mConst.Target_iObject THEN @@ -2229,7 +2098,7 @@ BEGIN END; IF target = mConst.Target_iKolibri THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Pic(reg1, BIN.IMPTAB, 0); push(reg1); // push IMPORT drop @@ -2243,7 +2112,7 @@ BEGIN END; IF pic THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Pic(reg1, BIN.PICCODE, entry); push(reg1); // push CODE drop @@ -2253,7 +2122,7 @@ BEGIN END; IF pic THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Pic(reg1, BIN.PICDATA, 0); push(reg1); // push _data drop @@ -2262,13 +2131,12 @@ BEGIN Reloc(BIN.RDATA, 0) END; - tcount := CHL.Length(code.types); dcount := CHL.Length(code.data); pushc(tcount); IF pic THEN - reg1 := REG.GetAnyReg(R); + reg1 := GetAnyReg(); Pic(reg1, BIN.PICDATA, tcount * 4 + dcount); push(reg1); // push _data + tcount * 4 + dcount drop @@ -2277,35 +2145,34 @@ BEGIN Reloc(BIN.RDATA, tcount * 4 + dcount) END; - CallRTL(pic, CODE._init) + CallRTL(pic, IL._init) END prolog; -PROCEDURE epilog (code: CODE.CODES; pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret: INTEGER); +PROCEDURE epilog (code: IL.CODES; pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret, sofinit: INTEGER); VAR - i, n: INTEGER; - exp: CODE.EXPORT_PROC; + exp: IL.EXPORT_PROC; path, name, ext: PATHS.PATH; - tcount, dcount: INTEGER; + dcount, i: INTEGER; PROCEDURE import (imp: LISTS.LIST); VAR - lib: CODE.IMPORT_LIB; - proc: CODE.IMPORT_PROC; + lib: IL.IMPORT_LIB; + proc: IL.IMPORT_PROC; BEGIN - lib := imp.first(CODE.IMPORT_LIB); + lib := imp.first(IL.IMPORT_LIB); WHILE lib # NIL DO BIN.Import(program, lib.name, 0); - proc := lib.procs.first(CODE.IMPORT_PROC); + proc := lib.procs.first(IL.IMPORT_PROC); WHILE proc # NIL DO BIN.Import(program, proc.name, proc.label); - proc := proc.next(CODE.IMPORT_PROC) + proc := proc.next(IL.IMPORT_PROC) END; - lib := lib.next(CODE.IMPORT_LIB) + lib := lib.next(IL.IMPORT_LIB) END END import; @@ -2315,7 +2182,7 @@ BEGIN IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iKolibri, mConst.Target_iELF32} THEN pushc(0); - CallRTL(pic, CODE._exit); + CallRTL(pic, IL._exit); ELSIF target = mConst.Target_iDLL THEN SetLabel(dllret); movrc(eax, 1); @@ -2324,11 +2191,15 @@ BEGIN ELSIF target = mConst.Target_iObject THEN movrc(eax, 1); OutByte(0C3H) // ret + ELSIF target = mConst.Target_iELFSO32 THEN + OutByte(0C3H); // ret + SetLabel(sofinit); + CallRTL(pic, IL._sofinit); + OutByte(0C3H) // ret END; fixup; - tcount := CHL.Length(code.types); dcount := CHL.Length(code.data); FOR i := 0 TO tcount - 1 DO @@ -2350,61 +2221,62 @@ BEGIN BIN.Export(program, "lib_init", dllinit); END; - exp := code.export.first(CODE.EXPORT_PROC); + exp := code.export.first(IL.EXPORT_PROC); WHILE exp # NIL DO BIN.Export(program, exp.name, exp.label); - exp := exp.next(CODE.EXPORT_PROC) + exp := exp.next(IL.EXPORT_PROC) END; import(code.import); - n := code.dmin - CHL.Length(code.data); - IF n > 0 THEN - INC(code.bss, n) - END; + code.bss := MAX(code.bss, MAX(code.dmin - CHL.Length(code.data), 4)); - BIN.SetParams(program, MAX(code.bss, 4), stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536)); + BIN.SetParams(program, code.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536)); END epilog; -PROCEDURE CodeGen* (code: CODE.CODES; outname: ARRAY OF CHAR; target, stack, base, ver: INTEGER; pic: BOOLEAN); +PROCEDURE CodeGen* (code: IL.CODES; outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); VAR - dllret, dllinit: INTEGER; + dllret, dllinit, sofinit: INTEGER; + opt: PROG.OPTIONS; BEGIN + tcount := CHL.Length(code.types); + opt := options; CodeList := LISTS.create(NIL); program := BIN.create(code.lcount); dllinit := NewLabel(); dllret := NewLabel(); + sofinit := NewLabel(); IF target = mConst.Target_iObject THEN - pic := FALSE + opt.pic := FALSE END; - IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, mConst.Target_iELF32} THEN - pic := TRUE + IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, mConst.Target_iELF32, mConst.Target_iELFSO32} THEN + opt.pic := TRUE END; - R := REG.Create(push, pop, mov, xchg, NIL, NIL, {eax, ecx, edx}, {}); + REG.Init(R, push, pop, mov, xchg, NIL, NIL, {eax, ecx, edx}, {}); - prolog(code, pic, target, stack, dllinit, dllret); - translate(code, pic, CHL.Length(code.types) * 4); - epilog(code, pic, outname, target, stack, ver, dllinit, dllret); + prolog(code, opt.pic, target, opt.stack, dllinit, dllret); + translate(code, opt.pic, tcount * 4); + epilog(code, opt.pic, outname, target, opt.stack, opt.version, dllinit, dllret, sofinit); BIN.fixup(program); IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN - PE32.write(program, outname, base, target = mConst.Target_iConsole, target = mConst.Target_iDLL, FALSE) + PE32.write(program, outname, opt.base, target = mConst.Target_iConsole, target = mConst.Target_iDLL, FALSE) ELSIF target = mConst.Target_iKolibri THEN KOS.write(program, outname) ELSIF target = mConst.Target_iObject THEN - MSCOFF.write(program, outname, ver) - ELSIF target = mConst.Target_iELF32 THEN - ELF.write(program, outname, FALSE) + MSCOFF.write(program, outname, opt.version) + ELSIF target IN {mConst.Target_iELF32, mConst.Target_iELFSO32} THEN + ELF.write(program, outname, sofinit, target = mConst.Target_iELFSO32, FALSE) END END CodeGen;