From 65c332bd368551d55286072add7cd11425674bd2 Mon Sep 17 00:00:00 2001 From: "Kirill Lipatov (Leency)" Date: Mon, 25 May 2020 20:48:33 +0000 Subject: [PATCH] oberon07: update to the latest version from https://github.com/AntKrotov/oberon-07-compiler git-svn-id: svn://kolibrios.org@7983 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/develop/oberon07/Compiler | Bin 0 -> 306680 bytes programs/develop/oberon07/Compiler.exe | Bin 0 -> 308736 bytes programs/develop/oberon07/Compiler.kex | Bin 64135 -> 268189 bytes programs/develop/oberon07/Docs/About1251.txt | 390 -- programs/develop/oberon07/Docs/About866.txt | 390 -- programs/develop/oberon07/Docs/KOSLib.txt | 566 +++ programs/develop/oberon07/Docs/KOSLib1251.txt | 566 --- programs/develop/oberon07/Docs/KOSLib866.txt | 566 --- programs/develop/oberon07/Docs/WinLib.txt | 312 ++ programs/develop/oberon07/Docs/x86.txt | 358 ++ programs/develop/oberon07/Docs/x86_64.txt | 346 ++ programs/develop/oberon07/GitHub.url | 2 + programs/develop/oberon07/LICENSE | 25 + .../develop/oberon07/Lib/KolibriOS/API.ob07 | 15 +- .../develop/oberon07/Lib/KolibriOS/Args.ob07 | 4 +- .../oberon07/Lib/KolibriOS/ColorDlg.ob07 | 4 +- .../oberon07/Lib/KolibriOS/Console.ob07 | 2 +- .../oberon07/Lib/KolibriOS/ConsoleLib.ob07 | 4 +- .../oberon07/Lib/KolibriOS/DateTime.ob07 | 4 +- .../develop/oberon07/Lib/KolibriOS/Debug.ob07 | 4 +- .../develop/oberon07/Lib/KolibriOS/File.ob07 | 4 +- .../develop/oberon07/Lib/KolibriOS/HOST.ob07 | 46 +- .../develop/oberon07/Lib/KolibriOS/In.ob07 | 2 +- .../oberon07/Lib/KolibriOS/KOSAPI.ob07 | 4 +- .../develop/oberon07/Lib/KolibriOS/Math.ob07 | 4 +- .../oberon07/Lib/KolibriOS/NetDevices.ob07 | 4 +- .../oberon07/Lib/KolibriOS/OpenDlg.ob07 | 4 +- .../develop/oberon07/Lib/KolibriOS/Out.ob07 | 4 +- .../develop/oberon07/Lib/KolibriOS/RTL.ob07 | 143 +- .../oberon07/Lib/KolibriOS/RasterWorks.ob07 | 4 +- .../develop/oberon07/Lib/KolibriOS/Read.ob07 | 4 +- .../oberon07/Lib/KolibriOS/UnixTime.ob07 | 128 +- .../oberon07/Lib/KolibriOS/Vector.ob07 | 4 +- .../develop/oberon07/Lib/KolibriOS/Write.ob07 | 4 +- .../oberon07/Lib/KolibriOS/kfonts.ob07 | 4 +- .../oberon07/Lib/KolibriOS/libimg.ob07 | 4 +- .../develop/oberon07/Lib/Linux32/API.ob07 | 30 +- .../develop/oberon07/Lib/Linux32/HOST.ob07 | 46 +- .../develop/oberon07/Lib/Linux32/LINAPI.ob07 | 14 +- .../develop/oberon07/Lib/Linux32/Libdl.ob07 | 65 + .../develop/oberon07/Lib/Linux32/Math.ob07 | 384 ++ .../develop/oberon07/Lib/Linux32/Out.ob07 | 277 ++ .../develop/oberon07/Lib/Linux32/RTL.ob07 | 143 +- .../develop/oberon07/Lib/Linux64/API.ob07 | 169 + .../develop/oberon07/Lib/Linux64/HOST.ob07 | 208 + .../develop/oberon07/Lib/Linux64/LINAPI.ob07 | 138 + .../develop/oberon07/Lib/Linux64/Libdl.ob07 | 65 + .../develop/oberon07/Lib/Linux64/Math.ob07 | 311 ++ .../develop/oberon07/Lib/Linux64/Out.ob07 | 276 ++ .../develop/oberon07/Lib/Linux64/RTL.ob07 | 516 +++ .../develop/oberon07/Lib/Windows32/API.ob07 | 64 +- .../develop/oberon07/Lib/Windows32/Args.ob07 | 101 + .../oberon07/Lib/Windows32/Console.ob07 | 100 + .../oberon07/Lib/Windows32/DateTime.ob07 | 174 + .../develop/oberon07/Lib/Windows32/File.ob07 | 142 + .../develop/oberon07/Lib/Windows32/HOST.ob07 | 46 +- .../develop/oberon07/Lib/Windows32/In.ob07 | 289 ++ .../develop/oberon07/Lib/Windows32/Math.ob07 | 384 ++ .../develop/oberon07/Lib/Windows32/Out.ob07 | 280 ++ .../develop/oberon07/Lib/Windows32/RTL.ob07 | 143 +- .../oberon07/Lib/Windows32/UnixTime.ob07 | 64 + .../develop/oberon07/Lib/Windows32/Utils.ob07 | 76 + .../oberon07/Lib/Windows32/WINAPI.ob07 | 241 ++ .../develop/oberon07/Lib/Windows64/API.ob07 | 130 + .../oberon07/Lib/Windows64/Console.ob07 | 100 + .../oberon07/Lib/Windows64/DateTime.ob07 | 174 + .../develop/oberon07/Lib/Windows64/HOST.ob07 | 371 ++ .../develop/oberon07/Lib/Windows64/In.ob07 | 295 ++ .../develop/oberon07/Lib/Windows64/Math.ob07 | 311 ++ .../develop/oberon07/Lib/Windows64/Out.ob07 | 308 ++ .../develop/oberon07/Lib/Windows64/RTL.ob07 | 516 +++ .../oberon07/Lib/Windows64/UnixTime.ob07 | 64 + .../oberon07/Lib/Windows64/WINAPI.ob07 | 170 + .../develop/oberon07/Samples/Dialogs.ob07 | 4 +- programs/develop/oberon07/Samples/HW.ob07 | 4 +- programs/develop/oberon07/Samples/HW_con.ob07 | 4 +- programs/develop/oberon07/Source/AMD64.ob07 | 732 ++-- programs/develop/oberon07/Source/ARITH.ob07 | 89 +- .../develop/oberon07/Source/AVLTREES.ob07 | 4 +- programs/develop/oberon07/Source/BIN.ob07 | 26 +- .../develop/oberon07/Source/CHUNKLISTS.ob07 | 10 +- .../develop/oberon07/Source/COLLECTIONS.ob07 | 4 +- programs/develop/oberon07/Source/CONSOLE.ob07 | 4 +- .../develop/oberon07/Source/CONSTANTS.ob07 | 49 - .../develop/oberon07/Source/Compiler.ob07 | 176 +- programs/develop/oberon07/Source/ELF.ob07 | 22 +- programs/develop/oberon07/Source/ERRORS.ob07 | 20 +- programs/develop/oberon07/Source/FILES.ob07 | 35 +- programs/develop/oberon07/Source/HEX.ob07 | 127 + programs/develop/oberon07/Source/IL.ob07 | 2394 +++++------ programs/develop/oberon07/Source/KOS.ob07 | 29 +- programs/develop/oberon07/Source/LISTS.ob07 | 4 +- programs/develop/oberon07/Source/MSCOFF.ob07 | 42 +- programs/develop/oberon07/Source/MSP430.ob07 | 3552 ++++++++--------- .../develop/oberon07/Source/MSP430RTL.ob07 | 1352 ++++--- programs/develop/oberon07/Source/PARS.ob07 | 105 +- programs/develop/oberon07/Source/PATHS.ob07 | 4 +- programs/develop/oberon07/Source/PE32.ob07 | 91 +- programs/develop/oberon07/Source/PROG.ob07 | 156 +- programs/develop/oberon07/Source/REG.ob07 | 4 +- programs/develop/oberon07/Source/SCAN.ob07 | 4 +- .../develop/oberon07/Source/STATEMENTS.ob07 | 241 +- programs/develop/oberon07/Source/STRINGS.ob07 | 41 +- programs/develop/oberon07/Source/TARGETS.ob07 | 116 + programs/develop/oberon07/Source/TEXTDRV.ob07 | 4 +- programs/develop/oberon07/Source/THUMB.ob07 | 2430 +++++++++++ programs/develop/oberon07/Source/UTILS.ob07 | 35 +- programs/develop/oberon07/Source/WRITER.ob07 | 4 +- programs/develop/oberon07/Source/X86.ob07 | 986 ++--- 109 files changed, 16414 insertions(+), 7600 deletions(-) create mode 100644 programs/develop/oberon07/Compiler create mode 100644 programs/develop/oberon07/Compiler.exe delete mode 100644 programs/develop/oberon07/Docs/About1251.txt delete mode 100644 programs/develop/oberon07/Docs/About866.txt create mode 100644 programs/develop/oberon07/Docs/KOSLib.txt delete mode 100644 programs/develop/oberon07/Docs/KOSLib1251.txt delete mode 100644 programs/develop/oberon07/Docs/KOSLib866.txt create mode 100644 programs/develop/oberon07/Docs/WinLib.txt create mode 100644 programs/develop/oberon07/Docs/x86.txt create mode 100644 programs/develop/oberon07/Docs/x86_64.txt create mode 100644 programs/develop/oberon07/GitHub.url create mode 100644 programs/develop/oberon07/LICENSE create mode 100644 programs/develop/oberon07/Lib/Linux32/Libdl.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux32/Math.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux32/Out.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/API.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/HOST.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/Libdl.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/Math.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/Out.ob07 create mode 100644 programs/develop/oberon07/Lib/Linux64/RTL.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/Args.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/Console.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/DateTime.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/File.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/In.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/Math.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/Out.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/UnixTime.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/Utils.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/API.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/Console.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/DateTime.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/HOST.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/In.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/Math.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/Out.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/RTL.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/UnixTime.ob07 create mode 100644 programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 delete mode 100644 programs/develop/oberon07/Source/CONSTANTS.ob07 create mode 100644 programs/develop/oberon07/Source/HEX.ob07 create mode 100644 programs/develop/oberon07/Source/TARGETS.ob07 create mode 100644 programs/develop/oberon07/Source/THUMB.ob07 diff --git a/programs/develop/oberon07/Compiler b/programs/develop/oberon07/Compiler new file mode 100644 index 0000000000000000000000000000000000000000..972db287b9855b3a78eeb1d4f86c06a591fdbf7d GIT binary patch literal 306680 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

iL*YZ6tRCf5y4gDMGzl&sLA^hLS`zBm z&Ycs;m~y;MP^GqK`$k`ox=<7#(g~O$o1MVaN{Q@ZmMG0x*+ywy3Sk%wnT;sR9gww% z1&No)>fhvJ(v1DkzcA`-m2KH|*`{%tO?8E;OM+7Zu4mXU1y;3{) z;&b&*Hn~~AC`f!n_CAJ38Q-6)wFOVRe}| z)}zW)>QNTAGo{g%F_ghj`jnI^LP}_>yM{AB)$>WtA-1@}d2!T^x}3q|=cN2K_Fx2M zW`E)EC`0~sxKP1EAVE%<2mA+{2d$tp@KM*qGD6MUh3*ko6T%AOv$vchrodZ(pBTEi zw5t4P$%MMui$j*}-SQlPE{5gd{Kv28W^X3+vFoF2-J~j}F6Q6Pd2;iNe=m{-GW-aZ z+vW+O$FR!NReR{igf(5}DThHMPk2m$_6IwRx})%Vhmq{IUXNZFrlzvZGFJ&l%6irf zSeD^nmYb_F%Ngk%tEcGUC!KLeQFgI(Fe=sk;ErVV`EP9Q@?}|iB}!TQ1|Haj*Bz##m#J2~VKt;X zkTmfft-4f;;li!##Kaho^81ENz&)BA&sqiNRn~%*rQZiNuSs@CElYpNmzEZ0AiOM7 zZG2wY)+;l!ab0D$Co{VRD-K2zBr|f#4F5Z?+^*%Hkdd58Q|MoqA8Hjo9JZHXCSWST zae}R1#j2EDdlEGSQP>K<-z@G)#Ta>lboR+3(H&%b@bV_lzTK1)@ny&zO_!pSshE(^b0aKuIk$FFC-k zMQ;%_!_Ay&WvAHERi~(`lCp*8MF>jf?vq7o20I&f;LUzU&dFhJU&Bw4oni8-Mp(F= z1*Q9qAwXZq>G)G1C!DX!1||g>g=z_&0yn5RcjL~OyugV5eb_&{6rjyBts>{3)CNgW z81p~kbQ;d;k*2x=ecf+e(!%UUsd3kfsfZXYaFe9;2F6{_Np7F|n~@##0=@E_66>oo z?naIYtOvw^o7tGT;U13ry3`#Juf34w?^xu(2TW9q^$$i_I_@uo^17kp5y<5NY?jN2 z8A|-3eAVzFs|4LYXE(TlVU-BYBG}n3kT0|oxHkXiY${k z>ivJAhKAGUsH#d-L(A1e&~DB50sdc55pdnne8u*+Q$2#!aO5i@WR3muK_rtU$Enj; zIGqgE8H@awNXkpj^!Eoztg&#q3n{0sG#TfrQ_;69W-UJu#odaiPLoghla4EWKF&CAu}v z{JG8o>vg%ab~0M>UCJah;zgCaQ*c_Bt7n6@*iE#LBG}s{I6APAirEc^LFnwt`~eg~ zctF(_B)GlRKiIH$?fbfzi2fh+Iq30W0CbOU2N$6`&n6aj#?_qXkXBcaxRn{dMh7Sm zcsN4ymQSKZ55Tt(e7gh2aZ@UrOx)1D;4m49oLkVARUWB((S2{crs#plmxG*4;SdX zKxF`sg=`?WnY1*2}f&_KRKNGZIEO}az^SD{$YB-x9w}zXIbJVrM znCkT@I3N^Aw6m)zAq9W^Xc*M~U`Ax?VELJY*0Px`t&*=*Pu z?9Eu}r0`PnyD)B?KUAkApIm7SXzu3cFb4c_G!k%~m)zY?QI_7LrTHOmyZf&r5WMXT zI*@&2fF97?*T0`h8<&#LF!8?r)d;R^yo3zu{k4nF4mp|ZpTkt9bR7;WrT#ID0goZE zQolkIV;<$pun3kD!!&NGUxr|gfO(d~C^LhHBG}crfkewy}tS!~#O{Zk)r);l6CBU)HJ_kNHZl>AxcuR8*Q4 zJJ^_8E&EAC3Q7NQ4WfdB$8K)7@EFT&$(`h1L?jy*jGBy(LV|||u#wi( zP;v4O7rroaO^ODZ4JbD?IMDF{)rEdvLIX3xb;2O>RR7=FL{sWeL5MPpJi~v3k)eq> zI7nCR|BX@Fjs&4K{$DjUk;oc!BTiOl`VBf#8zncRKllrEl;~(ix^w(Pb)-?#2+>-9 zcSeE_v&NX0to64;5bRFWRMh%|5o}C_1OE39uB8Zu7F4!Iwxw$Bk~h!jC&f!@MH+~O z)|?0~^n?iUl&&XYSt}7$Y9uC|jID)_hMs7*p~hQUYuzku8eIE|sk!Fd9v1i>ft{W2 zrJ$e8Rr6LOgPn}?{W1ik_JlhQ*1+(Ur~`i+urtf`zv)+A4Inrd=eQtoEpeY1E0<0ak> zFnS%(Nc@$Qcv8?&ntt5Ob_2rrdoEgNsz3%*YB9{UXp0?&&{CTb6VI~`Ss{!`jM zt2VUTXeW)b{iu*LJ76pq6LqPr%u8N!f1h&$@y1fb%LallDQdHjDe{sB$qtK-MaAk4 zWX1tV5OFh7cPuJW7vo2^h*g}AeT{naXox%1KiA-R#Kj?SsDGS96stotfeEV?cPnqe zfPa;ndLQzrcl=r6ESP2ENPk-b8cT~@BaoLoN*|GEET!i!o;<_ap+R>0AxI!9tw+tX z{nvC9R|@D7?FF7NbWmgPgWUA;fV1V#VK2a9;p*)<$E8m7+m^FfVuHkPp%JdO(^YyA|u zdPY8g$WS=7vJeg7$XbcaD0wV9hs@_P#}8Sc`t&bymw@DCM$gv@y&|=m0F1eLe}IYq zBb)cRCcf3luOJ~&#~{kohn~b5LWY@Tz7Vl?J=9FIG9&bN;EfYyAYo;X(u~#Sr35{; zyMF-Y{u=V~CCmv%@tkwxd_7d$M7+z0^&r%ah<3{C5V_2xL~nEsizGIm<5;SG5360Ns- z!8Q<`^xocbjzgtf@(w{fL`V%iaE>P9N`>XxEN0TRpg`l4kVXXS=E)hmAA+j=nL5}GW`?^ZW9gNa4p9EC6ptOT={wYur@k_mrmmkgM8J=Tt*J5S+BCxi(_ zvoERE?n^>p&{D2=7sY~D`hp{HMaMlHE_us&XbVERy&n%)blNVq*uRT5T(7uu`T>pz zrXLpjmmzqT?0f~q2AO2zEVU|s3bo09b(JIED*yg1Ol4wk)p?JJ4>4htw3f74(Nr9i z(6n)>lG{*NMtVB_P9PAnTf_6!BED1fHgB=NtqYPLLB*Pk@n9C^RMrZ!ws4t?{1p5s`6tkQZTd2VI$W3$ZCxy`pRC+Z}MggC|E@#wXK|*5K9XQq4 z2BzAr{nLtRfWj>{ z+~LIP%0>ZFgYc5ZQfUqnwuO43d~rkJD!uX&gsuC*46(^>nj93wF7(x>XF2?H_lqu5 z$l_Kmi!j7paK+gIDV}XJE7(ty%cvq|F!MM-{#h7xI?U8eK{6^Vr{Srv%fKuoT0=|4 za4yI*e1QqKlF>Xsl{wIMHNG?hC?b@Jg+Sxc_|Y{qtVJ2>)4Q1akfiT`8LBM$+MC7Y zZUo?T3~yB$U3+|;TtY@uYap{jNEIMEgGwgkh!DbCmByG`mE4Su4j~1J7b%~kI4W(< z&FK?t%kFW4W7tDG85(slyJQXN{@Gj7MU1)a(c)`XQkv!hmB46X<{WzX&AiC5AM90X z9{5Q{nBr&`$2LKPzZ>PZ3(FbVv$Ij}bNB>c{~Qc$17ouFn^M!>aw<=9XE0yK{8$cq ztWL(5s+^7_%);E{E&vTi387}tExmbnqi)QK^tm&?Q)8Bx7-DQ={yOgM+?tWcN7_!x z2BM9D!Oan(G-VyK%3<|AoT%fCB2;`Wg%wt>aq}DGrt)~ z+Nlr{GZ8V7LQogmzxJR-QHjZsHAt*j#5(r)&SHf_`89_R0CCS$Mv;w6l~FJ`mGW4) z1qeD_R-;q1@n@jr3`j!+JvuZ!HST6CBREMhGm>JLFhw<+S4JMcP+mJmQrJA;KyaZ- zcBZj>#{l5Gd-R*G=_tIt-O}RY8}P*Nq9ULc&g!CoxM9V=E8FdOi4Q zgC4K%+ACOepX(L08Lwcyw*GCA8l&aZYde^sL8~o4)@{jMm6~^1NVgSsIO9cAwqnwZ z1_(`At4*rh_Rtn-9H|>ZvDVC|he)AU@0uI~GVEH+`B>eMmu8q|HZNH4QOTXVLQm@& z?NnsVc&1B(1q?Xo)8hEE?hI)3*=zg`LI*>E`(tv{!zk_kV5X=TsW|^cNupbzbur#l zU^+t(O=#C3nRVjmy3n|ip?G`i>2Rkn)$n;o#mt&g!vs*rSJLDG9=&2f!k5SftN0Vu&f#UI-!apB@T?&axhq+MVS*?(-`$ z*aEBc81b);hm`|g$Ps{l2Qv-{hh(e_LUHdJmY|%=CH%M45bi91!yKxiWw%tre1@YE zBZoeWadMdabzzQ_f#`1&CIl(xQ{|Gn5%jAuimZ4JYONhUE3i|tQc3o>h#JDiTe~ei2f3jLxn;Nrw4JaTy#b<8hDo7VXiYfN5pHwzmajlohAvu@ z?C1?7TXPf>bPk?s5`Yx8e8@T7c5Vg1DO${qe!oedrd>`eJK{@wnl^r?v6F^%$L#x~ z0JStD1rfhJ%5sgfUK19ix(g|I%ju_Wv2dIW$taw|leLiEit|Duw!l>?51vjH34}ra zhGQaEmf-MfY3-r5JijWV3n`;)Y|X+56L(Jx$NV)&Ojy-fMjQ%?&WdYi%(u)C(g27d z#4TF*#o@)yCV;lycF>^-pn^`p;*+Gdr@QU(DMlXQM)C-9mFkNi3tl*n@uHM)r~KbI}@bE&Z` zW>W(y%xkGP)fOP$42v9){D&6C-(!rJHSzL1*asi6kcsIJu|SmG&E^U?l< zm5$1y)JLg_NLpOGOC5L0pv|=n>y)5dGyx92vx>*yUNefoiUu8!Ig)^yEb&XJ{~X}V zuA_DrbIwXK;GJj(aU2$I4)@2R%LI6|*R(C3yq2x_o|#BiOPxeN=^S?Unm)mk*YZB! zGZUT3QM;4qIh|;X*EAQUs_UhB#zt=)KGkdD^sLvy>jH&e%+NvHI65>9cMkK^|GS9s zx5uV3?hZWQuSV7M{D-~Au`+UxBa7XM%zGrW3EP55rsGyt2@SOE`~4xBp$f05l8hei zl#JWqs?aiB_!m?Sp7m*ZOZb0PtBMsnle`0$+fBm02}us|nhs z)hxitE-odxl9!F6m{F1ep$Neh%G|b8w>edaH>}4+9Wv9s z7ujXL&cnRGMnmG1sz%F^JPp#2|pP~m?wm_+T&d7G`6~Gegp(8$KVTA=Rvvn z9IB|(vQrbJ;zri#RZr~&kbRskuo~^c3lf*I65qr~;lEX)UY$Y4#^a`dO2BF?MJ?OM zYuXi*a4!)4%3g|MdPP6copZ!B0I@*t;5Bib$7}f!B?-|l0*&H!o@4Oe1`g>aVQKjf zCSPm}MYc5+VRGKx;$#NgSUoFMvttNap!2}?D4H$@jy`Sc5Z0FA!5^g=*w<_F&Sp-7#^iPzyRQddJp({)T%bai^eOOD{-t1E+o&@`~Ogh4U6`R*pp~&Z^d@ zCtybbA8_8idEif9lg10Ydm37b02+^F z(&$MVPrn_Zv6=&%)oK)4fIp%Lyfo*k-MRgy>W1IG{RYlaA4L51#nKmyYtsEu^(~^^HwOxdha5H6i(E^mV5S6n1 z4>?#U@258{F7U7a1tUag8mJ^F5Vh-N$eDXo>34E_)h$5q*H7obI>q?-v3XQ?Z=}5$ z_&VOH65_Z)9LxVmrD)E56ya5gQjksdP}^KV!nuFZY1s(!k_+W93HLq&gGPpu60^j` zoT?9#;G|OobEJz|F{n08sKq?J=E96F=Z zyhJDY(Ilz$MKs2ECm`#;B_em{)g2crHUZR1ha&@eU=_&PDr5@Ms*!0BumEkkX0*#Ri zL&@F@)SDrndIEgX%U;T2fZyr?5)jlemZLgSb^H{By*dfox{E1DXproy0frtOPuN@sCEF%n4N+jP7(}U5Ac_rmOb{>tdj^Z=_>#f4MiK7a6vz1_W`rA+ z+nrBXx$$mH|40JEqmE8CunK`RI?!@V3W9l?epXlMH$q*QzM@ll$UNq6 zre`D8fER(Rc*MNQq9(WDIAQ`Fd|w3slI!i1!zQmDk>om*jM=DjbEv5i5?pVDlNt#V z=?4wwbu#r3rfQ)D`nW+I%*;;kMtC$#)LOla4P;c;F4X)}R5ICHh^(Wv1NoMDD_#Nl z&N6=3q#7TlvNCbj<8dOul+-S{Z-I#u3^^aamI;%q8fbW*V9Jua<+2PlWd7oiS(n*F zpoQ2Zi_r{NlS<2I!>lw+IZ)zGLpOI^Efr&qZs5AW_sd9*im=IXvXRXiqn(;jy4%s! zIF@ZUm~4Qx(7jW|8_*V+y&x<|?D(0o?CM12I4OTS^8J3W0em?5QS`%y9sG}8~?-n~=D{tTe zQFnQ7gXx2KX^PM7HdGTH0-{{PA%R{j6ss%9z6Qy&L{VfHwvYFFliN4(Yq`ZPPybK^ z3s(WVE9j08di^tq%23)2v9fhwHdpWG%gXG#x`R+^k7y;);2ENDj=Iub_4d0Un$Zi< z01G-$;_fxSXRj#NDCrKYgpI)Tia1KjhO#D>XY*@Z%6QY)NqebZRl@#G_ilDBN_sbE zODU>^{F)jnV+~!+?Hyrn$9p0vu2Z=@C>8+o^)=fgQ5rgxg{zD$Iqs^(Ok`P_<`&v$ zz$0sTrhwpVZfvULCQg$iHN=8S^lCfV(KPTt#@Zt_FW)6FydFtjKgZE9@@jQt`B(}v z;<=eQe(R)+VpBnJ?#C|_r9^vYv|O>&Y2a}euc-+9*JX4}yiU@;mNJ*+yrsw-%X#<< z9-aPcE5fQZ3=4QUc=B3~BJw@EO}rl_Y+tU#B>pKAZzNXzIPM2njcy*BQ9&a$(ki%J`TBCsethK-^eps5~(?XVd-SIkVg1_Em5)(-Jn_))EB zhT9R6qajCoP4`Q^eA)@NJz?)KSmx1uVgD}(j8fZyutzlv6KH=CYJcuTZ8%{q8aBym zI#*y+t|+w~NgpC2I|hu2My z5-vg7)PbNnr*`kU@zJ=EjN27)i_whGJD?eL@^p75rXVp7Qt{K+m|~}v+;QJVMy^35 zZ33NL+c~leuTm%9gBbMEeJSa%BuU8TY`r{}1G1a0Bk{ z8n+Fq-oMh~Al&Uk_apSYcM1cm#pjKTa+%*d=sWyFNT)gXt4~lMxI*c0f-S}J9*<8H za$_m_6$-d(LPx;2^67jDK6e6Qdc94z<2U4Ms!Sq)w&(3v-tnK=ykIjccqh z5NR0qA_XP5J>rdOnf##LI>dNDSQ#EF2=gvm*Eo(pMyprgLGe9Q&EjwvkmoJ`H``1& zxCcE>yvXNVW3a+@2A3Qyg2@RdPB^*xG6k*o0~R8cob1I{nqh4HGqFvE$Imq@l0!JP zCN5TU?i(Lzsao%dE|8g)<+l7M5KXF~+KeRSQJ}0RfUq4oomz)6N*m_X)G+;(qCx7< zOTm>(vpzkrt_%bdB#4jVVKOR>>-Ps?mUav&zJ+Zgn1$jEreR(Z(~20$D@*cv07UwM zNH9lt)*q2obM7x6LR~PgFP{1DNb)T1M1iV-vH6CvEY*#SHRrB((Yq5}PINHef@&u0 z4i~luVcTn%C{i%@_eU4DCt*Kf4+f|?Q+uFxJYmK>HRrxE6op9sPK{&#+?@NoyzZ{H z*RLz(br02Fzdj>emVK zx}R*80(i8%?ysik*zM(Ysy?NLqaE^ErgqS=p1dBQ2I$vr^7?y~t6#q#Lea&Qd;zaH zw_RS#)hBF6&ABOgJy3DJ2d^K<>p^Ore%&Om73xX-`ii_(DxT*9c%8f+tp2QDpO)7{ zRI`44NM5THzkCPq9rAjpI#s{kD6i8Lk9Q;Xa(O*W9m-d~TvKW~@1-86`Kh!4K7uzl)J?Dv9@yyOmY!=pV! zXfLT5?#ot1+G?Y-HfBeCF+NszO^kmF?YPc2FS(Qc>}VtQ`G63c*j ziO5Ut>7M~yz~y*9!B-Z-erLj4{+bliiZU-bQEna7+a%yR+7eFEw+>pVNp<8U_wlzP z#ZaCYvRjEx*6Rf#6ZsHEUUIVk36wpMi6K(zzsx2;wnVn2{z|?_imqe!_ix)m%v8Tw z$JmPH;Crnz91T6QykwO>TQWrVDH$H>SLk={Q%2=Z^Cv~#r~6~&o!4uiD`9s6zhWW# zNZUK{w#J?S*|GtHsA65iv;20n5=2Q28wW~99pS$giDD;dQXT2DIU9nho^pFZq52oX zoPJd*9X&5sLYQSGzP}{RCNFuSf2Lr~Yr;QKUX9Qf__N&Cll)4)N@ca;`z|ctd`J*C z=4wV4`dooGWdI=1^Hcr)Is&R6X@QG;t`}H=$Op1Csnh)Tb%bofJ~mL8GyHW3ca#Y+ zL940u@9vsfjeluKO*oeCu;eAr^v_`gnTo72pp~>kU=SAfWmgvI(qbie8CrtBAJP~R znwu@gx*^Mn*&ZRf72(61BHn@o_iy<%F{l`sxxEL;qq<>q z(_EX`O!C2`Tj&!;s#_Er6y>s}nWQ*wLm-QrSc(G}2$##&AchaP#m3e$`viXnfyiAu zskbPDaMCNV!EBCbifl*7?tUgym><;=!^ibFNbq0hjH$)Ql^tt|adLOG#R@1q(lRt) z>k(3GlC=5?ppNJ9(QPnI&YUZU!Av3CT6_bgG}&AAJDbCBSg}IQ-avN#JJkJOI)Cit0c)p#%I`@9i`3s@`#L9K&%kbY1W%CQ zZ1t`Lm#En~c(??2Q){@{y*al?UVEy?`RWWfZr9N{65U%piNw5x%g)xT+SG3lSs^eYGPfA>gn#nARF#yb}?Jp7Q zB%-g{ml1i%t^F_2Z`y@r?EWZ#gn5uzC;^$!UyQTyoNTnX-`ZbvXU9qV7y169RMLQT&Ua>nKF_zQiwAESvluv4a0CHt#K z&VWaE7h|{9M+vPFA+2xvYrYEA5F-0)WOs+J_YGoz`ss8azVd|gJg=z@PhQJgeAi`s zA)xg#k!v(E-)lOW&Rc!Dm-%#`M&D!5ebvoGU#-!-y`~FJLPos*wX7 z9-9rKpPETTrABP!HBAy)dxo@X403=PP2>(5ImnUSi3YKw>PbYFMihBX?R{9@Px053 z_c(*>t=>Nk$Tt{MpWfQxtI{AwsDBXgh(-+dnr;zV*N3#q16r38*{G4*cuh}2kq@B)@$O&#=MpTLz;aJajs0|M$IAeFpb0%FLf@WZx;tNe@EmHqW{}R$X+aUX?tBGvU$UPkX5(d#*okhec8nLI>G+SsL9@09YI~*@G*gnnlJU5HsZ-^ z*}!*Q);}9$Z?%rde`w?shp+Pk#BD@erxE*kO-(}UypUGXAP1?%M4q9M`*)#lGYztj zI*iD2jl}WD@j`RAkmhrJbiMXbBZ(ZQk!22lTN_%VRUQ%l;rvs5`T(!#Gdy97Ki_p( zw>8Lt>YXHzuW01&9l3c1(OW%51V8@`T5+%GMxk|0Nb74)^EFugiOBOcvfSb8Q-kQO zP9@?5jX2P2nl7{s4r#q;kb_hikrOrYAg^gFj3FcT?a6@VHbnN-NSxy24g~D7?;e!3 zPjAiN5cSmpAU|PDeY(=&?_5Kxk9vuSXEowrujyetc`f&bwB`o<-Ad%O8hMB#x9JAa zQ`Hmk2aTxmni4|mxRBO(!&g6b1d)emnTrsQd9^j9C?20H&u>`sF;rh83m@#M9v;=9(7+YQYD>Iow6)5sYPf7ckq zw(3eEnl<8Zuc=mOof*<L4QUIdbwf%WE1dwD7SP%hzcE zt?h^$q>)EBe9bk8KC0tHAim8JT1R?Kn3YEv-{re5Is_&3y^FtnV9SAI0fj|2@Xw(}oUTFB-%^wT6hN zHR3q0>29I**O1oZ202t+N93g%d3+c8cDF(HS7#8pKqKdQO|yjNw2*%|I}tHNBj$Tey@XcxkXEfhdg?zX0Qn95qWbiSj@)j9q}WRiR-1@;StAl& zQ!AdlmM23`YH~p90U~eH$OR5xqYPrSY9V5UMkKwaYN53-q&3DMhpH2ZJW3-^vierS z87y5}I~e3PY9f*2H1cGxsaR+Z4rvZB$Q@K)BJ(uz6o@~e zdz##?&eD?YrA`7uPVS$}Q`#o_FNQ#GRl(>o@LXHF2^(-U{fmR>(TwKi$;Gu>2hmGR zbbr-{(fk(nt)FA?j>J{TD)pWmn#er~D1PVnzDs4|1Cw!j<+&Bn_*D4Da}dm_F+BsM zE@LWZzUXQVdjK#yeWn&=V5V!*C7iG4Zs@7{eLUXB@_mM;af;9w8{=Ixj12w!o~EG5l0{XPrtReb*ncoe6HU?hD`;3zvH@ zF={isn&1A-HhsekmRIU>l3Sq z`@$GczQ|sRx1C9EOvgv}Yjg_|?rRfn+jT+`A8avcXb(TeRHX83&_@VzOIrkiocN4v z*QiqbI6F!*6YpF|9f>7^VBK&@p}skp$GNa2H=X*#VHiZVCy_M}DD*dM!s?+vh51pM zPrw$4_UQSI+_SKmr%K%d&*-;mk2!TCcQoZB_elMNHIF*R%KM(F2gw6I>}^**ah9sh zTs*|BU&2 zHPqnB{AUq}B`Vm>IYm5920V_FmHAIIeb!rO=Lpe3oEG2)W@@QD3(wUbNDKR?@{))6 z)y%<&h-=RC^!tC4W?piJzYn0cTS}HSqZmS7OZgyygOK86?(^<0i?#lE#3@S9` zSw6Sb1e7ymI$OT>7nSK8|7xU&$aIeXM+5<8DsirVCf{*tmqvgaptLyW`rKM$H|T{c zR3bf5C|;1gr>14zlm5<{7S9ceo=pgtPx^xqXP8eTf9e&K=wx5E((n^DS?nE{ea$3z z3TbS!!gI1v70wZcO@f8~vs?q`7j2M0H$gEog=*G2VxVXSQ5f^3iPQbd^~yK(1!0?z z>FGW<#8ft3OB$gHo$jB*U{{4sm#-=4J@AHsGyJIz1MWArYW$rU!_`#;yE1d7w#3gN zNrhwLen<#c$jUgW_37^j2dFx7K!f|Z^Sk|`QYMvKcdwKmotg?63XgQ z7V~K!!eW|SxnCFDm>XG(C@6hxsqFov5Q5%ITLmlx-$ZJ2LCvc1=@`gRT}@OKqB1nO zda+gMg2c^CUJMMsvIiYCx^5!!5W(igukvNdA%)XqNmw_Cg2XLMy_t*Gj$!=@V+YNE zM8AY+%Yc6ljc`=ipl)nHSU>jEh9eM<>$wlizSr*LhiWpzZL5xX3 zVl{)f_6`ncjr*A1S^Bog=yvt>b_TtcXnyz!`Co|HCiM>tJT%`DbseIN#Mn^U5%uf+ zT&Y2!&groFRpdn1h|r%K(3j|aT>7-k*M#Zmb^5)S-s$iP66+cK0}ic;ea@CX&xF2* zP=JG8uOP93;C~|6?f6RNssV{wi70#3Kt{_pon1lVZPHk-NgJ`f!=Tf2(0>;)2dnt;K~7g#Dgu_MV-OX5T>(}@yWF8&FGze#3Oj0|M!erMXe&*WeWGa2 zjzOU$x*MWRq0->pv`x+v_;2H6BDQN6#j>Sm1UEI4ZO@n;OZHRW!JiJ(z!Sn3Uzvst z6lo%z>>ERK)mQB>Lz}BF-Ud2it~?T1_isbQ_}<1`i8R!7#0BQ6AK}*! zo*@k}SEFA;gf>^4##R^4#k(lNK&D%Wbh=WExx)S=IM-$u*vPOYK7RJ-skk31qfszzC4_E|R-O&xUj(V6)k=1mMG?;7R^Lnc!m018+PT83penooa+KFLMFI;{pEp zQKwiO9DD_zB?2zN@H1Jg-m9We%Sw@EZ8Xhf?cRsds9zP=Y3|Z#;z)B@G)<}BkeN?H zr#TC0=Bz4}$(YEAPwI1hx{q@i?|!J)NkSKA5$b>JgQ3Pj;^J2>*ua{hi;VB#;PiDd z-{e+FR3^vkn4eLP9VUv!Tg-7>;RY1W%>dpB?T>gTa7g&5fL==CReCIWSr$Vj@@Z+QS>2eiE z1YZpNH32?9il5>C2mW3JPgOoWz;ApwQryG+7o&K{82AH$*H!rN!4Pb7?oH8TGyN+v zlTk5#7bIJ(lO?0cX8Ch7lO>RB+aTEiI@#){WbOc!Jpz>tP3iLHrGYs}XREb2cVUny z3o6oeB38V1lacLnOklL4Id@Euyo7uBwv^{3kwgVL5&WiZAXtkxwnoe_>TrZD(qWj; z5yjIEBoNTD@Y~0smi4Pjp_=SP zIr|<)Zq$)g(a0j~31>%))Q@Svtn!9e&|PkKdR~HVU23^;O+puq?nUmQn|om-29}3m zV}=<@h_BUO+jc8V8}AzquES;smjiD0m5-ca7nPg+RA&GE;Wqo8^g4K=q;vLt z7npYZwLN@;+5ZbY5yvqMV&tTeuNKq!4$jx+Z zIcb_PZ2$|cR>ONhoT4bujp6H8>le#?zj)!?wwdMN9g#k79ke6&V3tE-)*z-zVVEIP z9H|FkfaoAfH|mag!SQYAq~Ytef*`X9&+_fVERrB({da!5U;$FpAO*{~jV%V}0fYP} zGuiJYe;x%w&YLJ!*Mf`RrZ5$|I-`a-b&hu)7 zLOZHWL8lp~ATrFhtoNEv081b+?mf{~_Dd^xVHAQ62x+oHDPR!BsNg7;qK7U;Ror_F zIk$175Xw>zKf%`H>vxbSi2Z;L*f1C+Hk-u$1}H?LiLFfYTjd;JATNo2Kq&DzkX{6B z&i&)Nnq6+2ULiN$H0NHir7VtS7DsF`3yD5hvhYzTFk7)DN^?ocb17w(To748j3@ih z-FB2I|3a-$7a{~TSI=DN7-nenYY%CS#x63e(U1a!u!z}Sg$~844L=aKg2NIpdjnEY zPs+ZLTJEGL1DPA0QGyS|rc+M;!@&I>EI|D;YVHrrY6`NdQg5Raf{9efIRtRFt4ciu zKx!ta{`>8qHVoNFl3FJD9Gyv(y1>%R%y%&{>jX28WZ{6Qqws*A={gOY;X@DVW+)QU z%}`6Ip2^Qda<>_-0Gbw}lRQ@t9S7RVvvV^P3yK-?U=Vl_)8rrxD3;=03z_m=Zw_1) zBw85#5hi_bEhHzMO~@+!O_xH-23uZR&vm4P3V>yDH6WcY7#mPya;NWVIi!#3$xCHgrtcZBr%7ErUM*_`{* z{W|+kk&mU0H3gP*GeFjmcQIxr*7VjTP7fwG{oo+N{uz2ZCw9c3$S zZaDFWk@LpVk^nBDJv6*n;9OQ{k6_i?sBfVN|V-DnW-!uf#<0n-~7EHr28;H;jan@$#7&d@Reo zjn-SvPkewvI+cLU-<;m-}YSj)5KPR)^>pi2iGcMlEB573t%yl-iMA3%`yW!v9J5Ss@(FvcvyE zOBm->9%MOM%%?F-30`E9sbLbd6F9dz3AVo7CP{AMJI$ih!oQfLZTC;oJ$B4LM}V0VtS}i>QH1*R9l1%)*y>H{N#6BmU$Ib z>2p&TVh3R>8=i1mwlT&)N9%wukw`*!_Yf~pB=){5w z##HZo9TYyrR4WNtmZs`p!=|KSb%m+qMwr{eREnt@3E@VobL;-V>iUM&wIe&nY6Krr zJFm`T@Yf9P!{9jxuBxr9JBYzwG5C9EOzHq+{YS~V5M;fU)A5&xPl4T6q1IgpVWPB`Cb1^aUy18B)sc zf|46H5lK13FsqecGWkhJj@8PNa`Pc6o@q88fT=>1G0yrXH5Na70x`1M!5hoDPKmCh z@=o?ZMe4|vES*fj?u{T=_tbU(0rAZ%V%DqFvN;0b)Y%{ni8yr%)nLbd7zEinQ@BUc ze;n_;`){96H?O- zj>AHKX0%6y1t$|;8t)I%vC`w|#VK>;%Rt8dfHrExs#zFhS@;jEldzzBLdX<%L4O8| zZihGsNzi_(H=Mv^R)YPNTFo#SN26G)Z%45(#HO>=ocjph8cXrE){eAEJWKUMjauRg zmBwv87XZxLaiAS$hP@X&>4{|hV6bjnFHoIJs>@n65aY=D9|@d9;En*&nd%s;nw>24 zR-wTz^G;hnh$%P0B!Sg@)M_GzM@6h zVl?ptW-&l#j~N(zY+Dp%hn&I)&K7BXMjUi=;9-h)u=2RIfzej_6q& zT{I7Dy+tf9MesJHht0)9)LE<=RD+prQ#lZGR7w8HOb*wX@B;xCqV%ly&<4Lq#O^@A zh#3>-7{Grqb}Jn_mM(wLE?#2H&)6kOyM+6Z!5E}97+iwiDix!f)SO$O-yL0%nKm|K zxvZ64Up2nc$0|-d%Bne-y<(vW;SL-%$qk`1pms(Gh~IOwWM;RrP+7mwF_+pHGnaIZ zsz8k+$vGxM8&>pbsja|4?WDTBsWVL^zMRtC0}U#x_QSef2u{vaix{>Y!m_n%P?&g= z&?6X(?}||rxfBJvhvtC;kqM>(aaX?7>8Sk>BX#-{fv@^zDl-gv1VIpE$&@228nCdc z`wI{&!i6;$6g4q3uSM>U)}JmIh@rfCb&92%4foftjnI{#IS4`rE?X`XZz!>!bjqr| z4IfZ|tL?!4{{wkWZQtd%jiAkm9C?gH}GSWruv2{;;xW(|NVg2@55+cNDZ zpSU8BptT612)KVm4RXkk_RS2;b^=}6A56BAC?V~}2yF>E+0cHOWS&BC0~TSxrLDpJ zEKIa8`p=X`Z@$tKSG=LbmXd8$(2?4m7i2$y+4qWMFF~JwtcylXRg*}6vdjMt0fC7m z@B+}GdPvaSh5(1G>L>V5mLsvTPv0Qz-B`FnpBsDFPQ9l2poe3L_!}CiIP*9P1jYF3 zfng0l_GUWva>h?&ydDWn0X3h!LkKyLkfM+TN3b=;Vf;aiPk$7Ucoy*~ep%OKQNj3) zjMrUsH#c!5BcBQrquWIXoSdz0!t{cFJxm4djn_07GWA;i8DZ=&rmeGtJC|)bRn71r1q!&*7|k565OV$o@dw?)_d)+x*o|=^#lX>vAO)( zJ^=9mi@KFz1&Onn$wQl?_KQA0&Sbnt++yPLl2cVR9?-A<&QpIpBUh} zZ4D$DcSt5U)undV>5t1ye`sdQfAs_BDe!#=Hz|i_TZKvC475MfOO9Ct z+lO^}+2^Sq)g(T=#^IhMUSWXd9whGRngmR@s?h{)b_uZfmxKf$HGIYQ4zgeVekf6- zraR25p43|y;aW=@_-DNmmou(EazKq-#^*dd+d5D1*q!>81XuOcJ`6hmVbk#0-d>3(7&ek&oP9h6vyZ(Je`DA{hEYe)79IUN z!?GAwka&qD@>n9<3b=-xsstEcCB6Vi+=Pz5lrq2BroO@;GPM}d6}6id_eW|w? z%n#We!keHOd;`&|8O-mcPOJT=MnB2myBRzl!Kc)g=-{Urd^v;Zpq{NA)S|>c7`%kR z*a1sc=e?Iv$z8L0BhwwgbP-l>V(=ISM_By}gNqm(VU_dADvQCLS^X44)-G6mg~0_0 zpR7LdZpbPfl>12TK>)0%u^Lu{;zY+fxIr50-AHPT=YB|q5596e#~MEz9>m(VhK&E( z>uUz&^RA@6VbpRUd>W|pbiP|_!uGho0Avt|_BdpvRmdd;i5!w_e}~Kj_E5YPFHB-*KGqiZDa=)yCk56d{G=vFbjK?>PC<(F!*1MIx@n!{%{h)|`7C zsRYgDtX9jV+0|!-M_R|I;|(nkIw3;H!a%UXVN0y)#4raMK+*W-@@i&3ycJ?EjuSzlI)WRv=#0z^1M#Y&c)Lmbc8Y8}gY zKv3o(2{T1Efw70{SdL%yD7E@>Q{P9zze(Y=UNL2InA(7Wu8cg3lGD|*95u5B^g#(A z&^D8K>K=q!W66q^6FbNT7rh)kQrAzI|G~`v^-b;!r!%@fgt3q7*kTNM^w(=Pj35^r zP5<*UP81cZv+gjg*xlEnVD};xj%5jI0&~1alGe%p4{7fKSXHsL4X2V2$_~{a0-=bZ zX|RF{Mi5ODG-5*(EGWj~Rih+=8VE5#L{2=|xfVdYDvBal02_v)G)wFeQ6ebJ_E=)& zh=u=o*39g^PYB-oy}$2!!#=Cenl)|B?AefoRKm)1w3io;0F#dz2b9dV{UlQ0O@O2Q z3b}xSdV-o2f(<)1D`pN0^ViFV%Ipcxk62g)!3jR=g=AG*gq1JHi5&wxI|Tg^(AExj z5=v^>uM4;`OSQ`pOdt#{q43$@X0q6G)?)|D-uQ}VWs}s@`lTejn55oa+}fcx-%W?+ zsNRcE?{J>&7bcS7FdFWCKnyMwXeU5X6j^a!dN?S=rGm-;$`pmWj}1UIaw$O&bOpuN zehOxNV%E46-(in;=`Ad@aj9V~BI~`Hl`a)KwhXj(2>KSFtsT~-V$2K<8E|U@UTuLK zOw3+IY{68_bVtZ~qy%%zEE_M8r$E)@;x_I5__BQ+V9*Ux&(T?Kqb}E zUdMW5j*j((5P`3B>3pq!wn|-jlI#!UzTA?-hZ?JY_R&9~lY2S+%r6{4#gpBKsZMRj zU$ZHcbN;sY=5KXsnx<$5XJCsJd6!}3c>p)OB#h{h666EgN%(*^GxT*D4sb%W2gD>p z4B<5fju^po039{<#6E@-s#8}*(BCmvS~R^Ig1Mvmp{KwfCtU9_z#9*f<1%uX6CU23 z@zXSarpN!R=AWqfGj&@MAwGTgL9A_;ShaCfQc0q6&fI~H~hXyk80qmoJtu&CM zl1hI^nD^Wv%p8i;$r}ZRwpLYd2Dx8A{YB`wRboB2La=P4J;PsAKAhAB%b|aIjKDL6(SmrP?Uxmeohdpr5}bBBBneOG!8OfqfV)Qv zOp;1yH$%bRKMewd#@IkQ}8lm@V|22Iv`)}h+$`}jNiX8^m|BuxuHk6Wa%Aj z0iO;qMs)gu(XGcHv-|xA`38`H=Z_Ncc{6*W%l&cC6Qr+P! zQ0ULyVyVpG$>oO~FdC|Jx}jLQmW_ppM6U%J4$A$f5^;1i*2#-t5%9peTwWjHl{cBv zN{uwXyaFCi2Cux*hkF&DPQD?+=LJV;%OYlb)CsSc9^a#GMQSHN%|_u*CNZ7#3_5_M z^3_;xYAK-i{*;>LPL+i7xoAQ<-~_!2XcN&fI+dZ|zx?0BfY3i@Q9k!rWc*|H)+2MO zP6E;={$0sfWM(2`}Q=WTx+;~Vl6Tc&#<2=K!+&;DfYrOnFYcUyJ;uX}KinYufQWWWC& z_97JIcYhl@(CHY}q5{O+P<9S_16`McL zqI(S@xV9Qhfg>B4@*Y+{+7v+#4w&K=YquDmA5ZpHL3_;Y1dV%wU|+xkWbTJCT4()M zK+tM{uo%XYSn;Bm;9UdAfl;GVwF~2vT1Q@lH2G0Fv*akG3``JYC8v9GF6a&ROkyW! zEay|;ZO~;LO-unrR@Mx%GZ7Da7P0*_Hs?)=RKs^RF>N#^cOSlUi2ZrDNG;w6doHmb zX>8s;*z<^8p|MkZtO>>QiTyXRJgft!m^aKeW6ek94Bw^1jMtd%s7%a6Kb((9 z!}}L{LNI{@LqH%SszizL`enrQB&*j^3n){A1|c5n_m<*q=z7&{t}co1S)Sf?cVd$Y zH8K~r!m~UJ!vHqouO!7fP_T3Q;(qi*_^8W>22(J-B=wIz2V2vPAKrh65@p-|;&I~l^@tD}^nlC5gn_!gQPt*wL36a%Q zcNSRDPbc$KO_@ox(U~xbic1GewBcpMuBuf>nk9XQsdss0VFdWh5=?3`rp~!fhJ;{e zMm}xmoz&GzblFLUd{yZ(8-G6ZE z(!CMcWKC8~r+Zh%l#DawHYu%pDR2}hQSM^h-c9}SfVz7GWd!VA+0EK5=xm^^-R^M2 zu8fLy0_b~c0cGvLE)PH^-WL+|p@8hDD4^8@1vH-QX%zGlpshwzUZ-jVWHAYz&7xLu zgTItaggj`xAKwPETpP_=QsHL7xJh_nIDMt zV5R|MhB2RK7kMs=Ge$sXY7i&NMuvco)iUBI%8D|w4FgA?Qtt1Vsg+A)vPNdm`Bb z|B^rx`H50WWiJxxaITa5AuxVb_%kU_Gy2{}`_`+%xsMusfA=@>l&PEQZqj$AWH~sG z_xu7m54gjS;ld#7-(pV>ATwV`B1j&Bibkuj~AazYE&4xNL!!%zQ zavuksU$3k&gO&FkZqry(V}ZR&dFLUdvAm@hR{*Zh5Cx`hkXIfGXaq8DdWB;!8B}|i z#$eHldW-obTOjuq=c@kIV5cYS^>5N6;!P@)h)u$Hg`c{2zmOxXm@kS81hiQn z_+=KTKWBr52SA*UUJ116898Nc04mV3k1`Sjal^No# zzZ41n&g35oer%6&8F~blGrH|D%+b5*;+UB4N^*zlW=oW%1k};0AenN7tXL}&&W|*R zr|g3-;9Tr;cB6tNh7%QT*0KV=A7D(-O(s)7RRAGE^5Pb5eEG}`QHE4+BDO`m^7bI^ zbd8g&1~Hh%2Wfhfrmsh%J2*YnH(u*YigZokRbh1pXcVUk`d8&wp*u+DlJs1|-#gN) z8WdCBYrt*0BVt^$)U$imA>{kFl+`I+yjPvPpO+l)n9qSqm6uYkgnk(~Dq|VG6zMWd z^AxgSO_DiPH{$$=u>lf?u)qgs(n4KG0i_7YE_aOFp(Or>CqQQB8Dar_A|Mj8YtPhT z@<{xeCN8EY^s-dIj{}SfFJ>;sD>ObJ7tcK1FmnZ-kh}kJt@KFaK$J(spYlI4O7@5~ zZ<-*iWJixnm(~8ciKE95b1ke>*1Fr{b^L@=A<~Qa)_njFx|(2-&WUGwZC|E&no05E z)}SxFR(%qEF$GkJI9UW6Pokzr5H-$6DXyDhwETql8uDzf~wWVWe z=|ae1*}a$N1sVpFLxJDMSffYio6u3~LUe^?MaRJ2tjW||!1Z1QcK77)^=G%6kpltE z1Kv8)qZ&u5-*KcBhUVqZ@^48PPei?kSdD4A4U!A>9RYz+9f7+6AHt1KTzB@a5|}_) z_XK3gr$7Bp$-k%8YVn2SX~`QzujhYpOt)c!%1&(7T@E{=|XU zeIwMV;#oCLD<&ft7;9BC;-Y&Jd27JS*ACAzG+s|%a)BSB zRx@{tK@j_zKrIJS8x@qj2GsBzC%29EECQ*GTSz&Vl==b;QQO5+E9e;kwUPrA#lABK z`{m>ZUEBgKE}g?BW)CB)yEI?S>$}$1q@j-V;j{!bC|SxDd{^{Va<|ZCXUW`&69qlB zv6-+CzdTX%6psi*L+})1;7blKdKzUqnY$@z^)_+96ga@l?gji5z?j)FMJK{;7Gd+O zuzU6qb{~b6P*`Qn6nHe<7bvLn8wos21dg%-hwmfs-xS!>7Z^A~C#dvB0(anOc%l09 zN>f}8e(}Y9hyvgL!m}{2pb^vxpn^rdPXsQu0w38&;Cu?K@C63eK!Td+3q*CCaFy)d zBOFW45|<7Y`KMX=C+;KvQOfV`%g^;)DyU|@eDpchsUL;3hRRrWnO0H1h(1w8#wTBJ zK#2>1MO3lsbI&Ktl9@0N6pzgqpFoA*qhYnxj4SGDD_UM;(V_!>T~6^AX&F6LhY`$>Z6E3lnnx@RKb9aglS$(&7wzps_=HjFEtcjw zp|OKvaFgms#?6;oV7)g|{zT9_1WE3Lnb%M^b^V`z%Xs4lzPtwe6zCB6JRL^~K6W>y zgf-UWKG@S^(i0=*ddjb?Ve$fdeX3IS`b>-ZodjoURvxAU!TLCYJtWB01Uy>DiwRpv9-7z5?~*Y^Zuw?G86il9K6csL?e zD-`r%pgExWJ`nJ20K-E(?-!S*NyS{xy$VR)IW^4qX5j<}LFP+%KHFk`@ z$7+nvAhx~67IFgX@wFsoPaPE@DI$&%&@O^dEPsT3=Mh9LMp%ru-U$2gAEGPs3$3Bl2T8I zL~Tn?t)NQ+YP|_jY2ea}LnvgJR)=Xj-Z{cI1lZr`nhm&Rr0?qfQhv=e2Gxa+Rs;{4 z1TwNhx#MHV+cz~A*#8o3al;a8+RTuSrM3qt!>jA#2?_(Ww|I;>JMtZRA^6*@O`2HI zI901ziE@B_I-Ww^)gQQRlzLDElVdxPf{%b;6LDOsa3D13VMMpr=p1O1JEy%B_;6x> z`v`W#?KzqFJc-ykV)abdh!pT@fT5AyP2Bl_lgaZRAomvMt5uVwFP6pA{(L3x@?I-S zY`c(mb1&9qqwm{ zUI{J)H5_h67E?p=GVsxqgJ8W8>PqwcD7=_TIsqAXZdIVkWT~vlE>xM06Ulzr62PtDLCS zx`T6A--c2Od=4CbnI{wUsDSbcwORqq0SJ*KNxe>xsh~3gYE4fYETv3~7@Y9TOp4p|9zsbUd*cign1AZJOH3NsiOZwquLyiS8o7fwZ}}P#rm` z>7K}rsay)o;)W@jF59UI;02WNaV_AIA_ABolBy3ou7N zrew?2Xy?f*CSKsPCHCxCK~bk`Q6{JabR0l7sMc{tD&7-Rf1phF)Wlv?A6R01y^^wj zdRNNGr6O)FT9d@#ah|k7R&y1^npTHo1iC-&(Ml%LwRJ4Pp|jSs*cY zn6KbvD!9m)lwYZmm;{`Zn(r(|OQwJDVZ(qu{6essOY%Ulzo;i@2qr;y0ouC5_5IE4&YimM}HO&Pu@hGbsgL>47QE8$-ac_)v33isuw)Cf8Q*ajgI$7RIPQG z3KY;y0>Tm*wXx66LS8W6{xw#Qx_UpLtWjW;@<@#f=uj=5t`2k`fkS5>l96xXAe!}| zv)TVeX|bpD6Y|!*9aJiymjL4QfJy^{7_&`5>ksh+)lpEy3YsOGO6<$bCj6&FUj{Uy z(70deVs9blRI0O4SM`++OVdexMuI-t9@(puo4x8`NkX(Ya|VmP0W%tS8~%{v=6h@4 z`Fc6R$nztNDN|wFDQxRoQaA>M8L9;Q2Ea^X%AHLzF4C$;)EBCq-tz7{(!44(VmjBU zcyZ)=f}a7HFOD39&pMLb_hP6f+!H;~*$#(7ySF zm_Ay8gtyz3Gwk4)hLYd|gEgpWe0AnobOS6noNrdz@_ziTO~C;vFyl$W`p?~{u_iPF zsk>xi7i%nM#gJ@f9rB9&oxq?xfpgmin@YY(8k=W2eys4n#(?D;){I1_YvK724uW-Y z1ZgA~pa}}K_CVS%omfX>$HdvzoS0uXifu)9*r`rkbFTDb(Hz89Ca;(9OM|aBT4Ah>tGT(slO|nCbGhUH2K%1V4b) ziO~BA4W>Z^S^+2`xCpg@qeTb$+72Sm1W%h>Ea&w~-H1FH$i2mx>f(^`4kJ7#!M@@# z3PU76wSd5$RpZJoBF`0t*^xMrj_fdS<+ltQ{V8tudWy-Ll0R#;o20vwB;2{t!=oBN zs`p5xQ}nr{tV1=SGLxO~Iy~VrVg9yq4<*NZp93AqYWH!?ky19V{A7>vFjAKKl(@=z zb+jCUQ_HR`zuF_qCE4jd8JhR%=opYSEBm0ln@2W~WQX`<*ymUs9SE|tvhD%0!%3Fl zlMNzSMo~Y4|9TVU#694_UPCTO$WnD@qHE(^?;VaYI%yr~08S$NQ(#B6PKj$|BZ!$p z!TMy22=}KGm^U=wdYwWw*(#VA)e1uG@TqX*NQq^_?rKzgsJ*~8S=jl6braYt7B+&g zY=J#(VFL;4AgS*87S@HZo&t+lSaZTU3T(QC@e26RfdVVGurCSgEU-%~>}}4gkh&hN zXF(W&I)-|P8N)5fQy`J_?0K39V;H*ae;C6$hPsQAYcb&$Clpx;U5pxZJx=&Z2nih` zx<0d%Luq1;aKCL~eF^I&u-7fDBVkNEKTn8iI78|=rgm~H(K9nME5Ke1&it>Fnw)}0 zlaDUiWJLtE7${VKv95kIF8zy4cWNe_TTA3Y!k8*&{Go62hkm&Q;7Tn)midf9d+G?J z#s;1Ob%$wjcsC@lQkS>qbBN(v4${H})ImUKo-%u8zgvRupkO34?=;+w565frD$4$8 zZE%(+pbr3o(5wJe4MA9)X$wqeK7;&^Yhn(;vFIHV?6wq`H|wKMesS=UIQoChGDyo8 z(8U13z*#(I=l);~6x5kO*||If(ala3Z)h?vMlnSt~XYur>L zZpp&^wG=ix&y-t0MF3gZKYnk^EvWMYvb}OkN9@gk=27awlxoUdTISm?@Aju_m0U8H zGMi$2vVe@=u7-)ld5xeS3v`g$^aPr2KOeb}EH4Q%2hc1^%qSA*VnS4h4_#cyyx%P z^ir#^O$I|THrffFyf^<_jWpVPo;l4`XVsG{wRV)A0rAE*44zy7mrn&Vs}iNeN2qZA z4U8xbXKkan#lovIL7rT;SuT(_q%V>5E}yiTq7U*>wUw9qUZo|%5Z_ujY( zrMCSXq})KtFISm?+?puV$)sKuN4=5M&->KcUNPs-(~LPOWV}-{_zsDGe@*I}gIT%` zZ2@oBU@lh>1?&S&1;0zCbv~2n%>?{RBc|%qJvtxa8(2&B8KC1NiRoT#q=2u{;CLh7 zBg5IgKIykIiUd4lAAK1n{~}X@4KQ3>niRryb20V%kHK30kb?hs)vM(!TLCE{+zK00 zo8zcIBK6xoH5XyNQ$8m4Szyr{(34r(lLDTr!Sp1WUBHu{km)9$DPJ=Qc!JLaDki(C zQ;#mty&cA~5*7=fo*GohLlrUADbC{0D84h~$aGZi)PSWSU!?dovXyi{zv9(MuC5UQ zZ`EMd2*1Q6IuEfrTTtg?4MCr7qpT;4Ea)YpVKaIQL%4W2rml%&t0!Br&z5JaA|aGc z>byAW?W7*&Q=8?kiO(Ix_5#*aMWObpfLm!W)^O54l%ao+I@I$l_j9nqLoeRSN#O1s zfB&DZNP&-ZNkw`@xCsNkBzFhDgF23a;HU^1EzIur;Mhgb@P zCB)ljIYegL+sNMe6pAo1rGfN@N0ghCYJb{dbUPc6O=sx$6`z{OWKfMYgAivBS7 zIQSi4pkRfRrJItZ*xeh~znQ&aCqqi9A({6cj|p=mF)4%ylmg zh-97SnKiM5pl=H99m6ERdhWA2-%jXLN%-8KuAdml7*&qmj>1z(Uw~|hV%n)gT=y?= zDrQ_9(hm#dUh(x`d=q{pHx2e>9Of?7jI0gWJxsuEghF$dc9bXzOK73$0>4Uiv8qbW$aL2fm8Ju6$g}fVRMR`7SI#NRl*M+d1e(@_d;v{K%QF*_HMR9BKs8*%C8&|``b$T#|kQN^Balr{KU^Q zO9g3*rsBMm?BYh7OO;iQP|0$4uvbED*jesxe|V)soWk^RxeTh<$ia1JXJ@$|1CPY- zm=kYH5=s2{-yw)jE(Tb!CEWrgj&I4Qef&4CTn#uxE4|RI&`KFDjP6{CZV+a{1Zi?< zm`>XRvQ5F=(~w+45BF&Wd$6Zdc& zZj8H`IKXGb!Oxc-%?x_#$~fFu_kJypBb&HO4>?TP$suoN1v*J*1)I{SY*w8)H=h=| z)aBl>61ZR%^SMAb5m$}SwfFoz(iO@Ey)?>Nc&D5B_!~}AN ztWjJz&|5w9kyIxmN>bu!p=;f(X#7S$ER*?OTBz8417Lg*=VR24PhIRT(bO~wL$}Xx zoqG=%a46)-b5Nfwzdm)$CZT&|viu73aq9!_947-^hFlWuZu2`nc4NHk zzY*EXRI)Na=6%CeFwX%aNz?>{qLk&{fM4Q+A){ywh4K5Jh_uquU^wjKzy8L5N%3Xo zjbLskE#U}A5S5$a+{aC_x1w>L;ujp;9XuwPtNua-azUA;o`@&nR~p<^ny3y$Hdb}I z7@jdzxP^50kq*7t?kOa+Q6N2@A=^Q+YlUo(x{XRX92?|UM294%P~tz7Xp29&a{(sOBZnn3RJ z8{(rHBm^>5i|auhoDY=@!910j`ya1sjOl53J^==CDO8*BjD5+$YXY;D327x$IJ=%Zz)QW1{BX7}LRV0)oSLprFPB1^3c{O;%3^ z`3DPsp1O5XkY7+;H9toWUujD+r2qq;j?r!w(2u(%_jnto3957p0z$eCL2U>9Mp*0kUj;4xodI#5(5c`5~cZ9pXs*lFI9QeQ}0 z3K>Env-Ky|j)oaNx*gG7#fEf1jl%_+F3>Tm{7f{2eT?rw#;<>)@nh5xqe0SD3pOI; z4!<`He#`05zfbTQ%3hT8AShvBp)R?AZUYFV?ng(rG)uRPB0=2KM@hwo=>8i>_v}@3cZ7t;NbAfXelyaY3!5sNd+K@&}44cfb9KOe3UnOT32I{hlVd z-bewXTno1rjB!p7=re@os#6$!a(o0QNHUeeoQ^XQqgXDEt8C0K(5p57o#2;1H5_v1 z+nK-_|4E78<8)O@BIuz&8~-Vn`u*kU@uy6v0TnCg( znh7DBfQ9L(!CS1dR^UV)rWOnpdzkFC2wo0#(rrBP*x(*dBTy`e;h9?TYYx7nlPT-T z>PcKrzJa0b|8%J^dlPox#-q@|-X(8RN`bT3EFwTKeF4&^tn8G~(a}fu)&}}Ux;AUn z?7QSHK)seMV9`;T=`47`UL3)~?Qm(KLGCpuiMbk%To_tGf(qchO~j)&_bzSXXum)N zRn$;6KdnQt=3+sd^zb`8i4dBp32SU=P?E&5pf!vEW6cN`dreJP6EoI~aBG0KS4c5a z@eK6Ke4BO$rUces&%I5)Ir4 z+DuzEc~RQD@$4NDE#V?8lMcsf(-iMqH_h$-Dy zpKk2XmaXM_QTRNkPV|-aoT#<2gUEZ32vccOTziJYom|Jsz{Dl5LE_?prAVW ztmj>nImFZEHAheQDB$Ge0$Hs_rb717$gFTS)jmsm(5m$}MbrZQvjGfTCRqRJXwN8m ziWaMruh^rtdSc~+X3&nSAD(r)CsPp`ZErG>OqX+-}NHznOn zOR`0+r}db}WAniM7{W~%H`8VI^e*%1RnG}BOP!#LtH)l>mipm3si5=j00BUa^sIzS zqeVfw54dWBJNddERCxjsK0I~h&J=u{=p(2bqb-c*3l$}}tG2P8Lh6w z1rC#Pv&W#{a@dfocoDnt!FsrvJ}~vn#lNw$0qt^cVA|@?s75dzPzc6@?u#?zLzM38 zSlu-p56WD%x0NoK>ywF1IgrUd(2s}DNp>a35D%snd50?K8r#U@|6S^wq12TyIhS^x$!6Zr*o8Ftzen^9mdXrz)`OBj zI2U>vIoda{vB?~kakkiwG``8a+TTqMnvBDZ{HijW4U;>%Z_1O23DB`8Q?u0l6W`(^Ui}*DM_wYD|9E`uN zIlIA%lfePwEx&Q>b&z`z32cOVtlp1sp1O2D!i3i^E`>+);>$EOHz@frEt!Nt@EyLw zXoAhC#LFquFHz~qQ6taGy8YBRQ)qkifS``Pz79LUHPXPXM9&B9IFJ^DnsK7A4dAt}!JPe#!p^zS8rFd4pnjU0jf z2LZBrK3oex-DTk}w`%vD&Ag~Q)R;{H2#;5B`y1%dtGjxHByK&F| zP@H2afh-@`>IG^#5-BsbqQ5urxA$ zgJ--@-3+RIjgL>>cPk%4Z~ZUDDdDjYu4RAIBPa9lm`!5ZY*&ema?<}7*}Me-qjD3n zIU%=`;BMvT|BvmVgy;1*b=48fsX3#jm|mQK1)exwZ`V=n>gc?uB>U>N(f2cBh4Ux>;7iRYGYwd$~BN!mEjeQwI=_ zu4Ss7=V0?FgHK!WWQ!6)9y3#I0z^Vxv=5Mt>3A6)JKy< zq{ap?B8mnzz}Gl+QCrRqMp_D%iaGkk#87t=dQ+Q7BQrO~(YNCLQDk;jgCmyTX9Na7 zE!J(#a8*#BLDSR$*`OTRTOj=EyeUWQ@sX=w)uJQ=}A7} zG-#%pk0%(w*b2Di47VTP;SiggrAV zCuK+5K+sJ~3ypKbdgU)w2v}(+xCjzNNP~7ch@}f=T{en>1{yI}8{FVm^5yP0h%F>? zsg)mB+==e-mVifnv{8-X{|YzD(p-fH?a@m}jl)tV3KXJ%r`F1Qm=$SrG)2)nh=hAb zWaEF_y;ITmpriq{j^#_Hx(--ZKKA9;I^l17iegyHYL(x6Phar~8^W1t3!eCIAJDVe zxRWNrwbiLrxUr#7z3|Hadq1Yv+B}TWUpYwIz}ifPI1go}gr-EFH+zB1{8XntT3{}J zKIcdjGj1w^B^RX(P#ba3E-1w$mac&1ak9>{vYIz3OCR{jRX1sIS=OkGqB{^4(nlF_ z@ya5^;vhbi4blUV*`#7VOA?^yh0u4vBzj^eq0ge6VpW- z8efD3#3XABi-7UX6yb+cOc5SA+!VoPS^`BlOtsZT2pGATB6(!c_p|Yr}KYnFX)D`NR z@#V?J8+Q*h-e|&%BUH*hX1qaV3n9|?Mxe?NPWmfrz?v0uAQ(7Sx)U{TE-F;V*16V{ zbZd&P7__tD7In%Fe7fO^Noeizxk5~ikru~x1!k#n0|hh4$ZHp@U&|hD%!S;Oo-MxiNRvbj|6YV_-L5>}{jQ>IUh)l># zgAM<*V%|o7jApMUSL^lQpdkzAdLjlBffpaLm29aA;!7g34I)R$2qB2=M5F=1UI5!x zEzktB3RZ7#h8-q6X5%qgKj!d&lu8Gw%~EJ3{GyiDF3BW*VU36!HQPgQ6VqL25V`7l z4GiK)aX6A~S{2H5`7UPF&JW(Q)9q_d`gK!*?y0&6?vfXPJ$k*f~#5S$#jC(}+@Cj>*N1x+q&(&P+NWqzdZ z6GA+Q6L03rY$jqRGg9t*$S!I#AMp?e5V6uAa@B1fLXM!!2Vy^Fj{d)zITKb9xjh2g zDhlf2%0h~e;E6qnML56|Aq(ZTJucIb!SBN19sF|USQ~}EYfqbOZm;h^tuD5O} zX$8g@7srqaBolVk9hMKpd!RUr&~$lTXfm?m{1`@ZQzp%30+z|C{K0JcQf=~e!sAIJ znIT!0z<5p=1hQJSl-lurrsLpc8bD^kf#FZJ;8{$T7)&-?p+){b3rEt=lTJZT1$=m- zI-yB;k~*X@92k;C(o7W`>d!bNSpTu+x!ve6q@j z!|TPREK=(6t}WkClJ}Q5W#kYf8_ir`nE@ALBTApyM29}=%J&g+3BVMpWF%@~nF1GG znu%W2R8+m-<%?`w-Pq!Z?Fs6dIBy6rQJo(Lq^m>C)hYq%sipQ#sFixMF(qn5e3^hA z&w9jA^HtFVwF^DQK8OUxFWBw_PE;2+1%@ECpeZqlKyW9wk)RBf6fjekq981hUfPz& zlze(XpH%c}h0L$SEh;Bd@h}P7Z>G{8TxRk?Aw%X$)cnJBvO)U`6$7wTsUXxI3y5x%Oa3EWXb!`Z*ULwEb zardFvyDT@{nuhs41l0R}4|OEV?H)@mSuV0Ht78~%Jhld-*K}+?0vRB$FEf3nG?@MO z2mj#^``#@YUBA;`OTtznmM+}synXC;|E=jzm3 z2Vu!+t`I93DE%iZBOkFV&7>EWKhk%`L75wLzd}6(YbZM*p^)*KrNYSd*duq@`ckjV z{Hto3vl>tsahrE!%d6pB@?&b9rA7w%u}aR=GO~Fv&M%t!@fsrO$FSkCo1H2XbmCRV>AjxlTWx8Gs&whMI04x8ht@+pn>-?6gua-$TNT7q%TC`4`Rd>0JhpeQsCFLW7>Mmk@ zJZ9*p3w^cxJq3b&u@{qUnpS4S_69-pddN&JyR`gb`J|Sy;Sv&`X=L^nX@lkO&s<)5 zqnt1OQZi&4>2pDfG=gH*3U3jpRrnWoCx~A%K@*ppV|z*6b(DBjcMR81)`z(D2WNTb zJ2=a``zhpI#AAYb1E?|j^u68P#lH5n%alP5yZ`M!vNa`}Kr_ePv~9;cvN`JGL5?m? z-%W=BElaJy%!8LAu;YXTLFC5l0DV4nXim_K9N=#*{KsOKAv5 zdC-$GnNqHdlOmu~gHi%hMC?PhK}d!Yw*QHUz?l}l3x@6z|5m4V)Fsk>m2Z0_LyWDK z-kwrH{o;BRs?T#_=3MnICey4M_`=+VSVaS01ugPerv01q(DFHtg}~r?%yb^=ow>%9 z!`(ct%WZc=A!Hfq+bE|5)bbIh)JaDe=a1TqUagZ>Ye;92w19$niBKW}CC(y2^DAqk zoaLkQ0xNV>o^Q8MrGU!V?Y^jeltIO&@3kw1t7?)_hP1d(G2Tui)+xEiB8Ok=VramY zXmODg{57B?EY8nFSj>HbT^Jni%xH!p`tefkBbenE#By>>^btvxV`f_*M)`Z#; z;QUcoB*u?@Ty)~3A%r0g`5iAotkDSc4EIpY9A8#F*z2{O_Y!p_P&yQfv~`8*WOVMR zz4Oax|15 zz{ysvy2EhsmG3&7O6wzoKqsI@=(UZ|8Ab9fma}1)yNki=3%{iNqUaT#a9q7ntA1d6 zfk{?4btjh%vbx(g5>DMIWuESz8*yh8Jx-_8;ma=3Yoh-u5*Ka4FA3mcbV2Gdq)AQ4 zr`iB+M?~01U|`oAZxb=eN90L-Yl3oC*#Ow=%HQkoXu7+rE6PXQH5T0w$WmIaQNV#VAwKwG{CS zHV*Egye_eb?1;dF_DUjh_ z5NF0mWbVv@akPLL)6VcEe@x`x+Xb0#S2a19^Q!sG7ybUwzWLiIM5pY93lsGD%{Hd_Acm#o|zbv2G%(ZvsfgD$?CoT;XZ z*Ae#>>E8f7yqbd>y%6o;=imz`!mU1BSIj=nEf0Lv_-k_9EgEtWzjyUB;ZwW;LS%Nu zBn*1qrO_L}om4il{4$Y~T=rb~p}voIQqE~wb1ur8Wx4Xem0FfteyDJzl=UwE-sjpy zt`0tz%;cymqezOazu%Qgc*WA$I$hqT8vSF$E6C5^t$*__vgHA*7+z zDf!wx`V*MLsAGRJR!biZ>E2evsH@&jE~xyb88+v5Si3s!KFe--VMem zYgez(0^CIgm#Dfl!XX^f%}y<}mGHF%oZXIt;i5<`Fhukm^aN3UsSiic>eJY_g4%lk z+ru?X1QP)Y|2Oil{79(H>o7$_A8_4rto)m)PB*_##=n*h4g5!J-^hFOR%-3(72oH*2ebo~GxYc~FjP)s-T7I+i zH$Bnw@P(}mAY}R88-Nvp$}SsIelAcgh&m5khm@UCK0;94%lel;1QcG5O^6;3R4)J= zL3Nd@4+n0H9t`loWgW`f3AkI?j`GFekXa=TSEE;U&)mwe!ZFm~N#E+!YjGwZPy_Se zWgVEOk|_mD_Kbj})SEg*2D1Vi`-~<=Kqthao2KWp$lt~iQS$+AzRE2dE&dH%yyBmq zvPa*BGf7y2@ZUf2uUi8ZjHcW4y1WcK0>triUj$zVurOVQS-X2Th(!|5g(XZc?Wl=o zfjHESY(qg6Ek^VWKN!P{O`)C5q;!@_#~fE=9mdISV;kjiF_uP-&iOY#b)b$c^(D$I z%s=4)lSE9(#TNsmU3zDHj8xs4*f6~Vc`!KON}Pfe_8m0%IQ12}BW@kRsu;TIOmy2= z;#|jix^Rnlf~lJ`FkQyKENB^utnLynRJz?7!C4QSnXT?Hq!%ZdZ80+99EJ=G^Bd16 zuwwFqU(!99U_wWhL$}Gdr-#BCCIVA9VR>C9ESR>6APyU##hFw0Q=Q(gv>?F`%DU^wtK=ZGniUHB(AN8)l2B0=_+`EJ~>VZ zW9n&it%~&1IS+PGRjHL0xSn_vf{mZiHQ-UPd|hjg%J{DTmhqWn^`h z_=>565F*;`lzRoba=E$7NR7!iCVc!Qz^mh-0h1ASCN{3(#su~u{&3?(I^uO5t$6wq zu>w7(H@tWc{mJexH4!Oe6E1 zm+O=KS88F)yR;?S+OoPn32AKA8u1ZI!p7Rc@CpT@t+eTmUa}8vkF?DJQd0r5O(BV` z*zQIqs9ZQX+Lq32jS7L6VfkdJ@hq=SU7x)l?nLzy?H2A@xSHIFYH)xXV>N0nTit-+ zT0d3cNgaR|qhlUnpRLX{)<;{RyLu1-ST?$Rcogf37!LxLeN%pr)P6Qfd=&z49IxSu&kev##hHchC55pS7nD%R40-R1lfFIx|Sa# z(s**QtWCN0QFbUz{eiS=$)!HXZUoH3R5F^hnh^0#Hw_q%PeGSzXqSvR0o8lZst zNtDPw13r3w8zgoX9IKK7haqjM??D}dE+EkAQGZAMn#}qe!>$zTsqUEZ%4ZgO!5A~+ zeGXnnxfEY<4b)wWVG>V;>Mr2nKi*$xMoB$N>&$BE2l$i+76)v%2(~_0ak?u$#0XJX z^hg>q7F+JNlR!Z&0?JGRrHcobQ+3m!GMF(_01@&DgA&j|D$eFfQq!OgrS$VPim554 zV-4ysqK0Y|&iKj4OzK_UG*1=bcLs3YvH^eD%ML;nxNqPG8eU@A7fxhAFO9eg0^FyG zsEE~r*9p&WPR0m9W(~}quK~^Fr#v(lylyvK5D9J0*sd_|Rp?VAJZ;s7% zY8|43eP&`W2n}I{>Q^86igQL0F5pdYo52eArT$Xn+eQ3B{BR;a z;u%~=?!$%4wiDdi_Zc(|ir;h-T?uN&=d3c+iB1_}RKz0m6q$1`_>I)Hh@$)Oq(-Ae zpxVGx&hHR}j$=1+8NA_H^r&rdo?YRBEyPfB*Dl#E$6CsKm62ELY35nC?6^V_qy#b~0@b^y*6;5@K7 zk-21MHdcd6n2v$JFZ@N+*TJBYqt$)%K79^vH9J0TqB(I52qmcHivtg0@~!xWT{J<} z%RgZG;JC)sBHtFcmJ{{r)Ty1N6{7j_%slGsdU}5}ko5j%Z27F|M3sgP$^8k-bGZE` zCw#*}w7+dvxmCFt4@4juzCcTM-_bM|IpLS_iUZ{r)D$gl}bd(+@8cNfjv$-kuPj6^cEY^R--$So29=Rx8~ZR!H}!)ui7fZi zJ|gMTvZYSsFti@3SdJiaYlx_beIX{K9YC3hf6_!;_^VtPiGMEmQI!1D2}+poYEUuw z-<_dZpBL8k5=1vaG|W+m0%Rl$)p-bRcO2;|V-ub562zDjc@6E>&DYG5C<+h64=2)( zAWT}|F~u|$o-r|~Nh(yeFrZM~Nnx2<7(V54B8CYk!qa>(*3e=W`X8aaoU~sd&QZ4i zh=Hdeee6Uw;hANxq! zADsw4u&8?NhyR23JpKyupQ8D>YwUz?MgkT+4z~@z!c4I#{dfEP*O5O>^Dh$q_Pxn} z0{%vOphU+z;rqG}Qg?_6m{cb`RBDJVLQVH|NZflpmKkj^(XC}cPlcjr4|NpC>9o_a zAku+&3>A_~AtA@l07fD5PaMzN{j!xrdSo zR~|Xx1BIhY56w}_DS|Y+&v6vQD4Ix)KT&RQjCaCH{LuAJXy=@AIM(Y(%s7!rkfC`W z@p(64D&^K_-f>QNIRd17rKY;sr}~go4``|jo$#%qVLE?{Eob_aTS!?(kepMNa*8x9svUP{)W-%S0<$f{8Z5TNowp@!p+``P?|LS#9qLQ?nZNge_@}TF9aJ8yve(U*nH^ik6<`gs)DQDzb*Eze)2s z{!ls`M>#zGBW|iu{0g>ONScQ!XKycY_($TfCwfxUc7nvv=Sg;#FG@Kmq8QfN7x)y?=M{I?ur3CB&PWT?_in@`9MZh0aTT2Kt!vDY+rXGb{HIKp*NLUfu zCdGH9_&e}7z*`G4xDf2>b@E<8-b=~5j)WC4rc#`6Hul||2pt&Uy+?S_q-)fR9Igo;qtK>m3EQeYY9ZFJ|S=<4;fvj%o^GS`12s7iuVHR^do zRihp-RLwwTYXpUXo%P0oQhaa#Q&&}tV2a|U*g7=O%kb=WqUn{fQBHV+H0#)I@KvYY zf4D#Hdkv2ht`0!nBuHG26vUMDhWIa$^-|kVB0N8UtQCkyk=Wi9mX5yriSDBDASYZW zPFaaos{JvZ+}-iVtt3rFtVVn{UIJ($LDKe)0R`p?bkz6g;@xvK@j4+cm5HdF))(Ro zpO}Xs-9B3T=}x!(YE2~PNSA+Pet&jDJx0nTu-xm%Nf|B#x+ zQxcwl;`Ve6=dEK=-|+IT+_>p+$K?F()c})5ZlzUyUa{XoV%co}_1jR6UH$ zA7;|`;U72F4GJq_Ji6k9uS;XOJ_E?DC%iIt7G}E$_41xd=`y0`&qe^CnS@%X)s%Jy z#Vph0XFK7C@#IAA$6xiL$HF62WNE4HAj?5ynWkCJ!3+bXb|OnKva4G>mhYuzspSH& zz$a$CI*Y});|<6w&V{_8l=l`hyN7CdH)H%46WZf1bgJ7y>$cIzUQYNgOk_~7K2GHL z&hUDBJa=`%!}mZ(Wvr(Y;i^Vj7U5oMN_I!;g~ESJtviARo6Hh13t@t3oBS@f8qBOL zS`(K&mkSQ#QJu;{sZO$pq9^+Dw3;=K*ap0ZYNT zR0qO5a!w{EQwo)_6XgC~gPc#~SRkAq$D* zSJsS>?@-J_wMwW#Ls6~O_?Ym42ZCp6;)Wu7b=u~ zp@N_F5WQO{=q3CK=pF0pZSL#sN4=9sehu~3VqFNSnNIixiB=xS&?097&8jV~1=*9D ztPLiRvXES_$!wIAQL`7yYw6LoT_k>$YAn&y&Iyk|h?eivb^1IA(RYybH#AcB z{R4%ktrK2_CnvI!zx~Gln2^_K>(zKDQ-i7MLCx0D3C|R^3jCEiYVU+g1#&GZBr@~B zU;-91mpV0#or4bL_N5%smGce@;hs#E%2;zJe7K0{uSM7p>*U#@ex@Nyx5JROnkU@} z$1t2Zk&QSXsMT%+TGY-Ou?YVzg5<<$t@oBLQiCIKEmBg^gAIJIWY8CJ4^ACqksP%U z_##A@OOtT;LJPv(kF@(dI{#9EA&6T_%16BkGozyblp_9|lc$XIp(vP(|no({I4^`M|N50Je1T9LManX(ME z=XH%*f(aOBWApIa-IgV8?&5?u$`MD+%FZqht22+suJ8RzjF3Lf~S&K$9?LC&L4y}Al)!!;XkXmrBQV#a|q z9AE>e#PWHz8`(5P;nI-~-po!gZU-zJ;O&12|8BlLUA*fxQ5n zZxmig0H@Xu3)K`%9h}H~nF1^I_cjhXv*;Pth1j8b$C}_qC%|5Dnoci)>UIEej3#|#b(eBH25&meDC*w~z0P5;`3dLs9i?2ah;d6~SnCNI zapWTcd=L~)0}#EwzD+b5@9=D*pAk0R%uTb zU3`fI{Q=NS2RwlBgH!!vl_i#&`hI{L`@yJ~ML;kr7&|2Zny9!EkMU74lJ4mAiXRor zIBTqkJu4QT3AIjSCKlvk6024^j&Yx(0Nlw66pa$m=1QLhK6p^lgY?vqBz*XLmQ!cc6Jv6xHL06S)j4 zQeB?KEXVDXB+W{q>NTW-_|996diD*L7AkAh@;4#sX)Wp#5p}PKItME%>CEmD;B*1r zL^^F6!KG~i#TW}^(E$caNw|Pi;vt)+?1gTa0y|`F%7ic$a&H5wHV}mtfIf$Nb7RZL zNGqsQH^Vfs5+gAlqo)F&RJNr&%i#O@_~yj-Wp$Mu=;1%JrL0pc@Q7X6nT)G$D^cQ? z>8Z+Cxf6a|R`Cn)S0*^qoNzKWd$34OF}~ELxS6I7)}>e=1}soFL8=tEGB%ATGT>04 z7N|clNJlXhvA>&f?ZKA4KphGe^)VBJ@A1!D_~Ra`Z5fUApV-o#ws2)|rV~!bbNP0u zQ*Fo3WLt(m@TRq6v~S0mK|4ws*)a{jjUCNs$LW++z&|J9kNY_1RuwT$mYr|}Kb#0d zTf%u29yqA()uXlTy)FlzsiK`Iqzb((hHWrmKv9w?SlNn#IOST2U7Q3-C#_V+VTo_J zyCZ|h8O&BB2-I@?aI>^EvPK9eiZy>=yFg;{HOO$n-{Pke*@?g6AGJbc$lN!?nEU*t zIAh5455_EkX48r9kWy_>X8`2Rq5R6&6;8NJ^xdHKSr1GQrKnphRMfApKy3`^KXaH&ddbk89Fi{xKP{sT4tl}@;sXibRM`Wd$6d9Ol37Eey(4*vFgshfSSmWrS1RGH+u zUUU7+3ActtNJ6072yl(?xmv4F5FBdD$KX0%b6x9%b3|7U{FT;swG-|rkWBn#3D$$W zP>qI@0#bhf(3HNVs-V;=O5KSdL+P(6TVB49yt9S3V?6Kk!i$z!7iz6WFkJOqYG~I+ zW9t9{8jr160GhG26&~Zq)&}-2uRZUNt>RnLOVZKGvehx|`VR?BYu1s7%=8zdiy$g2xE>Si#wUlUgmn=Y-R>mRI-4FE}# zsSsdi0X~65KtS^X2vXzmhg}NOy9?BpFea1@(JCA6Q+F>Hq^vrUR27OSJzX8P?USI` zwBf62#GCcTgi;(~VV{Rw*XJwIA?mHN1#tU2_-S~$f`{$?tLLC*70zO)m-y!e{Bb+# z;@l#Z@0FbF@AxbIQ6+%vk0x@iBEyXE%>^Ha85PkFrZ_xM0mrjsS*twVue|QrOC14w z2gKXk)wlN=@TiV7u?_#U#2@z>7=^gI(FqSm1v`>vw*r`idnJ1C5 zB336Q8h{^8Ecy(F+yUJvUoIxT zSkmC>C?|3oR<$@3HH*4rt*>$m)wyI#4dLcKu&HADX0+x#8o5&abet185>MbAOHwmw$}6Db zi4!%J)=dV3d%h-jke(9q6Y!TdJv24mrW>?Pe}GZUz`4j$US}SkJSblR8+c(h&lqLK z5$H6*coO7j0+p>#Ti2<6FI%ZT>@dKhd{d4tnc53QUdJ>LOuHXJryA-^Q6lf+*V8B+ zGVRjejsclY0j&kpox+i>GSl*?8N0MDl5`#3v^$9q{Q7obbWYX?Ejp z@pA)d-o+o52Srq94Jd2^Z`_l6_f8zmA`Z3cIq@p<)ExqKs+1Z&LE04>N}Vv1&*k|D z)-8aeOHNU>XtC;D6y9B?sV0|w=tTILMp*m;s2C43AxfwhlKK%+S8D1Toba`Haw1pq zw^)5F4X#ez-65{hpIo3t9WPF(Q%P?_(kJ*Ma!;k)0?O^D&v1H&P~Q%3)6UJ1kI~2wy&glgu7dE#k)QyBMZa)(rZ|$%F&GP5;ShlhR9FjUC8B zH5s}KRT3qwAZKN4gcB}A(xUu8_~&J9Sx2>$t^ZkQckk3xCp+P(qHi+(f^v?gJV4z_ z${D1*LQ|en_Eh<3P+X%aveadym_UjVn&LDkJP=Rir%OZ^IAMNa!HIOyl8@GWom7AF z^&?*^&39^9ZFvnOx7QS%RR$@VlOmcdWf|#&Kf#j|c@KX<`3>@-@brPIo=tlj_}tZ+ zvab_|@DuYy`PDb*LLI>Z;ojDysF$onXHXON>Jb{~S#2{Y!MND)~RRRt9# zhPtT9B));fV>I#oLfj48Ge~t}_yqCUnz*YvmBa-k?nmNEd;l$c0G^yk8~&EK+P)by ztMP}efeo)lodk|hH$I*AqO>wRLhO`hL3uMM-Oo9{tBBnzs^7#9C&K+%E$~hXERGZS zGYt}fdtUGawpNEwU|$LhYk^fFuv7%{`U)t$je^id5pU_Rur`zpEwwlYcZ1#DXors9 zy?YVm)~X{Bct`=L{`eQpZLLn>_%%R_e@w)86!Dn^i37ge1kwc64T@y^lhl|}-=Nx2 zwe3|ZB&ZaWz}?9%u_E?3#PHN#=J%jTR6D`X*8GxYXsbSC5Agwu^`d52EP9uL+=*m; zOR;L1VX7iia;SrvPbR)aZE6K#K7Q(c5h3QCP zI+P$O;a(I8B^<(nB0W>5GHor?sRMKktBuHVvJ~7IL9sii)|B0fvVVY3#7>$M{*2-y zAK@>Ga6dTk&m6;Onsx{E5rzi9?-6(d^bSLyyDSb2TuKSyyG2els(J$ys+JgRSGA4z(sR<+)34)m*C>xBPCQ%idYV4_{bW=k~ zbO?xUBT;*i&`(Rq*27sw5qk~yV$5;<4sR@@YcN59oyakl+u##)Z=mgtoqHqnpr1Y? z6RW$~)0yAEGytb;$5GI?j|uW{jie=TEYD4kC-xm;{Z~VHE}8$QN}uFaC>_3Si>@CZ z9-pXxer@;K7Owj2|0B{{M#-)CexZ zHP;P2^{7kcz3gB~Z!TUNmhoP=Y zfMsl0KOprg$w^FommzS`5F6ALON|LH!-TDC$udaYk}S&W8!4za3XZ`G8lYZcs6W5O zD7eE{(8p8Ij0!48#8RR!sT!u_Ug4kj@rT8e8{Qk#*_sot?)egQJctLdeoNb0NMn6(wR9RJGyLoqymdjZY0f;pwkOU|~D;8~!O8J{*8=`Lq$+(`q}P61U)~ zPM%J}(>wBXES}ck2}|PF2#{htk0+P6;Hl$LYSeQ~9ibl@RA2p|RCoPQ4{u>YifV%6 zlhk7Ukf2U{1CSK;{2EqWy?UHF;8}GE2>8}e3$;yyl2u2Na?ZO7#1NOFI>5t>g<_JV zfUBQyHGu0$g1EHpgNB8mK+N4o5ZS(XS{{-A(+>@*w|-Eni+-qQ3D*OItZC#BAntFs7qV6{Zok>a-bl4JIsurq7%S%ytB98@qh9GkPx>z3YE)5=7&_7T> z7W4$6P4@Vp{^GPsAedLBhBPFT5Scxsj?s{8O@sMF>d6{{uK^__$Q&y5NDax6dtOp|n_sxf zO9MJsKxIv`h9vutBtX1Zz>tzfHR5tD>1t!GO4HPEI3~&t2}|!h9zai-%FmBroaSso zf4>61`GA*c@$FuD&6mVH>Xj+PNbT>BxB&&ae3kC0Tm1buN7;ETWR#^!Tt8NW*Xu*M zY6w1;hyXidi;(nFc3A8qy!mR|O)^3ss1b-Gyl#qqv^up{4SHw%yYO}W?=r z{y-eLJ`-12FMZMhV&0X8JL?xrX!hcsjIAj5N(`P$p#cKUw*va`@{mQ)cMLdSOd*i{ z@d#t`;36Qp8d2;1at9umqAcecQ|m^6(PlV8E%^3t9nniUN5RR8U%zIZUXX<=OElSA zB)id)F~usMcb)Qs$eaVcYrrCJ11)+=2LHKInGb2Gwq^{isd$jq>@A(6zWg_fGe>m- z1g@G>sLr6c>eT;_v@d~=s!0A%LWYDxC!%OP&@ z$Q@s@YQO1vnsKrk3086{zgmud>IcerIU#I~TW8ooKBslUi3nzszC@(t{%(}H^b`_beL>Y<}60haCwp9|{6*_rXoEZZFiO6_#$zy5|o-_HM zAJO9JFv%g_nmHr+Duyqax!{Q&%zh|chdVR501H>d#njq2j5`y}8aK70>7iY6i8zHc zCdj+Zv%M!5btWTzt~Uv)gIN{@RnN*otbhaMaL^%-YJlcEc|^<7fD|+)2;|s-h&*P- zuPmgr$DnZnnQFI8%QV`@^k1|iBK#t6BfOa{V5}$wBLvm;qd(knWpl51309SIc$OJ8 z4fWRYW_U-XvqT4=PH`G>ATkPXCw&&^k(7v-x>OQN$=f5^qKgC$4r{&BsEW1&_+Vv* zd|J^Q4w{xlw7WX^HDg@ia3eYF;yA#PQ)ngK8q!PMU0KE0MH5-Kgu$1C&%gzH(MoPK zb28_U>r2~xz330*ibJ@v%-xKY!<6JDEBwm9 zb?j9kH$$0`%lpjledtJMk-8`!K(O#8?2AzG-A?X+ha11Y$EC zZp_iZzR{YiCB+pc#fe1nwMWRojARM?r|dYU>P5tvM8G#{czt5D_BfNMCvkjO6p6-^ zUQu>56O1R2Z>s`$40geNLEzp5?xKN1O3#bdVn`#JP9TEAc~GBPIu!><3}PY?pJ~K_ z*g%S3*g$HK1BhIqk(dv@3BSs&q#O)~@am^V92&kcsGxZYku@55a%pMVHB2!C-^ptr zeLvjvQ$$EUAw_`n;>NB@mN1|>gpLKY2QQ5zB%6?YKt}VrGeY_hau^`Pc`E}U*kPBF z+y{`3rCrO!J%nNi)WY~~cJu8Qm2IF}In}%Q%!j<2oGgl^-4CiIjO^(w>a$3)h z&Z60HUG>W$Am$wFzGTE`$t5h?n^IqaR}yP%S?Vb0@7R1vHh%*fQw3m`eO&b|;U;N` zxVR0DlzfHTQTA|@xB(XpAVl+KT`HQ0?4M#9lZ@e_+G_Ax&FX(pd_Surzfr3_^4^KO z(F@E+3kYq!j%4VI-%OHknwj4^qPB?p1hF85NK(cPK%jIoG4jxD zj%X;Tiwz0|-5M1ms(RLH@^cA>Q3!kAbZdKj4#isaH&$HVIE+EwJHS$LXa_%Hqll?Hgw0Q2U?F${1S88=>YS~rBLyyvJ1vH> z@5&KqlE7DA2gG$i^$6Md5-`h=;$2Mnt;{cov4RMjUl2nC5jMXdas&}J{|}Ur0YqE# z3u-gR0BuS}P-}<^nqQzR0oCS@_plykN&%BkDc;>o)qW`m{#wn|m4ZMo6|T4l1)3(i z8qVrOeuYc&H_8~KdCd1qQlNc>hb#20B<-q6S)JiBtD!N9VLt)NjfVBxIN0c>8^Y~O z!3SvMGDX~qb%ZOdKZtt;IG9AZiAM@_0ihLjF$~?M-Q`2F^_nAlx!!Ex(G}x!f7tu& z7e5!_yh}7kwv-4Hhn95G)jbtPz`Z(b&hORAnuyVfi3Wud^@vt65-|=vLt58#OP9=- zC$B1P!(xF8HmR6t7x3o*qx{v{_55>hq0Vt@8dm2L2s(qQkGek>_U0e0XxWMK}<^83DHR)hTZ{j6J zS?W>5Jl#&r+-JKlYocGW6?39!toB7rw<*3*?(Dxi$?~ z=2bvdGk1g3EZj)RG_c9h9~rRxkz{otStY7c&|^ZcTLM?MI^iCK4g*xvcv;%=+@QaH9!@%L7Q?{Mbf#j(Yv>fbgGq zPrGIZ;g~~m!vEq6m$%Uuf|n6aRmCQhhsuz{>)}wH&Th>j$7eB=`d=Jo(K@$3j|WSKp2oh^O#E9|t*s{oID%<^`2iV6lwwea%|}OYYr1o3tyrK-xd zlK!Rhc0jad0e(emrRy7%$UQ3Fo_``y2zaooZQiiStF1&n9FM&9!A@z^^;Y>CNokLR z*^VqJ1UI!SEnPiyd>cz{VD+wOJ{U*P@vH2dkTvBE`(yt^nh@;MuCxwnU>j-4%OUEJ zQruo162paK@1yT`oGBq#41%^MjHvgHYn>@{f(yvsvZr9OePoH0-qiP^XYM#qn=3W?O1b1_?OOu)CPfm z4=CDnpE0k+^4=$@Wt!WeSqM{;^QX%b2ngLH>-2 zv}3rtj4ee)$ehzjyy4rRm_1Bq98+5jrn<9*cIW|$rKr3z`SH0!}1F!Or9GCPf@c%8M>B228VRq2j?VZRP+?$VX|}l zKysamYT&)dFe!|fZX?5gZw_X9tjjdpJekikBc@^;hsjc-waOxtml&WFnlM6f z{&NqR&J8iO9z)ATnN9W?gF~GkkS4w_ElOE*G-KC!WL7|C!LA4mbp8k$XeO*dt(J&Y zY^wX1DjHH@pOUCH)C~xbUMUEiko!sAm<*cXz-SfQ60)8|)_7hU)(fP0h-sb(r8yEk zM!c#WKb`rIO*+jHbNOaW@j;*X2=a?S0sid(zR87Jspnu+Zg#|#$I^)_Xp9fnTpD31 zwD3<*+_54~I!1O1DW*y#o7kBsbPGw>UDHiNuc!fvG~h4mw*tw`b6mEcA+7ffw2=WX z`im{`3=A`0{GkgnirLH$PeRUh+6LFFeU{0dK{E7e^EoxifiWeuj8VxuWT$Jk+IXVQ zTlKrYsq8=sPsm2JXVUpa7B+0i>i*t$i1{vnx144SP zC8L=kM({B9HFWv^;L4vpTJ)uD`J0aCM`UoUFlb%=$bGy3B2f;8_+t`hY2s546JyO`OF4<*d^uZPGPE$Wj<&gK~ns>Hl#A!P3In8JqPNd59y&TsV z*@C~#;>9NgRBmKLXka$em$XE*wM^Dg2=5Dlw$tEwe4`kZK){0mHl9a2zl?>vL zfk}5`QoOZc)@jij4Z2#;*%ZmY`Zvh^*=FeyCVKR0#L5Bse;Cud{@+09gW?HJOnWgN zc&|za)B4Ldu3tMs&+*rH zqXS0Rg+AKaCm65Vs%6 z?VR?wt=!nQ6pDh}*tPIvuGVieekQkF+T(UzJKXjPa-%`LCj8@a`YXAu{Hh(h4Kmz< zrSNwDKu$Br?ST-tW^yZOkK6ayMoJH1hHRP6G~8rTmBoWQ-TiECC98wlWA#tNDp;UL z23cYK3`ZX0rKmudV>k+?ieG0U2v)LR#4T0+tO$2Cc&~mbvm*KJM~s+irWRJ;xGjqDh$xkZqi%SS_d^*wgoDOHw` zBpb=SfH}vaNGf&^d z)e;O*GFiqyZxZ`91wtiy?&+|QKapWpT73^3z;p{FovikNbxySEZW^^s*F5?KoD91G z*-V+f-5@5vNGErbY63ltP)xDJV(K0wL^AaO8Az{lAm+Q!M53FVrCtHlaXgwF_XsJp zdkIbkXQ{uFt_2q)$SP$H+p@0lzQhcn7Y6G4F!EUYIoaAw?Gvqf29}EBbt|;|49I>S zhLieXQtS2uvjdGBUDJ# z2eEY5k?uZCC;b&zKYoN}Wz68O8@;WqBMPOuK38#Ws|4up%p%)DvPD&xf(vSql&ii} z|26#fPD6-u2DpLbdx{p;bB}a`tdgTzQGUOX`LdLOHL7A-K=ey-`e8X7>>Z2Q6!t`j z#gTl=vh|YN9?%B`jhXlGQ2jm{5K{+$GG^)d3f0Vh@WG^xK~#9Mp%|Rv2Wp(`*{Q#r zTUpK`_{acwB_6V26QSSLh^b>hfCWej!y1gda-+vN?_*zyjB~y{&aX2rgSRt-Z+#lF zQOSYv4xlhaiV~7n{vII_dYj@_{V}jfPI7GiK{k~kHX}+7X9;$o;v79Wc6XBa%pkk3 zIJoE@2IQ6}6D%EN-Z2_-alB+!!x)$QPIM$5PHS5Flj#>Imd)^ zr7FA=1Oun5;U=8b(QU&Fgc0WbN^q5UZ0xs`DR^Iqix3!uKM!d9ub>Y(#|xyrpR~}F z?EO()Bh=Szb{3;vn;@_iiCR^Gm&xpOGP5;m6W4M2GcjX=v;Hzt9waJS-xrX)V4+93 zDO~X0L4Wc9F?fLAa`Ichj#;++1hh(nxP!J+3116#Dy(3VM?*;jbejQ%3PCW}0Aoh4 z@j-3#B(Ig7;TZa@##P8C+Vg2`lkmWq*UKeAR1#1YL9GiUj|P`{iebi`t`h?W@+8kC zu5AdKK|pmHloQI6U>*Smd1_Nd-==1BLYxG2r3QtAlVBzTgVoo;-1#{=WNCSq@z@YA z0UgvHFTrF11FdA;HANn9*|bsWvksH>RBrRf;%75Z;;~S^1p6+qrmUcgsTgaS?m4FO zYjtY0Y8?B#+B2jT;A_7wjXeE0E0pFyOm++S0)SZoe}THF3W=(Gd<&0nFcWAa=VC&w z0QKsjAW`Q_)`ebYX#-W;Q^e$ljVqXzk9^~rwh_sSIYs6iS_nS^VJpueC7yH(2*VH) z?LR52TL}})Twr|bJ4>+V=v^tPY*_ALXRyCTg~S};F|@`*a9;1mKm0uF49d%jd|JfB z{E+G%S?{eCGEJ0#G68CtR;0eh_Qp_xBoln|VIZ$nl?=|h84HnaCh0Pe;y_Yc#3ST^ zXSVTL$vY2pUCPk z%JsdlFj{pf2Wz++GfOcV^Y4AkJexE$XB9U~uRj*YE`!KNpP07ohXJl_!?;t^gz5qh zwRtN(@XM1SDBOS^DT-L#wvm1==$&qBP5MmZ=&HWs&*xkckHogn!-x|dDp6Rz-8ORb|0b--mvY2`q zfvB0y>a|_roxF3)Wh#@*=Lsk4*dwD=kCLX1xgH7>%6B!UP&%VfhORe-GP!@SP~Oxu zp+f0Gd51!tsbnnSsyyf^q2qWg0ENiAlKhYNg?yUp`Ux@LcS9GGBOi1z52YD7TWWXa zN_Qxb)4j>+S+EKeFM^qX?+~yp=pLk;Lr|!op_nukZKen|gA{Y>Flr9F<<7YKkx@Re zdS~7wjBz;uVAsv63mOq1{I>EW76Z6Lka@s+e==xUgY1{Dn2$2yIwkr%JrH0}Nv@G% zvs(8iEg#cx`P-vplwIzlAhfUtkZ2)^qDyAYB1iSJ&buM#LxKbeuxA3@Q_A5rD$>Vl zHRknKN9_z6Z}w}7=}z8N41yT);#MI6;-F-fI?n*(z4*mL@Ibce)yh*%hGVpHZ{0wd zNqRob>wRA@+U2{>IGJ6k2eyVVpMsiV$k99xB~ z%MBuiXc&pEbBxl!D3?mJm<`Pdq?zC|`T=)AV}Xy1=zfNXJ72v1nkWZ-ZhQu?BZ%D{ z*p_Mes8CHGnF{soky0UeAOfW)R88;swISJ4mIRE1Lh^VYSQOnfsUcIa%o*=N>vTmC z^6!Z(+3=bIYamN4gZSm!h=&gKRdio>$(_GEWrT5#yt5S?cuPh2wnUQRnCDLcW`7bOB35Nb?*! zFLC|!gTUlA=18&r{f_Pz>0|=>03amGgcg{{<4Z{Dias){0PhisS3ofyQA&pc0o?}> zYx~fNqvvEvb%lbNRPfoYTETcRvqz7guhZR6`4=Kx%c47wCmwzrlF7c^Z0LG}!$XaJ*V`gspDTnSPi=pS>-a zHZuc_4*LkP%QcqFadL{e8ZPs!Hf%mdqI*E(ya%IQZqh5%Z%v203@Okkj_IPR8OSK7 z2FFxME)ipP@*CmnX&FdbNA=s|@*?FWWat}?Vv9IP#ypZ??~jh{l5b4$?&$boK80oy zQ}MI)^D4&v&w}YYT=)~>P`!}00(AWt%%+>D57M@kyFFwP1+AZ4CUSjcVhdywFTqNAf z&p{8UCjr(_;tVI+KTR3ai3L>0%*2W&V#-lX?PV*2pm=?URE9ayg)6Mqe^^zAuuIz6 zK~R6{C}290v`oXEf29)J!EBCnUO<-zxR$z{bR$F&%MYnn5ZYg$`524dPI~Rcg4qig z)LdN$0?Ae~+4eUi|9PQgg82d%`&2V0#sVqjrO}m4iNSO(t=lW4=4<5qAn_Oiph1$g zHPq1ni&Z3%>mEG*ERF|F~fHHYMx} z7GtXCGLmSE2s9H=ScD4#$N`>9^dsauOysR@l}Mm#0Y#!5WY_KhYGT%N{K_zN5CW;=MBbStaR{lQ(4SPX zKJkN$2C1DTwFVh15+_2*KQ94$7?l52Bly2-ysj)=V1eJuU{fsnNZI8|*+tGG zteOUnM5~^l0jC#+8^6}$hFP*2V6S_bDB?ysudbSOmPqE?UBsATq^)G$O|!`}J78c0 zX*IZBw4+udT6rr~NmQ){cQnaW_53Rf9!BkL;hZYedK8fUv%E3l zqRVy?SA!T6ded|~63`3{%H@Ihnf5?DpJOy};#eK#7$>|nROr8G@S>HRxoM;No=9s{ zZ=p8ZS8CO(_xp3zxpM2(gV?DqpqDi$m-h|ufq993ss<*2A*gV&S0MTorzLm87)}#i z=!jq~(mG3Zq_}g1cOZBR^dvwLhow*Ee8JRpcz{gbWoh@}u}*I;K za|wYwK2trb&d<3(KV8n8MHxM$ZtDa)*^xAFjceBl=Xm z+&r;uRUj60r-B`sooRVafTY${!UW`QBeaY=1q!Sm2 zE|I=EbQ&7HO$u0k-Y!2!MxR>YEFcLl7By^q6wr7Lk|49D5$#eIMy&_F9vHO>SwF36 zAzUnrC#>(O<7P|@QeXq=hWU=(lNzRphIVT5m}pf$II&u``@Py07|z2u7$DYA5dA54u7fktp3&N2j`y9*T8!r;)+-uhJ7t%hGMb0zZ@sYz4_%adA^?50Ie zHKgZ*6w{(wVf7+-hC_kNRXZ8wOllqa01D96XyBc$IuA; z3pbW1nH4^$cz^;*^OxH!M~A1x2wIsihVtgOS*JZmm=%G*|GL8aU_^azP7{%aHxQDnQIT0B?U0NSxxGNoeM;(A- zxL;($(@dJCF49R;Z6-d`-;ZJ^4Lb5_6h6fY#<%aJdTJ@v!}d0*BLe!6ApaD%+Lc^< zH@J(5o|Qy_qtF7KM<}XEjMW5>)kH>!UY*q%Y(B>Q*dKwB8i*@$VAv)cyhV`g^_K89 z3OzvHXND9K(D1NA#W>pp7PyrbLlxF>URjp{z6`2Q0j8D_k%**R{@>XUSB^*Cegy@A zl8>K<8z8A}(X+6-%AvZe3V4QrmAe52(WR^>uZ?{WGVmAly+IEZke$=t1a(V6L-GSU zL+MtjXZ0`#N8>zdJdui_A`=#^+N7D9X!`bmU$ z%>k6%cHIM-#A+xr=r^PC$M+0zSxzo$2?VyTTv#aKB?m&V3Iw>3D<=SY4xqLNAaM<2 zgq7_ZXrPH$oR6++ZW zUPj~m@?B#0CRTecM#?I^H(2@U-y_9uizU06*$5SK&rvJO30fko?nWjir#t)dhkjeeKr%ZP`xI9Zg|Cjb% zHG-3hCTfv~UNkI9ITXQsuzD*Ee$5?}&6tE7kDcji-cF#Gioc1n)N^(cvY-jMmc8IB z^*y920k<-&v!K6ON^4@Whmnl>!{jIueS6fNDPp*6NBRRvuQ8<9jqa0v*Rq{9HZkBw zlAQ)JI3-I7&N1+@G)%+9;vLmWO&U<(CzAIjSG``NrQaQ5`7>!!3`>+1SgyrpNU}^- z(?X=bko3c6wRDt+n?Et?{Yrx8Gyz+HHUwKp@Hb7M&*d_1nAFWgUa66sKGRd62Dz2U z2^z^8GN9(~+YmwKust+1zmsNwrkSs4PHMI^tQ4kPwvlcp(4kxyAhcg`jA{tBlVI~R zLcn3QCcvP|68u4ew=@CoA<+cfS7bP}kl-;*zyY)-FnXq-)9EFEL@BNY5_x%UyVXT#H-vK>UMo781Zhv=Au9I+ufd2yr6C<9(mp2BLt7Y1F^+S~e2MXmVR^;fZ1%mP{NN+cVdumPe4y;@Z z1#{)9OD#3uQe)|!inKx(I&?1X3+#;iH?r&A0)P4&=eNl0g1SAB-e?)EmM8zOzQfPYc}CK(|kvtTFW`=KqqR|a;)Rn z0bMrCpN$B+X0gmFjci#l=HmBvlN3@Hvb0z1jI#4&?*ina$Bs-G3=h$HccOO-M!eSm zT}1)i01&+6U0j8zhM_MQKwSlt$&*5Mrb0CO!6~4ymGR=bjKT`lK|jRK!s2=LXeCc` znh%KCjgt2RFL_+PNqyTJO6US)At~)cJnHBD_8a@HmCGfaHa1g7@_PJVzkxZwptfaZzfxfWH3Y?JY(6j+B5WwWplftB+YG3)aG6g)wxJ) zdaJOK5=5bK$PVZcFH1*oF1?7UuLTAJs z+5lP124F<$gSSJ~76kjJz@QmUnyHaGb36AzZ z^N2mfe4^O$2a5p*F@}LTAx8=100Y7543qpul>!B>X;XxBt2A*sG2ffWQp!M#>i=S5 zr}~rrr>K6f`K0U|N&e3O!=3{92OzdPB6?yTfP&8RS&5BK3$V%(g0lmxx(Q^oubW8E z@i~a$cJV*OaB2Q$9>x8{8Dq)FV19n-e~OJh^gj!UeI1`xXLO)~7F#VXEG@PqUt8>R zo{1BZCHWmh&-V<(*l>o=Jd4aP@;@aP6a7!g#Yz6Bw+dr)2Xp^U30iiRRz1@zmMPA1jcC0OWLmydHp@A&}<+knsX} zAOM*tkXsC-W!e<#dA_en5kJTIpVRm`!vCDX&p}SlS+f|92t3}2n037c9z-DC%~92Xf{Zg>=~Si(~w&XWWEo%!$5BKA@dES6p&u65{Ue+zl60hR6$3WZtzFjC~cil;P1j^SaqlI4L( zF|VemLpHPIWH^51b1+`}&n}qT;J(f({F28n3h*(5A9yv0(;j$VLx15J3|ZS4Om^J> zAFJV+Fz)#`;L*B7B;P?sr@~|f6m9#B6?N(6@e8a_YsYCHp zR13P%52K=$%R$gXQd{+$Y0RN)?M8HcDF zov0kDK;47sFRIHy5rGB!+M}aO#^s>{i@9RGUc7wMPVAZJmpzcVUC4Qu=6tB*+_OE- z%NsMnwhP$0^t&>Bnoj@iqhf?SNsEUM@QK{#>C(Y&?a12>f)eUcl!CR@MB*mVvz9WQ=3VhDtJm_card{thwUBBXTob_h0GHtUHy-CL%XJ zWK6?*tPt0|LeV z_-V$gG1Xt|vy)53$S&%VDcglzG|4xx515j%QM-W_!xRm8zJs6ODYKav7dldAqHyV~ zl$1JHOe}Z>u1ugM?_z4)9SLwCH?ukZ)48FpCFE4TLWs0&ZH6W>c|{$1GLos$Mx>vy zNmv#K1NwnuAgxv+vLDlG(O?k>I2|2R=4uPdg;{nv`-%`>AIY5Gm=0$Zc+6vC8dH0S z(WI#imgBXz>CDe#iI>+kgfm}_F`CJI4(AX|>v|#?pDK(8t2;3muo3M{#|8Pw#JrZZ z&aoOpyBPx=>@@dnGzi-$kj*TO5@jmnH4sz&kzXJ5)ubn6X!=G#VFW{OoZ&4^Y9!Kn zFK9ACoB@&ke=y1$8?he{vq&0=B zdFHlDZhT=^P0q|16@Hr^Qo(T7*({hZJ;e7=x_$?vlH=<_|D^75;DpcsO_n~OwZ=P4 z>}NiYD}hYkC@)a8|2kK@#7(3wujABApgzp_#dnFkfJ>Z7mpBd#F)~&+U{GOQVz}ed z$|Vlcm_SCe0Wsz1yF_m#F0q{^D_jgV5U!5d^+@44>vJ}Fpg7quXY?5j+!y@B_hv; z$QYsTY(=Ky8uFZo+@Oh##TWoDX+v!Mc2bCxe22C}s(H7yCdj*K^2{;O=f|d*sV_Ww zA4vn_uu(6jbw2+R^Q0HQU&u;n=7r~(?9xF}(~O~#^T6X38e3C69;E6^i`-A7UqLy; zd}El#MxPmukghfd5XipwCS?X9J4zQ@mG zQ6Q7I!KC@{2=Nfy0dq6zaC|6&0D)}XjzL(770m)(eVffH9C@z|O}3+XL(^<-L-RB0 zsNwUlrs-7MT2{TIDJP8^vZ@)^bI2!$j6@me@qkaQkF2YG%0Yv2M^3R>eK0bh-r!KK zJ;Q!_x0oYjSRA5{yaR)WZCXj2KC#Jn8p}G0cGcHjyvo59 z@FX6&{EIX`JeTP43T(!el`1Z0B97y<_va{o9tKe-f4-f&FqwdLre!rk^pF*0yK}QY z#i*}wm4mg!-$O!e!!Nf&jR!~6r5HNqm?Rfa0fm^w&eYAAl5nVjKhA0(r>ZcXtJ|*Nm_Km_6{v!@ipT$(ldgBY^2!{Fw|} z{eH@Ne02yOFz8dQ5WZdh-U{Jo z=sF-=oy69O6z`3VVlCs20$Ku)b;s#gKiBRks7HYcWW*I`w6d_ZuRTHbam`-bv9b~2 z(riM`bTiI&jukpUMRuP_$|Je$XX|7HYrUMJH<{>74H{f{WS7qS$6~LWRDPf zZUB8qK=N(Q$>egb^EW{7w82Kl8xgpJk$(bHnyy&168mAHBSm3INN*|w@A#8n_L z*Ho9ojqAJVt&gemck84!NWH0MtE`6x$>*IftS8+gpyP_Au3>M?414e0$O)=_LONwJ zwT&6$nr2>#hg%!y%0*S^;i-Q%ZpWV7SGRky(&N37 zck6D;KQuKuD}7h&U>8<3Cf3d1$n@7T;{CkS#fNl1h2O*RZCi!OU+8inoaWQ6BD+YM zQDchnjSuuzxdM|t;xobxsJ;wlEBx&MQ`HNC=8J#H{YacU-d(Ll;8hPzn}QC3{qGTTQp;wO9Cuo{OjF2?us zVDua7ZR8?$z!iQ(tuKIH7_uGH++E5}R4^}d1Og44*r&o@ZNupRi`rtt z!N$I(JjZ)yKo(jowRM)Ai>bz19`@wwsx6f>u+rz2L=A^hZ#TnXDL7!-i^es$>pVV| z#X;#k8mAm?rniB(JXNkyjX*WSAicq&A)bXV?gVONfvNSN1h`(ntp7^DD>Zm^p`2Pw z6fDB{wO}d#L6@>*HK(ppp_`;yjZ_OHRYIqlUzn&G4+Rjs7thk0r8}t;-bW#5ILijX z0uD>pYZ#rlozy5#8M|X=kzt5G&D?_J<5}JiX}EBf**{)W17;qdvy(BIj%0dAmtfw~ z7&<9B1hRai|HM=SP)>x21EIhV+8g0x%Z1k{4beS`(s3bn^Z?b;Y=lDY{f?cI7rWd>F<(!()! z+l0x`kk`z6&msZ$do5bG<7r%UY~^5_m8raV#Ube2SS z!ER{=wXgdE=9P-bM92e{ui+CF(OMR@%X$v7E*5O9(Zl4{BgF09ZQ%AibAnBV z(HdTi60POyMq#aBzQN3AYmQve^4`KKg43^*952uuvElGk;mG&NoPuQ?d9tifApj?mAUj2s`4qkR0VTQomT&{0@#Ul7l>7@CbgDUFg(Yle%LU zdWPKI|J8S)9Z40s$3W){Gzn6ZCqiUq>7X(mY^QU!Yu&{ZBCnA8D(}n0or|OvTnM%y zk9&di#}cX=D5=G#uD7*V&<6n>sKwp@L|W*;XvaM#>iNs0n&v`d^jvfB2TW;V{-mAC z#uS}sZ(`EGX+a<&itw2f1m+sxh#)Y}0Q&`j80AUweS*Mz1Iz$W2P^})_6oGuR<{_F z_yP7EX8GNpktI$63ePb?>Yk)-V?!8vspp%G4JND)gspgAej*=V()Nkdd?5x`x z3fk>N(#4T}Lwfv>)ua(@J}ly$3=zpN8p?-rJ6l1Aye=P#1LjgD%z4_4gifbjwM{Oc3U1 z26^Z#g=*zXA8C_h#0Po2WyD&=`-+5tEvJE33fuJI3cS7|CbSJcBR<0GCSY9>{Kf%0 zzf~XVOCI6Uhzk)2Wh3@>o_M51M{4{f=e;WZ#MTI+b9ib>%dEE|1?LFj}~ zc$k)LYB(NLX`(GUv!Y_$*-9{Dj zmTW&_A6sre<=p}JrTCA%^YxM@@oA~-rcd}!B;WzD`ctH=>yagczK#5D67*m-u2|5k z9a=hw7YjO54b0Nb#Kvyj*7}L!I=h z6bRwr3>iouLo&sJSsA;P6{jy&tu*xji)V{o->$bb;M7rJb-^MY=F$SeI9rPswX_BJ z(^-JhU?^h&Biqk!HBQxwV3wtjy6s%)?0xxid;=I3Z46MP4e-b`Yk*NJ#Q=nd4PYPv z18^uzs4G#CqVvO_E-KL5ilvWRms&+ezs1Xp-ePcQlZIgBpm?1sqhesV&N%&Y~RPK`EI4FjbZ3XLXF=hKRw~>d;x&Cvg#<))W$HrI5n3 zVtt?1h$pRx579~pl)W5*-u@fsF?d#G)7*R=r)4pJs;JxqD^=ctR=*_$OUJjM#TrDl zEa(9ZqI3(Y)gYS8f=UVUTMESjoPzNISKdW@2GTpcM|?i<>}CtW*B1r}k|fv<1n_|I z>}hl^5>Quw&;^zCh?CxdUpdrvbfb0CUX=yK3aj-Wc1L-l&3%K{w`5<31jfOn7)dryB79mashA?uBv_vFe2qTnxLxTRvChsxeATPz2 zXS)*}&?)tfCe|-w0p$W@%lN{#tkDFuCs6H{ad8=X@EuwfQ;N}|6FFCi+;n#DL&(iI z@?nvo;^j7W?-9YuVQ?wB&)>9K2>Ne82egoFU2VkQL>}##xseBGhtyv;0!i@xgcy|b z)wTdnWkPM|9Z($ZD3Xt&tQ*-D&C!h7l;)6@#kMrZvx=d|+G7WNKgJOcbfrxhKZn8Q zG1#_c_4*0-k;c>F9emGQ0CLcD3(&krnhx<)pQcjNynK=4^SGwLffG|uQ#8%v0h${% zjgxhZrkNF>`HQAW_xWUNnll45$7`C1PxCYSyEww5{q(!ZtU3}YV`}MH_+ZaH2QNwV zVK*`|BF>@q1?XY@|E-}-)oW&3VWEZ*7N2SUXBIzynq;wZ>h4SbQ|1Le^gm^8;C25qk7=LxKjl!}0(`coz%4$R zq$>A6MV}%5r|5H#|0(+H?SG0sUHwndXFKjM)>#t;zQd=lKwxa`2SFK_9E->xv*s9} z*>!(?qb2(9f#cv!;B2}fGA4;gIz8^j)+xr*A2Is0^B}LIlc^gaL1B&3A76rz9(@;a z^le73or~@!i>K@Wwprc&H62gi8NetUn9rUADs(t)NWSuA>QKv6sc27uPQ4sL;Z!{%6g>? z2sm{gVltmhlIZBlG(j`ACSXuo01lDT0cA%T`CJHr8m*Gv&!mf7(i|r3TqId}l3i!t zP;9lm8wd(aeV)Pbjx_p$z5-|+iVKui&7xuz&P~xb2}!#c&yNpRN56<EwzI~v&y3rm5D*T&rV9!ZG2yJESZ0uv6_g~qBjW|?-4|L5dx`8` zLO;4)VgDj_p2kWCUH9gUDlZdTrm@o5k5`DEqS1LnXUn;-JcpK<+MycVPtea} zP0_bP9aHzz=p#7mpfft^YLn68Ats~x3LQ?5aCUG^b0N;Qk7iNzd!w-5`!Fq6chMDH zJ7&mQ%xJtzzU#SCmf9dw$7puWFPyU)4P812L3~zL48d^pkOok{N9rd)jUn2Y=#p;Z z;W>qKmVqpM118B^g6(g5_lRdg$J%4R^9|+R6tnjXcKT<}pU_ui* z)dkHEo}>FY(OND@pk*j&<{aZkSiIMnA2-8fJ{Mgp(sL(7=b}bXd%t6aiBsx}pGOfR zmSc_8Ob7kW?h$f147R`&P=S&`Rkr%Vz;`j;`yDuvAB_<@&u6TBK()XG$w&-JOyP{)Ml0i>D= zD&2_}KG|+L_4SmpLbLMQQulfa4u#4hGlB^Yg^qS#IC40`w+W{t#?#i=k@#>FnkXVe2)-(66akk1$p8^MgN;T`?ulQKR`jA zIe~BT%=N!9PnSPhFS>JRK5TSi9`lXglZKD6ci0pxV5uP(V(FU=_5!5fr}IxP^Amzb zIg_oMj~CCx@g3mcjad#M4$1XEpVUP70K`loNMat0<(W+>J_BK4nF2Ks&In?;nAtNT zGo5DA?)&2M+iDL;ew!SSE|?2EffvpR378x8oDL_4T_NEH&EgNIpr4HU?bb6m;(Iq> zq?s&4r&Bi>5{46zRhkks&C?Cds521$)RJZxE)mJVAsW1ErEW2t-n3MIpa&?Nx*1NN z;*<_3k!GQ#NfAz$Xil#RzM~ppIL)$D&$Z@sm!<@#^DWJianz|NIoYmaK=``VIW;vU-kc^a*-7_4&qLvh5Z#yvFhwQfnbuIMmTtWKl zMOI!b=p_QpR0|+UGZ$hGpV<^eZkT5BnSncDASxf3P|e6Qn!4+Oqbqy*^IH9BVm3sg zq$LC+OfwmV>t%&yoF2x#76Eq>^P7Dh~yYFD0i}y=W%8;5jk)& zU6`+yB>!quJ@zzM4K?XlOmm@VBC0>9z;Hi+CHM>q$KsvUKANDT+LZ*hMeh^O#;v|7 z8keEAV2UZ8hh?Jg_#->sNqvPM$=>lSP^~8{CBBPV!yj4kZfZ4uWX5+@%QPxoEx`|4 z1MnzosE87g0amFS$5N@C)r~q`S2a`r*h!V(2kwW(|5cp45)pNo$?D|;P!hO?U@&@D zfoljlNVvjfP=%PnqzS9#k1dGklCzND6C_wUvf_(WoT5R3m02c)BL*^!u#jz4ngg!i zZYwCARM@^4bBRp&Gl?)(kiy4w4M@}Ex1X)ixSCgdTj7lGe1g-}l?HrOSpyYQ!sS!x+Vx>j`QvLi|3;n13Ug1k# zLdmy4jLWZpE)PjY2Q_l*CC1X#N48^Ww#O{h|0MahB{t98KIQEmk}RMt-v;uG3SoRD zn}PKJtHV)en*Ez}F9={ zf5xBD)#Fx&`bq3}1p6nxaOo9=wG9};CkxubWJ;Suul$B`t1TjXH!*<^i-a>~G%1`T zILUbR?Ly}Ed}2}+>6{ho{=|yJ`Bs#4PM*POL$;685d~dP9ZF2mn1tFoJ3xkQ!W70u zBK+yw)F7nipVbDTJFVkoOk(y)x3U@2|0kQ}fUmI`CZcJ&ipD55fM)R)JN}$gl@c;2 z`?WiAOX7B9P=jmNpavH(C__2r23)axg&_-=_Rq+|MrK-LqL-#UJ&IC_YtS#4OIT1rhJ7-8McW@$=DROi9z@_ zVZeyVwrq)cS|&CNsufClsJ0TPFwgW$zwi)cWq>HNj#;V;u9869oi|ltzizC4LL%=} zFlxUS&b^ypV*0wf?1|X7p?62}@MDfW+1%9J`yQW%rEnQ@J z$*ou);$j2GOF&Bif-%`tr)DMD&y-GqG_-O9*6kz+bdHZhm9%}ZXytn7k4G*Ok@**x z2Jfyzf(;%ka2wU67tzC4Z5y+BR7f=e?d?>XgB~J;9BqXRa6-5YiJ7U|kJ*uyUFZg4Z(2rW84(2L8DKvElgInCmceO3TFc# zZ}YO8hYnpHhgtYP!|>r2erp&$!osf(!wW6^+%SBUg^wiMb`&bPQUWbl`z^sTolpV- zW*#hfK>)0qdyBa_gsB5ZizyCa7(^^)VhF>qWHI@`cyrsT_2`#kuhwea5&(zQx-x_b zsx>);392Ay;rqYav@Mv4z}Q?5#5A$3 z5)TID_$75OCZZ4rjyyLIVUM7I?{P~)`w{jDZABAdB@R6BxQzq-nRXe{x~M3i`Euz( zw(;H`)XNXj!r~mC#Q?G>4Y3fA-1Fd9!1c$0MKHDwWU?WmwVQYt&S;s4Or8?R-VhRI z2_gG35}kcU(aL|rYn*Np^jAJ+vv)MpHsVyL%btLi1LR`IRn*PTp0JqZvp9w<=7m@Y zXeL0YLHT*EJOzFe;I=%cVvVyE;{$!h$CB~z5Mu!yU>Nsvj0N5=z<8&&jNkpI&Gd0( zoNNqcT0n0D#Ncy;Rgc13sW;o_ay+>_9O5FN8vt@~wL@D)3Vas%WN}`Ig@8^F7B-01 z9n;D)hBDcHpb56Ro%EEHt@x%%Z99f!-`3`DDmZhSiA3PJ!H+6_V7r50j;8{qW2Yxs z*^y|MHSQMGX}Sct4dO?d!5kE1{pHb6TV|dNwkxn9!0(_4*7VRcmkBBd>%$VL7?aL2 zos4}8FvDYbE+q@okS_c0dF^3&y^n_7^139%D-qc=Sqn6x-X9vUTLx%-BW^tktJZvo z3|ii<6X~ADSuD*{H?lO_tG?|-r*v$0*J&~NjQ$_ey6P*SG=N<7T?*08jU_rQf5ftw zLKYi84YCl>GJu>Lmym@YRIsV+Tqe64G(jIU(dm^*f#`HT38xETd)aFzIvwEaHkE0I zg>(~8FVW2g-*sH^4M(R<58LcrNER&{g4q*LBS0>De{aj;KA%MqS^O)+LO}C`g{`Hh zwPi8cXMqhqDc;o~76O_GP^%az@Tq`Xj~h0)P4+tYjIrMb=gC5h1(a$S2V$hacM34} zILjQi+hY$|yJ3qI`oEt9?IxfF0EJ>Cg@-)j5~eICSzt`?KSU=#grp+lMX6}LOx^lH z>-*nCI9}x4wPU=R7noeu$|Dt^cu-3H?=xDi+G-b@2H-lQNeLQ?;Jl zz%Bi9L6ey5eN1x~wj?vGj;Vu~Y3^gdjSl@Tl`z)< zcSFY1$M^p4yU{rRjyO5*Oh1sM$EPM=#=t8Rt53OmVG!JMzjjq37D@OsPkY6Rs)#>Z zghqtxQPwP@V-79yjsT(XHF;JR{~Pk+pdhI z;l3CBegcwR?A3t^ndemo$s%M3hhg&LBh?;%hYiAFFY|5#EyX&Pm&rk}5X--MIH#vs z>M2%i-+;jnIm5W~VY{2sG!LcHk;)r6L+jYi@Wy~gOr3;(^)q^l7H-EkT0OS*7;?{- z?}Pc>f#0{t_ulxnr+Z4?b`#_kTY+1GY=qx#W@=JnG;huPY5<zvt{5-h zwkev>B+@Y3~4UAZ42q;~UmF$D8-v!EO%{WBaXf1E_Ozs2VJOS3>-?9_& zJa2jPeEcl^x~wmRWn-e8yJwu)p2n9qOoZj*U#}Yn9OcaqFwMAV?P~l@_6FcS0wzRj zxz#?oD*&8!kJhZ?zqM=eui?%Fj=P*){*nW4wF&>~!}jIP_e)w)w3efDk-#l^(VE%( zxAuAhqu|5ci_w~0V6U=jBcTx>CxK5{de@5tzD|@J2Nbuzl@2S*Pa?a`JhIGPf?|pn z`SDHJCx#U><5)e1FK>{r8bDT^ixv^m9l!0)J4v^^u>;Il2OI)M7UzBZgUYh;?q{BB zDdOY3>LZxcrbSRhY2z&It-NGUAC-O;zp>@E6R)jl1{&93G8o-r+96F5v{(*i^Vf z2iVTEKOt~&S)EsR*wPmZy9@PE%P@H&hYVgLHEnh$8qI-ZO@DXUf-1O#_aj>S=RANS3e z5bmy37RMMSn{m--)+hTTTIH5bEZY~`11p+)Mr&L|$0_1kaQ3(t9=N{InsWRqE0gp0 zy-M@SI)Q?nv*eXP_W|HpLFJTAE}IAxZ^cPY0_wohlgdU4YJU*j0o2VziR{Co--xc- zDe96Mbkz_`5w^`PY3{N2{*65*?5yd9Z0<-l*o%mLLu0vWr8oN4j5htVo4cC+Sv%Xg z$EcQS5f)%qOm^3VgauS7A$GFH4mNA*dV=9fVuk^O$eZ^%hEcMsJYv2w-5k$AFJ2WuCPoEx+yiA1& z9DG4Ffphsc#w8*T>O|TJ-y`3baaPKX{W{zR(Xs$3sD(h85um$3f^*F@1JpAIRMwEq zm7s-svV`oP+gMA?WMD8knhCRyym5us6ELKgI~qC{eL#w%NWl?eYC)67>xnpM@<~1< z$sQoVv=Th(1?y3}F2Tg#UqjqJBI#xv>_RzWejMe9<2(gTX~_ux@Sc!>+Csbx#71qe zSBTfgSafHw73yS&FZsXF2tQxfjUlO$h zDD7b5ZM|Bu6bswFmkSklpka|aTOY$})CaT#b0sivB-sdoLsy#fSL8ey80(KwfB0F< zaYB%6fGCiwQdt?`xxF0zYqIH1HWI_JpODo$HL35hG&Lznq9(m5%`c22v|%tj7xbq< z+X^j@D>L3P2u7>cuq&E~R1^e?rim=)A&o7XFKTVs3hL$nJHKfDjV<%$17c+p#zfJ| zj{r$VkW~c@C@WGnI2->;fro$^Hnz8?j&#hn5WSNy!(KU@Cqs1SlbQmL0B#rhk&(ID z$71Thrx6|T8gBA7ZzrhcWrp;Vy$3Jq_cwIJm>|c?!69Zje1$XNPKg#OF`FqEvBGmV zor?r}GqBtSxU=Q(AUGtCF5+2tfVYe=fx9NeI1Og;4oA|KX}O?UW2tTil{Z#LT~pQ_ zNtzzeI$BwwjcEunNbp5clpHL(uKWf|P@93GhL>0&sUcM|nfxK0ylox@`Uy7HZ%g(0 zLNJt2E}mZu3KzNg<&;-yz;apF$84$`5pi!)*!)#}T*9b+y{b8wjEwPk?=yVw^W#vT9;a35?p>;6+dc$=4!`r<+))742t9y`HQ zro*27qeY#3LSQ(Qh`h{HZXi|q68K4eWG#LfHgjqH)tj)0RL`RIa0c}vicL=W6@7+J zIj5^$C5#hc>RF_djqEodBx?rfzaf(5GLo9v$MU)*bSvM>Po{x!xrz)NCxRC;#%*MQ z79k1{w%6g|Wy1rlKqnpRQ<8nq-&KdR@?fQSbOKXSK5NDXZ!fTxL!Aid2#r}ID>h}Y zvy0#81aHbfXpE`fxUWkKNiXRX@2wO7Nzt9HKrsf}IqF9!2N*l2IrdB|Z_2G`&O(~0 z>N%Z8=C3fLKd;VA4VSRRqW(b`^Tee2fqae?y5-FsBrDW)`PL4ysh$@qS8UB68g27D zob=oM9Lq{$F7$}0K7J0^-?Ns(EePeRngy_h%?r6^w!@XjsC}lgK)4oLykcq%H+uaa z%BNOWpjPE`Da+>?u>6nZGeOIx5q0?#0?@jA#zKfGpIlu&sqq|L!B~8wQ0oH&B47+s zG3NM~)Huc=tdvZHMTsB=FpJrS;NquYYt89|%+gNrq3Q|jluD-PA0@dg}8v$onvL+oOqP2e% z$cRY&h@P$i9NUZd+tH)p0QG2$8@x|6p3|n$n(Ox=7c z`$06XoKqiiW{!6Sme+-+bQ@`c$xhC3l=Bn&Hi^jgqq?A!X3Yjily(a)vfD)Jj-d8_ z94^3fqBSQVf6>}+NW?)SuB67_CK}Mi(VYRR4}-ekgj2doK}dz4Xza`$0^5uT81Eh5 zr--xX>Ma&e%b5D)dQ4TEhHQ9OY0;(8n!n&zwDv51qx}40MTt5E5i8yV(X$vWsBr}*tt(Uq?u^InFD3)jc4pU>l6p{1l8}tFNu>3fPmr8X ziPn6HU(wo){7yvbhqN}<@07a^d#%(rdS=BMM|k%@7SnYW6$~mlzndyaUcI?m%DK^+ zy*g3K8WgB#tL-Z+M#OuIfZ09sQzc zZR#LQX`<)c%uYbG=Ey86djV&KxIV{*DOz)&rb$JBy!2mbF35o}* zgE7C24G1L-C}wX^s86#F-5wAj%pA-tCqF}JFP0WUEtEelTG@`IHCacwI6m~MAdPA~z>QLmYqWL_8 zDg27o9^IW`N~ua%-|J6gdGkiGL=VB2;#4>B=j*7VI-q8HT{Yd4LibBP`PASf98__> zjN3{|_S9zkt4s_wsFlcwTF55g5axfN%YRE9`UALZqJC!QqEl#v7dFyK>ebaq>dk`$ zsP(*vyFtVqfoXUV7p|JcrfOaUKS-u{=QCkN^BK{apVFx01S~MXpxvN{SEzC6rF%we zw;)zAlZQdKm?|K;uSVlG?QMfG4-Y?VQi^%c(uk?inqqOPPcS3n{eHX%!foEa_oblE z@vRyW78ug~C?AE4c!a^dmZ9S?WPp)(X^LczTaGbozKGf1^eGi-#J^0EuI_F7(DYA*gK~7Lxu2~juS1Pk@REX zUD4VBJs{+LR?VO_vY~i3ie0h)z#S6}Y6k1Zpmxo24V8Xt1I4_7e?w{0R4F6ym6Tl3 zoE@!s1r;#p)@N_Iu7Xo9oF-;~-8v#2gm)yvh~_KMa_=uB=K z5iK;g`I?(*GtE#%rU#N~SeU@0A`J7sDJlwKiY>Rd@>ns}hhnTBM9#;UI@59nx6%40 z3V8h!t2Mg)uR>o46J1(Z*EcW&qsaS0@~&t;CR+3FKN$TUkK#M%E8J8sC1QXmNEX5b zR5=N2{20yp*F$qUHd@mOzoNAr@UKdnwblHVK->eJ* zLOvP)s!6EK?PRhTX*gO$9+}N|!Ot70S+IzrHKSmyXs!50wq;>+y04#89+?TSxe;uV z1KZE*6U=L8$t#;5EL3LtxqX=t=lP>0w?pwF0Dj>`0Q?*GON_Ow7R@iNJ)o{PY2wMz znk$8P8o$LfY3OeTRN{qd-eh9Sn^#NDp2ojrd1@G&eSKB5gb!2tleqZ9`{A@<7BhJd zo%{_+-cjVGApWWr?!pgNX=j*)D8B%k%fMzwhFL+w{LnxrV1$QZzK4~x8$1Lhy?c)m z?O7Jlnj7&Etu4pDab5^+RaaL)mze5EbuS}*Me|wFn$bdh2|Q5S=4*C2T;>|sb=@w}*;VzQRdmua8D5~*8=6xgnO`ZVV>Y={Nd%#eCkoZ|4ewxI# zJ6yaIT6DVPVl)UzI$I-H?8coN4T}4vVU_}_#+jj-=>9aztLP+w(70blIyesi&!GEV zb(M8LLH7h&+)w(t0_wmN9K%;M?-H0^Vyn*5PIE9RO2X0uFiuSomg!*8%0=`iS6=z( zhk=Z9NUJ#og^rF=FLQDL+Xh>8b~-T^fBS%)9VRhtP`WEvA(#$=nC=WsM;WV5@EnjE zOLQTRgFzCs#HCkSO9(m}Xj2iJy(|41&8cR|(VT*%_`4K2OP#rMOUY8T6ZOTYEqQ=} zw_LZY{Mv$nMpKnRW@1UE9$|<~BymZ^@p!y+TdfYoMV3Y;silkj@MnQXu z)-wa`n`Qcqys*YDzVORB;~#Xf)MD*yzS|$bte?IX)&U20RvXDIj2=LA(Q+UZ-6hE( zNn6qb$*HrDt|94W7%Zu|wzq5TAd-LbJ~-1@PiZ&2$VnFbOT?=Oz==fffylcY;}vA2 zQ?%wR{EF6|$#3U65%e%cz0jth)uF0>1Vv9F>mrV1(IA}-3F;U0yS#3ieSWm&oeZ)c z(#O>IJ)$+6k0j)4{44ccq^jG{bH@W)(x9p@;kfEa@KHQi;JrrDisn6|HBU>@$HPe{ z1e1Qsq|=%7QYO8Lq~*XKAfpX>(tUB)C|B!wDxd< zq!C)qA%yMf9HjO_0{AJKH^oL_wOWgS;^(Lv8GrKshV~PEUK;Gy3 zo4ro~^?%=5Z>^WLvd`?9U!ULf*)zBwLpsa#xNEnsjM(pW8BqLJV28(f#Vn7%mqxKTOPTq}){4 z9Sd#>%-twSxmD#TKXG~2+E`{zTwg!ugSntb>dp58q7$ue^_LsyegK?zb<@e-sj<>~5H=3||1 zn=jlBKG|;DObw*|qSJk*xYmfP?{ptWCW&(KK7MH zmr~C7On>zCMSPlGM=K$I@Am?*jo$=8C(1)V{9Y4QDXZF9j`Fl#PnDt3lUj9h~%?RF*J0diekkvOzr2X$vhwpqJgN{wGkbYB1R>IrePX30B|95rhVU`G8* zeRdqKEll6g?^rb~mw1yBm%jp6T@Ezg?Lh`uDt*k>2|2i%1@|^^5s@9LR7xTa|5f6n zIU>`MzQVOj2f>Kc5SK(hl{$1KcD||Mp20i3Lq1Gn6CU#qEL@X$)*NyVUYL_!pKQ>K zpPH;7wOOFZjyQXsg+F9C;W|QJcD#Y|&rIATw-q_)%1D-e|3_xkFXb*$TNth);r8;U4E1o-d4=%o5Y`=PnZ9 zUqo3kzrrH-F-qeE=S!rbt9s^@`B1~fjiXdisv2Oa?p_ky>R85CHf?gG0hD)4+=6cI zeI6zr!#W#?=pFNcN5&ZbgTy;9Gw4hGauv2}wg z+`Tf*<;*Xm=zXTsGiylENs6)-vJ+JBkR#SBaHbn?!b9Q?-9Oy!lGacBtTg@lJN_ae z`oYzybhWNsnQ(_KH0^S*9b9)`#kn7;pxuYQbhw@KW$h?gzZiyKwV8fF>UBc2e|pdL z#m}P$m(Wb0c;09opti(?C}v(5-XZ9k%-yExH%vhX>FMedTCKE>bwaI`J3b%tL!=H* z^O%~dpc`SVD+*b!ptBU^SoIM_xDyi>FYF+QH>r!2^UE-{g-GjMY z2V1(dztx}9;XwTfB~FX&{RNS1Hslz+{_hdod&YH2=iA3}ruBD{!~XU{d;7k1z20Nf zdDy6aRZZqz6LJQf^&tHMPm@ZEd8Xzl*`j1eM9-~2<=Hil?iyNiXoL7FP zfrgY~gs2IIf}!D2l4Pvd0Ma4~dD9fpy0&f`<5caehKAGAM9W|qcaKWf93J5d>ziB^ zjQKl2nr~+5|PV)qbbpLZXkt+UFBvffGP{r`h7hYlt zT-^DRt*6BLhZk#q)|gGKUJ^^@+Am1$jct>k=9%k3jY$5=T$PfoPo8Z1|EX*_TN%O^ z&ng>V!D6mP6-+gc@Y*3}tCND%G(tf-srOv2ZS2MP+bO(>l4iPyR}OTiiTof@-qBM| zRL>65!#!0xCQs07#fwxmolcV)uH~Ulu6`>>tL4b!eV>6^eLnqVsJ_A@3myv z=M>LQui@GKtz~M(`E-%x4B7)A?7B#Y^*z;7gH#82(FH5i`!O3?G`i1KApei)(@Vsm zn{gQEejpFr?JvRMxj|;7(}L8!go5;)Jgo#w2vXO4DxT;50dce2aARjV@=rDS7kk{( ztDg?iXDDn?9Sy44?Tb)R{>>v89_pbd2C1=xg7l7AjMp`aP!08)CK8)nQs5hU@H47k z=Dy>SnE36{fZ#`}n6R@4Igc@ACsEw|)G6rTt`oUP8Ra|rtO@M}5co|3-@}9JTi+lx8$np1Al$k&GG1qq>l%%|JnduS>xr!XG)R9d zC=H%w8PqI#96r)>nhGbY4m6i|2wj)D(pUQwG&XgY$BoVX@`usb$hhB$sz|?FOtTfUVW z%|A;`Yqu4*#5A(sjl>g1wGER=i&nQk7XQA+zdg2jv-?suzf)bT7yFwu&zLm#@VGR23h51Ut%y>e^IMakN$2p8b5$+)RwV6pl zYD42Ugr`-)XEL>HF{=y0cX%dM^>Lk%o;<>ZAkyf1Lj<2J_5-9jd5(AuooMZXZFbM# zq3rTH)BO_XU9&qJ722!ja1W^EVI!?w18S?MQn<1BH_86m6N z)?lz8^%*Zg`a_=P%Tp|}?q^v*;XDU9Thz=!Zp2>POm~)h3wvVo&mT3L%e#fcVGeWo zaf^wj8hAkA1sy1ThKM_kj4jQuUi-?8(U@#jS!;Qpnk#hgbwag~9#_MNmD0b@@^Ey1oYh;es zX5#h5BYC_&du(N12D3mg?irr$U*dJXc-3agg48g2!a;h!kFjD0w+&n>SBr9M0tLdI ztpU+q9=b=6dPBmcmwhCEaPGX5{jwv{o1-cMp+RBo|nLHT(OCX0tReO-tY$h)3t|x^$ zeqvvf#N7oyiEbJbF9U<7-OeZ$XFHvcl zK$B2e;=W4 zlbLTK%`==i!YOhWf&=OmloT=iir>oa5$YVF{>P(EHPo{V^)#UtyWK!F57IOX9jVFz zShT6a?Z`cZ6e6}H&r%^f^kdJE`0NN`F}oV>od*m^u$bv~2`RezdHnmE{W(lGZkZt1&3 zZR(0Nx_c-h*2`{o|53Sk1b|lEyr>RG1_IED`iYMzKick7rB_3Od&9Cuv+=i4`osG@ z@LT)@sq6Gi&*W*+dmS(0HTgkSn%&%qdD7To`FcoWy#H)cYk~Mr6#vR?-GMN7WfE2g zDaHF`^7d>#FX){k=nW!KJGrGoDNEd^)Lx{z7p3)wJTQxv=UP~guE|K?>aodn%#N}> z_hD{9x%P|69RY{0&(P|1BQP^}Q*wd8q`CV5XM)!&;x%VJj$xg@g|sl?nX8*+?*uGJ z9nMRTK2T9sseDCurE-~Sk+CqUa1$sh;b@Pc-bIiaZWx1kQkN_T9Kjv)uAi1^K6mxq zx%Z~R9ZFSHxkluRYtxx_0~tMqzx6cMw;Q1rUV`-PH20L52Xln3%_meYLaRrFURT@G z3}iUZ6S~U?ZGsyG>BD(K=#(6xihM!~A0oMTL}~A#aTL=)~h< zeF2n3Hh@H=>@Tb3DSN6&_lihwEYh2cbeSjpnvwpgT*`jS)00km(ogBf%st+hWm&R5 zpLmcjcM~4umVgu9BTBWI&Oz#0qkJV#w4eGQ^oreNej-Wt%qRA&l4B#(LJZhpio;>} z$*%f6j`xInh(%52B9q^L2(q!FauW;h(_2zO?jaKT0_J^S-FVy$<`m+%^mgiu7j8CB zrT0TY^a3KWoKWIjy_UuZwGDl9NL_@q{GKe*$M+hObv%>rc@yhOmBkBiYj>V}`|7}C z)|_yV+7Xbz&Vutc?`q;QZ3s?I+}og3DDLXwT$|&30uXuP9uy-Kh}%m@`{a;D0%f0K znN3FXCKr0*ek6SjpANt2VUlY3gZ7^n=06pcv+iViN`->;6OXU&&YI*EOq%#PYsaT} zHG~4e`U~ly9MUx&irJuiYp*M)v_YA`X8`4fBB&cEX?O6_-eJ;iVA2lcX`f!5<8wdy z={}&#KXVX0^=f(@dUB+$NaAL5@g7Z6SMx7?8mtB1C zeeQC&gqqKYkv{wRuaI2Uz()v4J*pV#;lDr{U|;onP8)!fXvxy(%PWgFbz|$bW#`cf zPpbBtE~rp4#Em(`_j%i^>YdsMZQAR`Z|;+~Uoe%~eGa}9-lqOUP3B|h2dPVWVFi$< ztwrp@_czTLZWr(V-ROm_>K;4Dlvm%C^{I0q?=~h&!##XgWzXty$w5YMcfQMnPx5P< zZc2Pa*zFE@IKV^h#rn5N(21x2DBWPz7tAu2$jHn+f|Mf^q(9}E_(Wzgm}0>+dzi67 z>Uo2CS}=>UFdvfP;e#G#*XnnYy%N7?(-tVL-ly#rq^1%g{fBJ&%}PJlr;iI##}f+D zNAk?en#qD0FPNH)8qpy26kS`$n3z^o9VU=XJ;*hHRBsieN4|$$t?|6;8DGj*PzG`p z%r4-l>_4L-^`kw*%5#{P07n3>*J49 zygn|q3gUF$+(5Lca9`rmG4j>|>c9v3BNZs2lUhve96@YIw#8h` zXPoa!1Y6|$H-phXe9ePz6r`RY6r>;G>AJ<>Z{KO)*3bD_)MtC}5n743UX(x4;Hw9e z@A9BmC~^^?v{6?n{FK5)?khmZBm+nuoJaEP zJd%|${%@-JBccb!k$a11ri)o&WA=X#V*dwEH%f$Mg%xuQ?@GznAG~mp2j3(}J!Ihb z3cQoR%K?AQgPUsKiDjhPr-aR^QDv@RiYvEs|MkG8`vL(=(Z|p}JYGy{GS9)4rAy

0P7q_;b7Eu#5V)aaY-Y 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

je%<7C|$R^88@y}7Po$1 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 literal 0 HcmV?d00001 diff --git a/programs/develop/oberon07/Compiler.exe b/programs/develop/oberon07/Compiler.exe new file mode 100644 index 0000000000000000000000000000000000000000..7697d9f187112f727f31eba8231ff97e9058ee96 GIT binary patch literal 308736 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 literal 0 HcmV?d00001 diff --git a/programs/develop/oberon07/Compiler.kex b/programs/develop/oberon07/Compiler.kex index 2720d5973e1bc9c78d7517272a898b05b474fa57..55b5adbcf08dbf49bd4f0a2f2816e9357163283a 100644 GIT binary patch literal 268189 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

m{vaK`$QD$jQ+PJij9cEEcmM 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

[optional settings]"); C.Ln; + C.StringLn("target ="); IF UTILS.bit_depth = 64 THEN - 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 | elfso | msp430'); C.Ln; + OutTargetItem(TARGETS.Win64C, "Windows64 Console"); + OutTargetItem(TARGETS.Win64GUI, "Windows64 GUI"); + OutTargetItem(TARGETS.Win64DLL, "Windows64 DLL"); + OutTargetItem(TARGETS.Linux64, "Linux64 Exec"); + OutTargetItem(TARGETS.Linux64SO, "Linux64 SO") END; + OutTargetItem(TARGETS.Win32C, "Windows32 Console"); + OutTargetItem(TARGETS.Win32GUI, "Windows32 GUI"); + OutTargetItem(TARGETS.Win32DLL, "Windows32 DLL"); + OutTargetItem(TARGETS.Linux32, "Linux32 Exec"); + OutTargetItem(TARGETS.Linux32SO, "Linux32 SO"); + OutTargetItem(TARGETS.KolibriOS, "KolibriOS Exec"); + OutTargetItem(TARGETS.KolibriOSDLL, "KolibriOS DLL"); + OutTargetItem(TARGETS.MSP430, "MSP430x{1,2}xx microcontrollers"); + OutTargetItem(TARGETS.STM32CM3, "STM32 Cortex-M3 microcontrollers"); + C.Ln; C.StringLn("optional settings:"); C.Ln; - C.StringLn(" -out output"); C.Ln; - C.StringLn(" -stk set size of stack in megabytes"); C.Ln; - C.StringLn(' -nochk <"ptibcwra"> disable runtime checking (pointers, types, indexes,'); - C.StringLn(' BYTE, CHR, WCHR)'); C.Ln; - C.StringLn(" -ver set version of program ('obj' target)"); C.Ln; - C.StringLn(" -ram set size of RAM in bytes ('msp430' target)"); C.Ln; - C.StringLn(" -rom set size of ROM in bytes ('msp430' target)"); C.Ln; + C.StringLn(" -out output"); C.Ln; + C.StringLn(" -stk set size of stack in Mbytes (Windows, Linux, KolibriOS)"); C.Ln; + C.StringLn(" -nochk <'ptibcwra'> disable runtime checking (pointers, types, indexes,"); + C.StringLn(" BYTE, CHR, WCHR)"); C.Ln; + C.StringLn(" -ver set version of program (KolibriOS DLL)"); C.Ln; + C.StringLn(" -ram set size of RAM in bytes (MSP430) or Kbytes (STM32)"); C.Ln; + C.StringLn(" -rom set size of ROM in bytes (MSP430) or Kbytes (STM32)"); C.Ln; UTILS.Exit(0) END; + C.StringLn("--------------------------------------------"); PATHS.split(inname, path, modname, ext); - IF ext # mConst.FILE_EXT THEN + IF ext # UTILS.FILE_EXT THEN ERRORS.Error(207) END; @@ -235,76 +226,36 @@ BEGIN ERRORS.Error(205) END; - target := Target(param); - - IF target = 0 THEN + IF TARGETS.Select(param) THEN + target := TARGETS.target + ELSE ERRORS.Error(206) END; - 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; + IF target = TARGETS.MSP430 THEN options.ram := MSP430.minRAM; options.rom := MSP430.minROM END; - IF UTILS.bit_depth < bit_depth THEN + IF target = TARGETS.STM32CM3 THEN + options.ram := THUMB.STM32_minRAM; + options.rom := THUMB.STM32_minROM + END; + + IF UTILS.bit_depth < TARGETS.BitDepth THEN ERRORS.Error(206) END; STRINGS.append(lib_path, "lib"); STRINGS.append(lib_path, UTILS.slash); - - CASE target OF - |mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL: - STRINGS.append(lib_path, "Windows32") - - |mConst.Target_iKolibri, mConst.Target_iObject: - STRINGS.append(lib_path, "KolibriOS") - - |mConst.Target_iELF32, mConst.Target_iELFSO32: - STRINGS.append(lib_path, "Linux32") - - |mConst.Target_iELF64, mConst.Target_iELFSO64: - STRINGS.append(lib_path, "Linux64") - - |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, TARGETS.LibDir); STRINGS.append(lib_path, UTILS.slash); keys(options, outname); IF outname = "" THEN outname := path; STRINGS.append(outname, modname); - CASE target OF - |mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iConsole64, mConst.Target_iGUI64: - STRINGS.append(outname, ".exe") - - |mConst.Target_iObject: - STRINGS.append(outname, ".obj") - - |mConst.Target_iKolibri, mConst.Target_iELF32, mConst.Target_iELF64: - - |mConst.Target_iELFSO32, mConst.Target_iELFSO64: - STRINGS.append(outname, ".so") - - |mConst.Target_iDLL, mConst.Target_iDLL64: - STRINGS.append(outname, ".dll") - - |mConst.Target_iMSP430: - STRINGS.append(outname, ".hex") - END + STRINGS.append(outname, TARGETS.FileExt) ELSE IF PATHS.isRelative(outname) THEN PATHS.RelPath(app_path, outname, temp); @@ -312,15 +263,12 @@ BEGIN END END; - 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; + PARS.init(options); ST.compile(path, lib_path, modname, outname, target, options); time := UTILS.GetTickCount() - UTILS.time; - + C.StringLn("--------------------------------------------"); C.Int(PARS.lines); C.String(" lines, "); C.Int(time DIV 100); C.String("."); C.Int2(time MOD 100); C.String(" sec, "); C.Int(WRITER.counter); C.StringLn(" bytes"); @@ -331,4 +279,4 @@ END main; BEGIN main -END Compiler. +END Compiler. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/ELF.ob07 b/programs/develop/oberon07/Source/ELF.ob07 index d502af91a6..df64fcae5e 100644 --- a/programs/develop/oberon07/Source/ELF.ob07 +++ b/programs/develop/oberon07/Source/ELF.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2019, Anton Krotov @@ -142,23 +142,27 @@ END WritePH64; PROCEDURE fixup (program: BIN.PROGRAM; text, data, bss: INTEGER; amd64: BOOLEAN); VAR reloc: BIN.RELOC; - L, delta: INTEGER; + code: CHL.BYTELIST; + L, delta, delta0: INTEGER; BEGIN + code := program.code; + delta0 := 3 - 7 * ORD(amd64); reloc := program.rel_list.first(BIN.RELOC); + WHILE reloc # NIL DO - L := BIN.get32le(program.code, reloc.offset); - delta := 3 - reloc.offset - text - 7 * ORD(amd64); + L := BIN.get32le(code, reloc.offset); + delta := delta0 - reloc.offset - text; CASE reloc.opcode OF - |BIN.PICDATA: BIN.put32le(program.code, reloc.offset, L + data + delta) - |BIN.PICCODE: BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text + delta) - |BIN.PICBSS: BIN.put32le(program.code, reloc.offset, L + bss + delta) + |BIN.PICDATA: BIN.put32le(code, reloc.offset, L + data + delta) + |BIN.PICCODE: BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text + delta) + |BIN.PICBSS: BIN.put32le(code, reloc.offset, L + bss + delta) END; reloc := reloc.next(BIN.RELOC) - END; + END END fixup; @@ -648,4 +652,4 @@ BEGIN END write; -END ELF. +END ELF. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/ERRORS.ob07 b/programs/develop/oberon07/Source/ERRORS.ob07 index 0121f39d0d..b925b6fe5b 100644 --- a/programs/develop/oberon07/Source/ERRORS.ob07 +++ b/programs/develop/oberon07/Source/ERRORS.ob07 @@ -1,13 +1,13 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) MODULE ERRORS; -IMPORT C := CONSOLE, UTILS, mConst := CONSTANTS; +IMPORT C := CONSOLE, UTILS; PROCEDURE HintMsg* (name: ARRAY OF CHAR; line, col, hint: INTEGER); @@ -73,7 +73,7 @@ BEGIN | 43: str := "expression is not an integer" | 44: str := "out of range 0..MAXSET" | 45: str := "division by zero" - | 46: str := "integer division by zero" + | 46: str := "IV out of range" | 47: str := "'OF' or ',' expected" | 48: str := "undeclared identifier" | 49: str := "type expected" @@ -137,7 +137,7 @@ BEGIN |107: str := "too large parameter of CHR" |108: str := "a variable or a procedure expected" |109: str := "expression should be constant" - + |110: str := "out of range 0..65535" |111: str := "record [noalign] cannot have a base type" |112: str := "record [noalign] cannot be a base type" |113: str := "result type of procedure should not be REAL" @@ -146,8 +146,8 @@ BEGIN |116: str := "procedure too deep nested" |120: str := "too many formal parameters" - - |122: str := "negative divisor" + |121: str := "multiply defined handler" + |122: str := "bad divisor" |123: str := "illegal flag" |124: str := "unknown flag" |125: str := "flag not supported" @@ -184,7 +184,7 @@ END Error5; PROCEDURE WrongRTL* (ProcName: ARRAY OF CHAR); BEGIN - Error5("procedure ", mConst.RTL_NAME, ".", ProcName, " not found") + Error5("procedure ", UTILS.RTL_NAME, ".", ProcName, " not found") END WrongRTL; @@ -209,9 +209,9 @@ BEGIN |204: Error1("size of variables is too large") |205: Error1("not enough parameters") |206: Error1("bad parameter ") - |207: Error3('inputfile name extension must be "', mConst.FILE_EXT, '"') + |207: Error3('inputfile name extension must be "', UTILS.FILE_EXT, '"') END END Error; -END ERRORS. +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 7aa5b0be4a..1ef926ca01 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-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -17,7 +17,9 @@ TYPE ptr: INTEGER; buffer: ARRAY 64*1024 OF BYTE; - count: INTEGER + count: INTEGER; + + chksum*: INTEGER END; @@ -83,7 +85,8 @@ BEGIN IF ptr > 0 THEN file := NewFile(); file.ptr := ptr; - file.count := 0 + file.count := 0; + file.chksum := 0 ELSE file := NIL END @@ -190,30 +193,14 @@ END write; PROCEDURE WriteByte* (file: FILE; byte: BYTE): BOOLEAN; VAR - res: BOOLEAN; + arr: ARRAY 1 OF BYTE; BEGIN - res := TRUE; - IF (file # NIL) & (file.count >= 0) THEN - IF file.count = LEN(file.buffer) THEN - IF flush(file) # LEN(file.buffer) THEN - res := FALSE - ELSE - file.buffer[0] := byte; - file.count := 1 - END - ELSE - file.buffer[file.count] := byte; - INC(file.count) - END - ELSE - res := FALSE - END - - RETURN res + arr[0] := byte + RETURN write(file, arr, 1) = 1 END WriteByte; BEGIN files := C.create() -END FILES. +END FILES. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/HEX.ob07 b/programs/develop/oberon07/Source/HEX.ob07 new file mode 100644 index 0000000000..2bfbdd80e3 --- /dev/null +++ b/programs/develop/oberon07/Source/HEX.ob07 @@ -0,0 +1,127 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020, Anton Krotov + All rights reserved. +*) + +MODULE HEX; + +IMPORT FILES, WRITER, CHL := CHUNKLISTS; + + +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 Byte (file: FILES.FILE; byte: BYTE); +BEGIN + WRITER.WriteByte(file, hexdgt(byte DIV 16)); + WRITER.WriteByte(file, hexdgt(byte MOD 16)); + INC(file.chksum, byte); +END Byte; + + +PROCEDURE NewLine (file: FILES.FILE); +BEGIN + Byte(file, (-file.chksum) MOD 256); + file.chksum := 0; + WRITER.WriteByte(file, 0DH); + WRITER.WriteByte(file, 0AH) +END NewLine; + + +PROCEDURE StartCode (file: FILES.FILE); +BEGIN + WRITER.WriteByte(file, ORD(":")); + file.chksum := 0 +END StartCode; + + +PROCEDURE Data* (file: FILES.FILE; mem: ARRAY OF BYTE; idx, cnt: INTEGER); +VAR + i, len: INTEGER; + +BEGIN + WHILE cnt > 0 DO + len := MIN(cnt, 16); + StartCode(file); + Byte(file, len); + Byte(file, idx DIV 256); + Byte(file, idx MOD 256); + Byte(file, 0); + FOR i := 1 TO len DO + Byte(file, mem[idx]); + INC(idx) + END; + DEC(cnt, len); + NewLine(file) + END +END Data; + + +PROCEDURE ExtLA* (file: FILES.FILE; LA: INTEGER); +BEGIN + ASSERT((0 <= LA) & (LA <= 0FFFFH)); + StartCode(file); + Byte(file, 2); + Byte(file, 0); + Byte(file, 0); + Byte(file, 4); + Byte(file, LA DIV 256); + Byte(file, LA MOD 256); + NewLine(file) +END ExtLA; + + +PROCEDURE Data2* (file: FILES.FILE; mem: CHL.BYTELIST; idx, cnt, LA: INTEGER); +VAR + i, len, offset: INTEGER; + +BEGIN + ExtLA(file, LA); + offset := 0; + WHILE cnt > 0 DO + ASSERT(offset <= 65536); + IF offset = 65536 THEN + INC(LA); + ExtLA(file, LA); + offset := 0 + END; + len := MIN(cnt, 16); + StartCode(file); + Byte(file, len); + Byte(file, offset DIV 256); + Byte(file, offset MOD 256); + Byte(file, 0); + FOR i := 1 TO len DO + Byte(file, CHL.GetByte(mem, idx)); + INC(idx); + INC(offset) + END; + DEC(cnt, len); + NewLine(file) + END +END Data2; + + +PROCEDURE End* (file: FILES.FILE); +BEGIN + StartCode(file); + Byte(file, 0); + Byte(file, 0); + Byte(file, 0); + Byte(file, 1); + NewLine(file) +END End; + + +END HEX. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/IL.ob07 b/programs/develop/oberon07/Source/IL.ob07 index 9ca222672d..48e7d7eda7 100644 --- a/programs/develop/oberon07/Source/IL.ob07 +++ b/programs/develop/oberon07/Source/IL.ob07 @@ -1,1183 +1,1211 @@ -(* - 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; - - - _init *= 0; - _move *= 1; - _strcmpw *= 2; - _exit *= 3; - _set *= 4; - _set1 *= 5; - _lengthw *= 6; - _strcpy *= 7; - _length *= 8; - _divmod *= 9; - _dllentry *= 10; - _sofinit *= 11; - _arrcpy *= 12; - _rot *= 13; - _new *= 14; - _dispose *= 15; - _strcmp *= 16; - _error *= 17; - _is *= 18; - _isrec *= 19; - _guard *= 20; - _guardrec *= 21; - - -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 = 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 22 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 set_dmin* (value: INTEGER); -BEGIN - codes.dmin := value -END set_dmin; - - -PROCEDURE set_bss* (value: INTEGER); -BEGIN - codes.bss := value -END set_bss; - - -PROCEDURE set_rtl* (idx, label: INTEGER); -BEGIN - codes.rtl[idx] := label -END set_rtl; - - -PROCEDURE NewCmd (): COMMAND; -VAR - cmd: COMMAND; - citem: C.ITEM; - -BEGIN - citem := C.pop(commands); - IF citem = NIL THEN - NEW(cmd) - ELSE - cmd := citem(COMMAND) - END; - - 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 (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(ORD(s[i])); - INC(i) - END; - - PutByte(0) - - RETURN res -END putstr; - - -PROCEDURE putstr1* (c: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF codes.charoffs[c] = -1 THEN - res := CHL.Length(codes.data); - PutByte(c); - PutByte(0); - codes.charoffs[c] := res - ELSE - res := codes.charoffs[c] - END - - RETURN res -END putstr1; - - -PROCEDURE putstrW* (s: ARRAY OF CHAR): INTEGER; -VAR - i, n, res: INTEGER; - -BEGIN - res := CHL.Length(codes.data); - - IF ODD(res) THEN - PutByte(0); - INC(res) - END; - - n := STRINGS.Utf8To16(s, codes.wstr); - - i := 0; - WHILE i < n DO - IF endianness = little_endian THEN - PutByte(ORD(codes.wstr[i]) MOD 256); - PutByte(ORD(codes.wstr[i]) DIV 256) - ELSIF endianness = big_endian THEN - PutByte(ORD(codes.wstr[i]) DIV 256); - PutByte(ORD(codes.wstr[i]) MOD 256) - END; - INC(i) - END; - - PutByte(0); - PutByte(0) - - RETURN res -END putstrW; - - -PROCEDURE putstrW1* (c: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF codes.wcharoffs[c] = -1 THEN - res := CHL.Length(codes.data); - - IF ODD(res) THEN - PutByte(0); - INC(res) - END; - - IF endianness = little_endian THEN - PutByte(c MOD 256); - PutByte(c DIV 256) - ELSIF endianness = big_endian THEN - PutByte(c DIV 256); - PutByte(c MOD 256) - END; - - PutByte(0); - PutByte(0); - - codes.wcharoffs[c] := res - ELSE - res := codes.wcharoffs[c] - END - - RETURN res -END putstrW1; - - -PROCEDURE push (stk: CMDSTACK; cmd: COMMAND); -BEGIN - INC(stk.top); - stk.data[stk.top] := cmd -END push; - - -PROCEDURE pop (stk: CMDSTACK): COMMAND; -VAR - res: COMMAND; -BEGIN - res := stk.data[stk.top]; - DEC(stk.top) - RETURN res -END pop; - - -PROCEDURE pushBegEnd* (VAR beg, end: COMMAND); -BEGIN - push(codes.begcall, beg); - push(codes.endcall, end); - beg := codes.last; - end := beg.next(COMMAND) -END pushBegEnd; - - -PROCEDURE popBegEnd* (VAR beg, end: COMMAND); -BEGIN - beg := pop(codes.begcall); - end := pop(codes.endcall) -END popBegEnd; - - -PROCEDURE AddRec* (base: INTEGER); -BEGIN - CHL.PushInt(codes.types, base) -END AddRec; - - -PROCEDURE insert (cur, nov: COMMAND); -VAR - old_opcode, param2: INTEGER; - - - PROCEDURE set (cur: COMMAND; opcode, param2: INTEGER); - BEGIN - cur.opcode := opcode; - cur.param1 := cur.param2; - cur.param2 := param2 - END set; - - -BEGIN - 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 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.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. +(* + BSD 2-Clause License + + Copyright (c) 2018-2020, Anton Krotov + All rights reserved. +*) + +MODULE IL; + +IMPORT LISTS, SCAN, STRINGS, CHL := CHUNKLISTS, C := COLLECTIONS, TARGETS; + + +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; + 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; + + opONERR* = 222; opSAVEFI* = 223; opHANDLER* = 224; + + + opSADR_PARAM* = -1; opLOAD64_PARAM* = -2; opLLOAD64_PARAM* = -3; opGLOAD64_PARAM* = -4; + opVADR_PARAM* = -5; opCONST_PARAM* = -6; opGLOAD32_PARAM* = -7; opLLOAD32_PARAM* = -8; + opLOAD32_PARAM* = -9; + + opLADR_SAVEC* = -10; opGADR_SAVEC* = -11; opLADR_SAVE* = -12; + + opLADR_INCC* = -13; opLADR_INCCB* = -14; opLADR_DECCB* = -15; + opLADR_INC* = -16; opLADR_DEC* = -17; opLADR_INCB* = -18; opLADR_DECB* = -19; + opLADR_INCL* = -20; opLADR_EXCL* = -21; opLADR_INCLC* = -22; opLADR_EXCLC* = -23; + opLADR_UNPK* = -24; + + + _init *= 0; + _move *= 1; + _strcmpw *= 2; + _exit *= 3; + _set *= 4; + _set1 *= 5; + _lengthw *= 6; + _strcpy *= 7; + _length *= 8; + _divmod *= 9; + _dllentry *= 10; + _sofinit *= 11; + _arrcpy *= 12; + _rot *= 13; + _new *= 14; + _dispose *= 15; + _strcmp *= 16; + _error *= 17; + _is *= 18; + _isrec *= 19; + _guard *= 20; + _guardrec *= 21; + + _fmul *= 22; + _fdiv *= 23; + _fdivi *= 24; + _fadd *= 25; + _fsub *= 26; + _fsubi *= 27; + _fcmp *= 28; + _floor *= 29; + _flt *= 30; + _pack *= 31; + _unpk *= 32; + + +TYPE + + 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 = RECORD + + last: COMMAND; + begcall: CMDSTACK; + endcall: CMDSTACK; + commands*: LISTS.LIST; + export*: LISTS.LIST; + import*: LISTS.LIST; + types*: CHL.INTLIST; + data*: CHL.BYTELIST; + dmin*: INTEGER; + lcount*: INTEGER; + bss*: INTEGER; + rtl*: ARRAY 33 OF INTEGER; + errlabels*: ARRAY 12 OF INTEGER; + + charoffs: ARRAY 256 OF INTEGER; + wcharoffs: ARRAY 65536 OF INTEGER; + + fregs: INTEGER; + wstr: ARRAY 4*1024 OF WCHAR + END; + + +VAR + + codes*: CODES; + endianness, numRegsFloat, CPU: INTEGER; + + commands, variables: C.COLLECTION; + + +PROCEDURE set_dmin* (value: INTEGER); +BEGIN + codes.dmin := value +END set_dmin; + + +PROCEDURE set_bss* (value: INTEGER); +BEGIN + codes.bss := value +END set_bss; + + +PROCEDURE set_rtl* (idx, label: INTEGER); +BEGIN + codes.rtl[idx] := label +END set_rtl; + + +PROCEDURE NewCmd (): COMMAND; +VAR + cmd: COMMAND; + citem: C.ITEM; + +BEGIN + citem := C.pop(commands); + IF citem = NIL THEN + NEW(cmd) + ELSE + cmd := citem(COMMAND) + END; + + 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 (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(ORD(s[i])); + INC(i) + END; + + PutByte(0) + + RETURN res +END putstr; + + +PROCEDURE putstr1* (c: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF codes.charoffs[c] = -1 THEN + res := CHL.Length(codes.data); + PutByte(c); + PutByte(0); + codes.charoffs[c] := res + ELSE + res := codes.charoffs[c] + END + + RETURN res +END putstr1; + + +PROCEDURE putstrW* (s: ARRAY OF CHAR): INTEGER; +VAR + i, n, res: INTEGER; + +BEGIN + res := CHL.Length(codes.data); + + IF ODD(res) THEN + PutByte(0); + INC(res) + END; + + n := STRINGS.Utf8To16(s, codes.wstr); + + i := 0; + WHILE i < n DO + IF endianness = little_endian THEN + PutByte(ORD(codes.wstr[i]) MOD 256); + PutByte(ORD(codes.wstr[i]) DIV 256) + ELSIF endianness = big_endian THEN + PutByte(ORD(codes.wstr[i]) DIV 256); + PutByte(ORD(codes.wstr[i]) MOD 256) + END; + INC(i) + END; + + PutByte(0); + PutByte(0) + + RETURN res +END putstrW; + + +PROCEDURE putstrW1* (c: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF codes.wcharoffs[c] = -1 THEN + res := CHL.Length(codes.data); + + IF ODD(res) THEN + PutByte(0); + INC(res) + END; + + IF endianness = little_endian THEN + PutByte(c MOD 256); + PutByte(c DIV 256) + ELSIF endianness = big_endian THEN + PutByte(c DIV 256); + PutByte(c MOD 256) + END; + + PutByte(0); + PutByte(0); + + codes.wcharoffs[c] := res + ELSE + res := codes.wcharoffs[c] + END + + RETURN res +END putstrW1; + + +PROCEDURE push (stk: CMDSTACK; cmd: COMMAND); +BEGIN + INC(stk.top); + stk.data[stk.top] := cmd +END push; + + +PROCEDURE pop (stk: CMDSTACK): COMMAND; +VAR + res: COMMAND; +BEGIN + res := stk.data[stk.top]; + DEC(stk.top) + RETURN res +END pop; + + +PROCEDURE pushBegEnd* (VAR beg, end: COMMAND); +BEGIN + push(codes.begcall, beg); + push(codes.endcall, end); + beg := codes.last; + end := beg.next(COMMAND) +END pushBegEnd; + + +PROCEDURE popBegEnd* (VAR beg, end: COMMAND); +BEGIN + beg := pop(codes.begcall); + end := pop(codes.endcall) +END popBegEnd; + + +PROCEDURE AddRec* (base: INTEGER); +BEGIN + CHL.PushInt(codes.types, base) +END AddRec; + + +PROCEDURE insert (cur, nov: COMMAND); +VAR + old_opcode, param2: INTEGER; + + + PROCEDURE set (cur: COMMAND; opcode, param2: INTEGER); + BEGIN + cur.opcode := opcode; + cur.param1 := cur.param2; + cur.param2 := param2 + END set; + + +BEGIN + IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64, TARGETS.cpuMSP430} THEN + + old_opcode := cur.opcode; + param2 := nov.param2; + + IF (nov.opcode = opPARAM) & (param2 = 1) THEN + + CASE old_opcode OF + |opGLOAD64: cur.opcode := opGLOAD64_PARAM + |opLLOAD64: cur.opcode := opLLOAD64_PARAM + |opLOAD64: cur.opcode := opLOAD64_PARAM + |opGLOAD32: cur.opcode := opGLOAD32_PARAM + |opLLOAD32: cur.opcode := opLLOAD32_PARAM + |opLOAD32: cur.opcode := opLOAD32_PARAM + |opSADR: cur.opcode := opSADR_PARAM + |opVADR: cur.opcode := opVADR_PARAM + |opCONST: cur.opcode := opCONST_PARAM + ELSE + old_opcode := -1 + END + + ELSIF old_opcode = opLADR THEN + + CASE nov.opcode OF + |opSAVEC: set(cur, opLADR_SAVEC, param2) + |opSAVE: cur.opcode := opLADR_SAVE + |opINC: cur.opcode := opLADR_INC + |opDEC: cur.opcode := opLADR_DEC + |opINCB: cur.opcode := opLADR_INCB + |opDECB: cur.opcode := opLADR_DECB + |opINCL: cur.opcode := opLADR_INCL + |opEXCL: cur.opcode := opLADR_EXCL + |opUNPK: cur.opcode := opLADR_UNPK + |opINCC: set(cur, opLADR_INCC, param2) + |opINCCB: set(cur, opLADR_INCCB, param2) + |opDECCB: set(cur, opLADR_DECCB, param2) + |opINCLC: set(cur, opLADR_INCLC, param2) + |opEXCLC: set(cur, opLADR_EXCLC, param2) + ELSE + old_opcode := -1 + END + + ELSIF (nov.opcode = opSAVEC) & (old_opcode = opGADR) THEN + set(cur, opGADR_SAVEC, param2) + + ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN + cur.param2 := param2 * cur.param2 + + ELSE + old_opcode := -1 + END + ELSE + old_opcode := -1 + END; + + IF old_opcode = -1 THEN + LISTS.insert(codes.commands, cur, nov); + codes.last := nov + ELSE + C.push(commands, nov); + codes.last := cur + END +END insert; + + +PROCEDURE AddCmd* (opcode: INTEGER; param: INTEGER); +VAR + cmd: COMMAND; +BEGIN + cmd := NewCmd(); + cmd.opcode := opcode; + cmd.param1 := 0; + cmd.param2 := param; + insert(codes.last, cmd) +END AddCmd; + + +PROCEDURE AddCmd2* (opcode: INTEGER; param1, param2: INTEGER); +VAR + cmd: COMMAND; +BEGIN + cmd := NewCmd(); + cmd.opcode := opcode; + cmd.param1 := param1; + cmd.param2 := param2; + insert(codes.last, cmd) +END AddCmd2; + + +PROCEDURE Const* (val: INTEGER); +BEGIN + AddCmd(opCONST, val) +END Const; + + +PROCEDURE StrAdr* (adr: INTEGER); +BEGIN + AddCmd(opSADR, adr) +END StrAdr; + + +PROCEDURE Param1*; +BEGIN + AddCmd(opPARAM, 1) +END Param1; + + +PROCEDURE NewLabel* (): INTEGER; +BEGIN + INC(codes.lcount) + RETURN codes.lcount - 1 +END NewLabel; + + +PROCEDURE SetLabel* (label: INTEGER); +BEGIN + AddCmd2(opLABEL, label, 0) +END SetLabel; + + +PROCEDURE SetErrLabel* (errno: INTEGER); +BEGIN + codes.errlabels[errno] := NewLabel(); + SetLabel(codes.errlabels[errno]) +END SetErrLabel; + + +PROCEDURE AddCmd0* (opcode: INTEGER); +BEGIN + AddCmd(opcode, 0) +END AddCmd0; + + +PROCEDURE 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 + AddCmd2(opONERR, codes.errlabels[error], line) +END OnError; + + +PROCEDURE TypeGuard* (op, t: INTEGER; line, error: INTEGER); +VAR + label: INTEGER; +BEGIN + AddCmd(op, t); + label := NewLabel(); + 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* (inv: BOOLEAN); +BEGIN + IF inv THEN + AddCmd0(opSAVEFI) + ELSE + AddCmd0(opSAVEF) + END; + 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 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* (pCPU: INTEGER); +VAR + cmd: COMMAND; + i: INTEGER; + +BEGIN + commands := C.create(); + variables := C.create(); + + CPU := pCPU; + endianness := little_endian; + CASE CPU OF + |TARGETS.cpuAMD64: numRegsFloat := 6 + |TARGETS.cpuX86: numRegsFloat := 8 + |TARGETS.cpuMSP430: numRegsFloat := 0 + |TARGETS.cpuTHUMB: numRegsFloat := 256 + END; + + 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 0e5e551ec3..7f6b0aed75 100644 --- a/programs/develop/oberon07/Source/KOS.ob07 +++ b/programs/develop/oberon07/Source/KOS.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -116,6 +116,7 @@ VAR icount, dcount, ccount: INTEGER; + code: CHL.BYTELIST; BEGIN base := 0; @@ -141,43 +142,43 @@ BEGIN header.param := header.sp; header.path := header.param + PARAM_SIZE; - + code := program.code; reloc := program.rel_list.first(BIN.RELOC); WHILE reloc # NIL DO - L := BIN.get32le(program.code, reloc.offset); + L := BIN.get32le(code, reloc.offset); delta := 3 - reloc.offset - text; CASE reloc.opcode OF |BIN.RIMP: iproc := BIN.GetIProc(program, L); - BIN.put32le(program.code, reloc.offset, idata + iproc.label) + BIN.put32le(code, reloc.offset, idata + iproc.label) |BIN.RBSS: - BIN.put32le(program.code, reloc.offset, L + bss) + BIN.put32le(code, reloc.offset, L + bss) |BIN.RDATA: - BIN.put32le(program.code, reloc.offset, L + data) + BIN.put32le(code, reloc.offset, L + data) |BIN.RCODE: - BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text) + BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text) |BIN.PICDATA: - BIN.put32le(program.code, reloc.offset, L + data + delta) + BIN.put32le(code, reloc.offset, L + data + delta) |BIN.PICCODE: - BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text + delta) + BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + text + delta) |BIN.PICBSS: - BIN.put32le(program.code, reloc.offset, L + bss + delta) + BIN.put32le(code, reloc.offset, L + bss + delta) |BIN.PICIMP: iproc := BIN.GetIProc(program, L); - BIN.put32le(program.code, reloc.offset, idata + iproc.label + delta) + BIN.put32le(code, reloc.offset, idata + iproc.label + delta) |BIN.IMPTAB: - BIN.put32le(program.code, reloc.offset, idata + delta) + BIN.put32le(code, reloc.offset, idata + delta) END; @@ -198,7 +199,7 @@ BEGIN WR.Write32LE(File, header.param); WR.Write32LE(File, header.path); - CHL.WriteToFile(File, program.code); + CHL.WriteToFile(File, code); WR.Padding(File, FileAlignment); CHL.WriteToFile(File, program.data); @@ -215,4 +216,4 @@ BEGIN END write; -END KOS. +END KOS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/LISTS.ob07 b/programs/develop/oberon07/Source/LISTS.ob07 index 34cfdebce6..d9a8bcc2a9 100644 --- a/programs/develop/oberon07/Source/LISTS.ob07 +++ b/programs/develop/oberon07/Source/LISTS.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -199,4 +199,4 @@ BEGIN END create; -END LISTS. +END LISTS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/MSCOFF.ob07 b/programs/develop/oberon07/Source/MSCOFF.ob07 index 0907a22b12..cc37bea1e4 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-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -45,19 +45,11 @@ BEGIN WHILE reloc # NIL DO CASE reloc.opcode OF - - |BIN.RIMP, BIN.IMPTAB: - WriteReloc(File, reloc.offset, 4, 6) - - |BIN.RBSS: - WriteReloc(File, reloc.offset, 5, 6) - - |BIN.RDATA: - WriteReloc(File, reloc.offset, 2, 6) - - |BIN.RCODE: - WriteReloc(File, reloc.offset, 1, 6) - + |BIN.RIMP, + BIN.IMPTAB: WriteReloc(File, reloc.offset, 4, 6) + |BIN.RBSS: WriteReloc(File, reloc.offset, 5, 6) + |BIN.RDATA: WriteReloc(File, reloc.offset, 2, 6) + |BIN.RCODE: WriteReloc(File, reloc.offset, 1, 6) END; reloc := reloc.next(BIN.RELOC) @@ -70,23 +62,25 @@ VAR reloc: BIN.RELOC; iproc: BIN.IMPRT; res, L: INTEGER; + code: CHL.BYTELIST; BEGIN res := 0; + code := program.code; reloc := program.rel_list.first(BIN.RELOC); WHILE reloc # NIL DO INC(res); IF reloc.opcode = BIN.RIMP THEN - L := BIN.get32le(program.code, reloc.offset); + L := BIN.get32le(code, reloc.offset); iproc := BIN.GetIProc(program, L); - BIN.put32le(program.code, reloc.offset, iproc.label) + BIN.put32le(code, reloc.offset, iproc.label) END; IF reloc.opcode = BIN.RCODE THEN - L := BIN.get32le(program.code, reloc.offset); - BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L)) + L := BIN.get32le(code, reloc.offset); + BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L)) END; reloc := reloc.next(BIN.RELOC) @@ -159,7 +153,7 @@ BEGIN FileHeader.Machine := 014CX; FileHeader.NumberOfSections := 5X; FileHeader.TimeDateStamp := UTILS.UnixTime(); - //FileHeader.PointerToSymbolTable := 0; + (* FileHeader.PointerToSymbolTable := 0; *) FileHeader.NumberOfSymbols := 6; FileHeader.SizeOfOptionalHeader := 0X; FileHeader.Characteristics := 0184X; @@ -169,7 +163,7 @@ BEGIN flat.VirtualAddress := 0; flat.SizeOfRawData := ccount; flat.PointerToRawData := ORD(FileHeader.NumberOfSections) * PE32.SIZE_OF_IMAGE_SECTION_HEADER + PE32.SIZE_OF_IMAGE_FILE_HEADER; - //flat.PointerToRelocations := 0; + (* flat.PointerToRelocations := 0; *) flat.PointerToLinenumbers := 0; SetNumberOfRelocations(flat, RelocCount(program)); flat.NumberOfLinenumbers := 0X; @@ -191,7 +185,7 @@ BEGIN edata.VirtualAddress := 0; edata.SizeOfRawData := ((ExpCount + 1) * 2 + 1) * SIZE_OF_DWORD + LENGTH(szversion) + 1 + ecount; edata.PointerToRawData := data.PointerToRawData + data.SizeOfRawData; - //edata.PointerToRelocations := 0; + (* edata.PointerToRelocations := 0; *) edata.PointerToLinenumbers := 0; SetNumberOfRelocations(edata, ExpCount * 2 + 1); edata.NumberOfLinenumbers := 0X; @@ -202,7 +196,7 @@ BEGIN idata.VirtualAddress := 0; idata.SizeOfRawData := isize; idata.PointerToRawData := edata.PointerToRawData + edata.SizeOfRawData; - //idata.PointerToRelocations := 0; + (* idata.PointerToRelocations := 0; *) idata.PointerToLinenumbers := 0; SetNumberOfRelocations(idata, ICount(ImportTable, ILen)); idata.NumberOfLinenumbers := 0X; @@ -313,4 +307,4 @@ BEGIN END write; -END MSCOFF. +END MSCOFF. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/MSP430.ob07 b/programs/develop/oberon07/Source/MSP430.ob07 index b0ce4a0526..9b6ba48099 100644 --- a/programs/develop/oberon07/Source/MSP430.ob07 +++ b/programs/develop/oberon07/Source/MSP430.ob07 @@ -1,1793 +1,1759 @@ -(* - 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; -VAR - cmd, next: COMMAND; - - opcode, param1, param2, label, L, a, n, c1, c2: INTEGER; - - reg1, reg2: INTEGER; - - cc: INTEGER; - -BEGIN - cmd := IL.codes.commands.first(COMMAND); - - WHILE cmd # NIL DO - - param1 := cmd.param1; - param2 := cmd.param2; - - opcode := cmd.opcode; - - CASE opcode OF - |IL.opJMP: - 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* (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 IL.codes.bss > ram - minStackSize - RTL.VarSize THEN - ERRORS.Error(204) - END; - - Labels := CHL.CreateIntList(); - FOR i := 1 TO IL.codes.lcount DO - CHL.PushInt(Labels, 0) - END; - - FOR i := 0 TO LEN(mem) - 1 DO - mem[i] := 0 - END; - - TypesSize := CHL.Length(IL.codes.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; - epilog; - - Code.address := 10000H - rom; - Code.size := Fixup(Code.address, IntVectorSize + TypesSize); - Data.address := Code.address + Code.size; - Data.size := CHL.Length(IL.codes.data); - Data.size := Data.size + ORD(ODD(Data.size)); - TextSize := Code.size + Data.size; - - IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN - ERRORS.Error(203) - END; - - Bss.address := RTL.ram + RTL.VarSize; - Bss.size := IL.codes.bss + ORD(ODD(IL.codes.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(IL.codes.data) - 1 DO - mem[adr] := CHL.GetByte(IL.codes.data, i); - INC(adr) - END; - - adr := 10000H - IntVectorSize - TypesSize; - - FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO - PutWord(CHL.GetInt(IL.codes.types, i), adr) - END; - - FOR i := 0 TO 15 DO - PutWord((33 - i) * i, adr); - END; - - FOR n := 0 TO 15 DO - bits := ORD({0 .. n}); - FOR i := 0 TO 15 - n DO - PutWord(bits, adr); - bits := LSL(bits, 1) - END - END; - - 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. +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE MSP430; + +IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX, + UTILS, C := CONSOLE, PROG, RTL := MSP430RTL; + + +CONST + + minRAM* = 128; maxRAM* = 2048; + minROM* = 2048; maxROM* = 24576; + + minStackSize = 64; + + IntVectorSize* = RTL.IntVectorSize; + + PC = 0; SP = 1; SR = 2; CG = 3; + + R4 = 4; R5 = 5; R6 = 6; R7 = 7; + + HP = 14; IR = 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; + + StkCnt: INTEGER; + + +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; +VAR + res: INTEGER; + +BEGIN + IF (x = 0) & ~(Rn IN {PC, SR, CG}) THEN + res := Rn * 256 + sINDIR + ELSE + IdxWords.src := x; + res := Rn * 256 + sIDX + END + + RETURN res +END src_x; + + +PROCEDURE dst_x (x, Rn: INTEGER): INTEGER; +BEGIN + IdxWords.dst := x + RETURN Rn + dIDX +END dst_x; + + +PROCEDURE indir (Rn: INTEGER): INTEGER; + RETURN Rn * 256 + sINDIR +END indir; + + +PROCEDURE incr (Rn: INTEGER): INTEGER; + RETURN Rn * 256 + sINCR +END incr; + + +PROCEDURE imm (x: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + CASE x OF + | 0: res := CG * 256 + | 1: res := CG * 256 + sIDX + | 2: res := indir(CG) + | 4: res := indir(SR) + | 8: res := incr(SR) + |-1: res := incr(CG) + ELSE + res := incr(PC); + IdxWords.src := x + END + + RETURN res +END imm; + + +PROCEDURE Op2 (op, src, dst: INTEGER); +BEGIN + ASSERT(BITS(op) - {6, 12..15} = {}); + ASSERT(BITS(src) - {4, 5, 8..11} = {}); + ASSERT(BITS(dst) - {0..3, 7} = {}); + + EmitWord(op + src + dst); + + IF IdxWords.src # NOWORD THEN + EmitWord(IdxWords.src); + IdxWords.src := NOWORD + END; + + IF IdxWords.dst # NOWORD THEN + EmitWord(IdxWords.dst); + IdxWords.dst := NOWORD + END +END Op2; + + +PROCEDURE Op1 (op, reg, As: INTEGER); +BEGIN + EmitWord(op + reg + As) +END Op1; + + +PROCEDURE MovRR (src, dst: INTEGER); +BEGIN + Op2(opMOV, src * 256, dst) +END MovRR; + + +PROCEDURE PushImm (imm: INTEGER); +BEGIN + imm := UTILS.Long(imm); + CASE imm OF + | 0: Op1(opPUSH, CG, sREG) + | 1: Op1(opPUSH, CG, sIDX) + | 2: Op1(opPUSH, CG, sINDIR) + |-1: Op1(opPUSH, CG, sINCR) + ELSE + Op1(opPUSH, PC, sINCR); + EmitWord(imm) + END; + INC(StkCnt) +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); + INC(StkCnt) +END Push; + + +PROCEDURE Pop (reg: INTEGER); +BEGIN + Op2(opMOV, incr(SP), reg); + DEC(StkCnt) +END Pop; + + +PROCEDURE Test (reg: INTEGER); +BEGIN + Op2(opCMP, imm(0), reg) +END Test; + + +PROCEDURE Clear (reg: INTEGER); +BEGIN + Op2(opMOV, imm(0), reg) +END Clear; + + +PROCEDURE mov (dst, src: INTEGER); +BEGIN + MovRR(src, dst) +END mov; + + +PROCEDURE xchg (reg1, reg2: INTEGER); +BEGIN + Push(reg1); + 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); + DEC(StkCnt, params) + END +END CallRTL; + + +PROCEDURE UnOp (VAR reg: INTEGER); +BEGIN + REG.UnOp(R, reg) +END UnOp; + + +PROCEDURE BinOp (VAR reg1, reg2: INTEGER); +BEGIN + REG.BinOp(R, reg1, reg2) +END BinOp; + + +PROCEDURE GetRegA; +BEGIN + ASSERT(REG.GetReg(R, ACC)) +END GetRegA; + + +PROCEDURE drop; +BEGIN + REG.Drop(R) +END drop; + + +PROCEDURE GetAnyReg (): INTEGER; + RETURN REG.GetAnyReg(R) +END GetAnyReg; + + +PROCEDURE PushAll (NumberOfParameters: INTEGER); +BEGIN + REG.PushAll(R); + DEC(R.pushed, NumberOfParameters) +END PushAll; + + +PROCEDURE PushAll_1; +BEGIN + REG.PushAll_1(R) +END PushAll_1; + + +PROCEDURE cond (op: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + CASE op OF + |IL.opGT, IL.opGTC: res := jg + |IL.opGE, IL.opGEC: res := jge + |IL.opLT, IL.opLTC: res := jl + |IL.opLE, IL.opLEC: res := jle + |IL.opEQ, IL.opEQC: res := je + |IL.opNE, IL.opNEC: res := jne + END + + RETURN res +END cond; + + +PROCEDURE jcc (cc, label: INTEGER); +VAR + L: INTEGER; + +BEGIN + CASE cc OF + |jne: + EmitJmp(opJNE, label) + |je: + EmitJmp(opJEQ, label) + |jge: + EmitJmp(opJGE, label) + |jl: + EmitJmp(opJL, label) + |jle: + EmitJmp(opJL, label); + EmitJmp(opJEQ, label) + |jg: + L := NewLabel(); + EmitJmp(opJEQ, L); + EmitJmp(opJGE, label); + EmitLabel(L) + |jb: + EmitJmp(opJNC, label) + END +END jcc; + + +PROCEDURE setcc (cc, reg: INTEGER); +VAR + L: INTEGER; + +BEGIN + L := NewLabel(); + Op2(opMOV, imm(1), reg); + jcc(cc, L); + Clear(reg); + EmitLabel(L) +END setcc; + + +PROCEDURE Shift2 (op, reg, n: INTEGER); +VAR + reg2: INTEGER; + +BEGIN + IF n >= 8 THEN + CASE op OF + |IL.opASR2: Op1(opSWPB, reg, sREG); Op1(opSXT, reg, sREG) + |IL.opROR2: Op1(opSWPB, reg, sREG) + |IL.opLSL2: Op1(opSWPB, reg, sREG); Op2(opBIC, imm(255), reg) + |IL.opLSR2: Op2(opBIC, imm(255), reg); Op1(opSWPB, reg, sREG) + END; + DEC(n, 8) + END; + + IF (op = IL.opROR2) & (n > 0) THEN + reg2 := GetAnyReg(); + MovRR(reg, reg2) + ELSE + reg2 := -1 + END; + + WHILE n > 0 DO + CASE op OF + |IL.opASR2: Op1(opRRA, reg, sREG) + |IL.opROR2: Op1(opRRC, reg2, sREG); Op1(opRRC, reg, sREG) + |IL.opLSL2: Op2(opADD, reg * 256, reg) + |IL.opLSR2: Op2(opBIC, imm(1), SR); Op1(opRRC, reg, sREG) + END; + DEC(n) + END; + + IF reg2 # -1 THEN + drop + END + +END Shift2; + + +PROCEDURE Neg (reg: INTEGER); +BEGIN + Op2(opXOR, imm(-1), reg); + Op2(opADD, imm(1), reg) +END Neg; + + +PROCEDURE LocalOffset (offset: INTEGER): INTEGER; + RETURN (offset + StkCnt - ORD(offset > 0)) * 2 +END LocalOffset; + + +PROCEDURE LocalDst (offset: INTEGER): INTEGER; + RETURN dst_x(LocalOffset(offset), SP) +END LocalDst; + + +PROCEDURE LocalSrc (offset: INTEGER): INTEGER; + RETURN src_x(LocalOffset(offset), SP) +END LocalSrc; + + +PROCEDURE translate; +VAR + cmd, next: COMMAND; + + opcode, param1, param2, L, a, n, c1, c2: INTEGER; + + reg1, reg2: INTEGER; + + cc: INTEGER; + +BEGIN + cmd := IL.codes.commands.first(COMMAND); + + WHILE cmd # NIL DO + + param1 := cmd.param1; + param2 := cmd.param2; + + opcode := cmd.opcode; + + CASE opcode OF + |IL.opJMP: + 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); + INC(StkCnt); + EmitWord(param2); + Reloc(RDATA) + + |IL.opERR: + CallRTL(RTL._error, 2) + + |IL.opPUSHC: + PushImm(param2) + + |IL.opONERR: + PushImm(param2); + DEC(StkCnt); + EmitJmp(opJMP, param1) + + |IL.opLEAVEC: + Pop(PC) + + |IL.opENTER: + ASSERT(R.top = -1); + StkCnt := 0; + EmitLabel(param1); + 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); + ASSERT(StkCnt = param1); + IF param1 > 0 THEN + Op2(opADD, imm(param1 * 2), SP) + END; + Pop(PC) + + |IL.opRES: + ASSERT(R.top = -1); + GetRegA + + |IL.opCLEANUP: + IF param2 # 0 THEN + Op2(opADD, imm(param2 * 2), SP); + DEC(StkCnt, param2) + END + + |IL.opCONST: + next := cmd.next(COMMAND); + IF next.opcode = IL.opCONST THEN + c1 := param2; + c2 := next.param2; + next := next.next(COMMAND); + IF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN + Op2(opMOV + bw(next.opcode = IL.opSAVE8), imm(c1), dst_x(c2, SR)); + cmd := next + ELSE + Op2(opMOV, imm(param2), GetAnyReg()) + END + ELSIF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN + UnOp(reg1); + Op2(opMOV + bw(next.opcode = IL.opSAVE8), reg1 * 256, dst_x(param2, SR)); + drop; + cmd := next + ELSE + Op2(opMOV, imm(param2), GetAnyReg()) + END + + |IL.opSADR: + Op2(opMOV, incr(PC), GetAnyReg()); + EmitWord(param2); + Reloc(RDATA) + + |IL.opGADR: + Op2(opMOV, incr(PC), GetAnyReg()); + EmitWord(param2); + Reloc(RBSS) + + |IL.opLADR: + reg1 := GetAnyReg(); + n := LocalOffset(param2); + Op2(opMOV, SP * 256, reg1); + IF n # 0 THEN + Op2(opADD, imm(n), reg1) + END + + |IL.opLLOAD8: + Op2(opMOV + BW, LocalSrc(param2), GetAnyReg()) + + |IL.opLLOAD16, IL.opVADR: + Op2(opMOV, LocalSrc(param2), GetAnyReg()) + + |IL.opGLOAD8: + Op2(opMOV + BW, src_x(param2, SR), GetAnyReg()); + Reloc(RBSS) + + |IL.opGLOAD16: + Op2(opMOV, src_x(param2, SR), GetAnyReg()); + Reloc(RBSS) + + |IL.opLOAD8: + UnOp(reg1); + Op2(opMOV + BW, indir(reg1), reg1) + + |IL.opLOAD16: + UnOp(reg1); + Op2(opMOV, indir(reg1), reg1) + + |IL.opVLOAD8: + reg1 := GetAnyReg(); + Op2(opMOV, LocalSrc(param2), reg1); + Op2(opMOV + BW, indir(reg1), reg1) + + |IL.opVLOAD16: + reg1 := GetAnyReg(); + Op2(opMOV, LocalSrc(param2), reg1); + Op2(opMOV, indir(reg1), reg1) + + |IL.opSAVE, IL.opSAVE16: + BinOp(reg2, reg1); + Op2(opMOV, reg2 * 256, dst_x(0, reg1)); + drop; + drop + + |IL.opSAVE8: + BinOp(reg2, reg1); + Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1)); + drop; + drop + + |IL.opSAVE8C: + UnOp(reg1); + Op2(opMOV + BW, imm(param2), dst_x(0, reg1)); + drop + + |IL.opSAVE16C, IL.opSAVEC: + UnOp(reg1); + Op2(opMOV, imm(param2), dst_x(0, reg1)); + drop + + |IL.opUMINUS: + UnOp(reg1); + Neg(reg1) + + |IL.opADD: + BinOp(reg1, reg2); + Op2(opADD, reg2 * 256, reg1); + drop + + |IL.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 + Neg(reg1) + END + + |IL.opLADR_SAVEC: + Op2(opMOV, imm(param2), LocalDst(param1)) + + |IL.opLADR_SAVE: + UnOp(reg1); + Op2(opMOV, reg1 * 256, LocalDst(param2)); + drop + + |IL.opGADR_SAVEC: + Op2(opMOV, imm(param2), dst_x(param1, SR)); + Reloc(RBSS) + + |IL.opCONST_PARAM: + PushImm(param2) + + |IL.opPARAM: + IF param2 = 1 THEN + UnOp(reg1); + Push(reg1); + drop + ELSE + ASSERT(R.top + 1 <= param2); + PushAll(param2) + END + + |IL.opEQ..IL.opGE, + IL.opEQC..IL.opGEC: + + IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN + BinOp(reg1, reg2); + Op2(opCMP, reg2 * 256, reg1); + drop + ELSE + UnOp(reg1); + Op2(opCMP, imm(param2), reg1) + END; + + drop; + cc := cond(opcode); + next := cmd.next(COMMAND); + + IF next.opcode = IL.opJE THEN + jcc(cc, next.param1); + cmd := next + ELSIF next.opcode = IL.opJNE THEN + jcc(ORD(BITS(cc) / {0}), next.param1); + cmd := next + 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); + jcc(jb, param1) + END; + INCL(R.regs, reg1); + DEC(R.top); + R.stk[R.top] := reg2 + + |IL.opINCC, IL.opINCCB: + UnOp(reg1); + Op2(opADD + bw(opcode = IL.opINCCB), imm(param2), dst_x(0, reg1)); + drop + + |IL.opDECCB: + UnOp(reg1); + Op2(opSUB + BW, imm(param2), dst_x(0, reg1)); + drop + + |IL.opINC, IL.opINCB: + BinOp(reg1, reg2); + Op2(opADD + bw(opcode = IL.opINCB), reg1 * 256, dst_x(0, reg2)); + drop; + drop + + |IL.opDEC, IL.opDECB: + BinOp(reg1, reg2); + Op2(opSUB + bw(opcode = IL.opDECB), reg1 * 256, dst_x(0, reg2)); + drop; + drop + + |IL.opLADR_INCC, IL.opLADR_INCCB: + Op2(opADD + bw(opcode = IL.opLADR_INCCB), imm(param2), LocalDst(param1)) + + |IL.opLADR_DECCB: + Op2(opSUB + BW, imm(param2), LocalDst(param1)) + + |IL.opLADR_INC, IL.opLADR_INCB: + UnOp(reg1); + Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, LocalDst(param2)); + drop + + |IL.opLADR_DEC, IL.opLADR_DECB: + UnOp(reg1); + Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, LocalDst(param2)); + drop + + |IL.opPUSHT: + UnOp(reg1); + Op2(opMOV, src_x(-2, reg1), GetAnyReg()) + + |IL.opISREC: + PushAll(2); + PushImm(param2); + CallRTL(RTL._guardrec, 3); + GetRegA + + |IL.opIS: + PushAll(1); + PushImm(param2); + CallRTL(RTL._is, 2); + GetRegA + + |IL.opTYPEGR: + PushAll(1); + PushImm(param2); + CallRTL(RTL._guardrec, 2); + GetRegA + + |IL.opTYPEGP: + UnOp(reg1); + PushAll(0); + Push(reg1); + PushImm(param2); + CallRTL(RTL._guard, 2); + GetRegA + + |IL.opTYPEGD: + UnOp(reg1); + PushAll(0); + Op1(opPUSH, reg1, sIDX); + INC(StkCnt); + 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.opMAX,IL.opMIN: + BinOp(reg1, reg2); + Op2(opCMP, reg2 * 256, reg1); + IF opcode = IL.opMIN THEN + cc := opJL + 1 + ELSE + cc := opJGE + 1 + END; + EmitWord(cc); (* jge/jl L *) + MovRR(reg2, reg1); + (* L: *) + drop + + |IL.opMAXC, IL.opMINC: + UnOp(reg1); + Op2(opCMP, imm(param2), reg1); + L := NewLabel(); + IF opcode = IL.opMINC THEN + cc := jl + ELSE + cc := jge + END; + jcc(cc, L); + Op2(opMOV, imm(param2), reg1); + EmitLabel(L) + + |IL.opSWITCH: + UnOp(reg1); + IF param2 = 0 THEN + reg2 := ACC + ELSE + reg2 := R5 + END; + IF reg1 # reg2 THEN + ASSERT(REG.GetReg(R, reg2)); + ASSERT(REG.Exchange(R, reg1, reg2)); + drop + END; + drop + + |IL.opENDSW: + + |IL.opCASEL: + Op2(opCMP, imm(param1), ACC); + jcc(jl, param2) + + |IL.opCASER: + Op2(opCMP, imm(param1), ACC); + jcc(jg, param2) + + |IL.opCASELR: + Op2(opCMP, imm(param1), ACC); + 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.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); + INC(StkCnt); + 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: + reg1 := GetAnyReg(); + Op2(opMOV, LocalSrc(param2), reg1); + Push(reg1); + drop + + |IL.opNEW: + PushAll(1); + n := param2 + 2; + ASSERT(UTILS.Align(n, 2)); + PushImm(n); + PushImm(param1); + CallRTL(RTL._new, 3) + + |IL.opRSET: + PushAll(2); + CallRTL(RTL._set, 2); + GetRegA + + |IL.opRSETR: + PushAll(1); + PushImm(param2); + CallRTL(RTL._set, 2); + GetRegA + + |IL.opRSETL: + UnOp(reg1); + PushAll_1; + PushImm(param2); + Push(reg1); + drop; + CallRTL(RTL._set, 2); + GetRegA + + |IL.opRSET1: + PushAll(1); + CallRTL(RTL._set1, 1); + GetRegA + + |IL.opINCLC: + UnOp(reg1); + Op2(opBIS, imm(ORD({param2})), dst_x(0, reg1)); + drop + + |IL.opEXCLC: + UnOp(reg1); + Op2(opBIC, imm(ORD({param2})), dst_x(0, reg1)); + drop + + |IL.opIN: + PushAll(2); + CallRTL(RTL._in, 2); + GetRegA + + |IL.opINR: + PushAll(1); + PushImm(param2); + CallRTL(RTL._in, 2); + GetRegA + + |IL.opINL: + PushAll(1); + PushImm(param2); + CallRTL(RTL._in2, 2); + GetRegA + + |IL.opINCL: + PushAll(2); + CallRTL(RTL._incl, 2) + + |IL.opEXCL: + PushAll(2); + CallRTL(RTL._excl, 2) + + |IL.opLADR_INCL, IL.opLADR_EXCL: + PushAll(1); + MovRR(SP, ACC); + n := LocalOffset(param2); + IF n # 0 THEN + Op2(opADD, imm(n), ACC) + END; + Push(ACC); + IF opcode = IL.opLADR_INCL THEN + CallRTL(RTL._incl, 2) + ELSIF opcode = IL.opLADR_EXCL THEN + CallRTL(RTL._excl, 2) + END + + |IL.opLADR_INCLC: + Op2(opBIS, imm(ORD({param2})), LocalDst(param1)) + + |IL.opLADR_EXCLC: + Op2(opBIC, imm(ORD({param2})), LocalDst(param1)) + + END; + + cmd := cmd.next(COMMAND) + END; + + ASSERT(R.pushed = 0); + ASSERT(R.top = -1) +END translate; + + +PROCEDURE prolog (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 CodeGen* (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: WR.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 IL.codes.bss > ram - minStackSize - RTL.VarSize THEN + ERRORS.Error(204) + END; + + Labels := CHL.CreateIntList(); + FOR i := 1 TO IL.codes.lcount DO + CHL.PushInt(Labels, 0) + END; + + FOR i := 0 TO LEN(mem) - 1 DO + mem[i] := 0 + END; + + TypesSize := CHL.Length(IL.codes.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; + epilog; + + Code.address := 10000H - rom; + Code.size := Fixup(Code.address, IntVectorSize + TypesSize); + Data.address := Code.address + Code.size; + Data.size := CHL.Length(IL.codes.data); + Data.size := Data.size + Data.size MOD 2; + TextSize := Code.size + Data.size; + + IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN + ERRORS.Error(203) + END; + + Bss.address := RTL.ram + RTL.VarSize; + Bss.size := IL.codes.bss + IL.codes.bss MOD 2; + 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(IL.codes.data) - 1 DO + mem[adr] := CHL.GetByte(IL.codes.data, i); + INC(adr) + END; + + adr := 10000H - IntVectorSize - TypesSize; + + FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO + PutWord(CHL.GetInt(IL.codes.types, i), adr) + END; + + FOR i := 0 TO 15 DO + PutWord((33 - i) * i, adr); + END; + + FOR n := 0 TO 15 DO + bits := ORD({0 .. n}); + FOR i := 0 TO 15 - n DO + PutWord(bits, adr); + bits := LSL(bits, 1) + END + END; + + 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); + PutWord(0001H, adr); (* bsl signature (adr 0FFBEH) *) + + FOR i := 0 TO LEN(IV) - 1 DO + PutWord(LabelOffs(IV[i]) * 2, adr) + END; + + file := WR.Create(outname); + + HEX.Data(file, mem, Code.address, TextSize); + HEX.Data(file, mem, 10000H - IntVectorSize - TypesSize, IntVectorSize + TypesSize); + HEX.End(file); + + WR.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("%)") + +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 index 17c858b86c..e2c4f6c8cd 100644 --- a/programs/develop/oberon07/Source/MSP430RTL.ob07 +++ b/programs/develop/oberon07/Source/MSP430RTL.ob07 @@ -1,677 +1,675 @@ -(* - 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. +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, 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; + bsl = iv - 2; + sp = bsl - 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 (modNum, modName, 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 <- modNum *) + Word2(4115H, 4); (* MOV 4(SP), R5; R5 <- modName *) + Word2(4116H, 6); (* MOV 6(SP), R6; R6 <- err *) + Word2(4117H, 8); (* MOV 8(SP), R7; R7 <- line *) + Word2(4211H, sp); (* MOV sp(SR), SP *) + Word1(1207H); (* PUSH R7 *) + Word1(1206H); (* PUSH R6 *) + Word1(1205H); (* PUSH R5 *) + Word1(1204H); (* PUSH R4 *) + Word2(4214H, 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; + ram := 200H; + 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 6694d65668..eebcd1d848 100644 --- a/programs/develop/oberon07/Source/PARS.ob07 +++ b/programs/develop/oberon07/Source/PARS.ob07 @@ -1,13 +1,14 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) MODULE PARS; -IMPORT PROG, SCAN, ARITH, STRINGS, ERRORS, LISTS, IL, CONSOLE, PATHS, UTILS, C := COLLECTIONS, mConst := CONSTANTS; +IMPORT PROG, SCAN, ARITH, STRINGS, ERRORS, LISTS, IL, CONSOLE, PATHS, UTILS, + C := COLLECTIONS, TARGETS, THUMB; CONST @@ -77,7 +78,7 @@ VAR parsers: C.COLLECTION; - lines*: INTEGER; + lines*, modules: INTEGER; PROCEDURE destroy* (VAR parser: PARSER); @@ -132,7 +133,7 @@ VAR BEGIN SCAN.Next(parser.scanner, parser.lex); errno := parser.lex.error; - IF (errno = 0) & (program.target.sys = mConst.Target_iMSP430) THEN + IF (errno = 0) & (TARGETS.CPU = TARGETS.cpuMSP430) THEN IF parser.lex.sym = SCAN.lxFLOAT THEN errno := -SCAN.lxERROR13 ELSIF (parser.lex.sym = SCAN.lxCHAR) & (parser.lex.value.typ = ARITH.tWCHAR) THEN @@ -508,7 +509,7 @@ BEGIN check1(FALSE, parser, 124) END; - check1(sf IN program.target.sysflags, parser, 125); + check1(sf IN program.sysflags, parser, 125); IF proc THEN check1(sf IN PROG.proc_flags, parser, 123) @@ -532,15 +533,15 @@ BEGIN |PROG.sf_code: res := PROG.code |PROG.sf_windows: - IF program.target.sys IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN + IF TARGETS.OS = TARGETS.osWIN32 THEN res := PROG.stdcall - ELSIF program.target.sys IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64} THEN + ELSIF TARGETS.OS = TARGETS.osWIN64 THEN res := PROG.win64 END |PROG.sf_linux: - IF program.target.sys IN {mConst.Target_iELF32, mConst.Target_iELFSO32} THEN + IF TARGETS.OS = TARGETS.osLINUX32 THEN res := PROG.ccall16 - ELSIF program.target.sys IN {mConst.Target_iELF64, mConst.Target_iELFSO64} THEN + ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN res := PROG.systemv END |PROG.sf_noalign: @@ -577,6 +578,7 @@ BEGIN IF parser.sym = SCAN.lxCOMMA THEN ExpectSym(parser, SCAN.lxSTRING); dll := parser.lex.s; + STRINGS.UpCase(dll); ExpectSym(parser, SCAN.lxCOMMA); ExpectSym(parser, SCAN.lxSTRING); proc := parser.lex.s; @@ -586,16 +588,19 @@ BEGIN checklex(parser, SCAN.lxRSQUARE); Next(parser) ELSE - CASE program.target.bit_depth OF + CASE TARGETS.BitDepth OF |16: call := PROG.default16 - |32: call := PROG.default32 + |32: IF TARGETS.target = TARGETS.STM32CM3 THEN + call := PROG.ccall + ELSE + call := PROG.default32 + END |64: call := PROG.default64 END END; IF import # NIL THEN - check(~(program.target.sys IN {mConst.Target_iELF32, mConst.Target_iELF64, mConst.Target_iELFSO32, - mConst.Target_iELFSO64, mConst.Target_iMSP430}), pos, 70) + check(TARGETS.Import, pos, 70) END RETURN call @@ -751,8 +756,8 @@ BEGIN ExpectSym(parser, SCAN.lxTO); Next(parser); - t := PROG.enterType(program, PROG.tPOINTER, program.target.adr, 0, unit); - t.align := program.target.adr; + t := PROG.enterType(program, PROG.tPOINTER, TARGETS.AdrSize, 0, unit); + t.align := TARGETS.AdrSize; getpos(parser, pos); @@ -770,8 +775,8 @@ BEGIN ELSIF parser.sym = SCAN.lxPROCEDURE THEN NextPos(parser, pos); - t := PROG.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit); - t.align := program.target.adr; + t := PROG.enterType(program, PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit); + t.align := TARGETS.AdrSize; t.call := procflag(parser, import, FALSE); FormalParameters(parser, t) ELSE @@ -897,11 +902,13 @@ VAR variables: LISTS.LIST; int, flt: INTEGER; comma: BOOLEAN; - code: ARITH.VALUE; - codeProc: BOOLEAN; + code, iv: ARITH.VALUE; + codeProc, + handler: BOOLEAN; BEGIN endmod := FALSE; + handler := FALSE; unit := parser.unit; @@ -921,13 +928,27 @@ VAR check(PROG.openScope(unit, proc.proc), pos, 116); - proc.type := PROG.enterType(program, PROG.tPROCEDURE, program.target.adr, 0, unit); + proc.type := PROG.enterType(program, PROG.tPROCEDURE, TARGETS.AdrSize, 0, unit); t := proc.type; - t.align := program.target.adr; + t.align := TARGETS.AdrSize; t.call := call; FormalParameters(parser, t); + IF parser.sym = SCAN.lxLSQUARE THEN + getpos(parser, pos2); + check(TARGETS.target = TARGETS.STM32CM3, pos2, 24); + Next(parser); + getpos(parser, pos2); + ConstExpression(parser, iv); + check(iv.typ = ARITH.tINTEGER, pos2, 43); + check((0 <= ARITH.Int(iv)) & (ARITH.Int(iv) <= THUMB.maxIVT), pos2, 46); + check(THUMB.SetIV(ARITH.Int(iv)), pos2, 121); + checklex(parser, SCAN.lxRSQUARE); + Next(parser); + handler := TRUE + END; + codeProc := call IN {PROG.code, PROG._code}; IF call IN {PROG.systemv, PROG._systemv} THEN @@ -948,7 +969,11 @@ VAR IF import = NIL THEN label := IL.NewLabel(); - proc.proc.label := label + proc.proc.label := label; + proc.proc.used := handler; + IF handler THEN + IL.AddCmd2(IL.opHANDLER, label, ARITH.Int(iv)) + END END; IF codeProc THEN @@ -958,8 +983,10 @@ VAR getpos(parser, pos2); ConstExpression(parser, code); check(code.typ = ARITH.tINTEGER, pos2, 43); - IF program.target.sys # mConst.Target_iMSP430 THEN + IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN check(ARITH.range(code, 0, 255), pos2, 42) + ELSIF TARGETS.CPU = TARGETS.cpuTHUMB THEN + check(ARITH.range(code, 0, 65535), pos2, 110) END; IL.AddCmd(IL.opCODE, ARITH.getInt(code)); comma := parser.sym = SCAN.lxCOMMA; @@ -976,8 +1003,8 @@ VAR IF import = NIL THEN - IF parser.main & proc.export & program.dll THEN - IF program.obj THEN + IF parser.main & proc.export & TARGETS.Dll THEN + IF TARGETS.target = TARGETS.KolibriOSDLL THEN check((proc.name.s # "lib_init") & (proc.name.s # "version"), pos, 114) END; IL.AddExp(label, proc.name.s); @@ -1023,8 +1050,8 @@ VAR 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) + IF TARGETS.CPU = TARGETS.cpuMSP430 THEN + check((enter.param2 * ORD(~codeProc) + proc.type.parSize) * 2 + 16 < program.options.ram, pos1, 63) END END; @@ -1141,7 +1168,13 @@ BEGIN ImportList(parser) END; - CONSOLE.String("compiling "); CONSOLE.String(unit.name.s); + INC(modules); + + CONSOLE.String("compiling "); + IF TARGETS.CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuMSP430} THEN + CONSOLE.String("("); CONSOLE.Int(modules); CONSOLE.String(") ") + END; + CONSOLE.String(unit.name.s); IF parser.unit.sysimport THEN CONSOLE.String(" (SYSTEM)") END; @@ -1156,6 +1189,9 @@ BEGIN IL.SetLabel(errlabel); IL.StrAdr(name); IL.Param1; + IF TARGETS.CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuMSP430} THEN + IL.AddCmd(IL.opPUSHC, modules) + END; IL.AddCmd0(IL.opERR); FOR errno := 1 TO LEN(IL.codes.errlabels) - 1 DO @@ -1227,7 +1263,7 @@ BEGIN parser.path := path; parser.lib_path := lib_path; - parser.ext := mConst.FILE_EXT; + parser.ext := UTILS.FILE_EXT; parser.fname := path; parser.modname := ""; parser.scanner := NIL; @@ -1247,12 +1283,13 @@ BEGIN END create; -PROCEDURE init* (bit_depth, target: INTEGER; options: PROG.OPTIONS); +PROCEDURE init* (options: PROG.OPTIONS); BEGIN - program := PROG.create(bit_depth, target, options); + program := PROG.create(options); parsers := C.create(); - lines := 0 + lines := 0; + modules := 0 END init; -END PARS. +END PARS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/PATHS.ob07 b/programs/develop/oberon07/Source/PATHS.ob07 index 4410514158..5532b6ca1d 100644 --- a/programs/develop/oberon07/Source/PATHS.ob07 +++ b/programs/develop/oberon07/Source/PATHS.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -106,4 +106,4 @@ BEGIN END GetCurrentDirectory; -END PATHS. +END PATHS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/PE32.ob07 b/programs/develop/oberon07/Source/PE32.ob07 index 6dc88d8b70..32d1fc17e0 100644 --- a/programs/develop/oberon07/Source/PE32.ob07 +++ b/programs/develop/oberon07/Source/PE32.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -7,7 +7,7 @@ MODULE PE32; -IMPORT BIN, LISTS, UTILS, WR := WRITER, mConst := CONSTANTS, CHL := CHUNKLISTS; +IMPORT BIN, LISTS, UTILS, WR := WRITER, CHL := CHUNKLISTS; CONST @@ -165,11 +165,7 @@ VAR Relocations: LISTS.LIST; bit64: BOOLEAN; libcnt: INTEGER; - - -PROCEDURE SIZE (): INTEGER; - RETURN SIZE_OF_DWORD * (ORD(bit64) + 1) -END SIZE; + SizeOfWord: INTEGER; PROCEDURE Export (program: BIN.PROGRAM; DataRVA: INTEGER; VAR ExportDir: IMAGE_EXPORT_DIRECTORY): INTEGER; @@ -258,41 +254,42 @@ BEGIN import := import.next(BIN.IMPRT) END - RETURN (libcnt + 1) * 5 * SIZE_OF_DWORD + (proccnt + libcnt) * 2 * SIZE() + RETURN (libcnt + 1) * 5 * SIZE_OF_DWORD + (proccnt + libcnt) * 2 * SizeOfWord END GetImportSize; PROCEDURE fixup (program: BIN.PROGRAM; Address: VIRTUAL_ADDR); VAR - reloc: BIN.RELOC; - iproc: BIN.IMPRT; - L: INTEGER; - delta: INTEGER; - AdrImp: INTEGER; + reloc: BIN.RELOC; + iproc: BIN.IMPRT; + code: CHL.BYTELIST; + L, delta, delta0, AdrImp: INTEGER; BEGIN AdrImp := Address.Import + (libcnt + 1) * 5 * SIZE_OF_DWORD; - + code := program.code; reloc := program.rel_list.first(BIN.RELOC); + delta0 := 3 - 7 * ORD(bit64); + WHILE reloc # NIL DO - L := BIN.get32le(program.code, reloc.offset); - delta := 3 - reloc.offset - Address.Code - 7 * ORD(bit64); + L := BIN.get32le(code, reloc.offset); + delta := delta0 - reloc.offset - Address.Code; CASE reloc.opcode OF |BIN.PICDATA: - BIN.put32le(program.code, reloc.offset, L + Address.Data + delta) + BIN.put32le(code, reloc.offset, L + Address.Data + delta) |BIN.PICCODE: - BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + Address.Code + delta) + BIN.put32le(code, reloc.offset, BIN.GetLabel(program, L) + Address.Code + delta) |BIN.PICBSS: - BIN.put32le(program.code, reloc.offset, L + Address.Bss + delta) + BIN.put32le(code, reloc.offset, L + Address.Bss + delta) |BIN.PICIMP: iproc := BIN.GetIProc(program, L); - BIN.put32le(program.code, reloc.offset, iproc.FirstThunk * SIZE() + AdrImp + delta) + BIN.put32le(code, reloc.offset, iproc.FirstThunk * SizeOfWord + AdrImp + delta) END; @@ -418,7 +415,6 @@ VAR i: INTEGER; BEGIN - WriteWord(file, h.Magic); WR.WriteByte(file, h.MajorLinkerVersion); @@ -499,6 +495,7 @@ VAR BEGIN bit64 := amd64; + SizeOfWord := SIZE_OF_DWORD * (ORD(bit64) + 1); Relocations := LISTS.create(NIL); Size.Code := CHL.Length(program.code); @@ -532,8 +529,8 @@ BEGIN PEHeader.FileHeader.Characteristics := WCHR(010EH + (20H - 100H) * ORD(amd64) + 2000H * ORD(dll)); PEHeader.OptionalHeader.Magic := WCHR(010BH + 100H * ORD(amd64)); - PEHeader.OptionalHeader.MajorLinkerVersion := mConst.vMajor; - PEHeader.OptionalHeader.MinorLinkerVersion := mConst.vMinor; + PEHeader.OptionalHeader.MajorLinkerVersion := UTILS.vMajor; + PEHeader.OptionalHeader.MinorLinkerVersion := UTILS.vMinor; PEHeader.OptionalHeader.SizeOfCode := align(Size.Code, FileAlignment); PEHeader.OptionalHeader.SizeOfInitializedData := 0; PEHeader.OptionalHeader.SizeOfUninitializedData := 0; @@ -563,30 +560,30 @@ BEGIN PEHeader.OptionalHeader.NumberOfRvaAndSizes := IMAGE_NUMBEROF_DIRECTORY_ENTRIES; InitSection(SectionHeaders[0], ".text", SHC_text); - SectionHeaders[0].VirtualSize := Size.Code; - SectionHeaders[0].VirtualAddress := SectionAlignment; - SectionHeaders[0].SizeOfRawData := align(Size.Code, FileAlignment); - SectionHeaders[0].PointerToRawData := PEHeader.OptionalHeader.SizeOfHeaders; + SectionHeaders[0].VirtualSize := Size.Code; + SectionHeaders[0].VirtualAddress := SectionAlignment; + SectionHeaders[0].SizeOfRawData := align(Size.Code, FileAlignment); + SectionHeaders[0].PointerToRawData := PEHeader.OptionalHeader.SizeOfHeaders; InitSection(SectionHeaders[1], ".data", SHC_data); - SectionHeaders[1].VirtualSize := Size.Data; - SectionHeaders[1].VirtualAddress := align(SectionHeaders[0].VirtualAddress + SectionHeaders[0].VirtualSize, SectionAlignment); - SectionHeaders[1].SizeOfRawData := align(Size.Data, FileAlignment); - SectionHeaders[1].PointerToRawData := SectionHeaders[0].PointerToRawData + SectionHeaders[0].SizeOfRawData; + SectionHeaders[1].VirtualSize := Size.Data; + SectionHeaders[1].VirtualAddress := align(SectionHeaders[0].VirtualAddress + SectionHeaders[0].VirtualSize, SectionAlignment); + SectionHeaders[1].SizeOfRawData := align(Size.Data, FileAlignment); + SectionHeaders[1].PointerToRawData := SectionHeaders[0].PointerToRawData + SectionHeaders[0].SizeOfRawData; InitSection(SectionHeaders[2], ".bss", SHC_bss); - SectionHeaders[2].VirtualSize := Size.Bss; - SectionHeaders[2].VirtualAddress := align(SectionHeaders[1].VirtualAddress + SectionHeaders[1].VirtualSize, SectionAlignment); - SectionHeaders[2].SizeOfRawData := 0; - SectionHeaders[2].PointerToRawData := SectionHeaders[1].PointerToRawData + SectionHeaders[1].SizeOfRawData; + SectionHeaders[2].VirtualSize := Size.Bss; + SectionHeaders[2].VirtualAddress := align(SectionHeaders[1].VirtualAddress + SectionHeaders[1].VirtualSize, SectionAlignment); + SectionHeaders[2].SizeOfRawData := 0; + SectionHeaders[2].PointerToRawData := SectionHeaders[1].PointerToRawData + SectionHeaders[1].SizeOfRawData; Size.Import := GetImportSize(program.imp_list); InitSection(SectionHeaders[3], ".idata", SHC_data); - SectionHeaders[3].VirtualSize := Size.Import + CHL.Length(program.import); - SectionHeaders[3].VirtualAddress := align(SectionHeaders[2].VirtualAddress + SectionHeaders[2].VirtualSize, SectionAlignment); - SectionHeaders[3].SizeOfRawData := align(SectionHeaders[3].VirtualSize, FileAlignment); - SectionHeaders[3].PointerToRawData := SectionHeaders[2].PointerToRawData + SectionHeaders[2].SizeOfRawData; + SectionHeaders[3].VirtualSize := Size.Import + CHL.Length(program.import); + SectionHeaders[3].VirtualAddress := align(SectionHeaders[2].VirtualAddress + SectionHeaders[2].VirtualSize, SectionAlignment); + SectionHeaders[3].SizeOfRawData := align(SectionHeaders[3].VirtualSize, FileAlignment); + SectionHeaders[3].PointerToRawData := SectionHeaders[2].PointerToRawData + SectionHeaders[2].SizeOfRawData; Address.Code := SectionHeaders[0].VirtualAddress + PEHeader.OptionalHeader.ImageBase; Address.Data := SectionHeaders[1].VirtualAddress + PEHeader.OptionalHeader.ImageBase; @@ -599,10 +596,10 @@ BEGIN Size.Export := Export(program, SectionHeaders[1].VirtualAddress, ExportDir); InitSection(SectionHeaders[4], ".edata", SHC_data); - SectionHeaders[4].VirtualSize := Size.Export + CHL.Length(program.export); - SectionHeaders[4].VirtualAddress := align(SectionHeaders[3].VirtualAddress + SectionHeaders[3].VirtualSize, SectionAlignment); - SectionHeaders[4].SizeOfRawData := align(SectionHeaders[4].VirtualSize, FileAlignment); - SectionHeaders[4].PointerToRawData := SectionHeaders[3].PointerToRawData + SectionHeaders[3].SizeOfRawData; + SectionHeaders[4].VirtualSize := Size.Export + CHL.Length(program.export); + SectionHeaders[4].VirtualAddress := align(SectionHeaders[3].VirtualAddress + SectionHeaders[3].VirtualSize, SectionAlignment); + SectionHeaders[4].SizeOfRawData := align(SectionHeaders[4].VirtualSize, FileAlignment); + SectionHeaders[4].PointerToRawData := SectionHeaders[3].PointerToRawData + SectionHeaders[3].SizeOfRawData; END; FOR i := 0 TO IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 DO @@ -658,7 +655,7 @@ BEGIN n := (libcnt + 1) * 5; ImportTable := CHL.CreateIntList(); - FOR i := 0 TO (Size.Import - n * SIZE_OF_DWORD) DIV SIZE() + n - 1 DO + FOR i := 0 TO (Size.Import - n * SIZE_OF_DWORD) DIV SizeOfWord + n - 1 DO CHL.PushInt(ImportTable, 0) END; @@ -666,11 +663,11 @@ BEGIN import := program.imp_list.first(BIN.IMPRT); WHILE import # NIL DO IF import.label = 0 THEN - CHL.SetInt(ImportTable, i + 0, import.OriginalFirstThunk * SIZE() + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); + CHL.SetInt(ImportTable, i + 0, import.OriginalFirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); CHL.SetInt(ImportTable, i + 1, 0); CHL.SetInt(ImportTable, i + 2, 0); CHL.SetInt(ImportTable, i + 3, import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress); - CHL.SetInt(ImportTable, i + 4, import.FirstThunk * SIZE() + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); + CHL.SetInt(ImportTable, i + 4, import.FirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD); i := i + 5 END; import := import.next(BIN.IMPRT) @@ -738,4 +735,4 @@ BEGIN END write; -END PE32. +END PE32. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/PROG.ob07 b/programs/develop/oberon07/Source/PROG.ob07 index cb9804b191..a398bef3cd 100644 --- a/programs/develop/oberon07/Source/PROG.ob07 +++ b/programs/develop/oberon07/Source/PROG.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -7,7 +7,7 @@ MODULE PROG; -IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, mConst := CONSTANTS, IL, UTILS; +IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, IL, UTILS, TARGETS; CONST @@ -199,25 +199,15 @@ TYPE locsize*: INTEGER; procs*: LISTS.LIST; - dll*: BOOLEAN; - obj*: BOOLEAN; + + sysflags*: SET; + options*: OPTIONS; stTypes*: RECORD tINTEGER*, tBYTE*, tCHAR*, tWCHAR*, tSET*, tBOOLEAN*, tREAL*, tSTRING*, tNIL*, tCARD32*, tANYREC*: TYPE_ - END; - - target*: RECORD - - bit_depth*: INTEGER; - word*: INTEGER; - adr*: INTEGER; - sys*: INTEGER; - sysflags*: SET; - options*: OPTIONS - END END; @@ -249,7 +239,6 @@ END NewIdent; PROCEDURE getOffset* (program: PROGRAM; varIdent: IDENT): INTEGER; VAR - word: INTEGER; size: INTEGER; BEGIN @@ -263,9 +252,8 @@ BEGIN END END ELSE - word := program.target.word; - IF UTILS.Align(size, word) THEN - size := size DIV word; + IF UTILS.Align(size, TARGETS.WordSize) THEN + size := size DIV TARGETS.WordSize; IF UTILS.maxint - program.locsize >= size THEN INC(program.locsize, size); varIdent.offset := program.locsize @@ -682,10 +670,12 @@ BEGIN ident := addIdent(unit, SCAN.enterid("BOOLEAN"), idTYPE); ident.type := program.stTypes.tBOOLEAN; - IF program.target.sys # mConst.Target_iMSP430 THEN + IF TARGETS.RealSize # 0 THEN ident := addIdent(unit, SCAN.enterid("REAL"), idTYPE); - ident.type := program.stTypes.tREAL; + ident.type := program.stTypes.tREAL + END; + IF TARGETS.BitDepth >= 32 THEN ident := addIdent(unit, SCAN.enterid("WCHAR"), idTYPE); ident.type := program.stTypes.tWCHAR END @@ -737,14 +727,19 @@ BEGIN 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); + IF TARGETS.RealSize # 0 THEN + EnterProc(unit, "PACK", stPACK); + EnterProc(unit, "UNPK", stUNPK); + EnterFunc(unit, "FLOOR", stFLOOR); + EnterFunc(unit, "FLT", stFLT) + END; - EnterFunc(unit, "WCHR", stWCHR); - EnterFunc(unit, "FLOOR", stFLOOR); - EnterFunc(unit, "FLT", stFLT) + IF TARGETS.BitDepth >= 32 THEN + EnterFunc(unit, "WCHR", stWCHR) + END; + + IF TARGETS.Dispose THEN + EnterProc(unit, "DISPOSE", stDISPOSE) END END enterStProcs; @@ -782,7 +777,7 @@ BEGIN unit.sysimport := FALSE; - IF unit.name.s = mConst.RTL_NAME THEN + IF unit.name.s = UTILS.RTL_NAME THEN program.rtl := unit END @@ -1037,7 +1032,7 @@ BEGIN t.unit := unit; t.num := 0; - CASE program.target.bit_depth OF + CASE TARGETS.BitDepth OF |16: t.call := default16 |32: t.call := default32 |64: t.call := default64 @@ -1119,12 +1114,18 @@ BEGIN EnterProc(unit, "DINT", idSYSPROC, sysDINT) END; *) - IF program.target.sys # mConst.Target_iMSP430 THEN - EnterProc(unit, "WSADR", idSYSFUNC, sysWSADR); + IF TARGETS.RealSize # 0 THEN EnterProc(unit, "INF", idSYSFUNC, sysINF); + END; + + IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN + EnterProc(unit, "COPY", idSYSPROC, sysCOPY) + END; + + IF TARGETS.BitDepth >= 32 THEN + EnterProc(unit, "WSADR", idSYSFUNC, sysWSADR); EnterProc(unit, "PUT32", idSYSPROC, sysPUT32); EnterProc(unit, "PUT16", idSYSPROC, sysPUT16); - EnterProc(unit, "COPY", idSYSPROC, sysCOPY); ident := addIdent(unit, SCAN.enterid("CARD32"), idTYPE); ident.type := program.stTypes.tCARD32; @@ -1191,41 +1192,25 @@ BEGIN END DelUnused; -PROCEDURE create* (bit_depth, target: INTEGER; options: OPTIONS): PROGRAM; +PROCEDURE create* (options: OPTIONS): PROGRAM; VAR program: PROGRAM; BEGIN idents := C.create(); - UTILS.SetBitDepth(bit_depth); + UTILS.SetBitDepth(TARGETS.BitDepth, TARGETS.RealSize = 8); NEW(program); - program.target.bit_depth := bit_depth; - program.target.word := bit_depth DIV 8; - program.target.adr := bit_depth DIV 8; - program.target.sys := target; - program.target.options := options; + program.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} + CASE TARGETS.OS OF + |TARGETS.osWIN32: program.sysflags := {sf_windows, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} + |TARGETS.osLINUX32: program.sysflags := {sf_linux, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} + |TARGETS.osKOS: program.sysflags := {sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} + |TARGETS.osWIN64: program.sysflags := {sf_windows, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} + |TARGETS.osLINUX64: program.sysflags := {sf_linux, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} + |TARGETS.osNONE: program.sysflags := {sf_code} END; program.recCount := -1; @@ -1235,38 +1220,35 @@ BEGIN program.types := LISTS.create(NIL); program.procs := LISTS.create(NIL); - 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.tSET := enterType(program, tSET, program.target.word, 0, NIL); - program.stTypes.tBOOLEAN := enterType(program, tBOOLEAN, 1, 0, NIL); + program.stTypes.tINTEGER := enterType(program, tINTEGER, TARGETS.WordSize, 0, NIL); + program.stTypes.tBYTE := enterType(program, tBYTE, 1, 0, NIL); + program.stTypes.tCHAR := enterType(program, tCHAR, 1, 0, NIL); + program.stTypes.tSET := enterType(program, tSET, TARGETS.WordSize, 0, NIL); + program.stTypes.tBOOLEAN := enterType(program, tBOOLEAN, 1, 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.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.tINTEGER.align := TARGETS.WordSize; program.stTypes.tBYTE.align := 1; - program.stTypes.tCHAR.align := program.stTypes.tCHAR.size; - program.stTypes.tSET.align := program.stTypes.tSET.size; - program.stTypes.tBOOLEAN.align := program.stTypes.tBOOLEAN.size; + program.stTypes.tCHAR.align := 1; + program.stTypes.tSET.align := TARGETS.WordSize; + program.stTypes.tBOOLEAN.align := 1; - IF target # mConst.Target_iMSP430 THEN - program.stTypes.tWCHAR.align := program.stTypes.tWCHAR.size; - program.stTypes.tREAL.align := program.stTypes.tREAL.size; - program.stTypes.tCARD32.align := program.stTypes.tCARD32.size + IF TARGETS.BitDepth >= 32 THEN + program.stTypes.tWCHAR := enterType(program, tWCHAR, 2, 0, NIL); + program.stTypes.tCARD32 := enterType(program, tCARD32, 4, 0, NIL); + program.stTypes.tWCHAR.align := 2; + program.stTypes.tCARD32.align := 4 END; - program.dll := FALSE; - program.obj := FALSE; + IF TARGETS.RealSize # 0 THEN + program.stTypes.tREAL := enterType(program, tREAL, TARGETS.RealSize, 0, NIL); + program.stTypes.tREAL.align := TARGETS.RealSize + END; + + program.stTypes.tSTRING := enterType(program, tSTRING, TARGETS.WordSize, 0, NIL); + program.stTypes.tNIL := enterType(program, tNIL, TARGETS.WordSize, 0, NIL); + + program.stTypes.tANYREC := enterType(program, tRECORD, 0, 0, NIL); + program.stTypes.tANYREC.closed := TRUE; createSysUnit(program) @@ -1274,4 +1256,4 @@ BEGIN END create; -END PROG. +END PROG. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/REG.ob07 b/programs/develop/oberon07/Source/REG.ob07 index f5abb0f2c4..f0543cace6 100644 --- a/programs/develop/oberon07/Source/REG.ob07 +++ b/programs/develop/oberon07/Source/REG.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -435,4 +435,4 @@ BEGIN END Init; -END REG. +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 e6c0aef060..029b2f34df 100644 --- a/programs/develop/oberon07/Source/SCAN.ob07 +++ b/programs/develop/oberon07/Source/SCAN.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -606,4 +606,4 @@ END init; BEGIN init -END SCAN. +END SCAN. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/STATEMENTS.ob07 b/programs/develop/oberon07/Source/STATEMENTS.ob07 index c263d4f49b..269719d789 100644 --- a/programs/develop/oberon07/Source/STATEMENTS.ob07 +++ b/programs/develop/oberon07/Source/STATEMENTS.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -9,8 +9,8 @@ MODULE STATEMENTS; IMPORT - PARS, PROG, SCAN, ARITH, STRINGS, LISTS, IL, X86, AMD64, MSP430, - ERRORS, UTILS, AVL := AVLTREES, CONSOLE, C := COLLECTIONS, mConst := CONSTANTS; + PARS, PROG, SCAN, ARITH, STRINGS, LISTS, IL, X86, AMD64, MSP430, THUMB, + ERRORS, UTILS, AVL := AVLTREES, CONSOLE, C := COLLECTIONS, TARGETS; CONST @@ -29,8 +29,6 @@ CONST chkALL* = {chkIDX, chkGUARD, chkPTR, chkCHR, chkWCHR, chkBYTE}; - cpuX86 = 1; cpuAMD64 = 2; cpuMSP430 = 3; - TYPE @@ -362,8 +360,8 @@ END CheckRange; PROCEDURE assign (e: PARS.EXPR; VarType: PROG.TYPE_; line: INTEGER): BOOLEAN; VAR - res: BOOLEAN; - label: INTEGER; + res: BOOLEAN; + label: INTEGER; BEGIN IF isExpr(e) OR (e.obj IN {ePROC, eIMP}) THEN @@ -418,7 +416,7 @@ BEGIN IF e.obj = eCONST THEN IL.Float(ARITH.Float(e.value)) END; - IL.savef + IL.savef(e.obj = eCONST) ELSIF isChar(e) & (VarType = tCHAR) THEN IF e.obj = eCONST THEN IL.AddCmd(IL.opSAVE8C, ARITH.Int(e.value)) @@ -500,6 +498,7 @@ VAR PROCEDURE ArrLen (t: PROG.TYPE_; n: INTEGER): INTEGER; VAR res: INTEGER; + BEGIN REPEAT res := t.length; @@ -513,8 +512,8 @@ VAR PROCEDURE OpenArray (t, t2: PROG.TYPE_); VAR - n: INTEGER; - d1, d2: INTEGER; + n, d1, d2: INTEGER; + BEGIN IF t.length # 0 THEN IL.Param1; @@ -606,7 +605,7 @@ BEGIN IF p.type.base = tCHAR THEN stroffs := String(e); IL.StrAdr(stroffs); - IF (CPU = cpuMSP430) & (p.type.size - strlen(e) - 1 > MSP430.IntVectorSize) THEN + IF (CPU = TARGETS.cpuMSP430) & (p.type.size - strlen(e) - 1 > MSP430.IntVectorSize) THEN ERRORS.WarningMsg(pos.line, pos.col, 0) END ELSE (* WCHAR *) @@ -648,17 +647,16 @@ END PExpression; PROCEDURE stProc (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR - e2: PARS.EXPR; - pos: PARS.POSITION; - proc: INTEGER; - label: INTEGER; - n, i: INTEGER; - code: ARITH.VALUE; - e1: PARS.EXPR; - wchar: BOOLEAN; + e1, e2: PARS.EXPR; + pos: PARS.POSITION; + proc, + label, + n, i: INTEGER; + code: ARITH.VALUE; + wchar, + comma: BOOLEAN; cmd1, - cmd2: IL.COMMAND; - comma: BOOLEAN; + cmd2: IL.COMMAND; PROCEDURE varparam (parser: PARS.PARSER; pos: PARS.POSITION; isfunc: isXXX; readOnly: BOOLEAN; VAR e: PARS.EXPR); @@ -675,6 +673,7 @@ VAR PROCEDURE shift_minmax (proc: INTEGER): CHAR; VAR res: CHAR; + BEGIN CASE proc OF |PROG.stASR: res := "A" @@ -777,7 +776,7 @@ BEGIN |PROG.stNEW: varparam(parser, pos, isPtr, TRUE, e); - IF CPU = cpuMSP430 THEN + IF CPU = TARGETS.cpuMSP430 THEN PARS.check(e.type.base.size + 16 < Options.ram, pos, 63) END; IL.New(e.type.base.size, e.type.base.num) @@ -885,9 +884,9 @@ BEGIN PARS.check(e2.type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66); IF e2.obj = eCONST THEN IF e2.type = tREAL THEN - IL.setlast(endcall.prev(IL.COMMAND)); IL.Float(ARITH.Float(e2.value)); - IL.savef + IL.setlast(endcall.prev(IL.COMMAND)); + IL.savef(FALSE) ELSE LoadConst(e2); IL.setlast(endcall.prev(IL.COMMAND)); @@ -896,7 +895,7 @@ BEGIN ELSE IL.setlast(endcall.prev(IL.COMMAND)); IF e2.type = tREAL THEN - IL.savef + IL.savef(FALSE) ELSIF e2.type = tBYTE THEN IL.SysPut(tINTEGER.size) ELSE @@ -962,8 +961,10 @@ BEGIN getpos(parser, pos); PARS.ConstExpression(parser, code); PARS.check(code.typ = ARITH.tINTEGER, pos, 43); - IF CPU # cpuMSP430 THEN + IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN PARS.check(ARITH.range(code, 0, 255), pos, 42) + ELSIF CPU = TARGETS.cpuTHUMB THEN + PARS.check(ARITH.range(code, 0, 65535), pos, 110) END; IL.AddCmd(IL.opCODE, ARITH.getInt(code)); comma := parser.sym = SCAN.lxCOMMA; @@ -1113,7 +1114,7 @@ BEGIN IF e.obj = eCONST THEN ARITH.odd(e.value) ELSE - IL.AddCmd0(IL.opODD) + IL.AddCmd(IL.opMODR, 2) END |PROG.stORD: @@ -1340,7 +1341,7 @@ END qualident; PROCEDURE deref (pos: PARS.POSITION; e: PARS.EXPR; load: BOOLEAN; error: INTEGER); VAR - label: INTEGER; + label: INTEGER; BEGIN IF load THEN @@ -1409,9 +1410,8 @@ VAR PROCEDURE OpenIdx (parser: PARS.PARSER; pos: PARS.POSITION; e: PARS.EXPR); VAR - label: INTEGER; - type: PROG.TYPE_; - n, offset, k: INTEGER; + label, offset, n, k: INTEGER; + type: PROG.TYPE_; BEGIN @@ -1571,12 +1571,12 @@ END designator; PROCEDURE ProcCall (e: PARS.EXPR; procType: PROG.TYPE_; isfloat: BOOLEAN; VAR fregs: INTEGER; parser: PARS.PARSER; pos: PARS.POSITION; CallStat: BOOLEAN); VAR - cconv: INTEGER; - parSize: INTEGER; - callconv: INTEGER; - fparSize: INTEGER; - int, flt: INTEGER; - stk_par: INTEGER; + cconv, + parSize, + callconv, + fparSize, + int, flt, + stk_par: INTEGER; BEGIN cconv := procType.call; @@ -1862,11 +1862,8 @@ VAR PROCEDURE term (parser: PARS.PARSER; VAR e: PARS.EXPR); VAR pos: PARS.POSITION; - op: INTEGER; e1: PARS.EXPR; - - label: INTEGER; - label1: INTEGER; + op, label, label1: INTEGER; BEGIN factor(parser, e); @@ -1972,10 +1969,7 @@ VAR |SCAN.lxDIV, SCAN.lxMOD: PARS.check(isInt(e) & isInt(e1), pos, 37); IF e1.obj = eCONST THEN - PARS.check(~ARITH.isZero(e1.value), pos, 46); - IF CPU = cpuMSP430 THEN - PARS.check(ARITH.Int(e1.value) > 0, pos, 122) - END + PARS.check(ARITH.Int(e1.value) > 0, pos, 122) END; IF (e.obj = eCONST) & (e1.obj = eCONST) THEN @@ -1988,11 +1982,7 @@ VAR ELSE IF e1.obj # eCONST THEN label1 := IL.NewLabel(); - IF CPU = cpuMSP430 THEN - IL.AddJmpCmd(IL.opJG, label1) - ELSE - IL.AddJmpCmd(IL.opJNZ, label1) - END + IL.AddJmpCmd(IL.opJG, label1) END; IF e.obj = eCONST THEN IL.OnError(pos.line, errDIV); @@ -2223,7 +2213,6 @@ VAR res: BOOLEAN; BEGIN - res := TRUE; IF isString(e) & isCharArray(e1) THEN @@ -2527,11 +2516,11 @@ END expression; PROCEDURE ElementaryStatement (parser: PARS.PARSER); VAR - e, e1: PARS.EXPR; - pos: PARS.POSITION; - line: INTEGER; - call: BOOLEAN; - fregs: INTEGER; + e, e1: PARS.EXPR; + pos: PARS.POSITION; + line: INTEGER; + call: BOOLEAN; + fregs: INTEGER; BEGIN getpos(parser, pos); @@ -2590,8 +2579,8 @@ END ElementaryStatement; PROCEDURE IfStatement (parser: PARS.PARSER; if: BOOLEAN); VAR - e: PARS.EXPR; - pos: PARS.POSITION; + e: PARS.EXPR; + pos: PARS.POSITION; label, L: INTEGER; @@ -2731,16 +2720,16 @@ END NewVariant; PROCEDURE CaseStatement (parser: PARS.PARSER); VAR - e: PARS.EXPR; - pos: PARS.POSITION; + e: PARS.EXPR; + pos: PARS.POSITION; PROCEDURE Label (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR type: PROG.TYPE_): INTEGER; VAR - a: INTEGER; - label: PARS.EXPR; - pos: PARS.POSITION; - value: ARITH.VALUE; + a: INTEGER; + label: PARS.EXPR; + pos: PARS.POSITION; + value: ARITH.VALUE; BEGIN getpos(parser, pos); @@ -2856,11 +2845,11 @@ VAR PROCEDURE case (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; end: INTEGER); VAR - sym: INTEGER; - t: PROG.TYPE_; - variant: INTEGER; - node: AVL.NODE; - last: IL.COMMAND; + sym: INTEGER; + t: PROG.TYPE_; + variant: INTEGER; + node: AVL.NODE; + last: IL.COMMAND; BEGIN sym := parser.sym; @@ -2958,7 +2947,7 @@ VAR VAR table, end, else: INTEGER; tree: AVL.NODE; - item: LISTS.ITEM; + item: LISTS.ITEM; BEGIN LISTS.push(CaseVariants, NewVariant(0, NIL)); @@ -3026,11 +3015,11 @@ BEGIN ELSIF isRec(e) THEN IL.drop; IL.AddCmd(IL.opLADR, e.ident.offset - 1); - IL.load(PARS.program.target.word) + IL.load(TARGETS.WordSize) ELSIF isPtr(e) THEN deref(pos, e, FALSE, errPTR); - IL.AddCmd(IL.opSUBR, PARS.program.target.word); - IL.load(PARS.program.target.word) + IL.AddCmd(IL.opSUBR, TARGETS.WordSize); + IL.load(TARGETS.WordSize) END; PARS.checklex(parser, SCAN.lxOF); @@ -3222,7 +3211,7 @@ VAR PROCEDURE getproc (rtl: PROG.UNIT; name: SCAN.LEXSTR; idx: INTEGER); VAR - id: PROG.IDENT; + id: PROG.IDENT; BEGIN id := PROG.getIdent(rtl, SCAN.enterid(name), FALSE); @@ -3243,29 +3232,42 @@ BEGIN rtl := PARS.program.rtl; ASSERT(rtl # NIL); - IF CPU IN {cpuX86, cpuAMD64} THEN - getproc(rtl, "_strcmp", IL._strcmp); - getproc(rtl, "_length", IL._length); - getproc(rtl, "_arrcpy", IL._arrcpy); - getproc(rtl, "_is", IL._is); - getproc(rtl, "_guard", IL._guard); - getproc(rtl, "_guardrec", IL._guardrec); - getproc(rtl, "_error", IL._error); - getproc(rtl, "_new", IL._new); - getproc(rtl, "_rot", IL._rot); - getproc(rtl, "_strcpy", IL._strcpy); - getproc(rtl, "_move", IL._move); - getproc(rtl, "_divmod", IL._divmod); - getproc(rtl, "_set", IL._set); - getproc(rtl, "_set1", IL._set1); - 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) + getproc(rtl, "_strcmp", IL._strcmp); + getproc(rtl, "_length", IL._length); + getproc(rtl, "_arrcpy", IL._arrcpy); + getproc(rtl, "_is", IL._is); + getproc(rtl, "_guard", IL._guard); + getproc(rtl, "_guardrec", IL._guardrec); + getproc(rtl, "_new", IL._new); + getproc(rtl, "_rot", IL._rot); + getproc(rtl, "_strcpy", IL._strcpy); + getproc(rtl, "_move", IL._move); + getproc(rtl, "_set", IL._set); + getproc(rtl, "_set1", IL._set1); + getproc(rtl, "_lengthw", IL._lengthw); + getproc(rtl, "_strcmpw", IL._strcmpw); + getproc(rtl, "_init", IL._init); + + IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN + getproc(rtl, "_error", IL._error); + getproc(rtl, "_divmod", IL._divmod); + getproc(rtl, "_exit", IL._exit); + getproc(rtl, "_dispose", IL._dispose); + getproc(rtl, "_isrec", IL._isrec); + getproc(rtl, "_dllentry", IL._dllentry); + getproc(rtl, "_sofinit", IL._sofinit) + ELSIF CPU = TARGETS.cpuTHUMB THEN + getproc(rtl, "_fmul", IL._fmul); + getproc(rtl, "_fdiv", IL._fdiv); + getproc(rtl, "_fdivi", IL._fdivi); + getproc(rtl, "_fadd", IL._fadd); + getproc(rtl, "_fsub", IL._fsub); + getproc(rtl, "_fsubi", IL._fsubi); + getproc(rtl, "_fcmp", IL._fcmp); + getproc(rtl, "_floor", IL._floor); + getproc(rtl, "_flt", IL._flt); + getproc(rtl, "_pack", IL._pack); + getproc(rtl, "_unpk", IL._unpk) END END setrtl; @@ -3286,44 +3288,30 @@ BEGIN tREAL := PARS.program.stTypes.tREAL; Options := options; + CPU := TARGETS.CPU; - 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; + ext := UTILS.FILE_EXT; CaseLabels := C.create(); CaseVar := C.create(); CaseVariants := LISTS.create(NIL); LISTS.push(CaseVariants, NewVariant(0, NIL)); - 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; + IL.init(CPU); - IF CPU # cpuMSP430 THEN + IF CPU # TARGETS.cpuMSP430 THEN parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); - IF parser.open(parser, mConst.RTL_NAME) THEN + IF parser.open(parser, UTILS.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 parser.open(parser, mConst.RTL_NAME) THEN + IF parser.open(parser, UTILS.RTL_NAME) THEN parser.parse(parser); PARS.destroy(parser) ELSE - ERRORS.FileNotFound(lib_path, mConst.RTL_NAME, mConst.FILE_EXT) + ERRORS.FileNotFound(lib_path, UTILS.RTL_NAME, UTILS.FILE_EXT) END END END; @@ -3334,16 +3322,16 @@ BEGIN IF parser.open(parser, modname) THEN parser.parse(parser) ELSE - ERRORS.FileNotFound(path, modname, mConst.FILE_EXT) + ERRORS.FileNotFound(path, modname, UTILS.FILE_EXT) END; PARS.destroy(parser); - IF PARS.program.bss > mConst.MAX_GLOBAL_SIZE THEN + IF PARS.program.bss > UTILS.MAX_GLOBAL_SIZE THEN ERRORS.Error(204) END; - IF CPU # cpuMSP430 THEN + IF CPU # TARGETS.cpuMSP430 THEN setrtl END; @@ -3352,12 +3340,13 @@ BEGIN IL.set_bss(PARS.program.bss); CASE CPU OF - | cpuAMD64: AMD64.CodeGen(outname, target, options) - | cpuX86: X86.CodeGen(outname, target, options) - |cpuMSP430: MSP430.CodeGen(outname, target, options) + |TARGETS.cpuAMD64: AMD64.CodeGen(outname, target, options) + |TARGETS.cpuX86: X86.CodeGen(outname, target, options) + |TARGETS.cpuMSP430: MSP430.CodeGen(outname, target, options) + |TARGETS.cpuTHUMB: THUMB.CodeGen(outname, target, options) END END compile; -END STATEMENTS. +END STATEMENTS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/STRINGS.ob07 b/programs/develop/oberon07/Source/STRINGS.ob07 index 2ab48c5e74..af3baaeb4b 100644 --- a/programs/develop/oberon07/Source/STRINGS.ob07 +++ b/programs/develop/oberon07/Source/STRINGS.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -13,6 +13,7 @@ IMPORT UTILS; PROCEDURE append* (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR n1, n2, i, j: INTEGER; + BEGIN n1 := LENGTH(s1); n2 := LENGTH(s2); @@ -32,13 +33,12 @@ BEGIN END append; -PROCEDURE reverse* (VAR s: ARRAY OF CHAR); +PROCEDURE reverse (VAR s: ARRAY OF CHAR); VAR i, j: INTEGER; a, b: CHAR; BEGIN - i := 0; j := LENGTH(s) - 1; @@ -172,6 +172,27 @@ PROCEDURE space* (c: CHAR): BOOLEAN; END space; +PROCEDURE cap (VAR c: CHAR); +BEGIN + IF ("a" <= c) & (c <= "z") THEN + c := CHR(ORD(c) - 32) + END +END cap; + + +PROCEDURE UpCase* (VAR str: ARRAY OF CHAR); +VAR + i: INTEGER; + +BEGIN + i := 0; + WHILE (i < LEN(str)) & (str[i] # 0X) DO + cap(str[i]); + INC(i) + END +END UpCase; + + PROCEDURE StrToInt* (str: ARRAY OF CHAR; VAR x: INTEGER): BOOLEAN; VAR i, k: INTEGER; @@ -276,21 +297,21 @@ BEGIN u := ORD(c) |0C1X..0DFX: - u := LSL(ORD(c) - 0C0H, 6); + u := (ORD(c) - 0C0H) * 64; IF i + 1 < srclen THEN INC(i); - INC(u, ORD(BITS(ORD(src[i])) * {0..5})) + INC(u, ORD(src[i]) MOD 64) END |0E1X..0EFX: - u := LSL(ORD(c) - 0E0H, 12); + u := (ORD(c) - 0E0H) * 4096; IF i + 1 < srclen THEN INC(i); - INC(u, ORD(BITS(ORD(src[i])) * {0..5}) * 64) + INC(u, (ORD(src[i]) MOD 64) * 64) END; IF i + 1 < srclen THEN INC(i); - INC(u, ORD(BITS(ORD(src[i])) * {0..5})) + INC(u, ORD(src[i]) MOD 64) END (* |0F1X..0F7X: @@ -311,4 +332,4 @@ BEGIN END Utf8To16; -END STRINGS. +END STRINGS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/TARGETS.ob07 b/programs/develop/oberon07/Source/TARGETS.ob07 new file mode 100644 index 0000000000..39ceed4eb7 --- /dev/null +++ b/programs/develop/oberon07/Source/TARGETS.ob07 @@ -0,0 +1,116 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE TARGETS; + + +CONST + + MSP430* = 0; + Win32C* = 1; + Win32GUI* = 2; + Win32DLL* = 3; + KolibriOS* = 4; + KolibriOSDLL* = 5; + Win64C* = 6; + Win64GUI* = 7; + Win64DLL* = 8; + Linux32* = 9; + Linux32SO* = 10; + Linux64* = 11; + Linux64SO* = 12; + STM32CM3* = 13; + + cpuX86* = 0; cpuAMD64* = 1; cpuMSP430* = 2; cpuTHUMB* = 3; + + osNONE* = 0; osWIN32* = 1; osWIN64* = 2; + osLINUX32* = 3; osLINUX64* = 4; osKOS* = 5; + + +TYPE + + STRING = ARRAY 32 OF CHAR; + + TARGET = RECORD + + target, CPU, BitDepth, OS, RealSize: INTEGER; + ComLinePar*, LibDir, FileExt: STRING + + END; + + +VAR + + Targets*: ARRAY 14 OF TARGET; + + target*, CPU*, BitDepth*, OS*, RealSize*, WordSize*, AdrSize*: INTEGER; + ComLinePar*, LibDir*, FileExt*: STRING; + Import*, Dispose*, Dll*: BOOLEAN; + + +PROCEDURE Enter (idx, CPU, BitDepth, RealSize, OS: INTEGER; ComLinePar, LibDir, FileExt: STRING); +BEGIN + Targets[idx].target := idx; + Targets[idx].CPU := CPU; + Targets[idx].BitDepth := BitDepth; + Targets[idx].RealSize := RealSize; + Targets[idx].OS := OS; + Targets[idx].ComLinePar := ComLinePar; + Targets[idx].LibDir := LibDir; + Targets[idx].FileExt := FileExt; +END Enter; + + +PROCEDURE Select* (ComLineParam: ARRAY OF CHAR): BOOLEAN; +VAR + i: INTEGER; + res: BOOLEAN; + +BEGIN + i := 0; + WHILE (i < LEN(Targets)) & (Targets[i].ComLinePar # ComLineParam) DO + INC(i) + END; + + res := i < LEN(Targets); + IF res THEN + target := Targets[i].target; + CPU := Targets[i].CPU; + BitDepth := Targets[i].BitDepth; + RealSize := Targets[i].RealSize; + OS := Targets[i].OS; + ComLinePar := Targets[i].ComLinePar; + LibDir := Targets[i].LibDir; + FileExt := Targets[i].FileExt; + + Import := OS IN {osWIN32, osWIN64, osKOS}; + Dispose := ~(target IN {MSP430, STM32CM3}); + Dll := target IN {Linux32SO, Linux64SO, Win32DLL, Win64DLL, KolibriOSDLL}; + WordSize := BitDepth DIV 8; + AdrSize := WordSize + END + + RETURN res +END Select; + + +BEGIN + Enter( MSP430, cpuMSP430, 16, 0, osNONE, "msp430", "MSP430", ".hex"); + Enter( Win32C, cpuX86, 32, 8, osWIN32, "win32con", "Windows32", ".exe"); + Enter( Win32GUI, cpuX86, 32, 8, osWIN32, "win32gui", "Windows32", ".exe"); + Enter( Win32DLL, cpuX86, 32, 8, osWIN32, "win32dll", "Windows32", ".dll"); + Enter( KolibriOS, cpuX86, 32, 8, osKOS, "kosexe", "KolibriOS", ""); + Enter( KolibriOSDLL, cpuX86, 32, 8, osKOS, "kosdll", "KolibriOS", ".obj"); + Enter( Win64C, cpuAMD64, 64, 8, osWIN64, "win64con", "Windows64", ".exe"); + Enter( Win64GUI, cpuAMD64, 64, 8, osWIN64, "win64gui", "Windows64", ".exe"); + Enter( Win64DLL, cpuAMD64, 64, 8, osWIN64, "win64dll", "Windows64", ".dll"); + Enter( Linux32, cpuX86, 32, 8, osLINUX32, "linux32exe", "Linux32", ""); + Enter( Linux32SO, cpuX86, 32, 8, osLINUX32, "linux32so", "Linux32", ".so"); + Enter( Linux64, cpuAMD64, 64, 8, osLINUX64, "linux64exe", "Linux64", ""); + Enter( Linux64SO, cpuAMD64, 64, 8, osLINUX64, "linux64so", "Linux64", ".so"); + Enter( STM32CM3, cpuTHUMB, 32, 4, osNONE, "stm32cm3", "STM32CM3", ".hex"); +END TARGETS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/TEXTDRV.ob07 b/programs/develop/oberon07/Source/TEXTDRV.ob07 index 4e75c78db8..9ae8b68c35 100644 --- a/programs/develop/oberon07/Source/TEXTDRV.ob07 +++ b/programs/develop/oberon07/Source/TEXTDRV.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -177,4 +177,4 @@ END open; BEGIN texts := C.create() -END TEXTDRV. +END TEXTDRV. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/THUMB.ob07 b/programs/develop/oberon07/Source/THUMB.ob07 new file mode 100644 index 0000000000..d9e8ba9ecd --- /dev/null +++ b/programs/develop/oberon07/Source/THUMB.ob07 @@ -0,0 +1,2430 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE THUMB; + +IMPORT PROG, LISTS, CHL := CHUNKLISTS, BIN, REG, IL, C := CONSOLE, + UTILS, WR := WRITER, HEX, ERRORS, TARGETS; + + +CONST + + R0 = 0; R1 = 1; R2 = 2; R3 = 3; R4 = 4; + + SP = 13; LR = 14; PC = 15; + + ACC = R0; + + je = 0; jne = 1; jnb = 2; jb = 3; jge = 10; jl = 11; jg = 12; jle = 13; + + inf = 7F800000H; + + STM32_minROM* = 16; STM32_maxROM* = 65536; + STM32_minRAM* = 4; STM32_maxRAM* = 65536; + + maxIVT* = 1023; + + +TYPE + + COMMAND = IL.COMMAND; + + ANYCODE = POINTER TO RECORD (LISTS.ITEM) + + offset: INTEGER + + END; + + CODE = POINTER TO RECORD (ANYCODE) + + code: INTEGER + + END; + + LABEL = POINTER TO RECORD (ANYCODE) + + label: INTEGER + + END; + + JUMP = POINTER TO RECORD (ANYCODE) + + label, diff, len, cond: INTEGER; + short: BOOLEAN + + END; + + JMP = POINTER TO RECORD (JUMP) + + END; + + JCC = POINTER TO RECORD (JUMP) + + END; + + CBXZ = POINTER TO RECORD (JUMP) + + reg: INTEGER + + END; + + CALL = POINTER TO RECORD (JUMP) + + END; + + RELOC = POINTER TO RECORD (ANYCODE) + + reg, rel, value: INTEGER + + END; + + RELOCCODE = ARRAY 7 OF INTEGER; + + +VAR + + R: REG.REGS; + + tcount: INTEGER; + + CodeList: LISTS.LIST; + + program: BIN.PROGRAM; + + StkCount: INTEGER; + + Target: RECORD + FlashAdr, + SRAMAdr, + IVTLen, + MinStack, + Reserved: INTEGER; + InstrSet: RECORD thumb2, it, cbxz, sdiv: BOOLEAN END + END; + + IVT: ARRAY maxIVT + 1 OF INTEGER; + + sdivProc, trap, genTrap, entry, emptyProc, int0, genInt: INTEGER; + + +PROCEDURE Code (code: INTEGER); +VAR + c: CODE; + +BEGIN + NEW(c); + c.code := code; + LISTS.push(CodeList, c) +END Code; + + +PROCEDURE Label (label: INTEGER); +VAR + L: LABEL; + +BEGIN + NEW(L); + L.label := label; + LISTS.push(CodeList, L) +END Label; + + +PROCEDURE jcc (cond, label: INTEGER); +VAR + j: JCC; + +BEGIN + NEW(j); + j.label := label; + j.cond := cond; + j.short := FALSE; + j.len := 3; + LISTS.push(CodeList, j) +END jcc; + + +PROCEDURE cbxz (cond, reg, label: INTEGER); +VAR + j: CBXZ; + +BEGIN + NEW(j); + j.label := label; + j.cond := cond; + j.reg := reg; + j.short := FALSE; + j.len := 4; + LISTS.push(CodeList, j) +END cbxz; + + +PROCEDURE jmp (label: INTEGER); +VAR + j: JMP; + +BEGIN + NEW(j); + j.label := label; + j.short := FALSE; + j.len := 2; + LISTS.push(CodeList, j) +END jmp; + + +PROCEDURE call (label: INTEGER); +VAR + c: CALL; + +BEGIN + NEW(c); + c.label := label; + c.short := FALSE; + c.len := 2; + LISTS.push(CodeList, c) +END call; + + +PROCEDURE reloc (reg, rel, value: INTEGER); +VAR + r: RELOC; + +BEGIN + NEW(r); + r.reg := reg; + r.rel := rel; + r.value := value; + LISTS.push(CodeList, r) +END reloc; + + +PROCEDURE NewLabel (): INTEGER; +BEGIN + BIN.NewLabel(program) + RETURN IL.NewLabel() +END NewLabel; + + +PROCEDURE range (x, n: INTEGER): BOOLEAN; + RETURN (0 <= x) & (x < LSL(1, n)) +END range; + + +PROCEDURE srange (x, n: INTEGER): BOOLEAN; + RETURN (-LSL(1, n - 1) <= x) & (x < LSL(1, n - 1)) +END srange; + + +PROCEDURE gen1 (op, imm, rs, rd: INTEGER); +BEGIN + ASSERT(op IN {0..2}); + ASSERT(range(imm, 5)); + ASSERT(range(rs, 3)); + ASSERT(range(rd, 3)); + Code(LSL(op, 11) + LSL(imm, 6) + LSL(rs, 3) + rd) +END gen1; + + +PROCEDURE gen2 (i, op: BOOLEAN; imm, rs, rd: INTEGER); +BEGIN + ASSERT(range(imm, 3)); + ASSERT(range(rs, 3)); + ASSERT(range(rd, 3)); + Code(1800H + LSL(ORD(i), 10) + LSL(ORD(op), 9) + LSL(imm, 6) + LSL(rs, 3) + rd) +END gen2; + + +PROCEDURE gen3 (op, rd, imm: INTEGER); +BEGIN + ASSERT(range(op, 2)); + ASSERT(range(rd, 3)); + ASSERT(range(imm, 8)); + Code(2000H + LSL(op, 11) + LSL(rd, 8) + imm) +END gen3; + + +PROCEDURE gen4 (op, rs, rd: INTEGER); +BEGIN + ASSERT(range(op, 4)); + ASSERT(range(rs, 3)); + ASSERT(range(rd, 3)); + Code(4000H + LSL(op, 6) + LSL(rs, 3) + rd) +END gen4; + + +PROCEDURE gen5 (op: INTEGER; h1, h2: BOOLEAN; rs, rd: INTEGER); +BEGIN + ASSERT(range(op, 2)); + ASSERT(range(rs, 3)); + ASSERT(range(rd, 3)); + Code(4400H + LSL(op, 8) + LSL(ORD(h1), 7) + LSL(ORD(h2), 6) + LSL(rs, 3) + rd) +END gen5; + + +PROCEDURE gen7 (l, b: BOOLEAN; ro, rb, rd: INTEGER); +BEGIN + ASSERT(range(ro, 3)); + ASSERT(range(rb, 3)); + ASSERT(range(rd, 3)); + Code(5000H + LSL(ORD(l), 11) + LSL(ORD(b), 10) + LSL(ro, 6) + LSL(rb, 3) + rd) +END gen7; + + +PROCEDURE gen8 (h, s: BOOLEAN; ro, rb, rd: INTEGER); +BEGIN + ASSERT(range(ro, 3)); + ASSERT(range(rb, 3)); + ASSERT(range(rd, 3)); + Code(5200H + LSL(ORD(h), 11) + LSL(ORD(s), 10) + LSL(ro, 6) + LSL(rb, 3) + rd) +END gen8; + + +PROCEDURE gen9 (b, l: BOOLEAN; imm, rb, rd: INTEGER); +BEGIN + ASSERT(range(imm, 5)); + ASSERT(range(rb, 3)); + ASSERT(range(rd, 3)); + Code(6000H + LSL(ORD(b), 12) + LSL(ORD(l), 11) + LSL(imm, 6) + LSL(rb, 3) + rd) +END gen9; + + +PROCEDURE gen10 (l: BOOLEAN; imm, rb, rd: INTEGER); +BEGIN + ASSERT(range(imm, 5)); + ASSERT(range(rb, 3)); + ASSERT(range(rd, 3)); + Code(8000H + LSL(ORD(l), 11) + LSL(imm, 6) + LSL(rb, 3) + rd) +END gen10; + + +PROCEDURE gen11 (l: BOOLEAN; rd, imm: INTEGER); +BEGIN + ASSERT(range(rd, 3)); + ASSERT(range(imm, 8)); + Code(9000H + LSL(ORD(l), 11) + LSL(rd, 8) + imm) +END gen11; + + +PROCEDURE gen12 (sp: BOOLEAN; rd, imm: INTEGER); +BEGIN + ASSERT(range(rd, 3)); + ASSERT(range(imm, 8)); + Code(0A000H + LSL(ORD(sp), 11) + LSL(rd, 8) + imm) +END gen12; + + +PROCEDURE gen14 (l, r: BOOLEAN; rlist: SET); +VAR + i, n: INTEGER; + +BEGIN + ASSERT(range(ORD(rlist), 8)); + + n := ORD(r); + FOR i := 0 TO 7 DO + IF i IN rlist THEN + INC(n) + END + END; + + IF l THEN + n := -n + END; + + INC(StkCount, n); + + Code(0B400H + LSL(ORD(l), 11) + LSL(ORD(r), 8) + ORD(rlist)) +END gen14; + + +PROCEDURE split16 (imm16: INTEGER; VAR imm4, imm1, imm3, imm8: INTEGER); +BEGIN + ASSERT(range(imm16, 16)); + imm8 := imm16 MOD 256; + imm4 := LSR(imm16, 12); + imm3 := LSR(imm16, 8) MOD 8; + imm1 := LSR(imm16, 11) MOD 2; +END split16; + + +PROCEDURE LslImm (r, imm5: INTEGER); +BEGIN + gen1(0, imm5, r, r) +END LslImm; + + +PROCEDURE LsrImm (r, imm5: INTEGER); +BEGIN + gen1(1, imm5, r, r) +END LsrImm; + + +PROCEDURE AsrImm (r, imm5: INTEGER); +BEGIN + gen1(2, imm5, r, r) +END AsrImm; + + +PROCEDURE AddReg (rd, rs, rn: INTEGER); +BEGIN + gen2(FALSE, FALSE, rn, rs, rd) +END AddReg; + + +PROCEDURE SubReg (rd, rs, rn: INTEGER); +BEGIN + gen2(FALSE, TRUE, rn, rs, rd) +END SubReg; + + +PROCEDURE AddImm8 (rd, imm8: INTEGER); +BEGIN + IF imm8 # 0 THEN + gen3(2, rd, imm8) + END +END AddImm8; + + +PROCEDURE SubImm8 (rd, imm8: INTEGER); +BEGIN + IF imm8 # 0 THEN + gen3(3, rd, imm8) + END +END SubImm8; + + +PROCEDURE AddSubImm12 (r, imm12: INTEGER; sub: BOOLEAN); +VAR + imm4, imm1, imm3, imm8: INTEGER; + +BEGIN + split16(imm12, imm4, imm1, imm3, imm8); + Code(0F200H + LSL(imm1, 10) + r + 0A0H * ORD(sub)); (* addw/subw r, r, imm12 *) + Code(LSL(imm3, 12) + LSL(r, 8) + imm8) +END AddSubImm12; + + +PROCEDURE MovImm8 (rd, imm8: INTEGER); +BEGIN + gen3(0, rd, imm8) +END MovImm8; + + +PROCEDURE CmpImm8 (rd, imm8: INTEGER); +BEGIN + gen3(1, rd, imm8) +END CmpImm8; + + +PROCEDURE Neg (r: INTEGER); +BEGIN + gen4(9, r, r) +END Neg; + + +PROCEDURE Mul (rd, rs: INTEGER); +BEGIN + gen4(13, rs, rd) +END Mul; + + +PROCEDURE Str32 (rs, rb: INTEGER); +BEGIN + gen9(FALSE, FALSE, 0, rb, rs) +END Str32; + + +PROCEDURE Ldr32 (rd, rb: INTEGER); +BEGIN + gen9(FALSE, TRUE, 0, rb, rd) +END Ldr32; + + +PROCEDURE Str16 (rs, rb: INTEGER); +BEGIN + gen10(FALSE, 0, rb, rs) +END Str16; + + +PROCEDURE Ldr16 (rd, rb: INTEGER); +BEGIN + gen10(TRUE, 0, rb, rd) +END Ldr16; + + +PROCEDURE Str8 (rs, rb: INTEGER); +BEGIN + gen9(TRUE, FALSE, 0, rb, rs) +END Str8; + + +PROCEDURE Ldr8 (rd, rb: INTEGER); +BEGIN + gen9(TRUE, TRUE, 0, rb, rd) +END Ldr8; + + +PROCEDURE Cmp (r1, r2: INTEGER); +BEGIN + gen4(10, r2, r1) +END Cmp; + + +PROCEDURE Tst (r: INTEGER); +BEGIN + gen3(1, r, 0) (* cmp r, #0 *) +END Tst; + + +PROCEDURE LdrSp (r, offset: INTEGER); +BEGIN + gen11(TRUE, r, offset) +END LdrSp; + + +PROCEDURE MovImm32 (r, imm32: INTEGER); +BEGIN + MovImm8(r, LSR(imm32, 24) MOD 256); + LslImm(r, 8); + AddImm8(r, LSR(imm32, 16) MOD 256); + LslImm(r, 8); + AddImm8(r, LSR(imm32, 8) MOD 256); + LslImm(r, 8); + AddImm8(r, imm32 MOD 256) +END MovImm32; + + +PROCEDURE low (x: INTEGER): INTEGER; + RETURN x MOD 65536 +END low; + + +PROCEDURE high (x: INTEGER): INTEGER; + RETURN (x DIV 65536) MOD 65536 +END high; + + +PROCEDURE movwt (r, imm16, t: INTEGER); +VAR + imm1, imm3, imm4, imm8: INTEGER; + +BEGIN + ASSERT(range(r, 3)); + ASSERT(range(imm16, 16)); + ASSERT(range(t, 1)); + split16(imm16, imm4, imm1, imm3, imm8); + Code(0F240H + imm1 * 1024 + t * 128 + imm4); + Code(imm3 * 4096 + r * 256 + imm8); +END movwt; + + +PROCEDURE inv0 (cond: INTEGER): INTEGER; + RETURN ORD(BITS(cond) / {0}) +END inv0; + + +PROCEDURE fixup (CodeAdr, DataAdr, BssAdr: INTEGER); +VAR + code: ANYCODE; + count: INTEGER; + shorted: BOOLEAN; + jump: JUMP; + + first, second: INTEGER; + + reloc, i, diff, len: INTEGER; + + RelocCode: RELOCCODE; + + + PROCEDURE genjcc (cond, offset: INTEGER): INTEGER; + BEGIN + ASSERT(range(cond, 4)); + ASSERT(srange(offset, 8)) + RETURN 0D000H + cond * 256 + offset MOD 256 + END genjcc; + + + PROCEDURE genjmp (offset: INTEGER): INTEGER; + BEGIN + ASSERT(srange(offset, 11)) + RETURN 0E000H + offset MOD 2048 + END genjmp; + + + PROCEDURE genlongjmp (offset: INTEGER; VAR first, second: INTEGER); + BEGIN + ASSERT(srange(offset, 22)); + first := 0F000H + ASR(offset, 11) MOD 2048; + second := 0F800H + offset MOD 2048 + END genlongjmp; + + + PROCEDURE movwt (r, imm16, t: INTEGER; VAR code: RELOCCODE); + VAR + imm1, imm3, imm4, imm8: INTEGER; + + BEGIN + split16(imm16, imm4, imm1, imm3, imm8); + code[t * 2] := 0F240H + imm1 * 1024 + t * 128 + imm4; + code[t * 2 + 1] := imm3 * 4096 + r * 256 + imm8 + END movwt; + + + PROCEDURE genmovimm32 (r, value: INTEGER; VAR code: RELOCCODE); + BEGIN + IF Target.InstrSet.thumb2 THEN + movwt(r, low(value), 0, code); + movwt(r, high(value), 1, code) + ELSE + code[0] := 2000H + r * 256 + UTILS.Byte(value, 3); (* mov r, #imm8 *) + code[1] := 0200H + r * 9; (* lsl r, r, #8 *) + code[2] := 3000H + r * 256 + UTILS.Byte(value, 2); (* add r, #imm8 *) + code[3] := code[1]; (* lsl r, r, #8 *) + code[4] := 3000H + r * 256 + UTILS.Byte(value, 1); (* add r, #imm8 *) + code[5] := code[1]; (* lsl r, r, #8 *) + code[6] := 3000H + r * 256 + UTILS.Byte(value, 0) (* add r, #imm8 *) + END + END genmovimm32; + + + PROCEDURE PutCode (code: INTEGER); + BEGIN + BIN.PutCode16LE(program, code) + END PutCode; + + + PROCEDURE genbc (code: JUMP); + VAR + first, second: INTEGER; + + BEGIN + CASE code.len OF + |1: PutCode(genjcc(code.cond, code.diff)) + |2: PutCode(genjcc(inv0(code.cond), 0)); + PutCode(genjmp(code.diff)) + |3: PutCode(genjcc(inv0(code.cond), 1)); + genlongjmp(code.diff, first, second); + PutCode(first); + PutCode(second) + END + END genbc; + + + PROCEDURE SetIV (idx, label, CodeAdr: INTEGER); + VAR + l, h: ANYCODE; + + BEGIN + l := CodeList.first(ANYCODE); + h := l.next(ANYCODE); + WHILE idx > 0 DO + l := h.next(ANYCODE); + h := l.next(ANYCODE); + DEC(idx) + END; + label := BIN.GetLabel(program, label) * 2 + CodeAdr + 1; + l(CODE).code := low(label); + h(CODE).code := high(label) + END SetIV; + + +BEGIN + + REPEAT + + shorted := FALSE; + count := 0; + + code := CodeList.first(ANYCODE); + WHILE code # NIL DO + code.offset := count; + + CASE code OF + |CODE: INC(count) + |LABEL: BIN.SetLabel(program, code.label, count) + |JUMP: INC(count, code.len); code.offset := count + ORD(code.short) + |RELOC: INC(count, 7 - ORD(Target.InstrSet.thumb2) * 3 + code.rel MOD 2) + END; + + code := code.next(ANYCODE) + END; + + code := CodeList.first(ANYCODE); + WHILE code # NIL DO + + IF code IS JUMP THEN + jump := code(JUMP); + jump.diff := BIN.GetLabel(program, jump.label) - jump.offset; + len := jump.len; + diff := jump.diff; + CASE jump OF + |JMP: + IF (len = 2) & srange(diff, 11) THEN + len := 1 + END + + |JCC: + CASE len OF + |1: + |2: IF srange(diff, 8) THEN DEC(len) END + |3: IF srange(diff, 11) THEN DEC(len) END + END + + |CBXZ: + CASE len OF + |1: + |2: IF range(diff, 6) THEN DEC(len) END + |3: IF srange(diff, 8) THEN DEC(len) END + |4: IF srange(diff, 11) THEN DEC(len) END + END + + |CALL: + + END; + IF len # jump.len THEN + jump.len := len; + jump.short := TRUE; + shorted := TRUE + END + END; + + code := code.next(ANYCODE) + END + + UNTIL ~shorted; + + FOR i := 1 TO Target.IVTLen - 1 DO + SetIV(i, IVT[i], CodeAdr) + END; + + code := CodeList.first(ANYCODE); + WHILE code # NIL DO + + CASE code OF + + |CODE: BIN.PutCode16LE(program, code.code) + + |LABEL: + + |JMP: + IF code.len = 1 THEN + PutCode(genjmp(code.diff)) + ELSE + genlongjmp(code.diff, first, second); + PutCode(first); + PutCode(second) + END + + |JCC: genbc(code) + + |CBXZ: + IF code.len > 1 THEN + PutCode(2800H + code.reg * 256); (* cmp code.reg, #0 *) + DEC(code.len); + genbc(code) + ELSE + (* cb(n)z code.reg, L *) + PutCode(0B100H + 800H * ORD(code.cond = jne) + 200H * ORD(code.diff >= 32) + (code.diff MOD 32) * 8 + code.reg) + END + + |CALL: + genlongjmp(code.diff, first, second); + PutCode(first); + PutCode(second) + + |RELOC: + CASE code.rel OF + |BIN.RCODE, BIN.PICCODE: reloc := BIN.GetLabel(program, code.value) * 2 + CodeAdr + |BIN.RDATA, BIN.PICDATA: reloc := code.value + DataAdr + |BIN.RBSS, BIN.PICBSS: reloc := code.value + BssAdr + END; + IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN + DEC(reloc, CodeAdr + 2 * (code.offset - 3 * ORD(Target.InstrSet.thumb2) + 9)) + END; + genmovimm32(code.reg, reloc, RelocCode); + FOR i := 0 TO 6 - 3 * ORD(Target.InstrSet.thumb2) DO + PutCode(RelocCode[i]) + END; + IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN + PutCode(4478H + code.reg) (* add code.reg, PC *) + END + END; + + code := code.next(ANYCODE) + END + +END fixup; + + +PROCEDURE push (r: INTEGER); +BEGIN + gen14(FALSE, FALSE, {r}) +END push; + + +PROCEDURE pop (r: INTEGER); +BEGIN + gen14(TRUE, FALSE, {r}) +END pop; + + +PROCEDURE mov (r1, r2: INTEGER); +BEGIN + IF (r1 < 8) & (r2 < 8) THEN + gen1(0, 0, r2, r1) + ELSE + gen5(2, r1 >= 8, r2 >= 8, r2 MOD 8, r1 MOD 8) + END +END mov; + + +PROCEDURE xchg (r1, r2: INTEGER); +BEGIN + push(r1); push(r2); + pop(r1); pop(r2) +END xchg; + + +PROCEDURE drop; +BEGIN + REG.Drop(R) +END drop; + + +PROCEDURE GetAnyReg (): INTEGER; + RETURN REG.GetAnyReg(R) +END GetAnyReg; + + +PROCEDURE UnOp (VAR r: INTEGER); +BEGIN + REG.UnOp(R, r) +END UnOp; + + +PROCEDURE BinOp (VAR r1, r2: INTEGER); +BEGIN + REG.BinOp(R, r1, r2) +END BinOp; + + +PROCEDURE PushAll (NumberOfParameters: INTEGER); +BEGIN + REG.PushAll(R); + DEC(R.pushed, NumberOfParameters) +END PushAll; + + +PROCEDURE cond (op: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + CASE op OF + |IL.opGT, IL.opGTC: res := jg + |IL.opGE, IL.opGEC: res := jge + |IL.opLT, IL.opLTC: res := jl + |IL.opLE, IL.opLEC: res := jle + |IL.opEQ, IL.opEQC: res := je + |IL.opNE, IL.opNEC: res := jne + END + + RETURN res +END cond; + + +PROCEDURE GetRegA; +BEGIN + ASSERT(REG.GetReg(R, ACC)) +END GetRegA; + + +PROCEDURE MovConst (r, c: INTEGER); +BEGIN + IF (0 <= c) & (c <= 255) THEN + MovImm8(r, c) + ELSIF (-255 <= c) & (c < 0) THEN + MovImm8(r, -c); + Neg(r) + ELSIF UTILS.Log2(c) >= 0 THEN + MovImm8(r, 1); + LslImm(r, UTILS.Log2(c)) + ELSIF c = UTILS.min32 THEN + MovImm8(r, 1); + LslImm(r, 31) + ELSE + IF Target.InstrSet.thumb2 THEN + movwt(r, low(c), 0); + IF (c < 0) OR (c > 65535) THEN + movwt(r, high(c), 1) + END + ELSE + MovImm32(r, c) + END + END +END MovConst; + + +PROCEDURE CmpConst (r, c: INTEGER); +VAR + r2: INTEGER; + +BEGIN + IF (0 <= c) & (c <= 255) THEN + CmpImm8(r, c) + ELSE + r2 := GetAnyReg(); + ASSERT(r2 # r); + MovConst(r2, c); + Cmp(r, r2); + drop + END +END CmpConst; + + +PROCEDURE LocalOffset (offset: INTEGER): INTEGER; + RETURN offset + StkCount - ORD(offset > 0) +END LocalOffset; + + +PROCEDURE SetCC (cc, r: INTEGER); +VAR + L1, L2: INTEGER; + +BEGIN + IF Target.InstrSet.it THEN + Code(0BF00H + cc * 16 + ((cc + 1) MOD 2) * 8 + 4); (* ite cc *) + MovConst(r, 1); + MovConst(r, 0) + ELSE + L1 := NewLabel(); + L2 := NewLabel(); + jcc(cc, L1); + MovConst(r, 0); + jmp(L2); + Label(L1); + MovConst(r, 1); + Label(L2) + END +END SetCC; + + +PROCEDURE PushConst (n: INTEGER); +VAR + r: INTEGER; + +BEGIN + r := GetAnyReg(); + MovConst(r, n); + push(r); + drop +END PushConst; + + +PROCEDURE AddConst (r, n: INTEGER); +VAR + r2: INTEGER; + +BEGIN + IF n # 0 THEN + IF (-255 <= n) & (n <= 255) THEN + IF n > 0 THEN + AddImm8(r, n) + ELSE + SubImm8(r, -n) + END + ELSIF Target.InstrSet.thumb2 & (-4095 <= n) & (n <= 4095) THEN + IF n > 0 THEN + AddSubImm12(r, n, FALSE) + ELSE + AddSubImm12(r, -n, TRUE) + END + ELSE + r2 := GetAnyReg(); + ASSERT(r2 # r); + IF n > 0 THEN + MovConst(r2, n); + AddReg(r, r, r2) + ELSE + MovConst(r2, -n); + SubReg(r, r, r2) + END; + drop + END + END +END AddConst; + + +PROCEDURE AddHH (r1, r2: INTEGER); +BEGIN + ASSERT((r1 >= 8) OR (r2 >= 8)); + gen5(0, r1 >= 8, r2 >= 8, r2 MOD 8, r1 MOD 8) +END AddHH; + + +PROCEDURE AddSP (n: INTEGER); +BEGIN + IF n > 0 THEN + IF n < 127 THEN + Code(0B000H + n) (* add sp, n*4 *) + ELSE + ASSERT(R2 IN R.regs); + MovConst(R2, n * 4); + AddHH(SP, R2) + END; + DEC(StkCount, n) + END +END AddSP; + + +PROCEDURE cbz (r, label: INTEGER); +BEGIN + IF Target.InstrSet.cbxz THEN + cbxz(je, r, label) + ELSE + Tst(r); + jcc(je, label) + END +END cbz; + + +PROCEDURE cbnz (r, label: INTEGER); +BEGIN + IF Target.InstrSet.cbxz THEN + cbxz(jne, r, label) + ELSE + Tst(r); + jcc(jne, label) + END +END cbnz; + + +PROCEDURE Shift (op, r1, r2: INTEGER); +VAR + L: INTEGER; + +BEGIN + LslImm(r2, 27); + LsrImm(r2, 27); + L := NewLabel(); + cbz(r2, L); + CASE op OF + |IL.opLSL, IL.opLSL1: gen4(2, r2, r1) + |IL.opLSR, IL.opLSR1: gen4(3, r2, r1) + |IL.opASR, IL.opASR1: gen4(4, r2, r1) + |IL.opROR, IL.opROR1: gen4(7, r2, r1) + END; + Label(L) +END Shift; + + +PROCEDURE LocAdr (offs: INTEGER); +VAR + r1, n: INTEGER; + +BEGIN + r1 := GetAnyReg(); + n := LocalOffset(offs); + IF n <= 255 THEN + gen12(TRUE, r1, n) + ELSE + MovConst(r1, n * 4); + AddHH(r1, SP) + END +END LocAdr; + + +PROCEDURE CallRTL (proc, par: INTEGER); +BEGIN + call(IL.codes.rtl[proc]); + AddSP(par) +END CallRTL; + + +PROCEDURE divmod; +BEGIN + call(sdivProc); + AddSP(2) +END divmod; + + +PROCEDURE translate (pic, stroffs: INTEGER); +VAR + cmd, next: COMMAND; + opcode, param1, param2: INTEGER; + + r1, r2, r3: INTEGER; + + a, n, cc, L, L2: INTEGER; + +BEGIN + cmd := IL.codes.commands.first(COMMAND); + + WHILE cmd # NIL DO + + param1 := cmd.param1; + param2 := cmd.param2; + opcode := cmd.opcode; + + CASE opcode OF + + |IL.opJMP: + jmp(param1) + + |IL.opLABEL: + Label(param1) + + |IL.opHANDLER: + IF param2 = 0 THEN + int0 := param1 + ELSIF param2 = 1 THEN + trap := param1 + ELSE + IVT[param2] := param1 + END + + |IL.opCALL: + call(param1) + + |IL.opCALLP: + UnOp(r1); + AddImm8(r1, 1); + gen5(3, TRUE, FALSE, r1, 0); (* blx r1 *) + drop; + ASSERT(R.top = -1) + + |IL.opENTER: + ASSERT(R.top = -1); + + Label(param1); + + gen14(FALSE, TRUE, {}); (* push LR *) + + n := param2; + IF n >= 5 THEN + MovConst(ACC, 0); + MovConst(R2, n); + L := NewLabel(); + Label(L); + push(ACC); + SubImm8(R2, 1); + Tst(R2); + jcc(jne, L) + ELSIF n > 0 THEN + MovConst(ACC, 0); + WHILE n > 0 DO + push(ACC); + DEC(n) + END + END; + StkCount := param2 + + |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: + IF opcode # IL.opLEAVE THEN + UnOp(r1); + IF r1 # ACC THEN + GetRegA; + ASSERT(REG.Exchange(R, r1, ACC)); + drop + END; + drop + END; + + ASSERT(R.top = -1); + ASSERT(StkCount = param1); + + AddSP(param1); + gen14(TRUE, TRUE, {}) (* pop PC *) + + |IL.opLEAVEC: + gen5(3, FALSE, TRUE, 6, 0) (* bx LR *) + + |IL.opPRECALL: + PushAll(0) + + |IL.opPARAM: + n := param2; + IF n = 1 THEN + UnOp(r1); + push(r1); + drop + ELSE + ASSERT(R.top + 1 <= n); + PushAll(n) + END + + |IL.opCLEANUP: + AddSP(param2) + + |IL.opRES, IL.opRESF: + ASSERT(R.top = -1); + GetRegA + + |IL.opPUSHC: + PushConst(param2) + + |IL.opONERR: + MovConst(R0, param2); + push(R0); + DEC(StkCount); + jmp(param1) + + |IL.opERR: + call(genTrap) + + |IL.opNOP: + + |IL.opSADR: + reloc(GetAnyReg(), BIN.RDATA + pic, stroffs + param2) + + |IL.opGADR: + reloc(GetAnyReg(), BIN.RBSS + pic, param2) + + |IL.opLADR: + LocAdr(param2) + + |IL.opGLOAD32: + r1 := GetAnyReg(); + reloc(r1, BIN.RBSS + pic, param2); + Ldr32(r1, r1) + + |IL.opGLOAD16: + r1 := GetAnyReg(); + reloc(r1, BIN.RBSS + pic, param2); + Ldr16(r1, r1) + + |IL.opGLOAD8: + r1 := GetAnyReg(); + reloc(r1, BIN.RBSS + pic, param2); + Ldr8(r1, r1) + + |IL.opLLOAD32, IL.opVADR, IL.opVLOAD32: + r1 := GetAnyReg(); + n := LocalOffset(param2); + IF n <= 255 THEN + LdrSp(r1, n) + ELSE + drop; + LocAdr(param2); + UnOp(r1); + Ldr32(r1, r1) + END; + IF opcode = IL.opVLOAD32 THEN + Ldr32(r1, r1) + END + + |IL.opLLOAD16: + LocAdr(param2); + UnOp(r1); + Ldr16(r1, r1) + + |IL.opLLOAD8: + LocAdr(param2); + UnOp(r1); + Ldr8(r1, r1) + + |IL.opLOAD32, IL.opLOADF: + UnOp(r1); + Ldr32(r1, r1) + + |IL.opLOAD16: + UnOp(r1); + Ldr16(r1, r1) + + |IL.opLOAD8: + UnOp(r1); + Ldr8(r1, r1) + + |IL.opVLOAD16: + LocAdr(param2); + UnOp(r1); + Ldr32(r1, r1); + Ldr16(r1, r1) + + |IL.opVLOAD8: + LocAdr(param2); + UnOp(r1); + Ldr32(r1, r1); + Ldr8(r1, r1) + + |IL.opSBOOL: + BinOp(r2, r1); + Tst(r2); + SetCC(jne, r2); + Str8(r2, r1); + drop; + drop + + |IL.opSBOOLC: + UnOp(r1); + r2 := GetAnyReg(); + MovConst(r2, ORD(param2 # 0)); + Str8(r2, r1); + drop; + drop + + |IL.opSAVEC: + UnOp(r1); + r2 := GetAnyReg(); + MovConst(r2, param2); + Str32(r2, r1); + drop; + drop + + |IL.opSAVE16C: + UnOp(r1); + r2 := GetAnyReg(); + MovConst(r2, low(param2)); + Str16(r2, r1); + drop; + drop + + |IL.opSAVE8C: + UnOp(r1); + r2 := GetAnyReg(); + MovConst(r2, param2 MOD 256); + Str8(r2, r1); + drop; + drop + + |IL.opSAVE, IL.opSAVE32, IL.opSAVEF: + BinOp(r2, r1); + Str32(r2, r1); + drop; + drop + + |IL.opSAVEFI: + BinOp(r2, r1); + Str32(r1, r2); + drop; + drop + + |IL.opSAVE16: + BinOp(r2, r1); + Str16(r2, r1); + drop; + drop + + |IL.opSAVE8: + BinOp(r2, r1); + Str8(r2, r1); + drop; + drop + + |IL.opSAVEP: + UnOp(r1); + r2 := GetAnyReg(); + reloc(r2, BIN.RCODE + pic, param2); + Str32(r2, r1); + drop; + drop + + |IL.opPUSHP: + reloc(GetAnyReg(), BIN.RCODE + pic, param2) + + |IL.opEQB, IL.opNEB: + BinOp(r1, r2); + drop; + + L := NewLabel(); + cbz(r1, L); + MovConst(r1, 1); + Label(L); + + L := NewLabel(); + cbz(r2, L); + MovConst(r2, 1); + Label(L); + + Cmp(r1, r2); + IF opcode = IL.opEQB THEN + SetCC(je, r1) + ELSE + SetCC(jne, r1) + END + + |IL.opACC: + IF (R.top # 0) OR (R.stk[0] # ACC) THEN + PushAll(0); + GetRegA; + pop(ACC); + DEC(R.pushed) + END + + |IL.opDROP: + UnOp(r1); + drop + + |IL.opJNZ: + UnOp(r1); + cbnz(r1, param1) + + |IL.opJZ: + UnOp(r1); + cbz(r1, param1) + + |IL.opJG: + UnOp(r1); + Tst(r1); + jcc(jg, param1) + + |IL.opJE: + UnOp(r1); + cbnz(r1, param1); + drop + + |IL.opJNE: + UnOp(r1); + cbz(r1, param1); + drop + + |IL.opSWITCH: + UnOp(r1); + IF param2 = 0 THEN + r2 := ACC + ELSE + r2 := R2 + END; + IF r1 # r2 THEN + ASSERT(REG.GetReg(R, r2)); + ASSERT(REG.Exchange(R, r1, r2)); + drop + END; + drop + + |IL.opENDSW: + + |IL.opCASEL: + GetRegA; + CmpConst(ACC, param1); + jcc(jl, param2); + drop + + |IL.opCASER: + GetRegA; + CmpConst(ACC, param1); + jcc(jg, param2); + drop + + |IL.opCASELR: + GetRegA; + CmpConst(ACC, param1); + jcc(jl, param2); + jcc(jg, cmd.param3); + drop + + |IL.opCODE: + Code(param2) + + |IL.opEQ..IL.opGE, + IL.opEQC..IL.opGEC: + IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN + BinOp(r1, r2); + Cmp(r1, r2); + drop + ELSE + UnOp(r1); + CmpConst(r1, param2) + END; + + drop; + cc := cond(opcode); + next := cmd.next(COMMAND); + + IF next.opcode = IL.opJE THEN + jcc(cc, next.param1); + cmd := next + ELSIF next.opcode = IL.opJNE THEN + jcc(inv0(cc), next.param1); + cmd := next + ELSE + SetCC(cc, GetAnyReg()) + END + + |IL.opINCC: + UnOp(r1); + r2 := GetAnyReg(); + Ldr32(r2, r1); + AddConst(r2, param2); + Str32(r2, r1); + drop; + drop + + |IL.opINCCB, IL.opDECCB: + IF opcode = IL.opDECCB THEN + param2 := -param2 + END; + UnOp(r1); + r2 := GetAnyReg(); + Ldr8(r2, r1); + AddConst(r2, param2); + Str8(r2, r1); + drop; + drop + + |IL.opUMINUS: + UnOp(r1); + Neg(r1) + + |IL.opADD: + BinOp(r1, r2); + CASE cmd.next(COMMAND).opcode OF + |IL.opLOAD32, IL.opLOADF: + gen7(TRUE, FALSE, r2, r1, r1); (* ldr r1, [r1, r2] *) + cmd := cmd.next(COMMAND) + |IL.opLOAD8: + gen7(TRUE, TRUE, r2, r1, r1); (* ldrb r1, [r1, r2] *) + cmd := cmd.next(COMMAND) + |IL.opLOAD16: + gen8(TRUE, FALSE, r2, r1, r1); (* ldrh r1, [r1, r2] *) + cmd := cmd.next(COMMAND) + ELSE + AddReg(r1, r1, r2) + END; + drop + + |IL.opADDL, IL.opADDR: + UnOp(r1); + AddConst(r1, param2) + + |IL.opSUB: + BinOp(r1, r2); + SubReg(r1, r1, r2); + drop + + |IL.opSUBL, IL.opSUBR: + UnOp(r1); + AddConst(r1, -param2); + IF opcode = IL.opSUBL THEN + Neg(r1) + END + + |IL.opMUL: + BinOp(r1, r2); + Mul(r1, r2); + drop + + |IL.opMULC: + UnOp(r1); + + a := param2; + IF a > 1 THEN + n := UTILS.Log2(a) + ELSIF a < -1 THEN + n := UTILS.Log2(-a) + ELSE + n := -1 + END; + + IF a = 1 THEN + + ELSIF a = -1 THEN + Neg(r1) + ELSIF a = 0 THEN + MovConst(r1, 0) + ELSE + IF n > 0 THEN + IF a < 0 THEN + Neg(r1) + END; + LslImm(r1, n) + ELSE + r2 := GetAnyReg(); + MovConst(r2, a); + Mul(r1, r2); + drop + END + END + + |IL.opABS: + UnOp(r1); + Tst(r1); + L := NewLabel(); + jcc(jge, L); + Neg(r1); + Label(L) + + |IL.opNOT: + UnOp(r1); + Tst(r1); + SetCC(je, r1) + + |IL.opORD: + UnOp(r1); + Tst(r1); + SetCC(jne, r1) + + |IL.opCHR: + UnOp(r1); + Code(0B2C0H + r1 * 9) (* uxtb r1 *) + + |IL.opWCHR: + UnOp(r1); + Code(0B280H + r1 * 9) (* uxth r1 *) + + |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: + BinOp(r1, r2); + Shift(opcode, r1, r2); + drop + + |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: + MovConst(GetAnyReg(), param2); + BinOp(r2, r1); + Shift(opcode, r1, r2); + INCL(R.regs, r2); + DEC(R.top); + R.stk[R.top] := r1 + + |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: + n := param2 MOD 32; + IF n # 0 THEN + UnOp(r1); + CASE opcode OF + |IL.opASR2: AsrImm(r1, n) + |IL.opROR2: r2 := GetAnyReg(); MovConst(r2, n); Shift(IL.opROR, r1, r2); drop + |IL.opLSL2: LslImm(r1, n) + |IL.opLSR2: LsrImm(r1, n) + END + END + + |IL.opCHKBYTE: + BinOp(r1, r2); + CmpConst(r1, 256); + jcc(jb, param1) + + |IL.opCHKIDX: + UnOp(r1); + CmpConst(r1, param2); + jcc(jb, param1) + + |IL.opCHKIDX2: + BinOp(r1, r2); + IF param2 # -1 THEN + Cmp(r2, r1); + jcc(jb, param1) + END; + INCL(R.regs, r1); + DEC(R.top); + R.stk[R.top] := r2 + + |IL.opLEN: + n := param2; + UnOp(r1); + drop; + EXCL(R.regs, r1); + + WHILE n > 0 DO + UnOp(r2); + drop; + DEC(n) + END; + + INCL(R.regs, r1); + ASSERT(REG.GetReg(R, r1)) + + |IL.opLOOP, IL.opENDLOOP: + + |IL.opINF: + MovConst(GetAnyReg(), inf) + + |IL.opPUSHF: + UnOp(r1); + push(r1); + drop + + |IL.opCONST: + MovConst(GetAnyReg(), param2) + + |IL.opEQP, IL.opNEP: + reloc(GetAnyReg(), BIN.RCODE + pic, param1); + BinOp(r1, r2); + Cmp(r1, r2); + drop; + IF opcode = IL.opEQP THEN + SetCC(je, r1) + ELSE + SetCC(jne, r1) + END + + |IL.opPUSHT: + UnOp(r1); + r2 := GetAnyReg(); + mov(r2, r1); + SubImm8(r2, 4); + Ldr32(r2, r2) + + |IL.opGET, IL.opGETC: + IF opcode = IL.opGET THEN + BinOp(r1, r2) + ELSIF opcode = IL.opGETC THEN + UnOp(r2); + r1 := GetAnyReg(); + MovConst(r1, param1) + END; + drop; + drop; + + CASE param2 OF + |1: Ldr8(r1, r1); Str8(r1, r2) + |2: Ldr16(r1, r1); Str16(r1, r2) + |4: Ldr32(r1, r1); Str32(r1, r2) + END + + |IL.opINC, IL.opDEC: + BinOp(r2, r1); + r3 := GetAnyReg(); + Ldr32(r3, r1); + IF opcode = IL.opINC THEN + AddReg(r3, r3, r2) + ELSE + SubReg(r3, r3, r2) + END; + Str32(r3, r1); + drop; + drop; + drop + + |IL.opINCB, IL.opDECB: + BinOp(r2, r1); + r3 := GetAnyReg(); + Ldr8(r3, r1); + IF opcode = IL.opINCB THEN + AddReg(r3, r3, r2) + ELSE + SubReg(r3, r3, r2) + END; + Str8(r3, r1); + drop; + drop; + drop + + |IL.opMIN, IL.opMAX: + BinOp(r1, r2); + Cmp(r1, r2); + L := NewLabel(); + IF opcode = IL.opMIN THEN + cc := jle + ELSE + cc := jge + END; + jcc(cc, L); + mov(r1, r2); + Label(L); + drop + + |IL.opMINC, IL.opMAXC: + UnOp(r1); + CmpConst(r1, param2); + L := NewLabel(); + IF opcode = IL.opMINC THEN + cc := jle + ELSE + cc := jge + END; + jcc(cc, L); + MovConst(r1, param2); + Label(L) + + |IL.opMULS: + BinOp(r1, r2); + gen4(0, r2, r1); (* and r1, r2 *) + drop + + |IL.opMULSC: + MovConst(GetAnyReg(), param2); + BinOp(r1, r2); + gen4(0, r2, r1); (* and r1, r2 *) + drop + + |IL.opDIVS: + BinOp(r1, r2); + gen4(1, r2, r1); (* eor r1, r2 *) + drop + + |IL.opDIVSC: + MovConst(GetAnyReg(), param2); + BinOp(r1, r2); + gen4(1, r2, r1); (* eor r1, r2 *) + drop + + |IL.opADDS: + BinOp(r1, r2); + gen4(12, r2, r1); (* orr r1, r2 *) + drop + + |IL.opSUBS: + BinOp(r1, r2); + gen4(14, r2, r1); (* bic r1, r2 *) + drop + + |IL.opADDSL, IL.opADDSR: + MovConst(GetAnyReg(), param2); + BinOp(r1, r2); + gen4(12, r2, r1); (* orr r1, r2 *) + drop + + |IL.opSUBSL: + MovConst(GetAnyReg(), param2); + BinOp(r1, r2); + gen4(14, r1, r2); (* bic r2, r1 *) + INCL(R.regs, r1); + DEC(R.top); + R.stk[R.top] := r2 + + |IL.opSUBSR: + MovConst(GetAnyReg(), param2); + BinOp(r1, r2); + gen4(14, r2, r1); (* bic r1, r2 *) + drop + + |IL.opUMINS: + UnOp(r1); + gen4(15, r1, r1) (* mvn r1, r1 *) + + |IL.opINCL, IL.opEXCL: + BinOp(r1, r2); + r3 := GetAnyReg(); + MovConst(r3, 1); + CmpConst(r1, 32); + L := NewLabel(); + jcc(jnb, L); + gen4(2, r1, r3); (* lsl r3, r1 *) + Ldr32(r1, r2); + IF opcode = IL.opINCL THEN + gen4(12, r3, r1) (* orr r1, r3 *) + ELSE + gen4(14, r3, r1) (* bic r1, r3 *) + END; + Str32(r1, r2); + Label(L); + drop; + drop; + drop + + |IL.opINCLC, IL.opEXCLC: + UnOp(r2); + r1 := GetAnyReg(); + r3 := GetAnyReg(); + MovConst(r3, 1); + LslImm(r3, param2); + Ldr32(r1, r2); + IF opcode = IL.opINCLC THEN + gen4(12, r3, r1) (* orr r1, r3 *) + ELSE + gen4(14, r3, r1) (* bic r1, r3 *) + END; + Str32(r1, r2); + drop; + drop; + drop + + |IL.opLENGTH: + PushAll(2); + CallRTL(IL._length, 2); + GetRegA + + |IL.opLENGTHW: + PushAll(2); + CallRTL(IL._lengthw, 2); + GetRegA + + |IL.opSAVES: + UnOp(r2); + REG.PushAll_1(R); + r1 := GetAnyReg(); + reloc(r1, BIN.RDATA + pic, stroffs + param2); + push(r1); + drop; + push(r2); + drop; + PushConst(param1); + CallRTL(IL._move, 3) + + |IL.opEQS .. IL.opGES: + PushAll(4); + PushConst(opcode - IL.opEQS); + CallRTL(IL._strcmp, 5); + GetRegA + + |IL.opEQSW .. IL.opGESW: + PushAll(4); + PushConst(opcode - IL.opEQSW); + CallRTL(IL._strcmpw, 5); + GetRegA + + |IL.opCOPY: + PushAll(2); + PushConst(param2); + CallRTL(IL._move, 3) + + |IL.opMOVE: + PushAll(3); + CallRTL(IL._move, 3) + + |IL.opCOPYA: + PushAll(4); + PushConst(param2); + CallRTL(IL._arrcpy, 5); + GetRegA + + |IL.opCOPYS: + PushAll(4); + PushConst(param2); + CallRTL(IL._strcpy, 5) + + |IL.opDIV: + PushAll(2); + divmod; + GetRegA + + |IL.opDIVL: + UnOp(r1); + REG.PushAll_1(R); + PushConst(param2); + push(r1); + drop; + divmod; + GetRegA + + |IL.opDIVR: + n := UTILS.Log2(param2); + IF n > 0 THEN + UnOp(r1); + AsrImm(r1, n) + ELSIF n < 0 THEN + PushAll(1); + PushConst(param2); + divmod; + GetRegA + END + + |IL.opMOD: + PushAll(2); + divmod; + mov(R0, R1); + GetRegA + + |IL.opMODR: + n := UTILS.Log2(param2); + IF n > 0 THEN + UnOp(r1); + IF n = 8 THEN + Code(0B2C0H + r1 * 9) (* uxtb r1 *) + ELSIF n = 16 THEN + Code(0B280H + r1 * 9) (* uxth r1 *) + ELSE + LslImm(r1, 32 - n); + LsrImm(r1, 32 - n) + END + ELSIF n < 0 THEN + PushAll(1); + PushConst(param2); + divmod; + mov(R0, R1); + GetRegA + ELSE + UnOp(r1); + MovConst(r1, 0) + END + + |IL.opMODL: + UnOp(r1); + REG.PushAll_1(R); + PushConst(param2); + push(r1); + drop; + divmod; + mov(R0, R1); + GetRegA + + |IL.opIN, IL.opINR: + IF opcode = IL.opINR THEN + r2 := GetAnyReg(); + MovConst(r2, param2) + END; + L := NewLabel(); + L2 := NewLabel(); + BinOp(r1, r2); + r3 := GetAnyReg(); + CmpConst(r1, 32); + jcc(jb, L); + MovConst(r1, 0); + jmp(L2); + Label(L); + MovConst(r3, 1); + Shift(IL.opLSL, r3, r1); + gen4(0, r3, r2); (* and r2, r3 *) + SetCC(jne, r1); + Label(L2); + drop; + drop + + |IL.opINL: + UnOp(r1); + r2 := GetAnyReg(); + MovConst(r2, LSL(1, param2)); + gen4(0, r2, r1); (* and r1, r2 *) + SetCC(jne, r1); + drop + + |IL.opRSET: + PushAll(2); + CallRTL(IL._set, 2); + GetRegA + + |IL.opRSETR: + PushAll(1); + PushConst(param2); + CallRTL(IL._set, 2); + GetRegA + + |IL.opRSETL: + UnOp(r1); + REG.PushAll_1(R); + PushConst(param2); + push(r1); + drop; + CallRTL(IL._set, 2); + GetRegA + + |IL.opRSET1: + PushAll(1); + CallRTL(IL._set1, 1); + GetRegA + + |IL.opCONSTF: + MovConst(GetAnyReg(), UTILS.d2s(cmd.float)) + + |IL.opMULF: + PushAll(2); + CallRTL(IL._fmul, 2); + GetRegA + + |IL.opDIVF: + PushAll(2); + CallRTL(IL._fdiv, 2); + GetRegA + + |IL.opDIVFI: + PushAll(2); + CallRTL(IL._fdivi, 2); + GetRegA + + |IL.opADDF, IL.opADDFI: + PushAll(2); + CallRTL(IL._fadd, 2); + GetRegA + + |IL.opSUBFI: + PushAll(2); + CallRTL(IL._fsubi, 2); + GetRegA + + |IL.opSUBF: + PushAll(2); + CallRTL(IL._fsub, 2); + GetRegA + + |IL.opEQF..IL.opGEF: + PushAll(2); + PushConst(opcode - IL.opEQF); + CallRTL(IL._fcmp, 3); + GetRegA + + |IL.opFLOOR: + PushAll(1); + CallRTL(IL._floor, 1); + GetRegA + + |IL.opFLT: + PushAll(1); + CallRTL(IL._flt, 1); + GetRegA + + |IL.opUMINF: + UnOp(r1); + r2 := GetAnyReg(); + MovConst(r2, 1); + LslImm(r2, 31); + gen4(1, r2, r1); (* eor r1, r2 *) + drop + + |IL.opFABS: + UnOp(r1); + r2 := GetAnyReg(); + MovConst(r2, 1); + LslImm(r2, 31); + gen4(14, r2, r1); (* bic r1, r2 *) + drop + + |IL.opNEW: + PushAll(1); + n := param2 + 8; + ASSERT(UTILS.Align(n, 32)); + PushConst(n); + PushConst(param1); + CallRTL(IL._new, 3) + + |IL.opTYPEGP: + UnOp(r1); + PushAll(0); + push(r1); + PushConst(param2); + CallRTL(IL._guard, 2); + GetRegA + + |IL.opIS: + PushAll(1); + PushConst(param2); + CallRTL(IL._is, 2); + GetRegA + + |IL.opISREC: + PushAll(2); + PushConst(param2); + CallRTL(IL._guardrec, 3); + GetRegA + + |IL.opTYPEGR: + PushAll(1); + PushConst(param2); + CallRTL(IL._guardrec, 2); + GetRegA + + |IL.opTYPEGD: + UnOp(r1); + PushAll(0); + SubImm8(r1, 4); + Ldr32(r1, r1); + push(r1); + PushConst(param2); + CallRTL(IL._guardrec, 2); + GetRegA + + |IL.opCASET: + push(R2); + push(R2); + PushConst(param2); + CallRTL(IL._guardrec, 2); + pop(R2); + cbnz(ACC, param1) + + |IL.opROT: + PushAll(0); + mov(R2, SP); + push(R2); + PushConst(param2); + CallRTL(IL._rot, 2) + + |IL.opPACK: + PushAll(2); + CallRTL(IL._pack, 2) + + |IL.opPACKC: + PushAll(1); + PushConst(param2); + CallRTL(IL._pack, 2) + + |IL.opUNPK: + PushAll(2); + CallRTL(IL._unpk, 2) + + END; + + cmd := cmd.next(COMMAND) + END; + + ASSERT(R.pushed = 0); + ASSERT(R.top = -1) +END translate; + + +PROCEDURE prolog (GlobSize, tcount, pic, FlashAdr, sp, ivt_len: INTEGER); +VAR + r1, r2, i, dcount: INTEGER; + +BEGIN + entry := NewLabel(); + emptyProc := NewLabel(); + genInt := NewLabel(); + genTrap := NewLabel(); + sdivProc := NewLabel(); + + trap := emptyProc; + int0 := emptyProc; + + IVT[0] := sp; + IVT[1] := entry; + FOR i := 2 TO ivt_len - 1 DO + IVT[i] := genInt + END; + + FOR i := 0 TO ivt_len - 1 DO + Code(low(IVT[i])); + Code(high(IVT[i])) + END; + + Label(entry); + + r1 := GetAnyReg(); + r2 := GetAnyReg(); + reloc(r1, BIN.RDATA + pic, 0); + + FOR i := 0 TO tcount - 1 DO + MovConst(r2, CHL.GetInt(IL.codes.types, i)); + Str32(r2, r1); + AddImm8(r1, 4) + END; + + dcount := CHL.Length(IL.codes.data); + FOR i := 0 TO dcount - 1 BY 4 DO + MovConst(r2, BIN.get32le(IL.codes.data, i)); + Str32(r2, r1); + AddImm8(r1, 4) + END; + + drop; + drop; + + r1 := GetAnyReg(); + MovConst(r1, sp); + mov(SP, r1); + reloc(r1, BIN.RDATA + pic, 0); + push(r1); + reloc(r1, BIN.RBSS + pic, 0); + r2 := GetAnyReg(); + MovConst(r2, GlobSize); + AddReg(r1, r1, r2); + drop; + push(r1); + drop; + PushConst(tcount); + CallRTL(IL._init, 3) +END prolog; + + +PROCEDURE epilog; +VAR + L1, L2, L3, L4: INTEGER; + +BEGIN + Code(0BF30H); (* L2: wfi *) + Code(0E7FDH); (* b L2 *) + + Label(genInt); + Code(0F3EFH); Code(08105H); (* mrs r1, ipsr *) + gen14(FALSE, TRUE, {R1}); (* push {LR, R1} *) + call(int0); + gen14(TRUE, TRUE, {R1}); (* pop {PC, R1} *) + + Label(emptyProc); + Code(04770H); (* bx lr *) + + Label(genTrap); + call(trap); + call(entry); + + Label(sdivProc); + IF Target.InstrSet.sdiv THEN + Code(09800H); (* ldr r0, [sp + #0] *) + Code(09901H); (* ldr r1, [sp + #4] *) + Code(0FB91H); (* sdiv r2, r1, r0 *) + Code(0F2F0H); + Code(00013H); (* mov r3, r2 *) + Code(04343H); (* mul r3, r0 *) + Code(01AC9H); (* sub r1, r3 *) + Code(0DA01H); (* bge L *) + Code(04401H); (* add r1, r0 *) + Code(03A01H); (* sub r2, #1 *) + (* L: *) + Code(00010H); (* mov r0, r2 *) + Code(04770H); (* bx lr *) + ELSE + (* a / b; a >= 0 *) + L1 := NewLabel(); + L2 := NewLabel(); + L3 := NewLabel(); + L4 := NewLabel(); + + LdrSp(R1, 1); + LdrSp(R2, 0); + MovConst(R0, 0); + push(R4); + + Label(L4); + Cmp(R1, R2); + jcc(jl, L1); + MovConst(R3, 2); + mov(R4, R2); + LslImm(R4, 1); + Label(L3); + Cmp(R1, R4); + jcc(jl, L2); + CmpConst(R4, 0); + jcc(jle, L2); + LslImm(R4, 1); + LslImm(R3, 1); + jmp(L3); + Label(L2); + LsrImm(R4, 1); + LsrImm(R3, 1); + SubReg(R1, R1, R4); + AddReg(R0, R0, R3); + jmp(L4); + Label(L1); + + (* a / b; a < 0 *) + L1 := NewLabel(); + L2 := NewLabel(); + L3 := NewLabel(); + L4 := NewLabel(); + + Label(L4); + CmpConst(R1, 0); + jcc(jge, L1); + MovConst(R3, 2); + mov(R4, R2); + LslImm(R4, 1); + Neg(R1); + Label(L3); + Cmp(R1, R4); + jcc(jl, L2); + CmpConst(R4, 0); + jcc(jle, L2); + LslImm(R4, 1); + LslImm(R3, 1); + jmp(L3); + Label(L2); + Neg(R1); + LsrImm(R4, 1); + LsrImm(R3, 1); + AddReg(R1, R1, R4); + SubReg(R0, R0, R3); + jmp(L4); + Label(L1); + + pop(R4); + Code(04770H); (* bx lr *) + END + +END epilog; + + +PROCEDURE CortexM3; +BEGIN + Target.FlashAdr := 08000000H; + Target.SRAMAdr := 20000000H; + Target.IVTLen := 256; + Target.Reserved := 0; + Target.MinStack := 512; + Target.InstrSet.thumb2 := TRUE; + Target.InstrSet.it := TRUE; + Target.InstrSet.sdiv := TRUE; + Target.InstrSet.cbxz := TRUE +END CortexM3; + + +PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); +VAR + opt: PROG.OPTIONS; + + ram, rom: INTEGER; + + DataAdr, BssAdr, DataSize, BssSize, CodeSize: INTEGER; + + File: WR.FILE; + +BEGIN + IF target = TARGETS.STM32CM3 THEN + CortexM3 + END; + + ram := MIN(MAX(options.ram, STM32_minRAM), STM32_maxRAM) * 1024; + rom := MIN(MAX(options.rom, STM32_minROM), STM32_maxROM) * 1024; + + tcount := CHL.Length(IL.codes.types); + + opt := options; + CodeList := LISTS.create(NIL); + + program := BIN.create(IL.codes.lcount); + + REG.Init(R, push, pop, mov, xchg, NIL, NIL, {R0, R1, R2, R3}, {}); + + StkCount := 0; + + DataAdr := Target.SRAMAdr + Target.Reserved; + DataSize := CHL.Length(IL.codes.data) + tcount * 4 + Target.Reserved; + WHILE DataSize MOD 4 # 0 DO + CHL.PushByte(IL.codes.data, 0); + INC(DataSize) + END; + BssAdr := DataAdr + DataSize - Target.Reserved; + + IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4))); + + BssSize := IL.codes.bss; + ASSERT(UTILS.Align(BssSize, 4)); + + prolog(BssSize, tcount, ORD(opt.pic), Target.FlashAdr, Target.SRAMAdr + ram, Target.IVTLen); + translate(ORD(opt.pic), tcount * 4); + epilog; + + fixup(Target.FlashAdr, DataAdr, BssAdr); + + INC(DataSize, BssSize); + CodeSize := CHL.Length(program.code); + + IF CodeSize > rom THEN + ERRORS.Error(203) + END; + + IF DataSize > ram - Target.MinStack THEN + ERRORS.Error(204) + END; + + File := WR.Create(outname); + + HEX.Data2(File, program.code, 0, CodeSize, high(Target.FlashAdr)); + HEX.End(File); + + WR.Close(File); + + C.StringLn("--------------------------------------------"); + C.String( " rom: "); C.Int(CodeSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(CodeSize * 100 DIV rom); C.StringLn("%)"); + C.Ln; + C.String( " ram: "); C.Int(DataSize); C.String(" of "); C.Int(ram); C.String(" ("); C.Int(DataSize * 100 DIV ram); C.StringLn("%)") + +END CodeGen; + + +PROCEDURE SetIV* (idx: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + res := IVT[idx] = 0; + IVT[idx] := 1 + + RETURN res +END SetIV; + + +PROCEDURE init; +VAR + i: INTEGER; + +BEGIN + FOR i := 0 TO LEN(IVT) - 1 DO + IVT[i] := 0 + END +END init; + + +BEGIN + init +END THUMB. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/UTILS.ob07 b/programs/develop/oberon07/Source/UTILS.ob07 index e64b440ec0..81c04ceaf4 100644 --- a/programs/develop/oberon07/Source/UTILS.ob07 +++ b/programs/develop/oberon07/Source/UTILS.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -23,6 +23,14 @@ CONST min32* = -2147483647-1; max32* = 2147483647; + vMajor* = 1; + vMinor* = 29; + + FILE_EXT* = ".ob07"; + RTL_NAME* = "RTL"; + + MAX_GLOBAL_SIZE* = 1600000000; + TYPE @@ -110,6 +118,11 @@ PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; END splitf; +PROCEDURE d2s* (x: REAL): INTEGER; + RETURN HOST.d2s(x) +END d2s; + + PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; RETURN HOST.isRelative(path) END isRelative; @@ -143,7 +156,7 @@ BEGIN END UnixTime; -PROCEDURE SetBitDepth* (BitDepth: INTEGER); +PROCEDURE SetBitDepth* (BitDepth: INTEGER; Double: BOOLEAN); BEGIN ASSERT((BitDepth = 16) OR (BitDepth = 32) OR (BitDepth = 64)); bit_diff := bit_depth - BitDepth; @@ -154,8 +167,13 @@ BEGIN 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); + + IF Double THEN + target.maxReal := maxreal + ELSE + target.maxReal := 1.9; + PACK(target.maxReal, 127) + END END SetBitDepth; @@ -197,8 +215,6 @@ VAR n: INTEGER; BEGIN - ASSERT(x > 0); - n := 0; WHILE ~ODD(x) DO x := x DIV 2; @@ -258,7 +274,6 @@ END init; BEGIN time := GetTickCount(); COPY(HOST.eol, eol); - maxreal := 1.9; - PACK(maxreal, 1023); + maxreal := HOST.maxreal; init(days) -END UTILS. +END UTILS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/WRITER.ob07 b/programs/develop/oberon07/Source/WRITER.ob07 index 985f9ddaa6..58329005f2 100644 --- a/programs/develop/oberon07/Source/WRITER.ob07 +++ b/programs/develop/oberon07/Source/WRITER.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -108,4 +108,4 @@ BEGIN END Close; -END WRITER. +END WRITER. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/X86.ob07 b/programs/develop/oberon07/Source/X86.ob07 index af8fa42205..47cc4ae62a 100644 --- a/programs/develop/oberon07/Source/X86.ob07 +++ b/programs/develop/oberon07/Source/X86.ob07 @@ -1,14 +1,14 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) MODULE X86; IMPORT IL, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, PROG, - mConst := CONSTANTS, CHL := CHUNKLISTS, PATHS; + CHL := CHUNKLISTS, PATHS, TARGETS; CONST @@ -93,16 +93,6 @@ VAR tcount: INTEGER; -PROCEDURE Byte (n: INTEGER): BYTE; - RETURN UTILS.Byte(n, 0) -END Byte; - - -PROCEDURE Word (n: INTEGER): INTEGER; - RETURN UTILS.Byte(n, 0) + UTILS.Byte(n, 1) * 256 -END Word; - - PROCEDURE OutByte* (n: BYTE); VAR c: CODE; @@ -127,7 +117,7 @@ END OutByte; PROCEDURE OutInt (n: INTEGER); BEGIN - OutByte(UTILS.Byte(n, 0)); + OutByte(n MOD 256); OutByte(UTILS.Byte(n, 1)); OutByte(UTILS.Byte(n, 2)); OutByte(UTILS.Byte(n, 3)) @@ -174,7 +164,7 @@ END long; PROCEDURE OutIntByte (n: INTEGER); BEGIN IF isByte(n) THEN - OutByte(Byte(n)) + OutByte(n MOD 256) ELSE OutInt(n) END @@ -194,7 +184,7 @@ END shift; PROCEDURE mov (reg1, reg2: INTEGER); BEGIN - OutByte2(89H, 0C0H + reg2 * 8 + reg1) // mov reg1, reg2 + OutByte2(89H, 0C0H + reg2 * 8 + reg1) (* mov reg1, reg2 *) END mov; @@ -205,118 +195,128 @@ VAR BEGIN regs := {reg1, reg2}; IF regs = {eax, ecx} THEN - OutByte(91H) // xchg eax, ecx + OutByte(91H) (* xchg eax, ecx *) ELSIF regs = {eax, edx} THEN - OutByte(92H) // xchg eax, edx + OutByte(92H) (* xchg eax, edx *) ELSIF regs = {ecx, edx} THEN - OutByte2(87H, 0D1H) // xchg ecx, edx + OutByte2(87H, 0D1H) (* xchg ecx, edx *) END END xchg; PROCEDURE pop (reg: INTEGER); BEGIN - OutByte(58H + reg) // pop reg + OutByte(58H + reg) (* pop reg *) END pop; PROCEDURE push (reg: INTEGER); BEGIN - OutByte(50H + reg) // push reg + OutByte(50H + reg) (* push reg *) END push; PROCEDURE movrc (reg, n: INTEGER); BEGIN - OutByte(0B8H + reg); // mov reg, n + OutByte(0B8H + reg); (* mov reg, n *) OutInt(n) END movrc; PROCEDURE pushc (n: INTEGER); BEGIN - OutByte(68H + short(n)); // push n + OutByte(68H + short(n)); (* push n *) OutIntByte(n) END pushc; PROCEDURE test (reg: INTEGER); BEGIN - OutByte2(85H, 0C0H + reg * 9) // test reg, reg + OutByte2(85H, 0C0H + reg * 9) (* test reg, reg *) END test; PROCEDURE neg (reg: INTEGER); BEGIN - OutByte2(0F7H, 0D8H + reg) // neg reg + OutByte2(0F7H, 0D8H + reg) (* neg reg *) END neg; PROCEDURE not (reg: INTEGER); BEGIN - OutByte2(0F7H, 0D0H + reg) // not reg + OutByte2(0F7H, 0D0H + reg) (* not reg *) END not; PROCEDURE add (reg1, reg2: INTEGER); BEGIN - OutByte2(01H, 0C0H + reg2 * 8 + reg1) // add reg1, reg2 + OutByte2(01H, 0C0H + reg2 * 8 + reg1) (* add reg1, reg2 *) END add; PROCEDURE andrc (reg, n: INTEGER); BEGIN - OutByte2(81H + short(n), 0E0H + reg); // and reg, n + OutByte2(81H + short(n), 0E0H + reg); (* and reg, n *) OutIntByte(n) END andrc; PROCEDURE orrc (reg, n: INTEGER); BEGIN - OutByte2(81H + short(n), 0C8H + reg); // or reg, n + OutByte2(81H + short(n), 0C8H + reg); (* or reg, n *) OutIntByte(n) END orrc; PROCEDURE addrc (reg, n: INTEGER); BEGIN - OutByte2(81H + short(n), 0C0H + reg); // add reg, n + OutByte2(81H + short(n), 0C0H + reg); (* add reg, n *) OutIntByte(n) END addrc; PROCEDURE subrc (reg, n: INTEGER); BEGIN - OutByte2(81H + short(n), 0E8H + reg); // sub reg, n + OutByte2(81H + short(n), 0E8H + reg); (* sub reg, n *) OutIntByte(n) END subrc; PROCEDURE cmprr (reg1, reg2: INTEGER); BEGIN - OutByte2(39H, 0C0H + reg2 * 8 + reg1) // cmp reg1, reg2 + OutByte2(39H, 0C0H + reg2 * 8 + reg1) (* cmp reg1, reg2 *) END cmprr; PROCEDURE cmprc (reg, n: INTEGER); BEGIN - OutByte2(81H + short(n), 0F8H + reg); // cmp reg, n - OutIntByte(n) + IF n = 0 THEN + test(reg) + ELSE + OutByte2(81H + short(n), 0F8H + reg); (* cmp reg, n *) + OutIntByte(n) + END END cmprc; PROCEDURE setcc (cond, reg: INTEGER); BEGIN - OutByte3(0FH, cond, 0C0H + reg) // setcc reg + OutByte3(0FH, cond, 0C0H + reg) (* setcc reg *) END setcc; PROCEDURE xor (reg1, reg2: INTEGER); BEGIN - OutByte2(31H, 0C0H + reg2 * 8 + reg1) // xor reg1, reg2 + OutByte2(31H, 0C0H + reg2 * 8 + reg1) (* xor reg1, reg2 *) END xor; +PROCEDURE ret*; +BEGIN + OutByte(0C3H) +END ret; + + PROCEDURE drop; BEGIN REG.Drop(R) @@ -402,10 +402,10 @@ END call; PROCEDURE Pic (reg, opcode, value: INTEGER); BEGIN - OutByte(0E8H); OutInt(0); // call L - // L: + OutByte(0E8H); OutInt(0); (* call L + L: *) pop(reg); - OutByte2(081H, 0C0H + reg); // add reg, ... + OutByte2(081H, 0C0H + reg); (* add reg, ... *) Reloc(opcode, value) END Pic; @@ -423,10 +423,10 @@ BEGIN IF pic THEN reg1 := GetAnyReg(); Pic(reg1, BIN.PICIMP, label); - OutByte2(0FFH, 010H + reg1); // call dword[reg1] + OutByte2(0FFH, 010H + reg1); (* call dword[reg1] *) drop ELSE - OutByte2(0FFH, 015H); // call dword[label] + OutByte2(0FFH, 015H); (* call dword[label] *) Reloc(BIN.RIMP, label) END ELSE @@ -504,12 +504,11 @@ BEGIN END |LABEL: - BIN.SetLabel(program, code.label, code.offset) |JMP: IF code.short THEN BIN.PutCode(program, 0EBH); - BIN.PutCode(program, Byte(code.diff)) + BIN.PutCode(program, code.diff MOD 256) ELSE BIN.PutCode(program, 0E9H); BIN.PutCode32LE(program, code.diff) @@ -518,7 +517,7 @@ BEGIN |JCC: IF code.short THEN BIN.PutCode(program, code.jmp - 16); - BIN.PutCode(program, Byte(code.diff)) + BIN.PutCode(program, code.diff MOD 256) ELSE BIN.PutCode(program, 0FH); BIN.PutCode(program, code.jmp); @@ -573,9 +572,127 @@ BEGIN END GetRegA; +PROCEDURE fcmp; +BEGIN + GetRegA; + OutByte2(0DAH, 0E9H); (* fucompp *) + OutByte3(09BH, 0DFH, 0E0H); (* fstsw ax *) + OutByte(09EH); (* sahf *) + movrc(eax, 0) +END fcmp; + + +PROCEDURE movzx* (reg1, reg2, offs: INTEGER; word: BOOLEAN); (* movzx reg1, byte/word[reg2 + offs] *) +VAR + b: BYTE; + +BEGIN + OutByte2(0FH, 0B6H + ORD(word)); + IF (offs = 0) & (reg2 # ebp) THEN + b := 0 + ELSE + b := 40H + long(offs) + END; + OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8); + IF reg2 = esp THEN + OutByte(24H) + END; + IF b # 0 THEN + OutIntByte(offs) + END +END movzx; + + +PROCEDURE _movrm* (reg1, reg2, offs, size: INTEGER; mr: BOOLEAN); +VAR + b: BYTE; + +BEGIN + IF size = 16 THEN + OutByte(66H) + END; + IF (reg1 >= 8) OR (reg2 >= 8) OR (size = 64) THEN + OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8) + 8 * ORD(size = 64)) + END; + OutByte(8BH - 2 * ORD(mr) - ORD(size = 8)); + IF (offs = 0) & (reg2 # ebp) THEN + b := 0 + ELSE + b := 40H + long(offs) + END; + OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8); + IF reg2 = esp THEN + OutByte(24H) + END; + IF b # 0 THEN + OutIntByte(offs) + END +END _movrm; + + +PROCEDURE movmr (reg1, offs, reg2: INTEGER); (* mov dword[reg1+offs], reg2_8 *) +BEGIN + _movrm(reg2, reg1, offs, 32, TRUE) +END movmr; + + +PROCEDURE movrm (reg1, reg2, offs: INTEGER); (* mov reg1, dword[reg2 + offs] *) +BEGIN + _movrm(reg1, reg2, offs, 32, FALSE) +END movrm; + + +PROCEDURE movmr8* (reg1, offs, reg2: INTEGER); (* mov byte[reg1+offs], reg2_8 *) +BEGIN + _movrm(reg2, reg1, offs, 8, TRUE) +END movmr8; + + +PROCEDURE movrm8* (reg1, reg2, offs: INTEGER); (* mov reg1_8, byte[reg2+offs] *) +BEGIN + _movrm(reg1, reg2, offs, 8, FALSE) +END movrm8; + + +PROCEDURE movmr16* (reg1, offs, reg2: INTEGER); (* mov word[reg1+offs], reg2_16 *) +BEGIN + _movrm(reg2, reg1, offs, 16, TRUE) +END movmr16; + + +PROCEDURE movrm16* (reg1, reg2, offs: INTEGER); (* mov reg1_16, word[reg2+offs] *) +BEGIN + _movrm(reg1, reg2, offs, 16, FALSE) +END movrm16; + + +PROCEDURE pushm* (reg, offs: INTEGER); (* push qword[reg+offs] *) +VAR + b: BYTE; + +BEGIN + IF reg >= 8 THEN + OutByte(41H) + END; + OutByte(0FFH); + IF (offs = 0) & (reg # ebp) THEN + b := 30H + ELSE + b := 70H + long(offs) + END; + OutByte(b + reg MOD 8); + IF reg = esp THEN + OutByte(24H) + END; + IF b # 30H THEN + OutIntByte(offs) + END +END pushm; + + PROCEDURE translate (pic: BOOLEAN; stroffs: INTEGER); VAR - cmd: COMMAND; + cmd, next: COMMAND; reg1, reg2: INTEGER; @@ -607,16 +724,16 @@ BEGIN IF pic THEN reg1 := GetAnyReg(); Pic(reg1, BIN.PICIMP, param1); - OutByte2(0FFH, 010H + reg1); // call dword[reg1] + OutByte2(0FFH, 010H + reg1); (* call dword[reg1] *) drop ELSE - OutByte2(0FFH, 015H); // call dword[L] + OutByte2(0FFH, 015H); (* call dword[L] *) Reloc(BIN.RIMP, param1) END |IL.opCALLP: UnOp(reg1); - OutByte2(0FFH, 0D0H + reg1); // call reg1 + OutByte2(0FFH, 0D0H + reg1); (* call reg1 *) drop; ASSERT(R.top = -1) @@ -627,7 +744,7 @@ BEGIN END; WHILE n > 0 DO subrc(esp, 8); - OutByte3(0DDH, 01CH, 024H); // fstp qword[esp] + OutByte3(0DDH, 01CH, 024H); (* fstp qword[esp] *) DEC(n) END; PushAll(0) @@ -647,7 +764,7 @@ BEGIN GetRegA; n := param2; WHILE n > 0 DO - OutByte3(0DDH, 004H, 024H); // fld qword[esp] + OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *) addrc(esp, 8); DEC(n) END @@ -656,12 +773,12 @@ BEGIN n := param2; IF n > 0 THEN OutByte3(0DDH, 5CH + long(n * 8), 24H); - OutIntByte(n * 8); // fstp qword[esp + n*8] + OutIntByte(n * 8); (* fstp qword[esp + n*8] *) INC(n) END; WHILE n > 0 DO - OutByte3(0DDH, 004H, 024H); // fld qword[esp] + OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *) addrc(esp, 8); DEC(n) END @@ -677,8 +794,8 @@ BEGIN n := param2; IF n > 4 THEN movrc(ecx, n); - pushc(0); // @@: push 0 - OutByte2(0E2H, 0FCH) // loop @b + pushc(0); (* L: push 0 *) + OutByte2(0E2H, 0FCH) (* loop L *) ELSE WHILE n > 0 DO pushc(0); @@ -708,14 +825,18 @@ BEGIN n := param2; IF n > 0 THEN n := n * 4; - OutByte(0C2H); OutWord(Word(n)) // ret n + OutByte(0C2H); OutWord(n MOD 65536) (* ret n *) ELSE - OutByte(0C3H) // ret + ret END |IL.opPUSHC: pushc(param2) + |IL.opONERR: + pushc(param2); + jmp(param1) + |IL.opPARAM: n := param2; IF n = 1 THEN @@ -740,7 +861,7 @@ BEGIN movrc(GetAnyReg(), param2) |IL.opLABEL: - SetLabel(param1) // L: + SetLabel(param1) (* L: *) |IL.opNOP: @@ -749,121 +870,105 @@ BEGIN IF pic THEN Pic(reg1, BIN.PICBSS, param2) ELSE - OutByte(0B8H + reg1); // mov reg1, _bss + param2 + OutByte(0B8H + reg1); (* mov reg1, _bss + param2 *) Reloc(BIN.RBSS, param2) END |IL.opLADR: n := param2 * 4; - OutByte2(8DH, 45H + GetAnyReg() * 8 + long(n)); // lea reg1, dword[ebp + n] + OutByte2(8DH, 45H + GetAnyReg() * 8 + long(n)); (* lea reg1, dword[ebp + n] *) OutIntByte(n) - |IL.opVADR: - n := param2 * 4; - OutByte2(8BH, 45H + GetAnyReg() * 8 + long(n)); // mov reg1, dword[ebp + n] - OutIntByte(n) + |IL.opVADR, IL.opLLOAD32: + movrm(GetAnyReg(), ebp, param2 * 4) |IL.opSADR: reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICDATA, stroffs + param2); ELSE - OutByte(0B8H + reg1); // mov reg1, _data + stroffs + param2 + OutByte(0B8H + reg1); (* mov reg1, _data + stroffs + param2 *) Reloc(BIN.RDATA, stroffs + param2) END |IL.opSAVEC: UnOp(reg1); - OutByte2(0C7H, reg1); OutInt(param2); // mov dword[reg1], param2 + OutByte2(0C7H, reg1); OutInt(param2); (* mov dword[reg1], param2 *) drop |IL.opSAVE8C: UnOp(reg1); - OutByte3(0C6H, reg1, Byte(param2)); // mov byte[reg1], param2 + OutByte3(0C6H, reg1, param2 MOD 256); (* mov byte[reg1], param2 *) drop |IL.opSAVE16C: UnOp(reg1); - OutByte3(66H, 0C7H, reg1); OutWord(Word(param2)); // mov word[reg1], param2 + OutByte3(66H, 0C7H, reg1); OutWord(param2 MOD 65536); (* mov word[reg1], param2 *) drop |IL.opVLOAD32: n := param2 * 4; reg1 := GetAnyReg(); - OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] - OutIntByte(n); - OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] + movrm(reg1, ebp, param2 * 4); + movrm(reg1, reg1, 0) |IL.opGLOAD32: reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICBSS, param2); - OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] + movrm(reg1, reg1, 0) ELSE - OutByte2(08BH, 05H + reg1 * 8); // mov reg1, dword[_bss + param2] + OutByte2(08BH, 05H + reg1 * 8); (* mov reg1, dword[_bss + param2] *) Reloc(BIN.RBSS, param2) END - |IL.opLLOAD32: - n := param2 * 4; - OutByte2(8BH, 45H + GetAnyReg() * 8 + long(n)); // mov reg1, dword[ebp + n] - OutIntByte(n) - |IL.opLOAD32: UnOp(reg1); - OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] + movrm(reg1, reg1, 0) |IL.opVLOAD8: - n := param2 * 4; 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] + movrm(reg1, ebp, param2 * 4); + movzx(reg1, reg1, 0, FALSE) |IL.opGLOAD8: reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICBSS, param2); - OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] + movzx(reg1, reg1, 0, FALSE) ELSE - OutByte3(00FH, 0B6H, 05H + reg1 * 8); // movzx reg1, byte[_bss + param2] + OutByte3(00FH, 0B6H, 05H + reg1 * 8); (* movzx reg1, byte[_bss + param2] *) Reloc(BIN.RBSS, param2) END |IL.opLLOAD8: - n := param2 * 4; - OutByte3(0FH, 0B6H, 45H + GetAnyReg() * 8 + long(n)); // movzx reg1, byte[ebp + n] - OutIntByte(n) + movzx(GetAnyReg(), ebp, param2 * 4, FALSE) |IL.opLOAD8: UnOp(reg1); - OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] + movzx(reg1, reg1, 0, FALSE) |IL.opVLOAD16: - n := param2 * 4; 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] + movrm(reg1, ebp, param2 * 4); + movzx(reg1, reg1, 0, TRUE) |IL.opGLOAD16: reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICBSS, param2); - OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] + movzx(reg1, reg1, 0, TRUE) ELSE - OutByte3(00FH, 0B7H, 05H + reg1 * 8); // movzx reg1, word[_bss + param2] + OutByte3(00FH, 0B7H, 05H + reg1 * 8); (* movzx reg1, word[_bss + param2] *) Reloc(BIN.RBSS, param2) END |IL.opLLOAD16: - n := param2 * 4; - OutByte3(0FH, 0B7H, 45H + GetAnyReg() * 8 + long(n)); // movzx reg1, word[ebp + n] - OutIntByte(n) + movzx(GetAnyReg(), ebp, param2 * 4, TRUE) |IL.opLOAD16: UnOp(reg1); - OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] + movzx(reg1, reg1, 0, TRUE) |IL.opUMINUS: UnOp(reg1); @@ -877,27 +982,44 @@ BEGIN |IL.opADDL, IL.opADDR: IF param2 # 0 THEN UnOp(reg1); - IF param2 = 1 THEN - OutByte(40H + reg1) // inc reg1 - ELSIF param2 = -1 THEN - OutByte(48H + reg1) // dec reg1 + next := cmd.next(COMMAND); + CASE next.opcode OF + |IL.opLOAD32: + movrm(reg1, reg1, param2); + cmd := next + |IL.opLOAD16: + movzx(reg1, reg1, param2, TRUE); + cmd := next + |IL.opLOAD8: + movzx(reg1, reg1, param2, FALSE); + cmd := next + |IL.opLOAD32_PARAM: + pushm(reg1, param2); + drop; + cmd := next ELSE - addrc(reg1, param2) + IF param2 = 1 THEN + OutByte(40H + reg1) (* inc reg1 *) + ELSIF param2 = -1 THEN + OutByte(48H + reg1) (* dec reg1 *) + ELSE + addrc(reg1, param2) + END END END |IL.opSUB: BinOp(reg1, reg2); - OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2 + OutByte2(29H, 0C0H + reg2 * 8 + reg1); (* sub reg1, reg2 *) drop |IL.opSUBR, IL.opSUBL: UnOp(reg1); n := param2; IF n = 1 THEN - OutByte(48H + reg1) // dec reg1 + OutByte(48H + reg1) (* dec reg1 *) ELSIF n = -1 THEN - OutByte(40H + reg1) // inc reg1 + OutByte(40H + reg1) (* inc reg1 *) ELSIF n # 0 THEN subrc(reg1, n) END; @@ -906,60 +1028,67 @@ BEGIN END |IL.opMULC: - UnOp(reg1); - - a := param2; - IF a > 1 THEN - n := UTILS.Log2(a) - ELSIF a < -1 THEN - n := UTILS.Log2(-a) + IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN + BinOp(reg1, reg2); + OutByte3(8DH, 04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2)); (* lea reg1, [reg1 + reg2 * param2] *) + drop; + cmd := cmd.next(COMMAND) ELSE - n := -1 - END; + UnOp(reg1); - IF a = 1 THEN - - ELSIF a = -1 THEN - neg(reg1) - ELSIF a = 0 THEN - xor(reg1, reg1) - ELSE - IF n > 0 THEN - IF a < 0 THEN - neg(reg1) - END; - - IF n # 1 THEN - OutByte3(0C1H, 0E0H + reg1, n) // shl reg1, n - ELSE - OutByte2(0D1H, 0E0H + reg1) // shl reg1, 1 - END + a := param2; + IF a > 1 THEN + n := UTILS.Log2(a) + ELSIF a < -1 THEN + n := UTILS.Log2(-a) ELSE - OutByte2(69H + short(a), 0C0H + reg1 * 9); // imul reg1, a - OutIntByte(a) + n := -1 + END; + + IF a = 1 THEN + + ELSIF a = -1 THEN + neg(reg1) + ELSIF a = 0 THEN + xor(reg1, reg1) + ELSE + IF n > 0 THEN + IF a < 0 THEN + neg(reg1) + END; + + IF n # 1 THEN + OutByte3(0C1H, 0E0H + reg1, n) (* shl reg1, n *) + ELSE + OutByte2(0D1H, 0E0H + reg1) (* shl reg1, 1 *) + END + ELSE + OutByte2(69H + short(a), 0C0H + reg1 * 9); (* imul reg1, a *) + OutIntByte(a) + END END END |IL.opMUL: BinOp(reg1, reg2); - OutByte3(0FH, 0AFH, 0C0H + reg1 * 8 + reg2); // imul reg1, reg2 + OutByte3(0FH, 0AFH, 0C0H + reg1 * 8 + reg2); (* imul reg1, reg2 *) drop |IL.opSAVE, IL.opSAVE32: BinOp(reg2, reg1); - OutByte2(89H, reg2 * 8 + reg1); // mov dword[reg1], reg2 + movmr(reg1, 0, reg2); drop; drop |IL.opSAVE8: BinOp(reg2, reg1); - OutByte2(88H, reg2 * 8 + reg1); // mov byte[reg1], reg2 + movmr8(reg1, 0, reg2); drop; drop |IL.opSAVE16: BinOp(reg2, reg1); - OutByte3(66H, 89H, reg2 * 8 + reg1); // mov word[reg1], reg2 + movmr16(reg1, 0, reg2); drop; drop @@ -968,10 +1097,10 @@ BEGIN IF pic THEN reg2 := GetAnyReg(); Pic(reg2, BIN.PICCODE, param2); - OutByte2(089H, reg2 * 8 + reg1); // mov dword[reg1], reg2 + movmr(reg1, 0, reg2); drop ELSE - OutByte2(0C7H, reg1); // mov dword[reg1], L + OutByte2(0C7H, reg1); (* mov dword[reg1], L *) Reloc(BIN.RCODE, param2) END; drop @@ -981,13 +1110,13 @@ BEGIN IF pic THEN reg2 := GetAnyReg(); Pic(reg2, BIN.PICIMP, param2); - OutByte2(0FFH, 30H + reg2); // push dword[reg2] - OutByte2(08FH, reg1); // pop dword[reg1] + pushm(reg2, 0); + OutByte2(08FH, reg1); (* pop dword[reg1] *) drop ELSE - OutByte2(0FFH, 035H); // push dword[L] + OutByte2(0FFH, 035H); (* push dword[L] *) Reloc(BIN.RIMP, param2); - OutByte2(08FH, reg1) // pop dword[reg1] + OutByte2(08FH, reg1) (* pop dword[reg1] *) END; drop @@ -996,7 +1125,7 @@ BEGIN IF pic THEN Pic(reg1, BIN.PICCODE, param2) ELSE - OutByte(0B8H + reg1); // mov reg1, L + OutByte(0B8H + reg1); (* mov reg1, L *) Reloc(BIN.RCODE, param2) END @@ -1004,9 +1133,9 @@ BEGIN reg1 := GetAnyReg(); IF pic THEN Pic(reg1, BIN.PICIMP, param2); - OutByte2(08BH, reg1 * 9) // mov reg1, dword[reg1] + movrm(reg1, reg1, 0) ELSE - OutByte2(08BH, 05H + reg1 * 8); // mov reg1, dword[L] + OutByte2(08BH, 05H + reg1 * 8); (* mov reg1, dword[L] *) Reloc(BIN.RIMP, param2) END @@ -1025,19 +1154,15 @@ BEGIN |IL.opSBOOL: BinOp(reg2, reg1); test(reg2); - OutByte3(0FH, 95H, reg1); // setne byte[reg1] + OutByte3(0FH, 95H, reg1); (* setne byte[reg1] *) drop; drop |IL.opSBOOLC: UnOp(reg1); - OutByte3(0C6H, reg1, ORD(param2 # 0)); // mov byte[reg1], 0/1 + OutByte3(0C6H, reg1, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *) drop - |IL.opODD: - UnOp(reg1); - andrc(reg1, 1) - |IL.opEQ..IL.opGE, IL.opEQC..IL.opGEC: @@ -1047,26 +1172,19 @@ BEGIN drop ELSE UnOp(reg1); - IF param2 = 0 THEN - test(reg1) - ELSE - cmprc(reg1, param2) - END + cmprc(reg1, param2) END; drop; cc := cond(opcode); + next := cmd.next(COMMAND); - 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(inv0(cc), label); - cmd := cmd.next(COMMAND) - + IF next.opcode = IL.opJE THEN + jcc(cc, next.param1); + cmd := next + ELSIF next.opcode = IL.opJNE THEN + jcc(inv0(cc), next.param1); + cmd := next ELSE reg1 := GetAnyReg(); setcc(cc + 16, reg1); @@ -1078,13 +1196,13 @@ BEGIN drop; test(reg1); - OutByte2(74H, 5); // je @f - movrc(reg1, 1); // mov reg1, 1 - // @@: + OutByte2(74H, 5); (* je @f *) + movrc(reg1, 1); (* mov reg1, 1 + @@: *) test(reg2); - OutByte2(74H, 5); // je @f - movrc(reg2, 1); // mov reg2, 1 - // @@: + OutByte2(74H, 5); (* je @f *) + movrc(reg2, 1); (* mov reg2, 1 + @@: *) cmprr(reg1, reg2); IF opcode = IL.opEQB THEN @@ -1116,6 +1234,11 @@ BEGIN test(reg1); jcc(je, param1) + |IL.opJG: + UnOp(reg1); + test(reg1); + jcc(jg, param1) + |IL.opJE: UnOp(reg1); test(reg1); @@ -1171,26 +1294,15 @@ BEGIN drop; drop; - CASE param2 OF - |1: - OutByte2(8AH, reg1 * 9); // mov reg1, byte[reg1] - OutByte2(88H, reg1 * 8 + reg2) // mov byte[reg2], reg1 - - |2: - OutByte3(66H, 8BH, reg1 * 9); // mov reg1, word[reg1] - OutByte3(66H, 89H, reg1 * 8 + reg2) // mov word[reg2], reg1 - - |4: - OutByte2(8BH, reg1 * 9); // mov reg1, dword[reg1] - OutByte2(89H, reg1 * 8 + reg2) // mov dword[reg2], reg1 - - |8: + IF param2 # 8 THEN + _movrm(reg1, reg1, 0, param2 * 8, FALSE); + _movrm(reg1, reg2, 0, param2 * 8, TRUE) + ELSE PushAll(0); push(reg1); push(reg2); pushc(8); CallRTL(pic, IL._move) - END |IL.opSAVES: @@ -1203,7 +1315,7 @@ BEGIN push(reg1); drop ELSE - OutByte(068H); // push _data + stroffs + param2 + OutByte(068H); (* push _data + stroffs + param2 *) Reloc(BIN.RDATA, stroffs + param2); END; @@ -1226,14 +1338,11 @@ BEGIN BinOp(reg1, reg2); IF param2 # -1 THEN cmprr(reg2, reg1); - mov(reg1, reg2); - drop; jcc(jb, param1) - ELSE - INCL(R.regs, reg1); - DEC(R.top); - R.stk[R.top] := reg2 - END + END; + INCL(R.regs, reg1); + DEC(R.top); + R.stk[R.top] := reg2 |IL.opLEN: n := param2; @@ -1252,29 +1361,35 @@ BEGIN |IL.opINCC: UnOp(reg1); - OutByte2(81H + short(param2), reg1); OutIntByte(param2); // add dword[reg1], param2 + IF param2 = 1 THEN + OutByte2(0FFH, reg1) (* inc dword[reg1] *) + ELSIF param2 = -1 THEN + OutByte2(0FFH, reg1 + 8) (* dec dword[reg1] *) + ELSE + OutByte2(81H + short(param2), reg1); OutIntByte(param2) (* add dword[reg1], param2 *) + END; drop |IL.opINC, IL.opDEC: BinOp(reg1, reg2); - OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); // add/sub dword[reg2], reg1 + OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); (* add/sub dword[reg2], reg1 *) drop; drop |IL.opINCCB, IL.opDECCB: UnOp(reg1); - OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, Byte(param2)); // add/sub byte[reg1], n + OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, param2 MOD 256); (* add/sub byte[reg1], n *) drop |IL.opINCB, IL.opDECB: BinOp(reg1, reg2); - OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); // add/sub byte[reg2], reg1 + OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); (* add/sub byte[reg2], reg1 *) drop; drop |IL.opMULS: BinOp(reg1, reg2); - OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 + OutByte2(21H, 0C0H + reg2 * 8 + reg1); (* and reg1, reg2 *) drop |IL.opMULSC: @@ -1288,18 +1403,18 @@ BEGIN |IL.opDIVSC: UnOp(reg1); - OutByte2(81H + short(param2), 0F0H + reg1); // xor reg1, n + OutByte2(81H + short(param2), 0F0H + reg1); (* xor reg1, n *) OutIntByte(param2) |IL.opADDS: BinOp(reg1, reg2); - OutByte2(9H, 0C0H + reg2 * 8 + reg1); // or reg1, reg2 + OutByte2(9H, 0C0H + reg2 * 8 + reg1); (* or reg1, reg2 *) drop |IL.opSUBS: BinOp(reg1, reg2); not(reg2); - OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 + OutByte2(21H, 0C0H + reg2 * 8 + reg1); (* and reg1, reg2 *) drop |IL.opADDSL, IL.opADDSR: @@ -1348,7 +1463,7 @@ BEGIN BinOp(reg1, reg2); ASSERT(reg2 = ecx); OutByte(0D3H); - shift(opcode, reg1); // shift reg1, cl + shift(opcode, reg1); (* shift reg1, cl *) drop |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: @@ -1364,7 +1479,7 @@ BEGIN BinOp(reg1, reg2); ASSERT(reg1 = ecx); OutByte(0D3H); - shift(opcode, reg2); // shift reg2, cl + shift(opcode, reg2); (* shift reg2, cl *) drop; drop; ASSERT(REG.GetReg(R, reg2)) @@ -1377,66 +1492,39 @@ BEGIN ELSE OutByte(0D1H) END; - shift(opcode, reg1); // shift reg1, n + shift(opcode, reg1); (* shift reg1, n *) IF n # 1 THEN OutByte(n) END - |IL.opMIN: + |IL.opMAX, IL.opMIN: BinOp(reg1, reg2); cmprr(reg1, reg2); - OutByte2(07EH, 002H); // jle @f - mov(reg1, reg2); // mov reg1, reg2 - // @@: + OutByte2(07DH + ORD(opcode = IL.opMIN), 2); (* jge/jle L *) + mov(reg1, reg2); + (* L: *) drop - |IL.opMAX: - BinOp(reg1, reg2); - cmprr(reg1, reg2); - OutByte2(07DH, 002H); // jge @f - mov(reg1, reg2); // mov reg1, reg2 - // @@: - drop - - |IL.opMINC: + |IL.opMAXC, IL.opMINC: UnOp(reg1); cmprc(reg1, param2); - OutByte2(07EH, 005H); // jle @f - movrc(reg1, param2) // mov reg1, param2 - // @@: + OutByte2(07DH + ORD(opcode = IL.opMINC), 5); (* jge/jle L *) + movrc(reg1, param2) + (* L: *) - |IL.opMAXC: - UnOp(reg1); - cmprc(reg1, param2); - OutByte2(07DH, 005H); // jge @f - movrc(reg1, param2) // mov reg1, param2 - // @@: - - |IL.opIN: + |IL.opIN, IL.opINR: + IF opcode = IL.opINR THEN + reg2 := GetAnyReg(); + movrc(reg2, param2) + END; label := NewLabel(); BinOp(reg1, reg2); cmprc(reg1, 32); - OutByte2(72H, 4); // jb L + OutByte2(72H, 4); (* jb L *) xor(reg1, reg1); jmp(label); - //L: - OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1 - setcc(setc, reg1); - andrc(reg1, 1); - SetLabel(label); - drop - - |IL.opINR: - label := NewLabel(); - UnOp(reg1); - reg2 := GetAnyReg(); - cmprc(reg1, 32); - OutByte2(72H, 4); // jb L - xor(reg1, reg1); - jmp(label); - //L: - movrc(reg2, param2); - OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1 + (* L: *) + OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); (* bt reg2, reg1 *) setcc(setc, reg1); andrc(reg1, 1); SetLabel(label); @@ -1444,7 +1532,7 @@ BEGIN |IL.opINL: UnOp(reg1); - OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); // bt reg1, param2 + OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); (* bt reg1, param2 *) setcc(setc, reg1); andrc(reg1, 1) @@ -1476,26 +1564,26 @@ BEGIN |IL.opINCL, IL.opEXCL: BinOp(reg1, reg2); cmprc(reg1, 32); - OutByte2(73H, 03H); // jnb L + OutByte2(73H, 03H); (* jnb L *) OutByte(0FH); IF opcode = IL.opINCL THEN - OutByte(0ABH) // bts dword[reg2], reg1 + OutByte(0ABH) (* bts dword[reg2], reg1 *) ELSE - OutByte(0B3H) // btr dword[reg2], reg1 + OutByte(0B3H) (* btr dword[reg2], reg1 *) END; OutByte(reg2 + 8 * reg1); - //L: + (* L: *) drop; drop |IL.opINCLC: UnOp(reg1); - OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); //bts dword[reg1],param2 + OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); (* bts dword[reg1], param2 *) drop |IL.opEXCLC: UnOp(reg1); - OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); //btr dword[reg1],param2 + OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); (* btr dword[reg1], param2 *) drop |IL.opDIV: @@ -1504,48 +1592,19 @@ BEGIN GetRegA |IL.opDIVR: - 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 + n := UTILS.Log2(param2); + IF n > 0 THEN UnOp(reg1); - neg(reg1) - ELSE - IF n > 0 THEN - UnOp(reg1); - - IF a < 0 THEN - reg2 := GetAnyReg(); - mov(reg2, reg1); - IF n # 1 THEN - OutByte3(0C1H, 0F8H + reg1, n) // sar reg1, n - ELSE - OutByte2(0D1H, 0F8H + reg1) // sar reg1, 1 - END; - OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2 - drop - ELSE - IF n # 1 THEN - OutByte3(0C1H, 0F8H + reg1, n) // sar reg1, n - ELSE - OutByte2(0D1H, 0F8H + reg1) // sar reg1, 1 - END - END - + IF n # 1 THEN + OutByte3(0C1H, 0F8H + reg1, n) (* sar reg1, n *) ELSE - PushAll(1); - pushc(param2); - CallRTL(pic, IL._divmod); - GetRegA + OutByte2(0D1H, 0F8H + reg1) (* sar reg1, 1 *) END + ELSIF n < 0 THEN + PushAll(1); + pushc(param2); + CallRTL(pic, IL._divmod); + GetRegA END |IL.opDIVL: @@ -1564,42 +1623,19 @@ BEGIN GetRegA |IL.opMODR: - a := param2; - IF a > 1 THEN - n := UTILS.Log2(a) - ELSIF a < -1 THEN - n := UTILS.Log2(-a) + n := UTILS.Log2(param2); + IF n > 0 THEN + UnOp(reg1); + andrc(reg1, param2 - 1); + ELSIF n < 0 THEN + PushAll(1); + pushc(param2); + CallRTL(pic, IL._divmod); + mov(eax, edx); + GetRegA ELSE - n := -1 - END; - - IF ABS(a) = 1 THEN UnOp(reg1); xor(reg1, reg1) - ELSE - IF n > 0 THEN - UnOp(reg1); - andrc(reg1, ABS(a) - 1); - - IF a < 0 THEN - test(reg1); - OutByte(74H); // je @f - IF isByte(a) THEN - OutByte(3) - ELSE - OutByte(6) - END; - addrc(reg1, a) - // @@: - END - - ELSE - PushAll(1); - pushc(param2); - CallRTL(pic, IL._divmod); - mov(eax, edx); - GetRegA - END END |IL.opMODL: @@ -1618,9 +1654,9 @@ BEGIN |IL.opABS: UnOp(reg1); test(reg1); - OutByte2(07DH, 002H); // jge @f - neg(reg1) // neg reg1 - // @@: + OutByte2(07DH, 002H); (* jge L *) + neg(reg1) (* neg reg1 + L: *) |IL.opCOPY: PushAll(2); @@ -1682,7 +1718,7 @@ BEGIN cmprr(reg1, reg2); drop ELSE - OutByte2(081H, 0F8H + reg1); // cmp reg1, L + OutByte2(081H, 0F8H + reg1); (* cmp reg1, L *) Reloc(BIN.RCODE, param1) END @@ -1690,10 +1726,10 @@ BEGIN IF pic THEN reg2 := GetAnyReg(); Pic(reg2, BIN.PICIMP, param1); - OutByte2(03BH, reg1 * 8 + reg2); //cmp reg1, dword [reg2] + OutByte2(03BH, reg1 * 8 + reg2); (* cmp reg1, dword [reg2] *) drop ELSE - OutByte2(3BH, 05H + reg1 * 8); // cmp reg1, dword[L] + OutByte2(3BH, 05H + reg1 * 8); (* cmp reg1, dword[L] *) Reloc(BIN.RIMP, param1) END @@ -1710,8 +1746,7 @@ BEGIN |IL.opPUSHT: UnOp(reg1); - reg2 := GetAnyReg(); - OutByte3(8BH, 40H + reg2 * 8 + reg1, 0FCH) // mov reg2, dword[reg1 - 4] + movrm(GetAnyReg(), reg1, -4) |IL.opISREC: PushAll(2); @@ -1742,7 +1777,7 @@ BEGIN |IL.opTYPEGD: UnOp(reg1); PushAll(0); - OutByte3(0FFH, 070H + reg1, 0FCH); // push dword[reg1 - 4] + pushm(reg1, -4); pushc(param2 * tcount); CallRTL(pic, IL._guardrec); GetRegA @@ -1759,11 +1794,11 @@ BEGIN |IL.opPACK: BinOp(reg1, reg2); push(reg2); - OutByte3(0DBH, 004H, 024H); // fild dword[esp] - OutByte2(0DDH, reg1); // fld qword[reg1] - OutByte2(0D9H, 0FDH); // fscale - OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] - OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] + OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *) + OutByte2(0DDH, reg1); (* fld qword[reg1] *) + OutByte2(0D9H, 0FDH); (* fscale *) + OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) + OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *) pop(reg2); drop; drop @@ -1771,187 +1806,163 @@ BEGIN |IL.opPACKC: UnOp(reg1); pushc(param2); - OutByte3(0DBH, 004H, 024H); // fild dword[esp] - OutByte2(0DDH, reg1); // fld qword[reg1] - OutByte2(0D9H, 0FDH); // fscale - OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] - OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] + OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *) + OutByte2(0DDH, reg1); (* fld qword[reg1] *) + OutByte2(0D9H, 0FDH); (* fscale *) + OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) + OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *) pop(reg1); drop |IL.opUNPK: BinOp(reg1, reg2); - OutByte2(0DDH, reg1); // fld qword[reg1] - OutByte2(0D9H, 0F4H); // fxtract - OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] - OutByte2(0DBH, 018H + reg2); // fistp dword[reg2] + OutByte2(0DDH, reg1); (* fld qword[reg1] *) + OutByte2(0D9H, 0F4H); (* fxtract *) + OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) + OutByte2(0DBH, 018H + reg2); (* fistp dword[reg2] *) drop; drop |IL.opPUSHF: subrc(esp, 8); - OutByte3(0DDH, 01CH, 024H) // fstp qword[esp] + OutByte3(0DDH, 01CH, 024H) (* fstp qword[esp] *) |IL.opLOADF: UnOp(reg1); - OutByte2(0DDH, reg1); // fld qword[reg1] + OutByte2(0DDH, reg1); (* fld qword[reg1] *) drop |IL.opCONSTF: float := cmd.float; IF float = 0.0 THEN - OutByte2(0D9H, 0EEH) // fldz + OutByte2(0D9H, 0EEH) (* fldz *) ELSIF float = 1.0 THEN - OutByte2(0D9H, 0E8H) // fld1 + OutByte2(0D9H, 0E8H) (* fld1 *) ELSIF float = -1.0 THEN - OutByte2(0D9H, 0E8H); // fld1 - OutByte2(0D9H, 0E0H) // fchs + OutByte2(0D9H, 0E8H); (* fld1 *) + OutByte2(0D9H, 0E0H) (* fchs *) ELSE n := UTILS.splitf(float, a, b); pushc(b); pushc(a); - OutByte3(0DDH, 004H, 024H); // fld qword[esp] + OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *) addrc(esp, 8) END - |IL.opSAVEF: + |IL.opSAVEF, IL.opSAVEFI: UnOp(reg1); - OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] + OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) drop |IL.opADDF, IL.opADDFI: - OutByte2(0DEH, 0C1H) // faddp st1, st + OutByte2(0DEH, 0C1H) (* faddp st1, st *) |IL.opSUBF: - OutByte2(0DEH, 0E9H) // fsubp st1, st + OutByte2(0DEH, 0E9H) (* fsubp st1, st *) |IL.opSUBFI: - OutByte2(0DEH, 0E1H) // fsubrp st1, st + OutByte2(0DEH, 0E1H) (* fsubrp st1, st *) |IL.opMULF: - OutByte2(0DEH, 0C9H) // fmulp st1, st + OutByte2(0DEH, 0C9H) (* fmulp st1, st *) |IL.opDIVF: - OutByte2(0DEH, 0F9H) // fdivp st1, st + OutByte2(0DEH, 0F9H) (* fdivp st1, st *) |IL.opDIVFI: - OutByte2(0DEH, 0F1H) // fdivrp st1, st + OutByte2(0DEH, 0F1H) (* fdivrp st1, st *) |IL.opUMINF: - OutByte2(0D9H, 0E0H) // fchs + OutByte2(0D9H, 0E0H) (* fchs *) |IL.opFABS: - OutByte2(0D9H, 0E1H) // fabs + OutByte2(0D9H, 0E1H) (* fabs *) |IL.opFLT: UnOp(reg1); push(reg1); - OutByte3(0DBH, 004H, 024H); // fild dword[esp] + OutByte3(0DBH, 004H, 024H); (* fild dword[esp] *) pop(reg1); drop |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] - OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH); // and word[esp+4], 1111001111111111b - OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H); // or word[esp+4], 0000010000000000b - OutByte2(0D9H, 06CH); OutByte2(024H, 004H); // fldcw word[esp+4] - OutByte2(0D9H, 0FCH); // frndint - OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] + OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H); (* fstcw word[esp+4] *) + OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H); (* fstcw word[esp+6] *) + OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH); (* and word[esp+4], 1111001111111111b *) + OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H); (* or word[esp+4], 0000010000000000b *) + OutByte2(0D9H, 06CH); OutByte2(024H, 004H); (* fldcw word[esp+4] *) + OutByte2(0D9H, 0FCH); (* frndint *) + OutByte3(0DBH, 01CH, 024H); (* fistp dword[esp] *) pop(GetAnyReg()); - OutByte2(0D9H, 06CH); OutByte2(024H, 002H); // fldcw word[esp+2] + OutByte2(0D9H, 06CH); OutByte2(024H, 002H); (* fldcw word[esp+2] *) addrc(esp, 4) |IL.opEQF: - GetRegA; - OutByte2(0DAH, 0E9H); // fucompp - OutByte3(09BH, 0DFH, 0E0H); // fstsw ax - OutByte(09EH); // sahf - movrc(eax, 0); - OutByte2(07AH, 003H); // jp L + fcmp; + OutByte2(07AH, 003H); (* jp L *) setcc(sete, al) - // L: + (* L: *) |IL.opNEF: - GetRegA; - OutByte2(0DAH, 0E9H); // fucompp - OutByte3(09BH, 0DFH, 0E0H); // fstsw ax - OutByte(09EH); // sahf - movrc(eax, 0); - OutByte2(07AH, 003H); // jp L + fcmp; + OutByte2(07AH, 003H); (* jp L *) setcc(setne, al) - // L: + (* L: *) |IL.opLTF: - GetRegA; - OutByte2(0DAH, 0E9H); // fucompp - OutByte3(09BH, 0DFH, 0E0H); // fstsw ax - OutByte(09EH); // sahf - movrc(eax, 0); - OutByte2(07AH, 00EH); // jp L + fcmp; + OutByte2(07AH, 00EH); (* jp L *) setcc(setc, al); setcc(sete, ah); test(eax); setcc(sete, al); andrc(eax, 1) - // L: + (* L: *) |IL.opGTF: - GetRegA; - OutByte2(0DAH, 0E9H); // fucompp - OutByte3(09BH, 0DFH, 0E0H); // fstsw ax - OutByte(09EH); // sahf - movrc(eax, 0); - OutByte2(07AH, 00FH); // jp L + fcmp; + OutByte2(07AH, 00FH); (* jp L *) setcc(setc, al); setcc(sete, ah); cmprc(eax, 1); setcc(sete, al); andrc(eax, 1) - // L: + (* L: *) |IL.opLEF: - GetRegA; - OutByte2(0DAH, 0E9H); // fucompp - OutByte3(09BH, 0DFH, 0E0H); // fstsw ax - OutByte(09EH); // sahf - movrc(eax, 0); - OutByte2(07AH, 003H); // jp L + fcmp; + OutByte2(07AH, 003H); (* jp L *) setcc(setnc, al) - // L: + (* L: *) |IL.opGEF: - GetRegA; - OutByte2(0DAH, 0E9H); // fucompp - OutByte3(09BH, 0DFH, 0E0H); // fstsw ax - OutByte(09EH); // sahf - movrc(eax, 0); - OutByte2(07AH, 010H); // jp L + fcmp; + OutByte2(07AH, 010H); (* jp L *) setcc(setc, al); setcc(sete, ah); - OutByte2(000H, 0E0H); // add al,ah - OutByte2(03CH, 001H); // cmp al,1 + OutByte2(000H, 0E0H); (* add al, ah *) + OutByte2(03CH, 001H); (* cmp al, 1 *) setcc(sete, al); andrc(eax, 1) - // L: + (* L: *) |IL.opINF: pushc(7FF00000H); pushc(0); - OutByte3(0DDH, 004H, 024H); // fld qword[esp] + OutByte3(0DDH, 004H, 024H); (* fld qword[esp] *) addrc(esp, 8) |IL.opLADR_UNPK: n := param2 * 4; reg1 := GetAnyReg(); - OutByte2(8DH, 45H + reg1 * 8 + long(n)); // lea reg1, dword[ebp + n] + OutByte2(8DH, 45H + reg1 * 8 + long(n)); (* lea reg1, dword[ebp + n] *) OutIntByte(n); BinOp(reg1, reg2); - OutByte2(0DDH, reg1); // fld qword[reg1] - OutByte2(0D9H, 0F4H); // fxtract - OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] - OutByte2(0DBH, 018H + reg2); // fistp dword[reg2] + OutByte2(0DDH, reg1); (* fld qword[reg1] *) + OutByte2(0D9H, 0F4H); (* fxtract *) + OutByte2(0DDH, 018H + reg1); (* fstp qword[reg1] *) + OutByte2(0DBH, 018H + reg2); (* fistp dword[reg2] *) drop; drop @@ -1962,14 +1973,12 @@ BEGIN push(reg1); drop ELSE - OutByte(068H); // push _data + stroffs + param2 + OutByte(068H); (* push _data + stroffs + param2 *) Reloc(BIN.RDATA, stroffs + param2) END - |IL.opVADR_PARAM: - n := param2 * 4; - OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] - OutIntByte(n) + |IL.opVADR_PARAM, IL.opLLOAD32_PARAM: + pushm(ebp, param2 * 4) |IL.opCONST_PARAM: pushc(param2) @@ -1978,56 +1987,49 @@ BEGIN IF pic THEN reg1 := GetAnyReg(); Pic(reg1, BIN.PICBSS, param2); - OutByte2(0FFH, 30H + reg1); // push dword[reg1] + pushm(reg1, 0); drop ELSE - OutByte2(0FFH, 035H); // push dword[_bss + param2] + OutByte2(0FFH, 035H); (* push dword[_bss + param2] *) Reloc(BIN.RBSS, param2) END - |IL.opLLOAD32_PARAM: - n := param2 * 4; - OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] - OutIntByte(n) - |IL.opLOAD32_PARAM: UnOp(reg1); - OutByte2(0FFH, 30H + reg1); // push dword[reg1] + pushm(reg1, 0); drop |IL.opGADR_SAVEC: IF pic THEN reg1 := GetAnyReg(); Pic(reg1, BIN.PICBSS, param1); - OutByte2(0C7H, reg1); // mov dword[reg1], param2 + OutByte2(0C7H, reg1); (* mov dword[reg1], param2 *) OutInt(param2); drop ELSE - OutByte2(0C7H, 05H); // mov dword[_bss + param1], param2 + OutByte2(0C7H, 05H); (* mov dword[_bss + param1], param2 *) Reloc(BIN.RBSS, param1); OutInt(param2) END |IL.opLADR_SAVEC: n := param1 * 4; - OutByte2(0C7H, 45H + long(n)); // mov dword[ebp + n], param2 + OutByte2(0C7H, 45H + long(n)); (* mov dword[ebp + n], param2 *) OutIntByte(n); OutInt(param2) |IL.opLADR_SAVE: - n := param2 * 4; UnOp(reg1); - OutByte2(89H, 45H + reg1 * 8 + long(n)); // mov dword[ebp + n], reg1 - OutIntByte(n); + movmr(ebp, param2 * 4, reg1); drop |IL.opLADR_INCC: n := param1 * 4; IF ABS(param2) = 1 THEN - OutByte2(0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); // inc/dec dword[ebp + n] + 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 + OutByte2(81H + short(param2), 45H + long(n)); (* add dword[ebp + n], param2 *) OutIntByte(n); OutIntByte(param2) END @@ -2035,10 +2037,10 @@ BEGIN |IL.opLADR_INCCB, IL.opLADR_DECCB: n := param1 * 4; IF param2 = 1 THEN - OutByte2(0FEH, 45H + 8 * ORD(opcode = IL.opLADR_DECCB) + long(n)); // inc/dec byte[ebp + n] + 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 + OutByte2(80H, 45H + 28H * ORD(opcode = IL.opLADR_DECCB) + long(n)); (* add/sub byte[ebp + n], param2 *) OutIntByte(n); OutByte(param2 MOD 256) END @@ -2046,14 +2048,14 @@ BEGIN |IL.opLADR_INC, IL.opLADR_DEC: n := param2 * 4; UnOp(reg1); - OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); // add/sub dword[ebp + n], reg1 + OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); (* add/sub dword[ebp + n], reg1 *) OutIntByte(n); drop |IL.opLADR_INCB, IL.opLADR_DECB: n := param2 * 4; UnOp(reg1); - OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); // add/sub byte[ebp + n], reg1 + OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); (* add/sub byte[ebp + n], reg1 *) OutIntByte(n); drop @@ -2063,14 +2065,14 @@ BEGIN cmprc(reg1, 32); label := NewLabel(); jcc(jnb, label); - OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + reg1 * 8); // bts(r) dword[ebp + n], reg1 + OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + reg1 * 8); (* bts(r) dword[ebp + n], reg1 *) OutIntByte(n); SetLabel(label); drop |IL.opLADR_INCLC, IL.opLADR_EXCLC: n := param1 * 4; - OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); // bts(r) dword[ebp + n], param2 + OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); (* bts(r) dword[ebp + n], param2 *) OutIntByte(n); OutByte(param2) @@ -2096,28 +2098,28 @@ BEGIN entry := NewLabel(); SetLabel(entry); - IF target = mConst.Target_iDLL THEN + IF target = TARGETS.Win32DLL THEN push(ebp); mov(ebp, esp); - OutByte3(0FFH, 75H, 16); // push dword[ebp+16] - OutByte3(0FFH, 75H, 12); // push dword[ebp+12] - OutByte3(0FFH, 75H, 8); // push dword[ebp+8] + pushm(ebp, 16); + pushm(ebp, 12); + pushm(ebp, 8); CallRTL(pic, IL._dllentry); test(eax); jcc(je, dllret) - ELSIF target = mConst.Target_iObject THEN + ELSIF target = TARGETS.KolibriOSDLL THEN SetLabel(dllinit) END; - IF target = mConst.Target_iKolibri THEN + IF target = TARGETS.KolibriOS THEN reg1 := GetAnyReg(); Pic(reg1, BIN.IMPTAB, 0); - push(reg1); // push IMPORT + push(reg1); (* push IMPORT *) drop - ELSIF target = mConst.Target_iObject THEN - OutByte(68H); // push IMPORT + ELSIF target = TARGETS.KolibriOSDLL THEN + OutByte(68H); (* push IMPORT *) Reloc(BIN.IMPTAB, 0) - ELSIF target = mConst.Target_iELF32 THEN + ELSIF target = TARGETS.Linux32 THEN push(esp) ELSE pushc(0) @@ -2126,20 +2128,20 @@ BEGIN IF pic THEN reg1 := GetAnyReg(); Pic(reg1, BIN.PICCODE, entry); - push(reg1); // push CODE + push(reg1); (* push CODE *) drop ELSE - OutByte(68H); // push CODE + OutByte(68H); (* push CODE *) Reloc(BIN.RCODE, entry) END; IF pic THEN reg1 := GetAnyReg(); Pic(reg1, BIN.PICDATA, 0); - push(reg1); // push _data + push(reg1); (* push _data *) drop ELSE - OutByte(68H); // push _data + OutByte(68H); (* push _data *) Reloc(BIN.RDATA, 0) END; @@ -2150,16 +2152,16 @@ BEGIN IF pic THEN reg1 := GetAnyReg(); Pic(reg1, BIN.PICDATA, tcount * 4 + dcount); - push(reg1); // push _data + tcount * 4 + dcount + push(reg1); (* push _data + tcount * 4 + dcount *) drop ELSE - OutByte(68H); // push _data + OutByte(68H); (* push _data *) Reloc(BIN.RDATA, tcount * 4 + dcount) END; CallRTL(pic, IL._init); - IF target = mConst.Target_iELF32 THEN + IF target = TARGETS.Linux32 THEN L := NewLabel(); pushc(0); push(esp); @@ -2207,22 +2209,22 @@ VAR BEGIN - IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iKolibri, mConst.Target_iELF32} THEN + IF target IN {TARGETS.Win32C, TARGETS.Win32GUI, TARGETS.KolibriOS, TARGETS.Linux32} THEN pushc(0); CallRTL(pic, IL._exit); - ELSIF target = mConst.Target_iDLL THEN + ELSIF target = TARGETS.Win32DLL THEN SetLabel(dllret); movrc(eax, 1); - OutByte(0C9H); // leave - OutByte3(0C2H, 0CH, 0) // ret 12 - ELSIF target = mConst.Target_iObject THEN + OutByte(0C9H); (* leave *) + OutByte3(0C2H, 0CH, 0) (* ret 12 *) + ELSIF target = TARGETS.KolibriOSDLL THEN movrc(eax, 1); - OutByte(0C3H) // ret - ELSIF target = mConst.Target_iELFSO32 THEN - OutByte(0C3H); // ret + ret + ELSIF target = TARGETS.Linux32SO THEN + ret; SetLabel(sofinit); CallRTL(pic, IL._sofinit); - OutByte(0C3H) // ret + ret END; fixup; @@ -2244,7 +2246,7 @@ BEGIN BIN.PutDataStr(program, ext); BIN.PutData(program, 0); - IF target = mConst.Target_iObject THEN + IF target = TARGETS.KolibriOSDLL THEN BIN.Export(program, "lib_init", dllinit); END; @@ -2280,11 +2282,11 @@ BEGIN dllret := NewLabel(); sofinit := NewLabel(); - IF target = mConst.Target_iObject THEN + IF target = TARGETS.KolibriOSDLL THEN opt.pic := FALSE END; - IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, mConst.Target_iELF32, mConst.Target_iELFSO32} THEN + IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32} THEN opt.pic := TRUE END; @@ -2296,14 +2298,14 @@ BEGIN BIN.fixup(program); - IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN - PE32.write(program, outname, target = mConst.Target_iConsole, target = mConst.Target_iDLL, FALSE) - ELSIF target = mConst.Target_iKolibri THEN + IF TARGETS.OS = TARGETS.osWIN32 THEN + PE32.write(program, outname, target = TARGETS.Win32C, target = TARGETS.Win32DLL, FALSE) + ELSIF target = TARGETS.KolibriOS THEN KOS.write(program, outname) - ELSIF target = mConst.Target_iObject THEN + ELSIF target = TARGETS.KolibriOSDLL THEN 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) + ELSIF TARGETS.OS = TARGETS.osLINUX32 THEN + ELF.write(program, outname, sofinit, target = TARGETS.Linux32SO, FALSE) END END CodeGen; @@ -2316,4 +2318,4 @@ BEGIN END SetProgram; -END X86. +END X86. \ No newline at end of file

B+yOKazP{4K56mH#cR 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 z z;FF0}BGmmu{eczK@Fi@pQMnZSw(ACz4 zadU~?oOtI&>H*I(^%tE>+!>=k6?@poCRgv zGW<9!7)&@U7K;jazUc2^ClLdWBcK4Zs)~_n1+3z=;0nGpb)yKFKw%mg0cW78gn(a< zMqDL+!YN{S)u1!-csLw7Q({;{R3#d~Xffyj5Ri{vhRv>`q7bUb4U1^aXrK^7r_VJ6|$BBzNdJZvoHxkP@*15z+DI zUMcU7VQYZef*Lnhc5^<*{>P~{^GEdsU z9YMFjj`Vgcuofn+K=$*-PFwW`TB28x=(!%E5^40G72kyJLfuFndVnoF>W47R=k_>q%VH~mPgi3IKZx*4Oas#mDX0QigJhRu zE1PTVBz1u9GTc^OL*#ux|h1=u{B(=;#$`{3k@T#BmQp(U|5!fuBd{+ zHgxmO;KC^Wu4#+++cOW9^#?({%Ej~GhHQGxWPSOcOCz8i*e&F6A34k$ZgW85av7J= z5naY2_IozRXF>zMaX8Wyx9rW0bY zE7Gi=NmMN%))K32aX3+=4zDt8x+MPgb+k>Fh`opa>+RS9EZ5-@kH_I+ zv>?uDaDwFg(@BW%m2{A3w`j|AAi=>ft~6R-g9R>CZ5{0nIoj1--=>2i9j^c7fw@;l zNW0Zh&CQ}KUe5j5gH&_G>hwqPg*Y`6$xdk+Wk~fE-HZb4D_M%n;KdRr@M4K?F!@lr z7VWIRbQOQqrc5?{T0*>6?_7wjdRo3@^(Y)DDI;htOhqq9m(EOQ^FC(ts;`*MLy^sS zk(NHb&WjmMZ{c~JwXQF@soELb`m(<4Ot)mklSLv0lKQ=$6t4h9_NFGEhCgreNfL)4 z@iOdnEgb~i#gZWCS9Qgd%UjWu>p6kg3(?|3)cOt^Vz86)pA&qGy;t1s`DPe*IR)pa z78k;}7<^$9vRT(g`IJkC^0v?GheX)h-U!Iy`m>lj2}d^w_1(bH*-`cq$TUmt`R3vCD6W_N%*Ex_0Sq z?efz%7*yA+^a#I7f=$w`ILM4GWWJ($ z`0$k^;+L0$)b|w~sn3YR_>IA82`o?P>^9s}I{AEbP^K2z1Hap4GRvU@VdTBWlTj|;k@@bfXs@5MDR!~M$ma%)5>I? zeONL!GRf8gziQu{9ifNB2_$ishlE7jiipbTeX7DustPw!;L_A(C~eNSat0XJBYp&$ zzLKYswXH}EOSs|FX8Ss95_)1Ff>nT$S-ZJ$(Fm;(aSu)GpjvYZ& zLiTwYuk#2UZG#FRu3xoo=9UNSg4Fpx_bcRf;7&^P!uiNo{fwD9mC~h%bhtq9iX+Uh z`(pKqk*>ZgT@ef&TjIyXNQbO`#M_d8gbBC60`h-#2zWjq=Zibx3J!euO4e2F6rM)o zYE49sU@Xw-=%zwL6b%{GC!qAhC4x({mVIP5ruXus^H{T+9v`l!4W)K9MY#lMU!9C2 zFfx$bI5Rqs1QxqNJ1^3kW$65UEHde8D9snAv*=D(I@So6f~cwXOZxvu|7b0Ubto>F zg?N*3FwLTiJhh+{tEAz%z;9A=T44G=0i6V3ODviEO~~ z`ssWXP0u&xX~XQ`)gONKFUBFy1`T>l3;!J2RHqIKz1+h22i8Mzx3s6xV)5ILl}KHDC`)T7 z<5w>?f!i*v|2&ka*ka&EF^s9H*3Z0>(*64}q?_lC3?%MX#Nmb1E7<}9)34e=V!yhW zOl$?WnIRWSZX^*b49tCol2`Qz{VE-pZkeJlVzDPugjr z0gJ*&Q!n21@D**t2X0uzFUK4md_`*|;yFgN(7d<@Ig%0M=ibz?ENaUu}38w{Yg`oW6*6Y;}Iwvn+v;GWwn1(@ARsD za9x*yn7d>zIedo~R;0%}(O0kzWuThrvuTX80DC;sKPpt{1o{fzg~7Bj?RYnYd*XDX zJQK5|W<9hQ#>t)vHH&O`Xw*}owl6akN)q2dA}iEsec=({p{51( zP!~e4q+g56aac6%4lay866xtn|DR6|?|rC6XhZ0h8d_3$u-92*QsXJ$zZ8%TVF&9b zb3~1BM>mX_b%eXxurGfHaH?fSObhe6QK>@j3ahbD8;v)qxSt! zSWeX}wF4k6TQ26x!g1OLg&0veQ;=o24jWgZNmg7vt;r&UWL-mcNy#h+Ex1yI4%%gALXCB#+yvSKxJe-!KkK)@{ zpuc(SGg;k5nkm7q{5~r7)0B3T(h?6Px3XvZToTdx|1!KmRHL^z2D^n=nQ1$?`IZF< z)t1czQo_b%$F!CVZ>rl0Es252=<4hN4ozM3EaH46PnZ;2#fmXMA1wkOfGcbuKJ8cd z#$hl#yTu|y8lkqqE|P!JRhz6;bAMnK^Z{J>1eV-q1aAS|`GH`@JEM!b3GYt$~J#28r0+CMBIGu}nMPj;=0*%$2!jot&xlF&=C zew)QnFjnAXN(YD3bkE(>0u>9;8w5f=RH!);F2N87^mI9LR>QvXzQe=#zy&V&C0kn< z=3!khYQNVZmS2snN9DQcsjBj!{#MZbt0MVaIH19+y^=pG7d~7Jaxs!8cqB(N0LgI*PQ3?b8IpfO$*;t?%jqwY z+pfaNVukHEvI+(1rh6;M1R2NJA_fMF+wSBqzHT0tlY$S*rhdkewi!q`nG zBk{TziThOw#@Vs;-Tkurw3uu5?}gUh^V3(Jw6=(`4c1R6?#^2tqf^bYQa zG3h!aab!Cc#RXo?tt$Nte2gQtPc$`bk8>@SMU>NPq;?ULS{Q1rgj!%9OXUuJ+bM`4 zcypAs4j>3*~h z)Pn+02qT~Zs85{fNJF+@{{stzXKDNA`%Ia*n#TJH7iHL`ZHagf5%iz+k(htj%4ia{ zW{mpLi~lgd!wq909>?rgIGsZLf>a2R8sIi?89dQp=YYf7(K(9VL7p#}gb!ayAqqK_ zvAMAaj#<<|jbIeNT9p`8I8>$HZX|E;;Kp5-$HT&-k+0}Z;V~b-9v;>wx|Q~L|1I#3 z`mGZ8I^rsKQ=fnF1%0?0N`LkJn``h_+i}vw_^aV*=}F^`Dd1TI}oCS1KBE*3@;H94VL8GlOL_%^s{_HQ=Ig$R1I zRx`0o6SZu6k9EdYir_R zAwKUo#JMXE4zjQ4Y*@rsqBw8uDHE?^?kaem>Ah%OvxC5|?ga}%nzr^~nycas+L;@^ zq%*f^k1*{3()7f%r|F-eSK?9v0#XK$@J$|~ONscbC0aLhfhX-zrWHzBTghpOm|YW> zRLey`Mv+UsU?0iL2WyEIJJ8i4%VMhw?aD%Mz^4O;?a-PR8%NkK_S^Cz4ke!sM5!spHOdA}~ zlgK06w32bhIQR-_r71lMI1GF8pMlMFhH{zw5{z~*ParD2OCD=T&U3C7_io0sR43!M zC}x@l{eYnP0@_t@CE{jA#MzyyzWiEXg$uYmzIu1oY(0bac6-haMX)A%0BdBb-y&n! zk4d^ODA`6^BGM6|cSUC79u1GPZ`-y{i1zzd8pxdpmAD@eSGhZkXU08PYV21WG`QS1 z6&voKlg!IN!CV+H;P{urc~4fO;SgersOb6yVeTX=-l2o5a}b@~SdZM_GR8U^Z;IpU zxIbVzo%gFuLPsP>kpU6pgEr?6q}W#|wzX|~cp!7>*xMem*(bTZ$a~NyoGRIgiLeEg zXtwPMo-*{vQkJ-|o~$}RkYe1e6Wt5(AgU&+<#s|@bN)+-o_x)oC9YhHTMl9q??7VZ zT5eiUk8|HkW_hre6sB^!*6detkONl;iq-xj#gRbbQX3kyf;%V{cIzgq0@MdB+->}F z`NTnTr*$NEw#P)2_#mKL&KFZ<;rSUvAWhg=z2G#o` zfFs$^i-)TeCn3POg>Q%kHq(=w5kw^iqN zGS)KNs+sdDFb^*MPD0M(cve(b)g5t&f>E>}X~eA?OV@c^kTBpb!UwJ>#IF=G2<9R- zBI52>sevmH7EBI_aNT7_#JN=Hz-ychyW*WtK}Y)r&)B8Ylynxv(s5b~B9^`Di2#XK z090)ku{jY(R6+b6I?9d7AL7GT!kzb4)0Tv96ARBWZ~8u-Kyuu zu_F%CJTB$a2%cYsax2_$=F6=gyqSd6x+8GjQUX$MZU7{`u1E0~b@Ha*b(**9_VpvZ zKEgg@D4GjgP#v3=F1&`@ZBqiDz_{qPDTzC@330qJ%!)seV#K+PVK5FwJ`FNp$d+nL z(s|^*5tv+=__h}jJaZeh+!=x%YEM_Tbll(>*a~x~AjYZKp$;o@FQy}*3iSq{G*8(H z$U6)OVSM8W;eW^6}$xQAeAsDIfWrwpwLJ` z?^W6Nst0g)-!0gUq)A$4)5z?LGHLZ-*le66sK5m_M><17xHc8INj&fr87ag#JZNl4 zF{azkrv#3hhI$6q~eC85SYr7(RlsmI(&Po;A13rzwq(nq)j>Qc(T`W z%|%%)*JbtTjwDb{8d6qeH)~m2V-b?GW8P~pUSs&!K5KSg5BpVQf1+qJ8rdZ7gv8Zi zoc2N9%Vb8dk?Ds>or7r#_l6?Y;;bW`_cwyKaiUxJ3Ra=W$GSrcP&I?Y;1iJ8PC$d$ zDI$$N)v|$97LW>$(V>T}UY>9^SpTHYSla})8e`Sau-r4Mb zV(>N*uVoa^>{1pByu!3NNpqb>h-r6tTBWxT?6VElP%+W3BU)b;V;wvxWfQJsDLWLr zK>WEwQGc%2pOg*}D0^E;cRmQf3{n3^hV+Rc-50Y1ru8+#n?&#n0_r`>s*Zn)@%<q@IsSw3sDUGYA$HR zW^W>zmEz1&&vL;CEJ+53Gb<2}0Vasz4QgRtDl<+8!Q4{-_LB9T>!~>#utnm?VqY|S zQ`bBBm_U;>5cX7}jFn;-=~sW0ahCU;KPZ-t>5Ujv!EDRWN^>#k}23{Q7Gfq4g)PufsS`O={dro z7uvY4!9)~o4=K3_dJ#xrMlC>RUG-qW8|Gr91nQI9RN>~Hkt}Y7oUTIZ1j3zbNIgeV z-%4Q)-xeHMMS+F{O}7e|E86gY_OHiKpnp|fjY;6sHMEnia}u!~5!B;pGQV2aq>Bw} zxEj!j4#zI+1M;hu;HB+gTY5dI@hObRvN!_i&I6dlbp7lyw*7hnD^|VJ361_Ewk3t5Q`-8P{7)d>d&T89%M7cpaVQyj>rWxXR z{p_J|2>xwZ9D3;L9W;vkFi=Agj#6tzYQtP=LIXq5JXHs8 z82bWv0d^$tB{-=*1jao2akRwr2hKGg#1XH+exk$^1=FVP`GoUXI5w@0*;2G>wwVo+ z#Fa?o&aiZ7gcgs}(e*pQM#k+G4$%hbMhbJWC3 zR3VJutU<(a?F?TFri;jR$9SI^MSw*MN4SMlX)_^}L3>_%+$?Ar%>u!kt1;^kvj;J^ z#`USWh)PZi&IP~;bLh$n+`|lE)7eFVdSi|~6EXHg&mIOGoG*#$fhau;ZK)5WC3`or zVc`bh=tedUkn$p(Z1)fvF5zx&m;Wk_|DrY?wR`h9Bk^+gS4jmmv8Wa5UgA54fF4;EdAXT{{@w|RXpd=oa^;VV&gG3T9)w;-p6tu#c{1G0?D1z7 zpqDJn+{t`t#m#d&nG>7UU8y^B?P#nsM$|yYh!W}+Nxf06WNK1y zs_Kax0;*X=?SpnYcrvA31*_>{U3j=3!+5Aw&r8@h60E7?;ITL_0#w&b@lmj|*FC!( zLeqnAZEHwg1BP&-8wOv56WlNik8m9u&K@gfVJ)yM6UcHPSlSC)`Ph+oSb9C++JICY z?2R$=dmoI2am{V6H0r0{qa)L|FM(BNs9%&tA}0i;45g6EzNgv44}b^g#eb0ad&H3k zzIo{!NLuu>UC}YcXDYDhWS>Mwtf!)1yA{$Vdbf~J#6D!fW8#9@E(C`pIuCR)YLqk5 zCSq^L1gSgT_V@@2f6PAQFX~AFbLWzl{7hdUO`QV`(XgN?<55%@Xe~v3h&H`#XouZT z*$mE$wDA>uCb^MToK-4q-(S~=!Cl%jzD4mpixep}=Rx(6Hnjf-wG>s4o#VoA0>RfS zJ?46Bb{~$+MM~b9juw&YjHPzUwiD&-3OOsMXCT_IRv(5Mz2vh$qM>Am8VSH(7oa(W z$HYsF*&4%a&JUt4vbs&^GG@+$-^JSUb({v)p8bE&j}Re1(7Icn6vns{%QP=?niQhw znI5)TSnj;T(r*@;5!-{6uwHv|9v)_8aHzIInpy$sezoyiEe)KZ`0O;5hb9FmW^KGJ zK0Sr4r@aF0Y+CED<J3XG6(t1wIq4!Wh~`+Uwzpi{Y) z`-Rnf497Xl9g27hGm@-fe$-67symD|~n&13q>5JQ9*8+f;@yJp;@xeLdH(_ygumNsHDAeOelq~N$ zcSD&Ah&a7b$?_sNYj_=6L|@5d{02Me#qBip7{o$W*5!h?x<>+`Q<&?^yb1T|1kCrQ zsTaHnPaxn|kpt1(a~lpcB;Fmh_M%hNrQ~ogWOGh#?i_AM#$XN`!)w@M`_2ZsD@#E; zJRXg4&O12D(DgX*yGjW^jqsN5W?W!?q9hV2)ZlI#3rS-ptcH0c4S?npYD;a4PMJLIsIy<&1C(NzWP!)zceU zNQRKITS#h#{1U|vg@o^ZIx8PTA>oQRt$xSjqCfj|5iDfdC%^jrNjE#6#}F?#ME#Wx zMz}3da<#2hb5|5Dk8tO!_X(GTkGJ?CnR~uwQ$yzdx15<9RK3uyS1*fSo79F(O$uJ8 zmN1t+nX4b@JJ&FT42+s)~01pKQ0mo`H~?Sr$ud3P=NBJbpq zZ@>C}zhQd(yqkalGFXRBGA#i%zSYnYYzk#>FJ4lh zEuY<3HG(x3^3jvE!Hd)yYZ0A)138;it~#TxAYH`))K<`Yp8#i((H&Rn_BfBPo3E)0 ziLmcqau*{(-588NHqHrtbsKSdYL4q62RSZEAx9XZ8j}<}B_xTqW^(F6j_&XPov-8p z{6_O@9MpF6YXky*b>$bL%<*%fRj_l7MqPu-67J(R3r10%o0IT#ODGhk~%B|ID6ekW#oVA_GQnKrNkW!tave64fj z;V7J$PAJA(F?7WAcr(Q5BSd6FZts4yr6|wru@`+#X;_)<66H4Z|FO8f{Oy#nBg;FR zfB=L;X_Gz6GxfK4o%iA!djUR^`9JcEI!$&=CP#3}s|*3ht!Dv$5qQz|E_<|*`y6uo z3u-cJgIJeL1{elbX{y3T4pr+IDXs7cA`c*MQjalGmf@@`g}{zX1;tU`v~$u3J7Sy- z4g#v|{2lFCBqRtPGdpKi&8{_;a zUVELQ<|MIJs;JUY=jTp2+h_|{YXFM#^A0}nY?0oA@gww8i#Qzsy^1qedB)xU{Ye!M zh8xI9?AB1mSHd9{Te=f@jQASN#)_;>_=v^9Zphy--cvu=Bc?{>LU3K9R^fn!1hjiJ z-m^w$ow>s6%a5M%`f9ZR~e*Xs#xLulVKc7+2+c?xmco$3Ne7#4;&MFDJE{v4)FMl69AO+i}A8fhTJS-MMh(BT`;89K2e*c(&VBP z^{~FAZE_p=)qn&DgPkw5T?kFCD6hhg922LBUnLUA7Ko?;=*UIH!? zROFC0y8Y|_hq(~_pz%9ar#nc48Sn z?4CR6p*pF~v~5zbqiTf@_dy()a>q`WRCO=30w}u7#_FyI1v&jI^D14 zkQ6WQCaDY$sqP+9=|XC?A=OrsDmJ77megq^b+aM0L6>Y%@M%~P%0j`$szUsONrKy0 z-47;^YOo=-46=%XKO(~EYDg{jkh;P{>UObJQ$y-5ZL7a4D_}a@mnfv5;8K#}f*}>W z)I(~NhtwHD>RrKYtOjXPs|+bPbC3$8Mv@fo>>#OB52-l)-H43$gTFv`0Cf0Tg0A$K z^-=vTpm5l=x)E>+45X89@$MAsu-X3cJqLH%#h7Y*`k<>UDAEL66{v!JK~T z432gD)BQh-q8 z$NtkIn;Ags%wmpbnd`(9XDwy(iuun&;W=DxEaGWJU&)8~EzVpLSdNDa{kVLhXe73} z??5D*%ujQhFzqRmHl1nDOByb8S|a!?bA)-uzziqModVM>XIAblOj{vowN)>qg>PWn zx;z)hK9&TYH%LvHfQu`;=e(^GRvV0?ek2UQ>Saz3op4%hidkEI&x8(nk-<5Qb;23( zOo&(SG9e}K3+;3FBF-i*hA_y_L(b^B)C!tU^-=Sy@k@tO?yc#9G!~}rFe%$fm>Q2) zO2AhTklK#RSG|ennMB^tK+NyFiJzFnQ%vH|-oyhYk?&v;bGJ^!v=VqSPa!}|-XY@( z4vL)tuv`N)C+3a%yV^L$SFpi?->gBfW*#jIpfBjXj)5MUP2&A^YB$y;*e$wHr3L*1 z#;q=BXb@35Y1H1LQMwLb5W6h8eWhMExqPYth|BCalhj`)Gt!sO(_&~fP+)PPR_0=O z(M$0Evg)4nD%?xxIojVA)Ci<*y$7BZ_93XB{$?}Q5mx&LkT_9KBZS%-Vrry?d)>m# zCLG>HJEYb~RBONb>j+BpLCniiv&FjM)8(V7Ho@hZt>>U?!sTYZBMrsMi7$$tnUaWu zg_O!3bWH0tWV!mPE{m z;rQ4+hT}Vb8S~_kBX^2X$8`XP>9vl}NWhoR0%h_9IeDBsNnZ(4w*%Uio6t!%TfQyv z_;{$1?yd)%WrOZvJozU1bCS)U7mtmQLIgD8BoayuYy(3zoSByrc%9!F_;z^Cf*RfA z)o6;*s35A*@k`nHxS=sT##P6iAASPTnGwSk906l~Sj1=jkYYG53eaDM$ShYp`b?b>eBd3`e#l##xfBP#0Ar7AA$!eEm@0$ldofF^ zD{37pW){Uf%ZRzsE9Ni>`0^Ksn9Kf$ko(x!SRv1+kiA_YpWpHSBjnGRb=5*n{KMFC z1)fH79uWUHO}%)R)U?);(@*ID)=53>57=i?R~sOBX-3Sg;BIT}FR zoMHOAnwP|-aI~-^b#jd!(h0{xJ%b`O)v3qwkoIUpR2B07?%uq|s(}>@?SDmAvL0Sw z+?xfznpWkFLx8O2-psIY-(lKVTJlE-CuM23M4>D-#S7++&ooFI7J9O$pO(M6d(#O% zwp6PEmeclmQD;LU5)lz~Z%zeCac{n`LYxR8oJUb0#QcLbOPQhHo-gdHyEp4b7>*0b zaqaC6>_IR7V?vp;LhOgB$Z zYP8F__)gau$dbW1oKInop1wI>rN>qs@eZ(@uDydvQH&M_<1CAzkSRK!y4t9Z85Lx) z>nk#AU*U3{N7`3tsS~uXFi5BLsM%LYMrI%jt*`L-R(1hyOK>-W&IptV?i(!{fDd2E zo3M~>C@4b$EbbbyKLR+O10>fj9eF?XVbA^4)=outpzNwC!teiN@SRv{2xC{GsRZu! zxBCk~D0s8l`7_e7<}b#j9mMsTDXH1&Ii@BBXQ*B*0(@5zV@7PYzy~&4;5Rso&JtDn zM6}rT8kT%<#9<%0DUfvU_jn2MgqkCY`|{V&92Z%S22{;{GwlB-1-KBV%hl)1%2;m8 zbJ-)M@<@bPL>~uOswN&0-2giU@CxBK10E*ucCP32DpMa5YVKi%t>t*OGD=_z zL2feyZeX>)oCg?UgxW@!ON9)Cat|=<*g_x273Fn8ohnfJl!8RGHKZ$H*C3832;u1X zt{e74Uw0- z42juLHR^jBVzX!B<%At%t!I-ClJ#V=Hv4>g_zD`L9N6^lnSL(P_0~W8U~4Ha?B(&5 z&3-iqzDhtqy&B^ zlX0M0kij7}m3>VjPX zi;+}7YI!7`MM4>{mq(r2r1Rx%RHv)theW)~2<#2Dt-}?-v{Ld?Oy&;fNAiuf8EucD zZJ%JgE)~i8%4|922qkphr;zzo;3fMQQJ}wn2V-e?jrhC?(Ws&wY9t`#3qTtPkE$6{ z?S_9_A)EX3acg@`j_QYd;IM-ZRh#FE8U(LU&me{y4Nk{jE)07&mBz#LDp63%v5~=3 zNwzw6Un1iD$_F|9s?{bIaoOO3##8TmD9@Fuf@3@7*m5}OCo&0Rsi-_SP>n`NOOl-` zr~cFnFfr~H?aw*f<@n~`=AeqdwnaFT<~nsY%l|lRK$Pr~xK4=Uy@cV&piFU@Ha8l|$klMI0{D zftOsNzWI^*1~FlutUiPu#_n~4W7R1TO>gw>55ioulD8zwP-Uc9Mb^{@LoYCMOo4Fm)EMOn3CsV^eMl%)rY0m^YW;{xnsd5Mb znW|50G@WZRmBua>O_-?_$kbefpxy|IZCB#lt96PqlW~zzMhCQ^H$o@LyqOe#+N`J# zDG?(Ofz}3^dvMOOIJ1b;&x0coEf4{}Q_!&GG}W?7uxPguE#8AB5eH`)Ryf1x;_N=p zh&P)!?*YWl;7P<#B|^D#MlN;iXFlbTXuM%2J`fphA}aEX%)}Y6plIE ze~)je_kkL|saehq7Ud`lXh_T5(t$FHLrj%@*Du4HIs?Z^;pXZ<9JcG5HBa1`(6^My zek8+uU<@<+c!^W6ZE%8We-_FeX4ooVon_33AI>$J@@)v`yIVw4Ib)cNV_kBT`XQ#g zij=%pn0E1b6TYx6S5~w=I2^JN7h)A=?q4Q_`HCD_t=$_|e(wqwtEGwq@o1S6vKoYM5bJ4Y*|O0!X|4Esot@q zI>nG`UzJp%CMC5>s9AsJhL>m|?#n}(W$=mUKZD#;RVVzZ2JtB&)(S+Lsto|16_N{l z%2KI3h6JX8djHaDEl@^qyjpg8v;~r`U<%w&X*hl&>4_i>TSyDk*fumjGvzF#NDHKH zI)J9nv_ZcxsjVa-Q(`yU9YoQztLqXbcY>9trO1`}=)HiOXRbj;76mH&xvw|jdC?qoF+`Xkq9|(0z z1}*s?DCt^(FB0%2y8g)TS?WMt+OTg86U|TcW#1&~8`u-OS$nwx^A|XtnQ8p-v*3s2?nGtq?~) zxG`L_-(dr)wonN3GOt4(k5kL$qjf_5{2N z$#_Y842jkp5;0#xW3#ao+>O1WZn>Y-CL$eEG4`^gY;5GmbxSb)#Y{anmRDcPOA=4> z@REooLJKd#9}4rnD9K0NcwS0ke_c;jNG_NA^T?`PSY6K4eMt4Fwd+iymL%>#qE$;G zp0l)+VWm{J516Y53lo`ZLiZ}to#)aOpKFGtD~UI1x(hQ86lNYk#W0&=kH0C`Z*K0;mUBEyR{7f($uOZ~Q zh~UB0E$>B(O@Ij}Bf*nfEv+b$*bIp_w;NiKVpRuMSK8-}nQz8}!Pdo^yuKj`)*z&lZq^1ffxX9S(cTgR8 zSL!Nmi%_@WOIoaQH65S2Udr%LMDgY8KQYj@=E%V(e|zo6Z`6}ed0i<+vRUW&6dB1*`mFS+_go=ADpcGpVE4VLFMRY71(B^?-&VT z^vDCG()gGD6BX$`iWI&M5oR)=b*Lr#g4HY87kII52Ud6|%SdBzw<j#reFZ>RIdd6VcbGm~{7ow@^4df&Gc?fz~ z-6{GWQVJjt4tm!i8QlAJ7$Z;VaaNLf5*T@Ff26O;S4sUd5Y1PK*oO!_@Ob$`xIE}L z52-^?zjQlZUWCVR$gkE$HX3Kul0W3`*P!EL?DOjRG;8Xig+><}CyY1yZGrkWE$)vrzmL@;Pr$t<33 zDRKV~Qs`a*`=GGNZf+MPHhYGve?CJnOptQ-Q#}Ds#tiDubPk$r!IyM5ymPHDD>47y5ZU^5r(3wE~`*b1T=V}Y9GaG zPQ19_`7FIXSLg!wECjTsWc2{S5QFoj_RHUhzM=Rtlv%zK ztJ^3=*>kS3)A;rlJx}5UB$_JJNSuYI{{Pfbu=S+ zoDCw}L=Rk;aQ|IRxD59}W3%RyPhc#|C9BR5xj0jKidj600FIt}hN3(7qL>W_6sp5o zzbXQ6zv=`MsFUXMfoA0tf0dQ-5AvQ5-kjP;?L||x3Ogp3eF(Fs;nahBv*;qk6lShv znLy!OE9+*1f?QQgS2GBm6l|&@AL;tH0DmoqcnrIoHq|%`tj3|caL|rb9U}cSMNEPk zkP?uH&k(_$HW8hbTui1~N>NzmF-kcqL99{MeWZ=DOdDk;MDeS%r#NoVIb5I2=8&0b zZToT=!fWXVh3LF87|Xn%brHOCZE0CGapw<8pJXm!S>?ri*jXmwgOivcg?2*T99k#= zU^r!m#9};v`bOLO3hv^!ft{OSE&XwTmhPgG;g#FCZHO!5lfE)U!)25hU2-!}WoVh| z{sgN{c%X&7U+_;-J9kI%=ST7JRBkMOIr=x?H+Lne8*HbV>um0z8sLMi`asnS8Lj8T z?}b5GOjDqjlx=O>p0sVd$+WH8#YkKe#8vLLh2&I%9hp?M7&e2rvBfY6F_jx~fQtvN zkHDMdv~HYQ0f}_4lw#z#eL3ZbsQ-X~3E%M?&e%30dN=t6a4eewD=IFi<8y* z@6hax#}s8=WKc+6JWp1`F$*2Wga_hAAr5mx$*LdYaIy$-7i!Es3Nale=5!tNK09h$ z_70eVI%Wh$_u6-ohKq!*f?l>%PM~N%PPC%oWv);|!mNBk8@dl*!ymd6t9lfvrm>`E zVNTUOH0jG9hw{ZyBj(NGLpaLB8gQm@VRv<*p=s#3wlC4Wwy$XrvkScT zNrZ#N^qD)UNCVHZzJM$0++6yAe@-cW4I)>o@T z?FX6O&!$5&iRgj|Sek-7_F7bsB?PYL0hWj(4)>g4{C_tP_Z9q-Ey3Q?OQ`t_iZ%2jc<_P4Hd>|JO5(Hv}65(hdA1qSpw8sf;$*&7MN^;r3^L?TxWtS8Eg@_(F7l6uw~#D6D(w~RUpR% za~NzL$TPv~8Eg|+V1nZrY#Uf)f+G-=_V*1QHHycYj7;A}3)qJ&Nmq|!0UJ=pHVtb? z(bSKaIs~b5AyYyb+qW2iy#(lN0g}u3ZeI+*#{@{U0BL1>3n~WS69OC@YgjZc0F z0G|@z4GWN3#s~Id0QM1Jxdlis<2yS5$ZT15H@-02m9BQSLcL7v2PeI3g`^f2#9?MH z@LzqNk*T9rAYC~b@HM!sw=iCP$#1UVVI~%D>^+DOXOkF0_{4*7ugr++>U%2S)RU^> zTU)k()biy|N0(HZ;b7cWy6iswp16s>wHaf^!`pEJePKbx-w>reLK`RoN71@aqbbE%Pfw>6$nnTQ1`1w4`Hjy+bG30q81{K zD{!i6@;?Rsh0Ghr3M_HSR^Wlv1pbvc2QH_QuD}wv7jc!lt$dS~z@2O%nT9sR7>sQw zW=d7>XW3C5SNvpk$v$gukBKAXJ_(%WZygD9$y`vH5UnQY5rUo}g1WgOaot2vv`a8uU@@99^?5sZxbflNgSEoH1Z#(X3MPbq2quQV z4b};N6-)|$9!w5@6095kFqjg4KUgoki>+OfZS6AC0`@T6Yt7g}!vn$M}(luJ&a;*@e7FGS!8)~9 z#N|~){IG?HIJgE8|Lx6vKd}UxXj)i)@{iOxeNQ^Jh*rWnUM|m8;WABgxx5B0_k&BZ zC>v{t0kU)+qhc}_WU5MpVM`U}tEw>nwYjKR6Z7+zXi^4p~ zEdn!yxi4R#p|3&v2TzN!aWXQ^;W_jj1?9+oP%&mLEM|EAKP+Z5l7b_gF7P(ucltJB z@xqsX2QW;=#KMhqD$(-@TwY{)D8;uaR8h+rek|}&4o8&+JX?duJFSidKE}c5+JaxF z!Lee0ETJ!TW<XS8iZRhS|fsb_>N5N-?lBjAzcuI|CxzbS> za~eHogc=aGwjl5)F?>pmSQDL>qF57o#YzQ)!MLYVGRwIbF0k{bE1zx>N~;vcNvJNU zxmVXv77BZ@CLGjFg3^DY?TtELm&x?P0;X*{kXBes*!Z2O{xz1(@HB6ge6@-opEVUh zFwDfTmxG@0*~7j8Y+xm7Mnv2^5h)BNBK!J05qrHpVV0bpyZx+lf+3 zO~N{??RxvKD?5Bl70+wB$*P;OuAgeG3cah!BFyOm>)HzrOT+0H&%m1ts5>`BHm?#wuk zK2QZhYE@QLLPA0X2?_D1h+haO0s$32Rv-}lRp1vCff%trK%ff5k1pT2cV;}!ZYiDB z%-nnKx#!+{&bjAt*N!FARN~0?SukRrMV_hG-%pei`6R+-{8T7$m zmzyth`B<=xvKmM!;z5D_?kLM2|7DEb9ZYb?yY4~9lR*~c;G+zvGT@frev~gScGtLe zH%7@q&$}J2-LZ93@DSGqs&;d5FV{ZDwL@FC1vhi;Wv<<}b$jq1n5@gxeTC~dqznFv zdiUF^=XC-8655sS4^{2@fK$Tm&$)I8Gr;#Au5{nz+HG662K;%L?ps_t3|-)3uI}Ge zzZ-)ubL}0j3HaX^xOU%B)b8Ip6g-Vuu)yqkj6p|&MU(^nh*r1GfKLRo3=j->iUF&^ zF$NrF!0QaC21mJk=w6h^gIl=qAJ~=MJOdsJ{*7|*76S$hs0M#wz#9yBT>;)?06P~< z?mIZW06PxjrwF$ugC7A1as4{d3zUD8DE~fDj&&!<-YJy~os^7as`47XUMAy@4+L*R z*?x!ZESng(LjACBF#ZrNjs^0^n?il&8NHA4^h*P-#X9Rr-r}hID@t zp+aGQ{D@o+K-X5k$D^qsgeykj%oe2Jb%lPuqk4=BPaiD>4p?ep@uN#4%1pKuwsKDxsG(7Mw9c~32rvCe&j2ZvnK1>83Cft4- zXOK=~z!xVqI2ehNO|yBype zn$GS>``6L_;v1{MQ4s5Xj49j{l!0+&=C^Q2!8f_%g9jv@O>@3BrJ_ebWfq2 zycr%{$hPDa%{PL-*E^a|gva%z#Jz%YbTgdW`QrE5fjesBcD|U8l3uM*SgjCQ=Ek~d zn?5y~g?f{YyY1ss#{oP}+-&yxj_V7)4Z-SuEBSOAc7$nzaV4H7nHy6>HV1R%}*kD-AHP zURgQQpvml1ZZ{tGo7EC$<5Br%w^`#X{AxCYLuaJrK&Zkshw|@ z>Sw8Nw%V*~02Jz#<{~wUg%x^a@{`9ub1Xe^^4YN`p852t2j@?p7=Q9PVAKm2XhAzu zS)qjsBw4{^n^dZtrBaQwDwu;urA*pNiOL18muqzbpt8JLgQ(H9(xBy9iSISc2eP7C znSiuftE@CNyz8~1R$8lTRM(2NdI_&ptGVNFs;mHwaojyq(Mc_)1f-Zc zpNc^q^vja60NT8>Mh@JDV%`sI2gh1klBW|nVTl29mDKF5886= zy6!@CT>~@~mM3@vd4oQ0Ff2Qzgpd-(Uf;lo?c@kCOsS}_^`0Txj-iP3bidUFKfp_F zpw!80Q#sHfL5ou9M3)paCRv?GO$esRoI7zU(GpRJECKZfmT&g0eQfzn?4h<8atUj1 z4P4LMF@!QIluD9HjVI`O`?jy|g(8G)!SY>*7j}hG&n56oyXExyx^J=?Iei260c^Vl z(4&-6*^$n^(SfuaXx^sf>=GUz1tse{tfn!XGN!*bz#Lu-<>muyrw_Qlh%MpQXFYPeFhvXah3 zVtug8M$6LOQ7K3R8>`b$CK4{CX0rW`H-Or3u)QtE_I%y;rQO#BdO9%D+>KHv62saC z2K1d!$f9wf(bSenvXr+5+jnMYs34ST))JllE|`*F5&R7!Z(z%d*i$4o#sQU%anwc# zcQN#_r@Pyuj7W^)b)A9L=21o#8Opp~SfW2nW0 zmBU#^Dj+s=&ul4fhA#Jjb$Bu{fyC590t+?x6L<^m6v+lQE!u^luwbmLw!*PP!>Kxi z(jh4w<$Yy?g>3;tq>!YjNAT5r+a~-j?@eX*q@5eCus860(bci*Etq&qWI}2&#^`=c zENx8f*m0-`+)QHmsZvs9Qqtulnnxru3=Ak9QAQdZPQZu2?n`x7>xx_w+v&D&Y$#3) zilPq5BXmyAl-)1pIbs``B0JGDT0KD|bSqcwDlwKBALWFlZy46q233Kj$6-#3Smk&@ z9ORJ1;OQwZBIg_9liq5vqvQ<=qvQ6BwyFC@Jj2i=g@S)-fItgcleFUr%IpfSo&?W9 zj|sBVNbKEV?}N53KQl8u!%l+D$`iJOkvsO2kd?FmQiF8fCWg|wcSDq>B8m1cJ1^Yx zEG2ZQYlUjUtau_7g~cfWpCVH55v<~b33X>5!Bz>lLFXpkS;8);i0y$2}mY-DEX0Xm1k z8DVR2acyNug`P-i&S(fhdtN^`ouTE%D!^%m4t8jn2jvqvmr7TKSv;g=F$M#za~%*qhEWm8vR6AkU#RZi$f3 z#R#Ahg3##sJxsSZjXYy{I$K6|2H9!i0{9vI1mR5m) z#xqD&mXS*!SfSNIaS1uV>JpW!HQ<%2O_D~bRB5c%kbyiD&b3g&>?)6I)Zh}Q4wVu? zP_(+%oZ|=PQPPl@oYgS3GM$rnfI~=lPUVsE)Jt3`G#49~&kAyqGqk9kM^du3yg-xh z<3hIJIz8Sktk0;8(Zk~m)Fp7WfZWCN+cH57-;hj8*5wn^kqSWGKK6HShij}+N_y0C z+6LU7v}hDs5&(OB6VmMn8Y3~L_%cqb8mplXC5P7OzE0^4&!e=d%7%R9N;8GI46Z4D z;L53D8CRkzo5Ffr<^qk>-bY0aDhX&)<%L2<%VZXEnMaGI?9{?sW-3?Y(o8Ntmw$A2 zI-8lz%x3fD{4AbR`BFBMpT=9mzcS6{P|fCNfRvq`$!n-R%FkRbSDr!FdSFG6tc8=ly74Fk@c z7Sm}w#`#nQ@vpXm37w(`X`bd!(P=t;iq?@(wt9V9w+y@EcWE7&Y^%Rd>!wHRG6oA@ za5A)R8@sgbI=<@0Xg%a7s2L10{Hcfz&=g@5=}BBrBopnLibC9_)$|jOIJkd`*O}z9rC~SIz4fSM@Tm$kVoad}>TIko;Tidigu>0Fo zlsXRQHR<`=Gzphalh{;vIC$7js|zSL1WoqM7B(DC0!UC{8wV~zox6yLgxJ9*p~(%? z9|zg~zH4^6I7(=Zi)?0UZZez6W+p_z_R(_*d~$YZ&C@$L#fb^b_jII^DrG$#dl&J9 z(`SDMFAO%a?V{r(VD!KZcr?#w@kU$kwXi2wiq literal 64135 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 s8f9OWk@Hs@u;Z4Y(k èìÿ ðåçóëüòèðóþùåãî ôàéëà; ïî óìîë÷àíèþ, - ñîâïàäàåò ñ èìåíåì ãëàâíîãî ìîäóëÿ, íî ñ äðóãèì ðàñøèðåíèåì - (ñîîòâåòñòâóåò òèïó èñïîëíÿåìîãî ôàéëà) - -stk ðàçìåð ñòýêà â ìåãàáàéòàõ (ïî óìîë÷àíèþ 2 Ìá, - äîïóñòèìî îò 1 äî 32 Ìá) - -nochk <"ptibcwra"> îòêëþ÷èòü ïðîâåðêè ïðè âûïîëíåíèè (ñì. íèæå) - -ver âåðñèÿ ïðîãðàììû (òîëüêî äëÿ obj) - - ïàðàìåòð -nochk çàäàåòñÿ â âèäå ñòðîêè èç ñèìâîëîâ: - "p" - óêàçàòåëè - "t" - òèïû - "i" - èíäåêñû - "b" - íåÿâíîå ïðèâåäåíèå INTEGER ê BYTE - "c" - äèàïàçîí àðãóìåíòà ôóíêöèè CHR - "w" - äèàïàçîí àðãóìåíòà ôóíêöèè WCHR - "r" - ýêâèâàëåíòíî "bcw" - "a" - âñå ïðîâåðêè - - Ïîðÿäîê ñèìâîëîâ ìîæåò áûòü ëþáûì. Íàëè÷èå â ñòðîêå òîãî èëè èíîãî - ñèìâîëà îòêëþ÷àåò ñîîòâåòñòâóþùóþ ïðîâåðêó. - - Íàïðèìåð: -nochk it - îòêëþ÷èòü ïðîâåðêó èíäåêñîâ è îõðàíó òèïà. - -nochk a - îòêëþ÷èòü âñå îòêëþ÷àåìûå ïðîâåðêè. - - Íàïðèìåð: - - Compiler.exe "C:\example.ob07" console -out "C:\example.exe" -stk 1 - Compiler.exe "C:\example.ob07" dll -out "C:\example.dll" - Compiler.exe "C:\example.ob07" gui -out "C:\example.exe" -stk 4 - Compiler.exe "C:\example.ob07" console -out "C:\example.exe" -nochk pti - Compiler.kex "/tmp0/1/example.ob07" kos -out "/tmp0/1/example.kex" -stk 4 - Compiler.kex "/tmp0/1/example.ob07" obj -out "/tmp0/1/example.obj" -ver 2.7 - Compiler.exe "C:\example.ob07" elfexe -out "C:\example" -stk 1 -nochk a - -  ñëó÷àå óñïåøíîé êîìïèëÿöèè, êîìïèëÿòîð ïåðåäàåò êîä çàâåðøåíèÿ 0, èíà÷å 1. -Ïðè ðàáîòå êîìïèëÿòîðà â KolibriOS, êîä çàâåðøåíèÿ íå ïåðåäàåòñÿ. - ------------------------------------------------------------------------------- - Îòëè÷èÿ îò îðèãèíàëà - -1. Ðàñøèðåí ïñåâäîìîäóëü SYSTEM -2.  èäåíòèôèêàòîðàõ äîïóñêàåòñÿ ñèìâîë "_" -3. Äîáàâëåíû ñèñòåìíûå ôëàãè -4. Óñîâåðøåíñòâîâàí îïåðàòîð CASE (äîáàâëåíû êîíñòàíòíûå âûðàæåíèÿ â - ìåòêàõ âàðèàíòîâ è íåîáÿçàòåëüíàÿ âåòêà ELSE) -5. Ðàñøèðåí íàáîð ñòàíäàðòíûõ ïðîöåäóð -6. Ñåìàíòèêà îõðàíû/ïðîâåðêè òèïà óòî÷íåíà äëÿ íóëåâîãî óêàçàòåëÿ -7. Ñåìàíòèêà DIV è MOD óòî÷íåíà äëÿ îòðèöàòåëüíûõ ÷èñåë -8. Äîáàâëåíû îäíîñòðî÷íûå êîììåíòàðèè (íà÷èíàþòñÿ ñ ïàðû ñèìâîëîâ "//") -9. Ðàçðåøåíî íàñëåäîâàíèå îò òèïà-óêàçàòåëÿ -10. Äîáàâëåí ñèíòàêñèñ äëÿ èìïîðòà ïðîöåäóð èç âíåøíèõ áèáëèîòåê -11. "Ñòðîêè" ìîæíî çàêëþ÷àòü òàêæå â îäèíî÷íûå êàâû÷êè: 'ñòðîêà' -12. Äîáàâëåí òèï WCHAR - ------------------------------------------------------------------------------- - Îñîáåííîñòè ðåàëèçàöèè - -1. Îñíîâíûå òèïû - - Òèï Äèàïàçîí çíà÷åíèé Ðàçìåð, áàéò - - INTEGER -2147483648 .. 2147483647 4 - REAL 4.94E-324 .. 1.70E+308 8 - CHAR ñèìâîë ASCII (0X .. 0FFX) 1 - BOOLEAN FALSE, TRUE 1 - SET ìíîæåñòâî èç öåëûõ ÷èñåë {0 .. 31} 4 - BYTE 0 .. 255 1 - WCHAR ñèìâîë þíèêîäà (0X .. 0FFFFX) 2 - -2. Ìàêñèìàëüíàÿ äëèíà èäåíòèôèêàòîðîâ - 1024 ñèìâîëîâ -3. Ìàêñèìàëüíàÿ äëèíà ñòðîêîâûõ êîíñòàíò - 1024 ñèìâîëîâ (UTF-8) -4. Ìàêñèìàëüíàÿ ðàçìåðíîñòü îòêðûòûõ ìàññèâîâ - 5 -5. Ïðîöåäóðà NEW çàïîëíÿåò íóëÿìè âûäåëåííûé áëîê ïàìÿòè -6. Ãëîáàëüíûå è ëîêàëüíûå ïåðåìåííûå èíèöèàëèçèðóþòñÿ íóëÿìè -7.  îòëè÷èå îò ìíîãèõ Oberon-ðåàëèçàöèé, ñáîðùèê ìóñîðà è äèíàìè÷åñêàÿ - ìîäóëüíîñòü îòñóòñòâóþò -8. Òèï BYTE â âûðàæåíèÿõ âñåãäà ïðèâîäèòñÿ ê INTEGER -9. Êîíòðîëü ïåðåïîëíåíèÿ çíà÷åíèé âûðàæåíèé íå ïðîèçâîäèòñÿ -10. Îøèáêè âðåìåíè âûïîëíåíèÿ: - - - ASSERT(x), ïðè x = FALSE - - ðàçûìåíîâàíèå íóëåâîãî óêàçàòåëÿ - - öåëî÷èñëåííîå äåëåíèå íà 0 - - âûçîâ ïðîöåäóðû ÷åðåç ïðîöåäóðíóþ ïåðåìåííóþ ñ íóëåâûì çíà÷åíèåì - - îøèáêà îõðàíû òèïà - - íàðóøåíèå ãðàíèö ìàññèâà - - íåïðåäóñìîòðåííîå çíà÷åíèå âûðàæåíèÿ â îïåðàòîðå CASE - - îøèáêà êîïèðîâàíèÿ ìàññèâîâ v := x, åñëè LEN(v) < LEN(x) - - íåÿâíîå ïðèâåäåíèå x:INTEGER ê v:BYTE, åñëè (x < 0) OR (x > 255) - - CHR(x), åñëè (x < 0) OR (x > 255) - - WCHR(x), åñëè (x < 0) OR (x > 65535) - ------------------------------------------------------------------------------- - Ïñåâäîìîäóëü SYSTEM - - Ïñåâäîìîäóëü SYSTEM ñîäåðæèò íèçêîóðîâíåâûå è íåáåçîïàñíûå ïðîöåäóðû, -îøèáêè ïðè èñïîëüçîâàíèè ïðîöåäóð ïñåâäîìîäóëÿ SYSTEM ìîãóò ïðèâåñòè ê -ïîâðåæäåíèþ äàííûõ âðåìåíè âûïîëíåíèÿ è àâàðèéíîìó çàâåðøåíèþ ïðîãðàììû. - - PROCEDURE ADR(v: ëþáîé òèï): INTEGER - v - ïåðåìåííàÿ èëè ïðîöåäóðà; - âîçâðàùàåò àäðåñ v - - PROCEDURE SADR(x: ñòðîêîâàÿ êîíñòàíòà (CHAR UTF-8)): INTEGER - âîçâðàùàåò àäðåñ x - - PROCEDURE WSADR(x: ñòðîêîâàÿ êîíñòàíòà (WCHAR)): INTEGER - âîçâðàùàåò àäðåñ x - - PROCEDURE SIZE(T): INTEGER - âîçâðàùàåò ðàçìåð òèïà T - - PROCEDURE TYPEID(T): INTEGER - T - òèï-çàïèñü èëè òèï-óêàçàòåëü, - âîçâðàùàåò íîìåð òèïà â òàáëèöå òèïîâ-çàïèñåé - - PROCEDURE INF(): REAL - âîçâðàùàåò ñïåöèàëüíîå âåùåñòâåííîå çíà÷åíèå "áåñêîíå÷íîñòü" - - PROCEDURE GET(a: INTEGER; - VAR v: ëþáîé îñíîâíîé òèï, PROCEDURE, POINTER) - v := Ïàìÿòü[a] - - PROCEDURE PUT(a: INTEGER; x: ëþáîé îñíîâíîé òèï, PROCEDURE, POINTER) - Ïàìÿòü[a] := x; - Åñëè x: BYTE èëè x: WCHAR, òî çíà÷åíèå x áóäåò ðàñøèðåíî - äî 32 áèò, äëÿ çàïèñè áàéòîâ èñïîëüçîâàòü SYSTEM.PUT8, - äëÿ WCHAR -- SYSTEM.PUT16 - - PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) - Ïàìÿòü[a] := ìëàäøèå 8 áèò (x) - - PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) - Ïàìÿòü[a] := ìëàäøèå 16 áèò (x) - - PROCEDURE MOVE(Source, Dest, n: INTEGER) - Êîïèðóåò n áàéò ïàìÿòè èç Source â Dest, - îáëàñòè Source è Dest íå ìîãóò ïåðåêðûâàòüñÿ - - PROCEDURE COPY(VAR Source: ëþáîé òèï; VAR Dest: ëþáîé òèï; n: INTEGER) - Êîïèðóåò n áàéò ïàìÿòè èç Source â Dest. - Ýêâèâàëåíòíî - SYSTEM.MOVE(SYSTEM.ADR(Source), SYSTEM.ADR(Dest), n) - - PROCEDURE CODE(byte1, byte2,... : INTEGER) - Âñòàâêà ìàøèííîãî êîäà, - byte1, byte2 ... - êîíñòàíòû â äèàïàçîíå 0..255, - íàïðèìåð: - SYSTEM.CODE(08BH, 045H, 008H) (* mov eax, dword [ebp + 08h] *) - - - Ôóíêöèè ïñåâäîìîäóëÿ SYSTEM íåëüçÿ èñïîëüçîâàòü â êîíñòàíòíûõ âûðàæåíèÿõ. - ------------------------------------------------------------------------------- - Ñèñòåìíûå ôëàãè - - Ïðè îáúÿâëåíèè ïðîöåäóðíûõ òèïîâ è ãëîáàëüíûõ ïðîöåäóð, ïîñëå êëþ÷åâîãî -ñëîâà PROCEDURE ìîæåò áûòü óêàçàí ôëàã ñîãëàøåíèÿ î âûçîâå: [stdcall], -[ccall], [ccall16], [windows], [linux]. Íàïðèìåð: - - PROCEDURE [ccall] MyProc (x, y, z: INTEGER): INTEGER; - - Åñëè óêàçàí ôëàã [ccall16], òî ïðèíèìàåòñÿ ñîãëàøåíèå ccall, íî ïåðåä -âûçîâîì óêàçàòåëü ñòýêà áóäåò âûðàâíåí ïî ãðàíèöå 16 áàéò. - Ôëàã [windows] - ñèíîíèì äëÿ [stdcall], [linux] - ñèíîíèì äëÿ [ccall16]. - Çíàê "-" ïîñëå èìåíè ôëàãà ([stdcall-], [linux-], ...) îçíà÷àåò, ÷òî -ðåçóëüòàò ïðîöåäóðû ìîæíî èãíîðèðîâàòü (íå äîïóñêàåòñÿ äëÿ òèïà REAL). - - Ïðè îáúÿâëåíèè òèïîâ-çàïèñåé, ïîñëå êëþ÷åâîãî ñëîâà RECORD ìîæåò áûòü -óêàçàí ôëàã [noalign]. Ôëàã [noalign] îçíà÷àåò îòñóòñòâèå âûðàâíèâàíèÿ ïîëåé -çàïèñè. Çàïèñè ñ ñèñòåìíûì ôëàãîì íå ìîãóò èìåòü áàçîâûé òèï è íå ìîãóò áûòü -áàçîâûìè òèïàìè äëÿ äðóãèõ çàïèñåé. - Äëÿ èñïîëüçîâàíèÿ ñèñòåìíûõ ôëàãîâ, òðåáóåòñÿ èìïîðòèðîâàòü SYSTEM. - ------------------------------------------------------------------------------- - Îïåðàòîð CASE - - Ñèíòàêñèñ îïåðàòîðà CASE: - - CaseStatement = - CASE Expression OF Ñase {"|" Ñase} - [ELSE StatementSequence] END. - Case = [CaseLabelList ":" StatementSequence]. - CaseLabelList = CaseLabels {"," CaseLabels}. - CaseLabels = ConstExpression [".." ConstExpression]. - - Íàïðèìåð: - - CASE x OF - |-1: DoSomething1 - | 1: DoSomething2 - | 0: DoSomething3 - ELSE - DoSomething4 - END - -  ìåòêàõ âàðèàíòîâ ìîæíî èñïîëüçîâàòü êîíñòàíòíûå âûðàæåíèÿ, âåòêà ELSE -íåîáÿçàòåëüíà. Åñëè çíà÷åíèå x íå ñîîòâåòñòâóåò íè îäíîìó âàðèàíòó è ELSE -îòñóòñòâóåò, òî ïðîãðàììà ïðåðûâàåòñÿ ñ îøèáêîé âðåìåíè âûïîëíåíèÿ. - ------------------------------------------------------------------------------- - Òèï WCHAR - - Òèï WCHAR äîáàâëåí â ÿçûê äëÿ óäîáíîé ïîääåæêè þíèêîäà. Äëÿ òèïîâ WCHAR è -ARRAY OF WCHAR äîïóñêàþòñÿ âñå òå æå îïåðàöèè, êàê äëÿ òèïîâ CHAR è -ARRAY OF CHAR, çà èñêëþ÷åíèåì âñòðîåííîé ïðîöåäóðû CHR, êîòîðàÿ âîçâðàùàåò -òîëüêî òèï CHAR. Äëÿ ïîëó÷åíèÿ çíà÷åíèÿ òèïà WCHAR, ñëåäóåò èñïîëüçîâàòü -ïðîöåäóðó WCHR âìåñòî CHR. Äëÿ ïðàâèëüíîé ðàáîòû ñ òèïîì, íåîáõîäèìî ñîõðàíÿòü -èñõîäíûé êîä â êîäèðîâêå UTF-8 c BOM. - ------------------------------------------------------------------------------- - Ïðîâåðêà è îõðàíà òèïà íóëåâîãî óêàçàòåëÿ - - Îðèãèíàëüíîå ñîîáùåíèå î ÿçûêå íå îïðåäåëÿåò ïîâåäåíèå ïðîãðàììû ïðè -âûïîëíåíèè îõðàíû p(T) è ïðîâåðêè òèïà p IS T ïðè p = NIL. Âî ìíîãèõ -Oberon-ðåàëèçàöèÿõ âûïîëíåíèå òàêîé îïåðàöèè ïðèâîäèò ê îøèáêå âðåìåíè -âûïîëíåíèÿ.  äàííîé ðåàëèçàöèè îõðàíà òèïà íóëåâîãî óêàçàòåëÿ íå ïðèâîäèò ê -îøèáêå, à ïðîâåðêà òèïà äàåò ðåçóëüòàò FALSE.  ðÿäå ñëó÷àåâ ýòî ïîçâîëÿåò -çíà÷èòåëüíî ñîêðàòèòü ÷àñòîòó ïðèìåíåíèÿ îõðàíû òèïà. - ------------------------------------------------------------------------------- - Äîïîëíèòåëüíûå ñòàíäàðòíûå ïðîöåäóðû - - DISPOSE (VAR v: ëþáîé_óêàçàòåëü) - Îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ ïðîöåäóðîé NEW äëÿ - äèíàìè÷åñêîé ïåðåìåííîé v^, è ïðèñâàèâàåò ïåðåìåííîé v - çíà÷åíèå NIL. - - COPY (x: ARRAY OF CHAR/WCHAR; VAR v: ARRAY OF CHAR/WCHAR); - v := x; - Åñëè LEN(v) < LEN(x), òî ñòðîêà x áóäåò ñêîïèðîâàíà - íå ïîëíîñòüþ - - LSR (x, n: INTEGER): INTEGER - Ëîãè÷åñêèé ñäâèã x íà n áèò âïðàâî. - - MIN (a, b: INTEGER): INTEGER - Ìèíèìóì èç äâóõ çíà÷åíèé. - - MAX (a, b: INTEGER): INTEGER - Ìàêñèìóì èç äâóõ çíà÷åíèé. - - BITS (x: INTEGER): SET - Èíòåðïðåòèðóåò x êàê çíà÷åíèå òèïà SET. - Âûïîëíÿåòñÿ íà ýòàïå êîìïèëÿöèè. - - LENGTH (s: ARRAY OF CHAR/WCHAR): INTEGER - Äëèíà 0X-çàâåðøåííîé ñòðîêè s, áåç ó÷åòà ñèìâîëà 0X. - Åñëè ñèìâîë 0X îòñóòñòâóåò, ôóíêöèÿ âîçâðàùàåò äëèíó - ìàññèâà s. s íå ìîæåò áûòü êîíñòàíòîé. - - WCHR (n: INTEGER): WCHAR - Ïðåîáðàçîâàíèå òèïà, àíàëîãè÷íî CHR(n: INTEGER): CHAR - ------------------------------------------------------------------------------- - DIV è MOD - - x y x DIV y x MOD y - - 5 3 1 2 - -5 3 -2 1 - 5 -3 -2 -1 - -5 -3 1 -2 - ------------------------------------------------------------------------------- - Èìïîðòèðîâàííûå ïðîöåäóðû - - Ñèíòàêñèñ èìïîðòà: - - PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type; - - - callconv -- ñîãëàøåíèå î âûçîâå - - "library" -- èìÿ ôàéëà äèíàìè÷åñêîé áèáëèîòåêè - - "function" -- èìÿ èìïîðòèðóåìîé ïðîöåäóðû - - íàïðèìåð: - - PROCEDURE [windows, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); - - PROCEDURE [stdcall, "Console.obj", "con_exit"] exit (bCloseWindow: BOOLEAN); - -  êîíöå îáúÿâëåíèÿ ìîæåò áûòü äîáàâëåíî (íåîáÿçàòåëüíî) "END proc_name;" - - Îáúÿâëåíèÿ èìïîðòèðîâàííûõ ïðîöåäóð äîëæíû ðàñïîëàãàòüñÿ â ãëîáàëüíîé - îáëàñòè âèäèìîñòè ìîäóëÿ ïîñëå îáúÿâëåíèÿ ïåðåìåííûõ, âìåñòå ñ îáúÿâëåíèåì - "îáû÷íûõ" ïðîöåäóð, îò êîòîðûõ èìïîðòèðîâàííûå îòëè÷àþòñÿ òîëüêî îòñóòñòâèåì - òåëà ïðîöåäóðû.  îñòàëüíîì, ê òàêèì ïðîöåäóðàì ïðèìåíèìû òå æå ïðàâèëà: - èõ ìîæíî âûçâàòü, ïðèñâîèòü ïðîöåäóðíîé ïåðåìåííîé èëè ïîëó÷èòü àäðåñ. - - Òàê êàê èìïîðòèðîâàííàÿ ïðîöåäóðà âñåãäà èìååò ÿâíîå óêàçàíèå ñîãëàøåíèÿ î - âûçîâå, òî ñîâìåñòèìûé ïðîöåäóðíûé òèï òîæå äîëæåí áûòü îáúÿâëåí ñ óêàçàíèåì - ñîãëàøåíèÿ î âûçîâå: - - VAR - ExitProcess: PROCEDURE [windows] (code: INTEGER); - con_exit: PROCEDURE [stdcall] (bCloseWindow: BOOLEAN); - -  KolibriOS èìïîðòèðîâàòü ïðîöåäóðû ìîæíî òîëüêî èç áèáëèîòåê, ðàçìåùåííûõ - â /rd/1/lib. Èìïîðòèðîâàòü è âûçûâàòü ôóíêöèè èíèöèàëèçàöèè áèáëèîòåê - (lib_init, START) ïðè ýòîì íå íóæíî. - - Äëÿ Linux, èìïîðòèðîâàííûå ïðîöåäóðû íå ðåàëèçîâàíû. - ------------------------------------------------------------------------------- - Ñêðûòûå ïàðàìåòðû ïðîöåäóð - - Íåêîòîðûå ïðîöåäóðû ìîãóò èìåòü ñêðûòûå ïàðàìåòðû, îíè îòñóòñòâóþò â ñïèñêå -ôîðìàëüíûõ ïàðàìåòðîâ, íî ó÷èòûâàþòñÿ êîìïèëÿòîðîì ïðè òðàíñëÿöèè âûçîâîâ. -Ýòî âîçìîæíî â ñëåäóþùèõ ñëó÷àÿõ: - -1. Ïðîöåäóðà èìååò ôîðìàëüíûé ïàðàìåòð îòêðûòûé ìàññèâ: - PROCEDURE Proc (x: ARRAY OF ARRAY OF REAL); - Âûçîâ òðàíñëèðóåòñÿ òàê: - Proc(LEN(x), LEN(x[0]), SYSTEM.ADR(x)) -2. Ïðîöåäóðà èìååò ôîðìàëüíûé ïàðàìåòð-ïåðåìåííóþ òèïà RECORD: - PROCEDURE Proc (VAR x: Rec); - Âûçîâ òðàíñëèðóåòñÿ òàê: - Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) - ------------------------------------------------------------------------------- - Ìîäóëü RTL - - Âñå ïðîãðàììû íåÿâíî èñïîëüçóþò ìîäóëü RTL. Êîìïèëÿòîð òðàíñëèðóåò -íåêîòîðûå îïåðàöèè (ïðîâåðêà è îõðàíà òèïà, ñðàâíåíèå ñòðîê, ñîîáùåíèÿ îá -îøèáêàõ âðåìåíè âûïîëíåíèÿ è äð.) êàê âûçîâû ïðîöåäóð ýòîãî ìîäóëÿ. Íå -ñëåäóåò ÿâíî âûçûâàòü ýòè ïðîöåäóðû, çà èñêëþ÷åíèåì ïðîöåäóð SetDll è SetFini -åñëè ïðèëîæåíèå êîìïèëèðóåòñÿ êàê Windows DLL èëè Linux SO, ñîîòâåòñòâåííî: - - PROCEDURE SetDll - (process_detach, thread_detach, thread_attach: DLL_ENTRY); - ãäå TYPE DLL_ENTRY = - PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); - -SetDll íàçíà÷àåò ïðîöåäóðû process_detach, thread_detach, thread_attach -âûçûâàåìûìè ïðè -- âûãðóçêå dll-áèáëèîòåêè (process_detach) -- ñîçäàíèè íîâîãî ïîòîêà (thread_attach) -- óíè÷òîæåíèè ïîòîêà (thread_detach) - - - PROCEDURE SetFini (ProcFini: PROC); - ãäå TYPE PROC = PROCEDURE (* áåç ïàðàìåòðîâ *) - -SetFini íàçíà÷àåò ïðîöåäóðó ProcFini âûçûâàåìîé ïðè âûãðóçêå so-áèáëèîòåêè. - -Äëÿ ïðî÷èõ òèïîâ ïðèëîæåíèé, âûçîâ ïðîöåäóð SetDll è SetFini íå âëèÿåò íà -ïîâåäåíèå ïðîãðàììû. - - Ñîîáùåíèÿ îá îøèáêàõ âðåìåíè âûïîëíåíèÿ âûâîäÿòñÿ â äèàëîãîâûõ îêíàõ -(Windows), â òåðìèíàë (Linux), íà äîñêó îòëàäêè (KolibriOS). - ------------------------------------------------------------------------------- - Ìîäóëü API - - Ñóùåñòâóþò íåñêîëüêî ðåàëèçàöèé ìîäóëÿ API (äëÿ ðàçëè÷íûõ ÎÑ). - Êàê è ìîäóëü RTL, ìîäóëü API íå ïðåäíàçíà÷åí äëÿ ïðÿìîãî èñïîëüçîâàíèÿ. -Îí îáåñïå÷èâàåò ñâÿçü RTL ñ ÎÑ. - ------------------------------------------------------------------------------- - Ãåíåðàöèÿ èñïîëíÿåìûõ ôàéëîâ DLL - - Ðàçðåøàåòñÿ ýêñïîðòèðîâàòü òîëüêî ïðîöåäóðû. Äëÿ ýòîãî, ïðîöåäóðà äîëæíà -íàõîäèòüñÿ â ãëàâíîì ìîäóëå ïðîãðàììû, è åå èìÿ äîëæíî áûòü îòìå÷åíî ñèìâîëîì -ýêñïîðòà ("*"). KolibriOS DLL âñåãäà ýêñïîðòèðóþò èäåíòèôèêàòîðû "version" -(âåðñèÿ ïðîãðàììû) è "lib_init" - àäðåñ ïðîöåäóðû èíèöèàëèçàöèè DLL: - - PROCEDURE [stdcall] lib_init (): INTEGER - -Ýòà ïðîöåäóðà äîëæíà áûòü âûçâàíà ïåðåä èñïîëüçîâàíèåì DLL. -Ïðîöåäóðà âñåãäà âîçâðàùàåò 1. \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/About866.txt b/programs/develop/oberon07/Docs/About866.txt deleted file mode 100644 index 55dc8f9e0b..0000000000 --- a/programs/develop/oberon07/Docs/About866.txt +++ /dev/null @@ -1,390 +0,0 @@ - Š®¬¯¨«ïâ®à ï§ëª  ¯à®£à ¬¬¨à®¢ ­¨ï Oberon-07/16 ¤«ï i486 - Windows/Linux/KolibriOS. ------------------------------------------------------------------------------- - -  à ¬¥âàë ª®¬ ­¤­®© áâப¨ - - ‚室 - ⥪áâ®¢ë¥ ä ©«ë ¬®¤ã«¥© á à áè¨à¥­¨¥¬ ".ob07", ª®¤¨à®¢ª  ANSI ¨«¨ -UTF-8 á BOM-ᨣ­ âãன. - ‚ë室 - ¨á¯®­ï¥¬ë© ä ©« ä®à¬ â  PE32, ELF ¨«¨ MENUET01/MSCOFF. -  à ¬¥âàë: - 1) ¨¬ï £« ¢­®£® ¬®¤ã«ï - 2) ⨯ ¯à¨«®¦¥­¨ï - "console" - Windows console - "gui" - Windows GUI - "dll" - Windows DLL - "kos" - KolibriOS - "obj" - KolibriOS DLL - "elfexe" - Linux ELF-EXEC - "elfso" - Linux ELF-SO - 3) ­¥®¡ï§ â¥«ì­ë¥ ¯ à ¬¥âàë-ª«îç¨ - -out ¨¬ï १ã«ìâ¨àãî饣® ä ©« ; ¯® 㬮«ç ­¨î, - ᮢ¯ ¤ ¥â á ¨¬¥­¥¬ £« ¢­®£® ¬®¤ã«ï, ­® á ¤à㣨¬ à áè¨à¥­¨¥¬ - (ᮮ⢥âáâ¢ã¥â ⨯㠨ᯮ«­ï¥¬®£® ä ©« ) - -stk à §¬¥à áâíª  ¢ ¬¥£ ¡ ©â å (¯® 㬮«ç ­¨î 2 Œ¡, - ¤®¯ãá⨬® ®â 1 ¤® 32 Œ¡) - -nochk <"ptibcwra"> ®âª«îç¨âì ¯à®¢¥àª¨ ¯à¨ ¢ë¯®«­¥­¨¨ (á¬. ­¨¦¥) - -ver ¢¥àá¨ï ¯à®£à ¬¬ë (⮫쪮 ¤«ï obj) - - ¯ à ¬¥âà -nochk § ¤ ¥âáï ¢ ¢¨¤¥ áâப¨ ¨§ ᨬ¢®«®¢: - "p" - 㪠§ â¥«¨ - "t" - ⨯ë - "i" - ¨­¤¥ªáë - "b" - ­¥ï¢­®¥ ¯à¨¢¥¤¥­¨¥ INTEGER ª BYTE - "c" - ¤¨ ¯ §®­  à£ã¬¥­â  ä㭪樨 CHR - "w" - ¤¨ ¯ §®­  à£ã¬¥­â  ä㭪樨 WCHR - "r" - íª¢¨¢ «¥­â­® "bcw" - "a" - ¢á¥ ¯à®¢¥àª¨ - - ®à冷ª ᨬ¢®«®¢ ¬®¦¥â ¡ëâì «î¡ë¬.  «¨ç¨¥ ¢ áâப¥ ⮣® ¨«¨ ¨­®£® - ᨬ¢®«  ®âª«îç ¥â ᮮ⢥âáâ¢ãîéãî ¯à®¢¥àªã. - -  ¯à¨¬¥à: -nochk it - ®âª«îç¨âì ¯à®¢¥àªã ¨­¤¥ªá®¢ ¨ ®åà ­ã ⨯ . - -nochk a - ®âª«îç¨âì ¢á¥ ®âª«îç ¥¬ë¥ ¯à®¢¥àª¨. - -  ¯à¨¬¥à: - - Compiler.exe "C:\example.ob07" console -out "C:\example.exe" -stk 1 - Compiler.exe "C:\example.ob07" dll -out "C:\example.dll" - Compiler.exe "C:\example.ob07" gui -out "C:\example.exe" -stk 4 - Compiler.exe "C:\example.ob07" console -out "C:\example.exe" -nochk pti - Compiler.kex "/tmp0/1/example.ob07" kos -out "/tmp0/1/example.kex" -stk 4 - Compiler.kex "/tmp0/1/example.ob07" obj -out "/tmp0/1/example.obj" -ver 2.7 - Compiler.exe "C:\example.ob07" elfexe -out "C:\example" -stk 1 -nochk a - - ‚ á«ãç ¥ ãᯥ譮© ª®¬¯¨«ï樨, ª®¬¯¨«ïâ®à ¯¥à¥¤ ¥â ª®¤ § ¢¥à襭¨ï 0, ¨­ ç¥ 1. -ਠࠡ®â¥ ª®¬¯¨«ïâ®à  ¢ KolibriOS, ª®¤ § ¢¥à襭¨ï ­¥ ¯¥à¥¤ ¥âáï. - ------------------------------------------------------------------------------- - Žâ«¨ç¨ï ®â ®à¨£¨­ «  - -1.  áè¨à¥­ ¯á¥¢¤®¬®¤ã«ì SYSTEM -2. ‚ ¨¤¥­â¨ä¨ª â®à å ¤®¯ã᪠¥âáï ᨬ¢®« "_" -3. „®¡ ¢«¥­ë á¨á⥬­ë¥ ä« £¨ -4. “ᮢ¥à襭á⢮¢ ­ ®¯¥à â®à CASE (¤®¡ ¢«¥­ë ª®­áâ ­â­ë¥ ¢ëà ¦¥­¨ï ¢ - ¬¥âª å ¢ à¨ ­â®¢ ¨ ­¥®¡ï§ â¥«ì­ ï ¢¥âª  ELSE) -5.  áè¨à¥­ ­ ¡®à áâ ­¤ àâ­ëå ¯à®æ¥¤ãà -6. ‘¥¬ ­â¨ª  ®åà ­ë/¯à®¢¥àª¨ ⨯  ãâ®ç­¥­  ¤«ï ­ã«¥¢®£® 㪠§ â¥«ï -7. ‘¥¬ ­â¨ª  DIV ¨ MOD ãâ®ç­¥­  ¤«ï ®âà¨æ â¥«ì­ëå ç¨á¥« -8. „®¡ ¢«¥­ë ®¤­®áâà®ç­ë¥ ª®¬¬¥­â à¨¨ (­ ç¨­ îâáï á ¯ àë ᨬ¢®«®¢ "//") -9.  §à¥è¥­® ­ á«¥¤®¢ ­¨¥ ®â ⨯ -㪠§ â¥«ï -10. „®¡ ¢«¥­ ᨭ⠪á¨á ¤«ï ¨¬¯®àâ  ¯à®æ¥¤ãà ¨§ ¢­¥è­¨å ¡¨¡«¨®â¥ª -11. "‘âப¨" ¬®¦­® § ª«îç âì â ª¦¥ ¢ ®¤¨­®ç­ë¥ ª ¢ë窨: 'áâப ' -12. „®¡ ¢«¥­ ⨯ WCHAR - ------------------------------------------------------------------------------- - Žá®¡¥­­®á⨠ॠ«¨§ æ¨¨ - -1. Žá­®¢­ë¥ ⨯ë - - ’¨¯ „¨ ¯ §®­ §­ ç¥­¨©  §¬¥à, ¡ ©â - - INTEGER -2147483648 .. 2147483647 4 - REAL 4.94E-324 .. 1.70E+308 8 - CHAR ᨬ¢®« ASCII (0X .. 0FFX) 1 - BOOLEAN FALSE, TRUE 1 - SET ¬­®¦¥á⢮ ¨§ 楫ëå ç¨á¥« {0 .. 31} 4 - BYTE 0 .. 255 1 - WCHAR ᨬ¢®« î­¨ª®¤  (0X .. 0FFFFX) 2 - -2. Œ ªá¨¬ «ì­ ï ¤«¨­  ¨¤¥­â¨ä¨ª â®à®¢ - 1024 ᨬ¢®«®¢ -3. Œ ªá¨¬ «ì­ ï ¤«¨­  áâப®¢ëå ª®­áâ ­â - 1024 ᨬ¢®«®¢ (UTF-8) -4. Œ ªá¨¬ «ì­ ï à §¬¥à­®áâì ®âªàëâëå ¬ áᨢ®¢ - 5 -5. à®æ¥¤ãà  NEW § ¯®«­ï¥â ­ã«ï¬¨ ¢ë¤¥«¥­­ë© ¡«®ª ¯ ¬ï⨠-6. ƒ«®¡ «ì­ë¥ ¨ «®ª «ì­ë¥ ¯¥à¥¬¥­­ë¥ ¨­¨æ¨ «¨§¨àãîâáï ­ã«ï¬¨ -7. ‚ ®â«¨ç¨¥ ®â ¬­®£¨å Oberon-ॠ«¨§ æ¨©, á¡®à騪 ¬ãá®à  ¨ ¤¨­ ¬¨ç¥áª ï - ¬®¤ã«ì­®áâì ®âáãâáâ¢ãîâ -8. ’¨¯ BYTE ¢ ¢ëà ¦¥­¨ïå ¢á¥£¤  ¯à¨¢®¤¨âáï ª INTEGER -9. Š®­âà®«ì ¯¥à¥¯®«­¥­¨ï §­ ç¥­¨© ¢ëà ¦¥­¨© ­¥ ¯à®¨§¢®¤¨âáï -10. Žè¨¡ª¨ ¢à¥¬¥­¨ ¢ë¯®«­¥­¨ï: - - - ASSERT(x), ¯à¨ x = FALSE - - ࠧ묥­®¢ ­¨¥ ­ã«¥¢®£® 㪠§ â¥«ï - - 楫®ç¨á«¥­­®¥ ¤¥«¥­¨¥ ­  0 - - ¢ë§®¢ ¯à®æ¥¤ãàë ç¥à¥§ ¯à®æ¥¤ãà­ãî ¯¥à¥¬¥­­ãî á ­ã«¥¢ë¬ §­ ç¥­¨¥¬ - - ®è¨¡ª  ®åà ­ë ⨯  - - ­ àã襭¨¥ £à ­¨æ ¬ áᨢ  - - ­¥¯à¥¤ãᬮâ७­®¥ §­ ç¥­¨¥ ¢ëà ¦¥­¨ï ¢ ®¯¥à â®à¥ CASE - - ®è¨¡ª  ª®¯¨à®¢ ­¨ï ¬ áᨢ®¢ v := x, ¥á«¨ LEN(v) < LEN(x) - - ­¥ï¢­®¥ ¯à¨¢¥¤¥­¨¥ x:INTEGER ª v:BYTE, ¥á«¨ (x < 0) OR (x > 255) - - CHR(x), ¥á«¨ (x < 0) OR (x > 255) - - WCHR(x), ¥á«¨ (x < 0) OR (x > 65535) - ------------------------------------------------------------------------------- - ᥢ¤®¬®¤ã«ì SYSTEM - - ᥢ¤®¬®¤ã«ì SYSTEM ᮤ¥à¦¨â ­¨§ª®ã஢­¥¢ë¥ ¨ ­¥¡¥§®¯ á­ë¥ ¯à®æ¥¤ãàë, -®è¨¡ª¨ ¯à¨ ¨á¯®«ì§®¢ ­¨¨ ¯à®æ¥¤ãà ¯á¥¢¤®¬®¤ã«ï SYSTEM ¬®£ã⠯ਢ¥á⨠ª -¯®¢à¥¦¤¥­¨î ¤ ­­ëå ¢à¥¬¥­¨ ¢ë¯®«­¥­¨ï ¨  ¢ à¨©­®¬ã § ¢¥à襭¨î ¯à®£à ¬¬ë. - - PROCEDURE ADR(v: «î¡®© ⨯): INTEGER - v - ¯¥à¥¬¥­­ ï ¨«¨ ¯à®æ¥¤ãà ; - ¢®§¢à é ¥â  ¤à¥á v - - PROCEDURE SADR(x: áâப®¢ ï ª®­áâ ­â  (CHAR UTF-8)): INTEGER - ¢®§¢à é ¥â  ¤à¥á x - - PROCEDURE WSADR(x: áâப®¢ ï ª®­áâ ­â  (WCHAR)): INTEGER - ¢®§¢à é ¥â  ¤à¥á x - - PROCEDURE SIZE(T): INTEGER - ¢®§¢à é ¥â à §¬¥à ⨯  T - - PROCEDURE TYPEID(T): INTEGER - T - ⨯-§ ¯¨áì ¨«¨ ⨯-㪠§ â¥«ì, - ¢®§¢à é ¥â ­®¬¥à ⨯  ¢ â ¡«¨æ¥ ⨯®¢-§ ¯¨á¥© - - PROCEDURE INF(): REAL - ¢®§¢à é ¥â ᯥ樠«ì­®¥ ¢¥é¥á⢥­­®¥ §­ ç¥­¨¥ "¡¥áª®­¥ç­®áâì" - - PROCEDURE GET(a: INTEGER; - VAR v: «î¡®© ®á­®¢­®© ⨯, PROCEDURE, POINTER) - v :=  ¬ïâì[a] - - PROCEDURE PUT(a: INTEGER; x: «î¡®© ®á­®¢­®© ⨯, PROCEDURE, POINTER) -  ¬ïâì[a] := x; - …᫨ x: BYTE ¨«¨ x: WCHAR, â® §­ ç¥­¨¥ x ¡ã¤¥â à áè¨à¥­® - ¤® 32 ¡¨â, ¤«ï § ¯¨á¨ ¡ ©â®¢ ¨á¯®«ì§®¢ âì SYSTEM.PUT8, - ¤«ï WCHAR -- SYSTEM.PUT16 - - PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) -  ¬ïâì[a] := ¬« ¤è¨¥ 8 ¡¨â (x) - - PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) -  ¬ïâì[a] := ¬« ¤è¨¥ 16 ¡¨â (x) - - PROCEDURE MOVE(Source, Dest, n: INTEGER) - Š®¯¨àã¥â n ¡ ©â ¯ ¬ï⨠¨§ Source ¢ Dest, - ®¡« á⨠Source ¨ Dest ­¥ ¬®£ãâ ¯¥à¥ªà뢠âìáï - - PROCEDURE COPY(VAR Source: «î¡®© ⨯; VAR Dest: «î¡®© ⨯; n: INTEGER) - Š®¯¨àã¥â n ¡ ©â ¯ ¬ï⨠¨§ Source ¢ Dest. - ª¢¨¢ «¥­â­® - SYSTEM.MOVE(SYSTEM.ADR(Source), SYSTEM.ADR(Dest), n) - - PROCEDURE CODE(byte1, byte2,... : INTEGER) - ‚áâ ¢ª  ¬ è¨­­®£® ª®¤ , - byte1, byte2 ... - ª®­áâ ­âë ¢ ¤¨ ¯ §®­¥ 0..255, - ­ ¯à¨¬¥à: - SYSTEM.CODE(08BH, 045H, 008H) (* mov eax, dword [ebp + 08h] *) - - - ”㭪樨 ¯á¥¢¤®¬®¤ã«ï SYSTEM ­¥«ì§ï ¨á¯®«ì§®¢ âì ¢ ª®­áâ ­â­ëå ¢ëà ¦¥­¨ïå. - ------------------------------------------------------------------------------- - ‘¨á⥬­ë¥ ä« £¨ - - ਠ®¡ê¥­¨¨ ¯à®æ¥¤ãà­ëå ⨯®¢ ¨ £«®¡ «ì­ëå ¯à®æ¥¤ãà, ¯®á«¥ ª«î祢®£® -á«®¢  PROCEDURE ¬®¦¥â ¡ëâì 㪠§ ­ ä« £ ᮣ« è¥­¨ï ® ¢ë§®¢¥: [stdcall], -[ccall], [ccall16], [windows], [linux].  ¯à¨¬¥à: - - PROCEDURE [ccall] MyProc (x, y, z: INTEGER): INTEGER; - - …᫨ 㪠§ ­ ä« £ [ccall16], â® ¯à¨­¨¬ ¥âáï ᮣ« è¥­¨¥ ccall, ­® ¯¥à¥¤ -¢ë§®¢®¬ 㪠§ â¥«ì áâíª  ¡ã¤¥â ¢ëà ¢­¥­ ¯® £à ­¨æ¥ 16 ¡ ©â. - ”« £ [windows] - ᨭ®­¨¬ ¤«ï [stdcall], [linux] - ᨭ®­¨¬ ¤«ï [ccall16]. - ‡­ ª "-" ¯®á«¥ ¨¬¥­¨ ä« £  ([stdcall-], [linux-], ...) ®§­ ç ¥â, çâ® -१ã«ìâ â ¯à®æ¥¤ãàë ¬®¦­® ¨£­®à¨à®¢ âì (­¥ ¤®¯ã᪠¥âáï ¤«ï ⨯  REAL). - - ਠ®¡ê¥­¨¨ ⨯®¢-§ ¯¨á¥©, ¯®á«¥ ª«î祢®£® á«®¢  RECORD ¬®¦¥â ¡ëâì -㪠§ ­ ä« £ [noalign]. ”« £ [noalign] ®§­ ç ¥â ®âáãâá⢨¥ ¢ëà ¢­¨¢ ­¨ï ¯®«¥© -§ ¯¨á¨. ‡ ¯¨á¨ á á¨á⥬­ë¬ ä« £®¬ ­¥ ¬®£ãâ ¨¬¥âì ¡ §®¢ë© ⨯ ¨ ­¥ ¬®£ãâ ¡ëâì -¡ §®¢ë¬¨ ⨯ ¬¨ ¤«ï ¤àã£¨å § ¯¨á¥©. - „«ï ¨á¯®«ì§®¢ ­¨ï á¨á⥬­ëå ä« £®¢, âॡã¥âáï ¨¬¯®àâ¨à®¢ âì SYSTEM. - ------------------------------------------------------------------------------- - Ž¯¥à â®à CASE - - ‘¨­â ªá¨á ®¯¥à â®à  CASE: - - CaseStatement = - CASE Expression OF ‘ase {"|" ‘ase} - [ELSE StatementSequence] END. - Case = [CaseLabelList ":" StatementSequence]. - CaseLabelList = CaseLabels {"," CaseLabels}. - CaseLabels = ConstExpression [".." ConstExpression]. - -  ¯à¨¬¥à: - - CASE x OF - |-1: DoSomething1 - | 1: DoSomething2 - | 0: DoSomething3 - ELSE - DoSomething4 - END - - ‚ ¬¥âª å ¢ à¨ ­â®¢ ¬®¦­® ¨á¯®«ì§®¢ âì ª®­áâ ­â­ë¥ ¢ëà ¦¥­¨ï, ¢¥âª  ELSE -­¥®¡ï§ â¥«ì­ . …᫨ §­ ç¥­¨¥ x ­¥ ᮮ⢥âáâ¢ã¥â ­¨ ®¤­®¬ã ¢ à¨ ­âã ¨ ELSE -®âáãâáâ¢ã¥â, â® ¯à®£à ¬¬  ¯à¥à뢠¥âáï á ®è¨¡ª®© ¢à¥¬¥­¨ ¢ë¯®«­¥­¨ï. - ------------------------------------------------------------------------------- - ’¨¯ WCHAR - - ’¨¯ WCHAR ¤®¡ ¢«¥­ ¢ ï§ëª ¤«ï 㤮¡­®© ¯®¤¤¥¦ª¨ î­¨ª®¤ . „«ï ⨯®¢ WCHAR ¨ -ARRAY OF WCHAR ¤®¯ã᪠îâáï ¢á¥ â¥ ¦¥ ®¯¥à æ¨¨, ª ª ¤«ï ⨯®¢ CHAR ¨ -ARRAY OF CHAR, §  ¨áª«î祭¨¥¬ ¢áâ஥­­®© ¯à®æ¥¤ãàë CHR, ª®â®à ï ¢®§¢à é ¥â -⮫쪮 ⨯ CHAR. „«ï ¯®«ã祭¨ï §­ ç¥­¨ï ⨯  WCHAR, á«¥¤ã¥â ¨á¯®«ì§®¢ âì -¯à®æ¥¤ãàã WCHR ¢¬¥áâ® CHR. „«ï ¯à ¢¨«ì­®© à ¡®âë á ⨯®¬, ­¥®¡å®¤¨¬® á®åà ­ïâì -¨á室­ë© ª®¤ ¢ ª®¤¨à®¢ª¥ UTF-8 c BOM. - ------------------------------------------------------------------------------- - ஢¥àª  ¨ ®åà ­  ⨯  ­ã«¥¢®£® 㪠§ â¥«ï - - Žà¨£¨­ «ì­®¥ á®®¡é¥­¨¥ ® ï§ëª¥ ­¥ ®¯à¥¤¥«ï¥â ¯®¢¥¤¥­¨¥ ¯à®£à ¬¬ë ¯à¨ -¢ë¯®«­¥­¨¨ ®åà ­ë p(T) ¨ ¯à®¢¥àª¨ ⨯  p IS T ¯à¨ p = NIL. ‚® ¬­®£¨å -Oberon-ॠ«¨§ æ¨ïå ¢ë¯®«­¥­¨¥ â ª®© ®¯¥à æ¨¨ ¯à¨¢®¤¨â ª ®è¨¡ª¥ ¢à¥¬¥­¨ -¢ë¯®«­¥­¨ï. ‚ ¤ ­­®© ॠ«¨§ æ¨¨ ®åà ­  ⨯  ­ã«¥¢®£® 㪠§ â¥«ï ­¥ ¯à¨¢®¤¨â ª -®è¨¡ª¥,   ¯à®¢¥àª  ⨯  ¤ ¥â १ã«ìâ â FALSE. ‚ à拉 á«ãç ¥¢ íâ® ¯®§¢®«ï¥â -§­ ç¨â¥«ì­® ᮪à â¨âì ç áâ®â㠯ਬ¥­¥­¨ï ®åà ­ë ⨯ . - ------------------------------------------------------------------------------- - „®¯®«­¨â¥«ì­ë¥ áâ ­¤ àâ­ë¥ ¯à®æ¥¤ãàë - - DISPOSE (VAR v: «î¡®©_㪠§ â¥«ì) - Žá¢®¡®¦¤ ¥â ¯ ¬ïâì, ¢ë¤¥«¥­­ãî ¯à®æ¥¤ãன NEW ¤«ï - ¤¨­ ¬¨ç¥áª®© ¯¥à¥¬¥­­®© v^, ¨ ¯à¨á¢ ¨¢ ¥â ¯¥à¥¬¥­­®© v - §­ ç¥­¨¥ NIL. - - COPY (x: ARRAY OF CHAR/WCHAR; VAR v: ARRAY OF CHAR/WCHAR); - v := x; - …᫨ LEN(v) < LEN(x), â® áâப  x ¡ã¤¥â ᪮¯¨à®¢ ­  - ­¥ ¯®«­®áâìî - - LSR (x, n: INTEGER): INTEGER - ‹®£¨ç¥áª¨© ᤢ¨£ x ­  n ¡¨â ¢¯à ¢®. - - MIN (a, b: INTEGER): INTEGER - Œ¨­¨¬ã¬ ¨§ ¤¢ãå §­ ç¥­¨©. - - MAX (a, b: INTEGER): INTEGER - Œ ªá¨¬ã¬ ¨§ ¤¢ãå §­ ç¥­¨©. - - BITS (x: INTEGER): SET - ˆ­â¥à¯à¥â¨àã¥â x ª ª §­ ç¥­¨¥ ⨯  SET. - ‚믮«­ï¥âáï ­  íâ ¯¥ ª®¬¯¨«ï樨. - - LENGTH (s: ARRAY OF CHAR/WCHAR): INTEGER - „«¨­  0X-§ ¢¥à襭­®© áâப¨ s, ¡¥§ ãç¥â  ᨬ¢®«  0X. - …᫨ ᨬ¢®« 0X ®âáãâáâ¢ã¥â, äã­ªæ¨ï ¢®§¢à é ¥â ¤«¨­ã - ¬ áᨢ  s. s ­¥ ¬®¦¥â ¡ëâì ª®­á⠭⮩. - - WCHR (n: INTEGER): WCHAR - ८¡à §®¢ ­¨¥ ⨯ ,  ­ «®£¨ç­® CHR(n: INTEGER): CHAR - ------------------------------------------------------------------------------- - DIV ¨ MOD - - x y x DIV y x MOD y - - 5 3 1 2 - -5 3 -2 1 - 5 -3 -2 -1 - -5 -3 1 -2 - ------------------------------------------------------------------------------- - ˆ¬¯®àâ¨à®¢ ­­ë¥ ¯à®æ¥¤ãàë - - ‘¨­â ªá¨á ¨¬¯®àâ : - - PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type; - - - callconv -- ᮣ« è¥­¨¥ ® ¢ë§®¢¥ - - "library" -- ¨¬ï ä ©«  ¤¨­ ¬¨ç¥áª®© ¡¨¡«¨®â¥ª¨ - - "function" -- ¨¬ï ¨¬¯®àâ¨à㥬®© ¯à®æ¥¤ãàë - - ­ ¯à¨¬¥à: - - PROCEDURE [windows, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); - - PROCEDURE [stdcall, "Console.obj", "con_exit"] exit (bCloseWindow: BOOLEAN); - - ‚ ª®­æ¥ ®¡ê¥­¨ï ¬®¦¥â ¡ëâì ¤®¡ ¢«¥­® (­¥®¡ï§ â¥«ì­®) "END proc_name;" - - Ž¡ê¥­¨ï ¨¬¯®àâ¨à®¢ ­­ëå ¯à®æ¥¤ãà ¤®«¦­ë à á¯®« £ âìáï ¢ £«®¡ «ì­®© - ®¡« á⨠¢¨¤¨¬®á⨠¬®¤ã«ï ¯®á«¥ ®¡ê¥­¨ï ¯¥à¥¬¥­­ëå, ¢¬¥áâ¥ á ®¡ê¥­¨¥¬ - "®¡ëç­ëå" ¯à®æ¥¤ãà, ®â ª®â®àëå ¨¬¯®àâ¨à®¢ ­­ë¥ ®â«¨ç îâáï ⮫쪮 ®âáãâá⢨¥¬ - ⥫  ¯à®æ¥¤ãàë. ‚ ®áâ «ì­®¬, ª â ª¨¬ ¯à®æ¥¤ãà ¬ ¯à¨¬¥­¨¬ë ⥠¦¥ ¯à ¢¨« : - ¨å ¬®¦­® ¢ë§¢ âì, ¯à¨á¢®¨âì ¯à®æ¥¤ãà­®© ¯¥à¥¬¥­­®© ¨«¨ ¯®«ãç¨âì  ¤à¥á. - - ’ ª ª ª ¨¬¯®àâ¨à®¢ ­­ ï ¯à®æ¥¤ãà  ¢á¥£¤  ¨¬¥¥â ®¥ 㪠§ ­¨¥ ᮣ« è¥­¨ï ® - ¢ë§®¢¥, ⮠ᮢ¬¥áâ¨¬ë© ¯à®æ¥¤ãà­ë© ⨯ ⮦¥ ¤®«¦¥­ ¡ëâì ®¡ê¥­ á 㪠§ ­¨¥¬ - ᮣ« è¥­¨ï ® ¢ë§®¢¥: - - VAR - ExitProcess: PROCEDURE [windows] (code: INTEGER); - con_exit: PROCEDURE [stdcall] (bCloseWindow: BOOLEAN); - - ‚ KolibriOS ¨¬¯®àâ¨à®¢ âì ¯à®æ¥¤ãàë ¬®¦­® ⮫쪮 ¨§ ¡¨¡«¨®â¥ª, à §¬¥é¥­­ëå - ¢ /rd/1/lib. ˆ¬¯®àâ¨à®¢ âì ¨ ¢ë§ë¢ âì ä㭪樨 ¨­¨æ¨ «¨§ æ¨¨ ¡¨¡«¨®â¥ª - (lib_init, START) ¯à¨ í⮬ ­¥ ­ã¦­®. - - „«ï Linux, ¨¬¯®àâ¨à®¢ ­­ë¥ ¯à®æ¥¤ãàë ­¥ ॠ«¨§®¢ ­ë. - ------------------------------------------------------------------------------- - ‘ªàëâë¥ ¯ à ¬¥âàë ¯à®æ¥¤ãà - - ¥ª®â®àë¥ ¯à®æ¥¤ãàë ¬®£ãâ ¨¬¥âì áªàëâë¥ ¯ à ¬¥âàë, ®­¨ ®âáãâáâ¢ãîâ ¢ ᯨ᪥ -ä®à¬ «ì­ëå ¯ à ¬¥â஢, ­® ãç¨â뢠îâáï ª®¬¯¨«ïâ®à®¬ ¯à¨ âà ­á«ï樨 ¢ë§®¢®¢. -â® ¢®§¬®¦­® ¢ á«¥¤ãîé¨å á«ãç ïå: - -1. à®æ¥¤ãà  ¨¬¥¥â ä®à¬ «ì­ë© ¯ à ¬¥âà ®âªàëâë© ¬ áᨢ: - PROCEDURE Proc (x: ARRAY OF ARRAY OF REAL); - ‚맮¢ â࠭᫨àã¥âáï â ª: - Proc(LEN(x), LEN(x[0]), SYSTEM.ADR(x)) -2. à®æ¥¤ãà  ¨¬¥¥â ä®à¬ «ì­ë© ¯ à ¬¥âà-¯¥à¥¬¥­­ãî ⨯  RECORD: - PROCEDURE Proc (VAR x: Rec); - ‚맮¢ â࠭᫨àã¥âáï â ª: - Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) - ------------------------------------------------------------------------------- - Œ®¤ã«ì RTL - - ‚ᥠ¯à®£à ¬¬ë ­¥ï¢­® ¨á¯®«ì§ãîâ ¬®¤ã«ì RTL. Š®¬¯¨«ïâ®à â࠭᫨àã¥â -­¥ª®â®àë¥ ®¯¥à æ¨¨ (¯à®¢¥àª  ¨ ®åà ­  ⨯ , áà ¢­¥­¨¥ áâப, á®®¡é¥­¨ï ®¡ -®è¨¡ª å ¢à¥¬¥­¨ ¢ë¯®«­¥­¨ï ¨ ¤à.) ª ª ¢ë§®¢ë ¯à®æ¥¤ãà í⮣® ¬®¤ã«ï. ¥ -á«¥¤ã¥â ® ¢ë§ë¢ âì í⨠¯à®æ¥¤ãàë, §  ¨áª«î祭¨¥¬ ¯à®æ¥¤ãà SetDll ¨ SetFini -¥á«¨ ¯à¨«®¦¥­¨¥ ª®¬¯¨«¨àã¥âáï ª ª Windows DLL ¨«¨ Linux SO, ᮮ⢥âá⢥­­®: - - PROCEDURE SetDll - (process_detach, thread_detach, thread_attach: DLL_ENTRY); - £¤¥ TYPE DLL_ENTRY = - PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); - -SetDll ­ §­ ç ¥â ¯à®æ¥¤ãàë process_detach, thread_detach, thread_attach -¢ë§ë¢ ¥¬ë¬¨ ¯à¨ -- ¢ë£à㧪¥ dll-¡¨¡«¨®â¥ª¨ (process_detach) -- ᮧ¤ ­¨¨ ­®¢®£® ¯®â®ª  (thread_attach) -- ã­¨ç⮦¥­¨¨ ¯®â®ª  (thread_detach) - - - PROCEDURE SetFini (ProcFini: PROC); - £¤¥ TYPE PROC = PROCEDURE (* ¡¥§ ¯ à ¬¥â஢ *) - -SetFini ­ §­ ç ¥â ¯à®æ¥¤ãàã ProcFini ¢ë§ë¢ ¥¬®© ¯à¨ ¢ë£à㧪¥ so-¡¨¡«¨®â¥ª¨. - -„«ï ¯à®ç¨å ⨯®¢ ¯à¨«®¦¥­¨©, ¢ë§®¢ ¯à®æ¥¤ãà SetDll ¨ SetFini ­¥ ¢«¨ï¥â ­  -¯®¢¥¤¥­¨¥ ¯à®£à ¬¬ë. - - ‘®®¡é¥­¨ï ®¡ ®è¨¡ª å ¢à¥¬¥­¨ ¢ë¯®«­¥­¨ï ¢ë¢®¤ïâáï ¢ ¤¨ «®£®¢ëå ®ª­ å -(Windows), ¢ â¥à¬¨­ « (Linux), ­  ¤®áªã ®â« ¤ª¨ (KolibriOS). - ------------------------------------------------------------------------------- - Œ®¤ã«ì API - - ‘ãé¥áâ¢ãîâ ­¥áª®«ìª® ॠ«¨§ æ¨© ¬®¤ã«ï API (¤«ï à §«¨ç­ëå Ž‘). - Š ª ¨ ¬®¤ã«ì RTL, ¬®¤ã«ì API ­¥ ¯à¥¤­ §­ ç¥­ ¤«ï ¯àאַ£® ¨á¯®«ì§®¢ ­¨ï. -Ž­ ®¡¥á¯¥ç¨¢ ¥â á¢ï§ì RTL á Ž‘. - ------------------------------------------------------------------------------- - ƒ¥­¥à æ¨ï ¨á¯®«­ï¥¬ëå ä ©«®¢ DLL - -  §à¥è ¥âáï íªá¯®àâ¨à®¢ âì ⮫쪮 ¯à®æ¥¤ãàë. „«ï í⮣®, ¯à®æ¥¤ãà  ¤®«¦­  -­ å®¤¨âìáï ¢ £« ¢­®¬ ¬®¤ã«¥ ¯à®£à ¬¬ë, ¨ ¥¥ ¨¬ï ¤®«¦­® ¡ëâì ®â¬¥ç¥­® ᨬ¢®«®¬ -íªá¯®àâ  ("*"). KolibriOS DLL ¢á¥£¤  íªá¯®àâ¨àãîâ ¨¤¥­â¨ä¨ª â®àë "version" -(¢¥àá¨ï ¯à®£à ¬¬ë) ¨ "lib_init" -  ¤à¥á ¯à®æ¥¤ãàë ¨­¨æ¨ «¨§ æ¨¨ DLL: - - PROCEDURE [stdcall] lib_init (): INTEGER - -â  ¯à®æ¥¤ãà  ¤®«¦­  ¡ëâì ¢ë§¢ ­  ¯¥à¥¤ ¨á¯®«ì§®¢ ­¨¥¬ DLL. -à®æ¥¤ãà  ¢á¥£¤  ¢®§¢à é ¥â 1. \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/KOSLib.txt b/programs/develop/oberon07/Docs/KOSLib.txt new file mode 100644 index 0000000000..01364faf9e --- /dev/null +++ b/programs/develop/oberon07/Docs/KOSLib.txt @@ -0,0 +1,566 @@ +============================================================================== + + Библиотека (KolibriOS) + +------------------------------------------------------------------------------ +MODULE Out - конÑольный вывод + + PROCEDURE Open + формально открывает конÑольный вывод + + PROCEDURE Int(x, width: INTEGER) + вывод целого чиÑла x; + width - количеÑтво знакомеÑÑ‚, иÑпользуемых Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð° + + PROCEDURE Real(x: REAL; width: INTEGER) + вывод вещеÑтвенного чиÑла x в плавающем формате; + width - количеÑтво знакомеÑÑ‚, иÑпользуемых Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð° + + PROCEDURE Char(x: CHAR) + вывод Ñимвола x + + PROCEDURE FixReal(x: REAL; width, p: INTEGER) + вывод вещеÑтвенного чиÑла x в фикÑированном формате; + width - количеÑтво знакомеÑÑ‚, иÑпользуемых Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð°; + p - количеÑтво знаков поÑле деÑÑтичной точки + + PROCEDURE Ln + переход на Ñледующую Ñтроку + + PROCEDURE String(s: ARRAY OF CHAR) + вывод Ñтроки s + +------------------------------------------------------------------------------ +MODULE In - конÑольный ввод + + VAR Done: BOOLEAN + принимает значение TRUE в Ñлучае уÑпешного Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ + операции ввода, иначе FALSE + + PROCEDURE Open + формально открывает конÑольный ввод, + также приÑваивает переменной Done значение TRUE + + PROCEDURE Int(VAR x: INTEGER) + ввод чиÑла типа INTEGER + + PROCEDURE Char(VAR x: CHAR) + ввод Ñимвола + + PROCEDURE Real(VAR x: REAL) + ввод чиÑла типа REAL + + PROCEDURE String(VAR s: ARRAY OF CHAR) + ввод Ñтроки + + PROCEDURE Ln + ожидание Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ENTER + +------------------------------------------------------------------------------ +MODULE Console - дополнительные процедуры конÑольного вывода + + CONST + + Следующие конÑтанты определÑÑŽÑ‚ цвет конÑольного вывода + + Black = 0 Blue = 1 Green = 2 + Cyan = 3 Red = 4 Magenta = 5 + Brown = 6 LightGray = 7 DarkGray = 8 + LightBlue = 9 LightGreen = 10 LightCyan = 11 + LightRed = 12 LightMagenta = 13 Yellow = 14 + White = 15 + + PROCEDURE Cls + очиÑтка окна конÑоли + + PROCEDURE SetColor(FColor, BColor: INTEGER) + уÑтановка цвета конÑольного вывода: FColor - цвет текÑта, + BColor - цвет фона, возможные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ - вышеперечиÑленные + конÑтанты + + PROCEDURE SetCursor(x, y: INTEGER) + уÑтановка курÑора конÑоли в позицию (x, y) + + PROCEDURE GetCursor(VAR x, y: INTEGER) + запиÑывает в параметры текущие координаты курÑора конÑоли + + PROCEDURE GetCursorX(): INTEGER + возвращает текущую x-координату курÑора конÑоли + + PROCEDURE GetCursorY(): INTEGER + возвращает текущую y-координату курÑора конÑоли + +------------------------------------------------------------------------------ +MODULE ConsoleLib - обертка библиотеки console.obj + +------------------------------------------------------------------------------ +MODULE Math - математичеÑкие функции + + CONST + + pi = 3.141592653589793E+00 + e = 2.718281828459045E+00 + + + PROCEDURE IsNan(x: REAL): BOOLEAN + возвращает TRUE, еÑли x - не чиÑло + + PROCEDURE IsInf(x: REAL): BOOLEAN + возвращает TRUE, еÑли x - беÑконечноÑÑ‚ÑŒ + + PROCEDURE sqrt(x: REAL): REAL + квадратный корень x + + PROCEDURE exp(x: REAL): REAL + ÑкÑпонента x + + PROCEDURE ln(x: REAL): REAL + натуральный логарифм x + + PROCEDURE sin(x: REAL): REAL + ÑÐ¸Ð½ÑƒÑ x + + PROCEDURE cos(x: REAL): REAL + коÑÐ¸Ð½ÑƒÑ x + + PROCEDURE tan(x: REAL): REAL + Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ x + + PROCEDURE arcsin(x: REAL): REAL + аркÑÐ¸Ð½ÑƒÑ x + + PROCEDURE arccos(x: REAL): REAL + арккоÑÐ¸Ð½ÑƒÑ x + + PROCEDURE arctan(x: REAL): REAL + Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ x + + PROCEDURE arctan2(y, x: REAL): REAL + Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ y/x + + PROCEDURE power(base, exponent: REAL): REAL + возведение чиÑла base в Ñтепень exponent + + PROCEDURE log(base, x: REAL): REAL + логарифм x по оÑнованию base + + PROCEDURE sinh(x: REAL): REAL + гиперболичеÑкий ÑÐ¸Ð½ÑƒÑ x + + PROCEDURE cosh(x: REAL): REAL + гиперболичеÑкий коÑÐ¸Ð½ÑƒÑ x + + PROCEDURE tanh(x: REAL): REAL + гиперболичеÑкий Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ x + + PROCEDURE arsinh(x: REAL): REAL + обратный гиперболичеÑкий ÑÐ¸Ð½ÑƒÑ x + + PROCEDURE arcosh(x: REAL): REAL + обратный гиперболичеÑкий коÑÐ¸Ð½ÑƒÑ x + + PROCEDURE artanh(x: REAL): REAL + обратный гиперболичеÑкий Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ x + + PROCEDURE round(x: REAL): REAL + округление x до ближайшего целого + + PROCEDURE frac(x: REAL): REAL; + Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ чиÑла x + + PROCEDURE floor(x: REAL): REAL + наибольшее целое чиÑло (предÑтавление как REAL), + не больше x: floor(1.2) = 1.0 + + PROCEDURE ceil(x: REAL): REAL + наименьшее целое чиÑло (предÑтавление как REAL), + не меньше x: ceil(1.2) = 2.0 + + PROCEDURE sgn(x: REAL): INTEGER + еÑли x > 0 возвращает 1 + еÑли x < 0 возвращает -1 + еÑли x = 0 возвращает 0 + + PROCEDURE fact(n: INTEGER): REAL + факториал n + +------------------------------------------------------------------------------ +MODULE Debug - вывод на доÑку отладки + Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ ÐºÐ°Ðº модуль Out + + PROCEDURE Open + открывает доÑку отладки + +------------------------------------------------------------------------------ +MODULE File - работа Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð¾Ð¹ ÑиÑтемой + + TYPE + + FNAME = ARRAY 520 OF CHAR + + FS = POINTER TO rFS + + rFS = RECORD (* Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ñтруктура файла *) + subfunc, pos, hpos, bytes, buffer: INTEGER; + name: FNAME + END + + FD = POINTER TO rFD + + rFD = RECORD (* Ñтруктура блока данных входа каталога *) + attr: INTEGER; + ntyp: CHAR; + reserved: ARRAY 3 OF CHAR; + time_create, date_create, + time_access, date_access, + time_modif, date_modif, + size, hsize: INTEGER; + name: FNAME + END + + CONST + + SEEK_BEG = 0 + SEEK_CUR = 1 + SEEK_END = 2 + + PROCEDURE Load(FName: ARRAY OF CHAR; VAR size: INTEGER): INTEGER; + Загружает в памÑÑ‚ÑŒ файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName, запиÑывает в параметр + size размер файла, возвращает Ð°Ð´Ñ€ÐµÑ Ð·Ð°Ð³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ð¾Ð³Ð¾ файла + или 0 (ошибка). При необходимоÑти, раÑпаковывает + файл (kunpack). + + PROCEDURE GetFileInfo(FName: ARRAY OF CHAR; VAR Info: rFD): BOOLEAN + ЗапиÑывает Ñтруктуру блока данных входа каталога Ð´Ð»Ñ Ñ„Ð°Ð¹Ð»Ð° + или папки Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName в параметр Info. + При ошибке возвращает FALSE. + + PROCEDURE Exists(FName: ARRAY OF CHAR): BOOLEAN + возвращает TRUE, еÑли файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName ÑущеÑтвует + + PROCEDURE Close(VAR F: FS) + оÑвобождает памÑÑ‚ÑŒ, выделенную Ð´Ð»Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¾Ð¹ Ñтруктуры + файла F и приÑваивает F значение NIL + + PROCEDURE Open(FName: ARRAY OF CHAR): FS + возвращает указатель на информационную Ñтруктуру файла Ñ + именем FName, при ошибке возвращает NIL + + PROCEDURE Delete(FName: ARRAY OF CHAR): BOOLEAN + удалÑет файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName, при ошибке возвращает FALSE + + PROCEDURE Seek(F: FS; Offset, Origin: INTEGER): INTEGER + уÑтанавливает позицию чтениÑ-запиÑи файла F на Offset, + отноÑительно Origin = (SEEK_BEG - начало файла, + SEEK_CUR - Ñ‚ÐµÐºÑƒÑ‰Ð°Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ, SEEK_END - конец файла), + возвращает позицию отноÑительно начала файла, например: + Seek(F, 0, SEEK_END) + уÑтанавливает позицию на конец файла и возвращает длину + файла; при ошибке возвращает -1 + + PROCEDURE Read(F: FS; Buffer, Count: INTEGER): INTEGER + Читает данные из файла в памÑÑ‚ÑŒ. F - указатель на + информационную Ñтруктуру файла, Buffer - Ð°Ð´Ñ€ÐµÑ Ð¾Ð±Ð»Ð°Ñти + памÑти, Count - количеÑтво байт, которое требуетÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚ÑŒ + из файла; возвращает количеÑтво байт, которое было прочитано + и ÑоответÑтвующим образом изменÑет позицию чтениÑ/запиÑи в + информационной Ñтруктуре F. + + PROCEDURE Write(F: FS; Buffer, Count: INTEGER): INTEGER + ЗапиÑывает данные из памÑти в файл. F - указатель на + информационную Ñтруктуру файла, Buffer - Ð°Ð´Ñ€ÐµÑ Ð¾Ð±Ð»Ð°Ñти + памÑти, Count - количеÑтво байт, которое требуетÑÑ Ð·Ð°Ð¿Ð¸Ñать + в файл; возвращает количеÑтво байт, которое было запиÑано и + ÑоответÑтвующим образом изменÑет позицию чтениÑ/запиÑи в + информационной Ñтруктуре F. + + PROCEDURE Create(FName: ARRAY OF CHAR): FS + Ñоздает новый файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName (полное имÑ), возвращает + указатель на информационную Ñтруктуру файла, + при ошибке возвращает NIL + + PROCEDURE CreateDir(DirName: ARRAY OF CHAR): BOOLEAN + Ñоздает папку Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ DirName, вÑе промежуточные папки + должны ÑущеÑтвовать, при ошибке возвращает FALSE + + PROCEDURE DeleteDir(DirName: ARRAY OF CHAR): BOOLEAN + удалÑет пуÑтую папку Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ DirName, + при ошибке возвращает FALSE + + PROCEDURE DirExists(DirName: ARRAY OF CHAR): BOOLEAN + возвращает TRUE, еÑли папка Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ DirName ÑущеÑтвует + +------------------------------------------------------------------------------ +MODULE Read - чтение оÑновных типов данных из файла F + + Процедуры возвращают TRUE в Ñлучае уÑпешной операции Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð¸ + ÑоответÑтвующим образом изменÑÑŽÑ‚ позицию чтениÑ/запиÑи в + информационной Ñтруктуре F + + PROCEDURE Char(F: File.FS; VAR x: CHAR): BOOLEAN + + PROCEDURE Int(F: File.FS; VAR x: INTEGER): BOOLEAN + + PROCEDURE Real(F: File.FS; VAR x: REAL): BOOLEAN + + PROCEDURE Boolean(F: File.FS; VAR x: BOOLEAN): BOOLEAN + + PROCEDURE Set(F: File.FS; VAR x: SET): BOOLEAN + + PROCEDURE WChar(F: File.FS; VAR x: WCHAR): BOOLEAN + +------------------------------------------------------------------------------ +MODULE Write - запиÑÑŒ оÑновных типов данных в файл F + + Процедуры возвращают TRUE в Ñлучае уÑпешной операции запиÑи и + ÑоответÑтвующим образом изменÑÑŽÑ‚ позицию чтениÑ/запиÑи в + информационной Ñтруктуре F + + PROCEDURE Char(F: File.FS; x: CHAR): BOOLEAN + + PROCEDURE Int(F: File.FS; x: INTEGER): BOOLEAN + + PROCEDURE Real(F: File.FS; x: REAL): BOOLEAN + + PROCEDURE Boolean(F: File.FS; x: BOOLEAN): BOOLEAN + + PROCEDURE Set(F: File.FS; x: SET): BOOLEAN + + PROCEDURE WChar(F: File.FS; x: WCHAR): BOOLEAN + +------------------------------------------------------------------------------ +MODULE DateTime - дата, Ð²Ñ€ÐµÐ¼Ñ + + CONST ERR = -7.0E5 + + PROCEDURE Now(VAR Year, Month, Day, Hour, Min, Sec: INTEGER) + запиÑывает в параметры компоненты текущей ÑиÑтемной даты и + времени + + PROCEDURE Encode(Year, Month, Day, Hour, Min, Sec: INTEGER): REAL + возвращает дату, полученную из компонентов + Year, Month, Day, Hour, Min, Sec; + при ошибке возвращает конÑтанту ERR = -7.0E5 + + PROCEDURE Decode(Date: REAL; VAR Year, Month, Day, + Hour, Min, Sec: INTEGER): BOOLEAN + извлекает компоненты + Year, Month, Day, Hour, Min, Sec из даты Date; + при ошибке возвращает FALSE + +------------------------------------------------------------------------------ +MODULE Args - параметры программы + + VAR argc: INTEGER + количеÑтво параметров программы, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¸Ð¼Ñ + иÑполнÑемого файла + + PROCEDURE GetArg(n: INTEGER; VAR s: ARRAY OF CHAR) + запиÑывает в Ñтроку s n-й параметр программы, + Ð½ÑƒÐ¼ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð² от 0 до argc - 1, + нулевой параметр -- Ð¸Ð¼Ñ Ð¸ÑполнÑемого файла + +------------------------------------------------------------------------------ +MODULE KOSAPI + + PROCEDURE sysfunc1(arg1: INTEGER): INTEGER + PROCEDURE sysfunc2(arg1, arg2: INTEGER): INTEGER + ... + PROCEDURE sysfunc7(arg1, arg2, ..., arg7: INTEGER): INTEGER + Обертки Ð´Ð»Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¹ API Ñдра KolibriOS. + arg1 .. arg7 ÑоответÑтвуют региÑтрам + eax, ebx, ecx, edx, esi, edi, ebp; + возвращают значение региÑтра eax поÑле ÑиÑтемного вызова. + + PROCEDURE sysfunc22(arg1, arg2: INTEGER; VAR res2: INTEGER): INTEGER + Обертка Ð´Ð»Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¹ API Ñдра KolibriOS. + arg1 - региÑÑ‚Ñ€ eax, arg2 - региÑÑ‚Ñ€ ebx, + res2 - значение региÑтра ebx поÑле ÑиÑтемного вызова; + возвращает значение региÑтра eax поÑле ÑиÑтемного вызова. + + PROCEDURE malloc(size: INTEGER): INTEGER + ВыделÑет блок памÑти. + size - размер блока в байтах, + возвращает Ð°Ð´Ñ€ÐµÑ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð½Ð¾Ð³Ð¾ блока + + PROCEDURE free(ptr: INTEGER): INTEGER + ОÑвобождает ранее выделенный блок памÑти Ñ Ð°Ð´Ñ€ÐµÑом ptr, + возвращает 0 + + PROCEDURE realloc(ptr, size: INTEGER): INTEGER + ПерераÑпределÑет блок памÑти, + ptr - Ð°Ð´Ñ€ÐµÑ Ñ€Ð°Ð½ÐµÐµ выделенного блока, + size - новый размер, + возвращает указатель на перераÑпределенный блок, + 0 при ошибке + + PROCEDURE GetCommandLine(): INTEGER + Возвращает Ð°Ð´Ñ€ÐµÑ Ñтроки параметров + + PROCEDURE GetName(): INTEGER + Возвращает Ð°Ð´Ñ€ÐµÑ Ñтроки Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ программы + + PROCEDURE LoadLib(name: ARRAY OF CHAR): INTEGER + Загружает DLL Ñ Ð¿Ð¾Ð»Ð½Ñ‹Ð¼ именем name. Возвращает Ð°Ð´Ñ€ÐµÑ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹ + ÑкÑпорта. При ошибке возвращает 0. + + PROCEDURE GetProcAdr(name: ARRAY OF CHAR; lib: INTEGER): INTEGER + name - Ð¸Ð¼Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ + lib - Ð°Ð´Ñ€ÐµÑ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹ ÑкÑпорта DLL + Возвращает Ð°Ð´Ñ€ÐµÑ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹. При ошибке возвращает 0. + +------------------------------------------------------------------------------ +MODULE ColorDlg - работа Ñ Ð´Ð¸Ð°Ð»Ð¾Ð³Ð¾Ð¼ "Color Dialog" + + TYPE + + Dialog = POINTER TO RECORD (* Ñтруктура диалога *) + status: INTEGER (* ÑоÑтоÑние диалога: + 0 - пользователь нажал Cancel + 1 - пользователь нажал OK + 2 - диалог открыт *) + + color: INTEGER (* выбранный цвет *) + END + + PROCEDURE Create(draw_window: DRAW_WINDOW): Dialog + Ñоздать диалог + draw_window - процедура перериÑовки оÑновного окна + (TYPE DRAW_WINDOW = PROCEDURE); + процедура возвращает указатель на Ñтруктуру диалога + + PROCEDURE Show(cd: Dialog) + показать диалог + cd - указатель на Ñтруктуру диалога, который был Ñоздан ранее + процедурой Create + + PROCEDURE Destroy(VAR cd: Dialog) + уничтожить диалог + cd - указатель на Ñтруктуру диалога + +------------------------------------------------------------------------------ +MODULE OpenDlg - работа Ñ Ð´Ð¸Ð°Ð»Ð¾Ð³Ð¾Ð¼ "Open Dialog" + + TYPE + + Dialog = POINTER TO RECORD (* Ñтруктура диалога *) + status: INTEGER (* ÑоÑтоÑние диалога: + 0 - пользователь нажал Cancel + 1 - пользователь нажал OK + 2 - диалог открыт *) + + FileName: ARRAY 4096 OF CHAR (* Ð¸Ð¼Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ файла *) + FilePath: ARRAY 4096 OF CHAR (* полное Ð¸Ð¼Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ + файла *) + END + + PROCEDURE Create(draw_window: DRAW_WINDOW; type: INTEGER; def_path, + filter: ARRAY OF CHAR): Dialog + Ñоздать диалог + draw_window - процедура перериÑовки оÑновного окна + (TYPE DRAW_WINDOW = PROCEDURE) + type - тип диалога + 0 - открыть + 1 - Ñохранить + 2 - выбрать папку + def_path - путь по умолчанию, папка def_path будет открыта + при первом запуÑке диалога + filter - в Ñтроке запиÑано перечиÑление раÑширений файлов, + которые будут показаны в диалоговом окне, раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ + разделÑÑŽÑ‚ÑÑ Ñимволом "|", например: "ASM|TXT|INI" + процедура возвращает указатель на Ñтруктуру диалога + + PROCEDURE Show(od: Dialog; Width, Height: INTEGER) + показать диалог + od - указатель на Ñтруктуру диалога, который был Ñоздан ранее + процедурой Create + Width и Height - ширина и выÑота диалогового окна + + PROCEDURE Destroy(VAR od: Dialog) + уничтожить диалог + od - указатель на Ñтруктуру диалога + +------------------------------------------------------------------------------ +MODULE kfonts - работа Ñ kf-шрифтами + + CONST + + bold = 1 + italic = 2 + underline = 4 + strike_through = 8 + smoothing = 16 + bpp32 = 32 + + TYPE + + TFont = POINTER TO TFont_desc (* указатель на шрифт *) + + PROCEDURE LoadFont(file_name: ARRAY OF CHAR): TFont + загрузить шрифт из файла + file_name Ð¸Ð¼Ñ kf-файла + рез-Ñ‚: указатель на шрифт/NIL (ошибка) + + PROCEDURE SetSize(Font: TFont; font_size: INTEGER): BOOLEAN + уÑтановить размер шрифта + Font указатель на шрифт + font_size размер шрифта + рез-Ñ‚: TRUE/FALSE (ошибка) + + PROCEDURE Enabled(Font: TFont; font_size: INTEGER): BOOLEAN + проверить, еÑÑ‚ÑŒ ли шрифт, заданного размера + Font указатель на шрифт + font_size размер шрифта + рез-Ñ‚: TRUE/FALSE (шрифта нет) + + PROCEDURE Destroy(VAR Font: TFont) + выгрузить шрифт, оÑвободить динамичеÑкую памÑÑ‚ÑŒ + Font указатель на шрифт + ПриÑваивает переменной Font значение NIL + + PROCEDURE TextHeight(Font: TFont): INTEGER + получить выÑоту Ñтроки текÑта + Font указатель на шрифт + рез-Ñ‚: выÑота Ñтроки текÑта в пикÑелÑÑ… + + PROCEDURE TextWidth(Font: TFont; + str, length, params: INTEGER): INTEGER + получить ширину Ñтроки текÑта + Font указатель на шрифт + str Ð°Ð´Ñ€ÐµÑ Ñтроки текÑта в кодировке Win-1251 + length количеÑтво Ñимволов в Ñтроке или -1, еÑли Ñтрока + завершаетÑÑ Ð½ÑƒÐ»ÐµÐ¼ + params параметры-флаги Ñм. ниже + рез-Ñ‚: ширина Ñтроки текÑта в пикÑелÑÑ… + + PROCEDURE TextOut(Font: TFont; + canvas, x, y, str, length, color, params: INTEGER) + вывеÑти текÑÑ‚ в буфер + Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð° буфера в окно, иÑпользовать Ñ„.65 или + Ñ„.7 (еÑли буфер 24-битный) + Font указатель на шрифт + canvas Ð°Ð´Ñ€ÐµÑ Ð³Ñ€Ð°Ñ„Ð¸Ñ‡ÐµÑкого буфера + Ñтруктура буфера: + Xsize dd + Ysize dd + picture rb Xsize * Ysize * 4 (32 бита) + или Xsize * Ysize * 3 (24 бита) + x, y координаты текÑта отноÑительно левого верхнего + угла буфера + str Ð°Ð´Ñ€ÐµÑ Ñтроки текÑта в кодировке Win-1251 + length количеÑтво Ñимволов в Ñтроке или -1, еÑли Ñтрока + завершаетÑÑ Ð½ÑƒÐ»ÐµÐ¼ + color цвет текÑта 0x00RRGGBB + params параметры-флаги: + 1 жирный + 2 курÑив + 4 подчеркнутый + 8 перечеркнутый + 16 применить Ñглаживание + 32 вывод в 32-битный буфер + возможно иÑпользование флагов в любых ÑочетаниÑÑ… +------------------------------------------------------------------------------ +MODULE RasterWorks - обертка библиотеки Rasterworks.obj +------------------------------------------------------------------------------ +MODULE libimg - обертка библиотеки libimg.obj +------------------------------------------------------------------------------ \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/KOSLib1251.txt b/programs/develop/oberon07/Docs/KOSLib1251.txt deleted file mode 100644 index 985b4d0ccb..0000000000 --- a/programs/develop/oberon07/Docs/KOSLib1251.txt +++ /dev/null @@ -1,566 +0,0 @@ -============================================================================== - - Áèáëèîòåêà (KolibriOS) - ------------------------------------------------------------------------------- -MODULE Out - êîíñîëüíûé âûâîä - - PROCEDURE Open - ôîðìàëüíî îòêðûâàåò êîíñîëüíûé âûâîä - - PROCEDURE Int(x, width: INTEGER) - âûâîä öåëîãî ÷èñëà x; - width - êîëè÷åñòâî çíàêîìåñò, èñïîëüçóåìûõ äëÿ âûâîäà - - PROCEDURE Real(x: REAL; width: INTEGER) - âûâîä âåùåñòâåííîãî ÷èñëà x â ïëàâàþùåì ôîðìàòå; - width - êîëè÷åñòâî çíàêîìåñò, èñïîëüçóåìûõ äëÿ âûâîäà - - PROCEDURE Char(x: CHAR) - âûâîä ñèìâîëà x - - PROCEDURE FixReal(x: REAL; width, p: INTEGER) - âûâîä âåùåñòâåííîãî ÷èñëà x â ôèêñèðîâàííîì ôîðìàòå; - width - êîëè÷åñòâî çíàêîìåñò, èñïîëüçóåìûõ äëÿ âûâîäà; - p - êîëè÷åñòâî çíàêîâ ïîñëå äåñÿòè÷íîé òî÷êè - - PROCEDURE Ln - ïåðåõîä íà ñëåäóþùóþ ñòðîêó - - PROCEDURE String(s: ARRAY OF CHAR) - âûâîä ñòðîêè s - ------------------------------------------------------------------------------- -MODULE In - êîíñîëüíûé ââîä - - VAR Done: BOOLEAN - ïðèíèìàåò çíà÷åíèå TRUE â ñëó÷àå óñïåøíîãî âûïîëíåíèÿ - îïåðàöèè ââîäà, èíà÷å FALSE - - PROCEDURE Open - ôîðìàëüíî îòêðûâàåò êîíñîëüíûé ââîä, - òàêæå ïðèñâàèâàåò ïåðåìåííîé Done çíà÷åíèå TRUE - - PROCEDURE Int(VAR x: INTEGER) - ââîä ÷èñëà òèïà INTEGER - - PROCEDURE Char(VAR x: CHAR) - ââîä ñèìâîëà - - PROCEDURE Real(VAR x: REAL) - ââîä ÷èñëà òèïà REAL - - PROCEDURE String(VAR s: ARRAY OF CHAR) - ââîä ñòðîêè - - PROCEDURE Ln - îæèäàíèå íàæàòèÿ ENTER - ------------------------------------------------------------------------------- -MODULE Console - äîïîëíèòåëüíûå ïðîöåäóðû êîíñîëüíîãî âûâîäà - - CONST - - Ñëåäóþùèå êîíñòàíòû îïðåäåëÿþò öâåò êîíñîëüíîãî âûâîäà - - Black = 0 Blue = 1 Green = 2 - Cyan = 3 Red = 4 Magenta = 5 - Brown = 6 LightGray = 7 DarkGray = 8 - LightBlue = 9 LightGreen = 10 LightCyan = 11 - LightRed = 12 LightMagenta = 13 Yellow = 14 - White = 15 - - PROCEDURE Cls - î÷èñòêà îêíà êîíñîëè - - PROCEDURE SetColor(FColor, BColor: INTEGER) - óñòàíîâêà öâåòà êîíñîëüíîãî âûâîäà: FColor - öâåò òåêñòà, - BColor - öâåò ôîíà, âîçìîæíûå çíà÷åíèÿ - âûøåïåðå÷èñëåííûå - êîíñòàíòû - - PROCEDURE SetCursor(x, y: INTEGER) - óñòàíîâêà êóðñîðà êîíñîëè â ïîçèöèþ (x, y) - - PROCEDURE GetCursor(VAR x, y: INTEGER) - çàïèñûâàåò â ïàðàìåòðû òåêóùèå êîîðäèíàòû êóðñîðà êîíñîëè - - PROCEDURE GetCursorX(): INTEGER - âîçâðàùàåò òåêóùóþ x-êîîðäèíàòó êóðñîðà êîíñîëè - - PROCEDURE GetCursorY(): INTEGER - âîçâðàùàåò òåêóùóþ y-êîîðäèíàòó êóðñîðà êîíñîëè - ------------------------------------------------------------------------------- -MODULE ConsoleLib - îáåðòêà áèáëèîòåêè console.obj - ------------------------------------------------------------------------------- -MODULE Math - ìàòåìàòè÷åñêèå ôóíêöèè - - CONST - - pi = 3.141592653589793E+00 - e = 2.718281828459045E+00 - - - PROCEDURE IsNan(x: REAL): BOOLEAN - âîçâðàùàåò TRUE, åñëè x - íå ÷èñëî - - PROCEDURE IsInf(x: REAL): BOOLEAN - âîçâðàùàåò TRUE, åñëè x - áåñêîíå÷íîñòü - - PROCEDURE sqrt(x: REAL): REAL - êâàäðàòíûé êîðåíü x - - PROCEDURE exp(x: REAL): REAL - ýêñïîíåíòà x - - PROCEDURE ln(x: REAL): REAL - íàòóðàëüíûé ëîãàðèôì x - - PROCEDURE sin(x: REAL): REAL - ñèíóñ x - - PROCEDURE cos(x: REAL): REAL - êîñèíóñ x - - PROCEDURE tan(x: REAL): REAL - òàíãåíñ x - - PROCEDURE arcsin(x: REAL): REAL - àðêñèíóñ x - - PROCEDURE arccos(x: REAL): REAL - àðêêîñèíóñ x - - PROCEDURE arctan(x: REAL): REAL - àðêòàíãåíñ x - - PROCEDURE arctan2(y, x: REAL): REAL - àðêòàíãåíñ y/x - - PROCEDURE power(base, exponent: REAL): REAL - âîçâåäåíèå ÷èñëà base â ñòåïåíü exponent - - PROCEDURE log(base, x: REAL): REAL - ëîãàðèôì x ïî îñíîâàíèþ base - - PROCEDURE sinh(x: REAL): REAL - ãèïåðáîëè÷åñêèé ñèíóñ x - - PROCEDURE cosh(x: REAL): REAL - ãèïåðáîëè÷åñêèé êîñèíóñ x - - PROCEDURE tanh(x: REAL): REAL - ãèïåðáîëè÷åñêèé òàíãåíñ x - - PROCEDURE arsinh(x: REAL): REAL - îáðàòíûé ãèïåðáîëè÷åñêèé ñèíóñ x - - PROCEDURE arcosh(x: REAL): REAL - îáðàòíûé ãèïåðáîëè÷åñêèé êîñèíóñ x - - PROCEDURE artanh(x: REAL): REAL - îáðàòíûé ãèïåðáîëè÷åñêèé òàíãåíñ x - - PROCEDURE round(x: REAL): REAL - îêðóãëåíèå x äî áëèæàéøåãî öåëîãî - - PROCEDURE frac(x: REAL): REAL; - äðîáíàÿ ÷àñòü ÷èñëà x - - PROCEDURE floor(x: REAL): REAL - íàèáîëüøåå öåëîå ÷èñëî (ïðåäñòàâëåíèå êàê REAL), - íå áîëüøå x: floor(1.2) = 1.0 - - PROCEDURE ceil(x: REAL): REAL - íàèìåíüøåå öåëîå ÷èñëî (ïðåäñòàâëåíèå êàê REAL), - íå ìåíüøå x: ceil(1.2) = 2.0 - - PROCEDURE sgn(x: REAL): INTEGER - åñëè x > 0 âîçâðàùàåò 1 - åñëè x < 0 âîçâðàùàåò -1 - åñëè x = 0 âîçâðàùàåò 0 - - PROCEDURE fact(n: INTEGER): REAL - ôàêòîðèàë n - ------------------------------------------------------------------------------- -MODULE Debug - âûâîä íà äîñêó îòëàäêè - Èíòåðôåéñ êàê ìîäóëü Out - - PROCEDURE Open - îòêðûâàåò äîñêó îòëàäêè - ------------------------------------------------------------------------------- -MODULE File - ðàáîòà ñ ôàéëîâîé ñèñòåìîé - - TYPE - - FNAME = ARRAY 520 OF CHAR - - FS = POINTER TO rFS - - rFS = RECORD (* èíôîðìàöèîííàÿ ñòðóêòóðà ôàéëà *) - subfunc, pos, hpos, bytes, buffer: INTEGER; - name: FNAME - END - - FD = POINTER TO rFD - - rFD = RECORD (* ñòðóêòóðà áëîêà äàííûõ âõîäà êàòàëîãà *) - attr: INTEGER; - ntyp: CHAR; - reserved: ARRAY 3 OF CHAR; - time_create, date_create, - time_access, date_access, - time_modif, date_modif, - size, hsize: INTEGER; - name: FNAME - END - - CONST - - SEEK_BEG = 0 - SEEK_CUR = 1 - SEEK_END = 2 - - PROCEDURE Load(FName: ARRAY OF CHAR; VAR size: INTEGER): INTEGER; - Çàãðóæàåò â ïàìÿòü ôàéë ñ èìåíåì FName, çàïèñûâàåò â ïàðàìåòð - size ðàçìåð ôàéëà, âîçâðàùàåò àäðåñ çàãðóæåííîãî ôàéëà - èëè 0 (îøèáêà). Ïðè íåîáõîäèìîñòè, ðàñïàêîâûâàåò - ôàéë (kunpack). - - PROCEDURE GetFileInfo(FName: ARRAY OF CHAR; VAR Info: rFD): BOOLEAN - Çàïèñûâàåò ñòðóêòóðó áëîêà äàííûõ âõîäà êàòàëîãà äëÿ ôàéëà - èëè ïàïêè ñ èìåíåì FName â ïàðàìåòð Info. - Ïðè îøèáêå âîçâðàùàåò FALSE. - - PROCEDURE Exists(FName: ARRAY OF CHAR): BOOLEAN - âîçâðàùàåò TRUE, åñëè ôàéë ñ èìåíåì FName ñóùåñòâóåò - - PROCEDURE Close(VAR F: FS) - îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ äëÿ èíôîðìàöèîííîé ñòðóêòóðû - ôàéëà F è ïðèñâàèâàåò F çíà÷åíèå NIL - - PROCEDURE Open(FName: ARRAY OF CHAR): FS - âîçâðàùàåò óêàçàòåëü íà èíôîðìàöèîííóþ ñòðóêòóðó ôàéëà ñ - èìåíåì FName, ïðè îøèáêå âîçâðàùàåò NIL - - PROCEDURE Delete(FName: ARRAY OF CHAR): BOOLEAN - óäàëÿåò ôàéë ñ èìåíåì FName, ïðè îøèáêå âîçâðàùàåò FALSE - - PROCEDURE Seek(F: FS; Offset, Origin: INTEGER): INTEGER - óñòàíàâëèâàåò ïîçèöèþ ÷òåíèÿ-çàïèñè ôàéëà F íà Offset, - îòíîñèòåëüíî Origin = (SEEK_BEG - íà÷àëî ôàéëà, - SEEK_CUR - òåêóùàÿ ïîçèöèÿ, SEEK_END - êîíåö ôàéëà), - âîçâðàùàåò ïîçèöèþ îòíîñèòåëüíî íà÷àëà ôàéëà, íàïðèìåð: - Seek(F, 0, SEEK_END) - óñòàíàâëèâàåò ïîçèöèþ íà êîíåö ôàéëà è âîçâðàùàåò äëèíó - ôàéëà; ïðè îøèáêå âîçâðàùàåò -1 - - PROCEDURE Read(F: FS; Buffer, Count: INTEGER): INTEGER - ×èòàåò äàííûå èç ôàéëà â ïàìÿòü. F - óêàçàòåëü íà - èíôîðìàöèîííóþ ñòðóêòóðó ôàéëà, Buffer - àäðåñ îáëàñòè - ïàìÿòè, Count - êîëè÷åñòâî áàéò, êîòîðîå òðåáóåòñÿ ïðî÷èòàòü - èç ôàéëà; âîçâðàùàåò êîëè÷åñòâî áàéò, êîòîðîå áûëî ïðî÷èòàíî - è ñîîòâåòñòâóþùèì îáðàçîì èçìåíÿåò ïîçèöèþ ÷òåíèÿ/çàïèñè â - èíôîðìàöèîííîé ñòðóêòóðå F. - - PROCEDURE Write(F: FS; Buffer, Count: INTEGER): INTEGER - Çàïèñûâàåò äàííûå èç ïàìÿòè â ôàéë. F - óêàçàòåëü íà - èíôîðìàöèîííóþ ñòðóêòóðó ôàéëà, Buffer - àäðåñ îáëàñòè - ïàìÿòè, Count - êîëè÷åñòâî áàéò, êîòîðîå òðåáóåòñÿ çàïèñàòü - â ôàéë; âîçâðàùàåò êîëè÷åñòâî áàéò, êîòîðîå áûëî çàïèñàíî è - ñîîòâåòñòâóþùèì îáðàçîì èçìåíÿåò ïîçèöèþ ÷òåíèÿ/çàïèñè â - èíôîðìàöèîííîé ñòðóêòóðå F. - - PROCEDURE Create(FName: ARRAY OF CHAR): FS - ñîçäàåò íîâûé ôàéë ñ èìåíåì FName (ïîëíîå èìÿ), âîçâðàùàåò - óêàçàòåëü íà èíôîðìàöèîííóþ ñòðóêòóðó ôàéëà, - ïðè îøèáêå âîçâðàùàåò NIL - - PROCEDURE CreateDir(DirName: ARRAY OF CHAR): BOOLEAN - ñîçäàåò ïàïêó ñ èìåíåì DirName, âñå ïðîìåæóòî÷íûå ïàïêè - äîëæíû ñóùåñòâîâàòü, ïðè îøèáêå âîçâðàùàåò FALSE - - PROCEDURE DeleteDir(DirName: ARRAY OF CHAR): BOOLEAN - óäàëÿåò ïóñòóþ ïàïêó ñ èìåíåì DirName, - ïðè îøèáêå âîçâðàùàåò FALSE - - PROCEDURE DirExists(DirName: ARRAY OF CHAR): BOOLEAN - âîçâðàùàåò TRUE, åñëè ïàïêà ñ èìåíåì DirName ñóùåñòâóåò - ------------------------------------------------------------------------------- -MODULE Read - ÷òåíèå îñíîâíûõ òèïîâ äàííûõ èç ôàéëà F - - Ïðîöåäóðû âîçâðàùàþò TRUE â ñëó÷àå óñïåøíîé îïåðàöèè ÷òåíèÿ è - ñîîòâåòñòâóþùèì îáðàçîì èçìåíÿþò ïîçèöèþ ÷òåíèÿ/çàïèñè â - èíôîðìàöèîííîé ñòðóêòóðå F - - PROCEDURE Char(F: File.FS; VAR x: CHAR): BOOLEAN - - PROCEDURE Int(F: File.FS; VAR x: INTEGER): BOOLEAN - - PROCEDURE Real(F: File.FS; VAR x: REAL): BOOLEAN - - PROCEDURE Boolean(F: File.FS; VAR x: BOOLEAN): BOOLEAN - - PROCEDURE Set(F: File.FS; VAR x: SET): BOOLEAN - - PROCEDURE WChar(F: File.FS; VAR x: WCHAR): BOOLEAN - ------------------------------------------------------------------------------- -MODULE Write - çàïèñü îñíîâíûõ òèïîâ äàííûõ â ôàéë F - - Ïðîöåäóðû âîçâðàùàþò TRUE â ñëó÷àå óñïåøíîé îïåðàöèè çàïèñè è - ñîîòâåòñòâóþùèì îáðàçîì èçìåíÿþò ïîçèöèþ ÷òåíèÿ/çàïèñè â - èíôîðìàöèîííîé ñòðóêòóðå F - - PROCEDURE Char(F: File.FS; x: CHAR): BOOLEAN - - PROCEDURE Int(F: File.FS; x: INTEGER): BOOLEAN - - PROCEDURE Real(F: File.FS; x: REAL): BOOLEAN - - PROCEDURE Boolean(F: File.FS; x: BOOLEAN): BOOLEAN - - PROCEDURE Set(F: File.FS; x: SET): BOOLEAN - - PROCEDURE WChar(F: File.FS; x: WCHAR): BOOLEAN - ------------------------------------------------------------------------------- -MODULE DateTime - äàòà, âðåìÿ - - CONST ERR = -7.0E5 - - PROCEDURE Now(VAR Year, Month, Day, Hour, Min, Sec: INTEGER) - çàïèñûâàåò â ïàðàìåòðû êîìïîíåíòû òåêóùåé ñèñòåìíîé äàòû è - âðåìåíè - - PROCEDURE Encode(Year, Month, Day, Hour, Min, Sec: INTEGER): REAL - âîçâðàùàåò äàòó, ïîëó÷åííóþ èç êîìïîíåíòîâ - Year, Month, Day, Hour, Min, Sec; - ïðè îøèáêå âîçâðàùàåò êîíñòàíòó ERR = -7.0E5 - - PROCEDURE Decode(Date: REAL; VAR Year, Month, Day, - Hour, Min, Sec: INTEGER): BOOLEAN - èçâëåêàåò êîìïîíåíòû - Year, Month, Day, Hour, Min, Sec èç äàòû Date; - ïðè îøèáêå âîçâðàùàåò FALSE - ------------------------------------------------------------------------------- -MODULE Args - ïàðàìåòðû ïðîãðàììû - - VAR argc: INTEGER - êîëè÷åñòâî ïàðàìåòðîâ ïðîãðàììû, âêëþ÷àÿ èìÿ - èñïîëíÿåìîãî ôàéëà - - PROCEDURE GetArg(n: INTEGER; VAR s: ARRAY OF CHAR) - çàïèñûâàåò â ñòðîêó s n-é ïàðàìåòð ïðîãðàììû, - íóìåðàöèÿ ïàðàìåòðîâ îò 0 äî argc - 1, - íóëåâîé ïàðàìåòð -- èìÿ èñïîëíÿåìîãî ôàéëà - ------------------------------------------------------------------------------- -MODULE KOSAPI - - PROCEDURE sysfunc1(arg1: INTEGER): INTEGER - PROCEDURE sysfunc2(arg1, arg2: INTEGER): INTEGER - ... - PROCEDURE sysfunc7(arg1, arg2, ..., arg7: INTEGER): INTEGER - Îáåðòêè äëÿ ôóíêöèé API ÿäðà KolibriOS. - arg1 .. arg7 ñîîòâåòñòâóþò ðåãèñòðàì - eax, ebx, ecx, edx, esi, edi, ebp; - âîçâðàùàþò çíà÷åíèå ðåãèñòðà eax ïîñëå ñèñòåìíîãî âûçîâà. - - PROCEDURE sysfunc22(arg1, arg2: INTEGER; VAR res2: INTEGER): INTEGER - Îáåðòêà äëÿ ôóíêöèé API ÿäðà KolibriOS. - arg1 - ðåãèñòð eax, arg2 - ðåãèñòð ebx, - res2 - çíà÷åíèå ðåãèñòðà ebx ïîñëå ñèñòåìíîãî âûçîâà; - âîçâðàùàåò çíà÷åíèå ðåãèñòðà eax ïîñëå ñèñòåìíîãî âûçîâà. - - PROCEDURE malloc(size: INTEGER): INTEGER - Âûäåëÿåò áëîê ïàìÿòè. - size - ðàçìåð áëîêà â áàéòàõ, - âîçâðàùàåò àäðåñ âûäåëåííîãî áëîêà - - PROCEDURE free(ptr: INTEGER): INTEGER - Îñâîáîæäàåò ðàíåå âûäåëåííûé áëîê ïàìÿòè ñ àäðåñîì ptr, - âîçâðàùàåò 0 - - PROCEDURE realloc(ptr, size: INTEGER): INTEGER - Ïåðåðàñïðåäåëÿåò áëîê ïàìÿòè, - ptr - àäðåñ ðàíåå âûäåëåííîãî áëîêà, - size - íîâûé ðàçìåð, - âîçâðàùàåò óêàçàòåëü íà ïåðåðàñïðåäåëåííûé áëîê, - 0 ïðè îøèáêå - - PROCEDURE GetCommandLine(): INTEGER - Âîçâðàùàåò àäðåñ ñòðîêè ïàðàìåòðîâ - - PROCEDURE GetName(): INTEGER - Âîçâðàùàåò àäðåñ ñòðîêè ñ èìåíåì ïðîãðàììû - - PROCEDURE LoadLib(name: ARRAY OF CHAR): INTEGER - Çàãðóæàåò DLL ñ ïîëíûì èìåíåì name. Âîçâðàùàåò àäðåñ òàáëèöû - ýêñïîðòà. Ïðè îøèáêå âîçâðàùàåò 0. - - PROCEDURE GetProcAdr(name: ARRAY OF CHAR; lib: INTEGER): INTEGER - name - èìÿ ïðîöåäóðû - lib - àäðåñ òàáëèöû ýêñïîðòà DLL - Âîçâðàùàåò àäðåñ ïðîöåäóðû. Ïðè îøèáêå âîçâðàùàåò 0. - ------------------------------------------------------------------------------- -MODULE ColorDlg - ðàáîòà ñ äèàëîãîì "Color Dialog" - - TYPE - - Dialog = POINTER TO RECORD (* ñòðóêòóðà äèàëîãà *) - status: INTEGER (* ñîñòîÿíèå äèàëîãà: - 0 - ïîëüçîâàòåëü íàæàë Cancel - 1 - ïîëüçîâàòåëü íàæàë OK - 2 - äèàëîã îòêðûò *) - - color: INTEGER (* âûáðàííûé öâåò *) - END - - PROCEDURE Create(draw_window: DRAW_WINDOW): Dialog - ñîçäàòü äèàëîã - draw_window - ïðîöåäóðà ïåðåðèñîâêè îñíîâíîãî îêíà - (TYPE DRAW_WINDOW = PROCEDURE); - ïðîöåäóðà âîçâðàùàåò óêàçàòåëü íà ñòðóêòóðó äèàëîãà - - PROCEDURE Show(cd: Dialog) - ïîêàçàòü äèàëîã - cd - óêàçàòåëü íà ñòðóêòóðó äèàëîãà, êîòîðûé áûë ñîçäàí ðàíåå - ïðîöåäóðîé Create - - PROCEDURE Destroy(VAR cd: Dialog) - óíè÷òîæèòü äèàëîã - cd - óêàçàòåëü íà ñòðóêòóðó äèàëîãà - ------------------------------------------------------------------------------- -MODULE OpenDlg - ðàáîòà ñ äèàëîãîì "Open Dialog" - - TYPE - - Dialog = POINTER TO RECORD (* ñòðóêòóðà äèàëîãà *) - status: INTEGER (* ñîñòîÿíèå äèàëîãà: - 0 - ïîëüçîâàòåëü íàæàë Cancel - 1 - ïîëüçîâàòåëü íàæàë OK - 2 - äèàëîã îòêðûò *) - - FileName: ARRAY 4096 OF CHAR (* èìÿ âûáðàííîãî ôàéëà *) - FilePath: ARRAY 4096 OF CHAR (* ïîëíîå èìÿ âûáðàííîãî - ôàéëà *) - END - - PROCEDURE Create(draw_window: DRAW_WINDOW; type: INTEGER; def_path, - filter: ARRAY OF CHAR): Dialog - ñîçäàòü äèàëîã - draw_window - ïðîöåäóðà ïåðåðèñîâêè îñíîâíîãî îêíà - (TYPE DRAW_WINDOW = PROCEDURE) - type - òèï äèàëîãà - 0 - îòêðûòü - 1 - ñîõðàíèòü - 2 - âûáðàòü ïàïêó - def_path - ïóòü ïî óìîë÷àíèþ, ïàïêà def_path áóäåò îòêðûòà - ïðè ïåðâîì çàïóñêå äèàëîãà - filter - â ñòðîêå çàïèñàíî ïåðå÷èñëåíèå ðàñøèðåíèé ôàéëîâ, - êîòîðûå áóäóò ïîêàçàíû â äèàëîãîâîì îêíå, ðàñøèðåíèÿ - ðàçäåëÿþòñÿ ñèìâîëîì "|", íàïðèìåð: "ASM|TXT|INI" - ïðîöåäóðà âîçâðàùàåò óêàçàòåëü íà ñòðóêòóðó äèàëîãà - - PROCEDURE Show(od: Dialog; Width, Height: INTEGER) - ïîêàçàòü äèàëîã - od - óêàçàòåëü íà ñòðóêòóðó äèàëîãà, êîòîðûé áûë ñîçäàí ðàíåå - ïðîöåäóðîé Create - Width è Height - øèðèíà è âûñîòà äèàëîãîâîãî îêíà - - PROCEDURE Destroy(VAR od: Dialog) - óíè÷òîæèòü äèàëîã - od - óêàçàòåëü íà ñòðóêòóðó äèàëîãà - ------------------------------------------------------------------------------- -MODULE kfonts - ðàáîòà ñ kf-øðèôòàìè - - CONST - - bold = 1 - italic = 2 - underline = 4 - strike_through = 8 - smoothing = 16 - bpp32 = 32 - - TYPE - - TFont = POINTER TO TFont_desc (* óêàçàòåëü íà øðèôò *) - - PROCEDURE LoadFont(file_name: ARRAY OF CHAR): TFont - çàãðóçèòü øðèôò èç ôàéëà - file_name èìÿ kf-ôàéëà - ðåç-ò: óêàçàòåëü íà øðèôò/NIL (îøèáêà) - - PROCEDURE SetSize(Font: TFont; font_size: INTEGER): BOOLEAN - óñòàíîâèòü ðàçìåð øðèôòà - Font óêàçàòåëü íà øðèôò - font_size ðàçìåð øðèôòà - ðåç-ò: TRUE/FALSE (îøèáêà) - - PROCEDURE Enabled(Font: TFont; font_size: INTEGER): BOOLEAN - ïðîâåðèòü, åñòü ëè øðèôò, çàäàííîãî ðàçìåðà - Font óêàçàòåëü íà øðèôò - font_size ðàçìåð øðèôòà - ðåç-ò: TRUE/FALSE (øðèôòà íåò) - - PROCEDURE Destroy(VAR Font: TFont) - âûãðóçèòü øðèôò, îñâîáîäèòü äèíàìè÷åñêóþ ïàìÿòü - Font óêàçàòåëü íà øðèôò - Ïðèñâàèâàåò ïåðåìåííîé Font çíà÷åíèå NIL - - PROCEDURE TextHeight(Font: TFont): INTEGER - ïîëó÷èòü âûñîòó ñòðîêè òåêñòà - Font óêàçàòåëü íà øðèôò - ðåç-ò: âûñîòà ñòðîêè òåêñòà â ïèêñåëÿõ - - PROCEDURE TextWidth(Font: TFont; - str, length, params: INTEGER): INTEGER - ïîëó÷èòü øèðèíó ñòðîêè òåêñòà - Font óêàçàòåëü íà øðèôò - str àäðåñ ñòðîêè òåêñòà â êîäèðîâêå Win-1251 - length êîëè÷åñòâî ñèìâîëîâ â ñòðîêå èëè -1, åñëè ñòðîêà - çàâåðøàåòñÿ íóëåì - params ïàðàìåòðû-ôëàãè ñì. íèæå - ðåç-ò: øèðèíà ñòðîêè òåêñòà â ïèêñåëÿõ - - PROCEDURE TextOut(Font: TFont; - canvas, x, y, str, length, color, params: INTEGER) - âûâåñòè òåêñò â áóôåð - äëÿ âûâîäà áóôåðà â îêíî, èñïîëüçîâàòü ô.65 èëè - ô.7 (åñëè áóôåð 24-áèòíûé) - Font óêàçàòåëü íà øðèôò - canvas àäðåñ ãðàôè÷åñêîãî áóôåðà - ñòðóêòóðà áóôåðà: - Xsize dd - Ysize dd - picture rb Xsize * Ysize * 4 (32 áèòà) - èëè Xsize * Ysize * 3 (24 áèòà) - x, y êîîðäèíàòû òåêñòà îòíîñèòåëüíî ëåâîãî âåðõíåãî - óãëà áóôåðà - str àäðåñ ñòðîêè òåêñòà â êîäèðîâêå Win-1251 - length êîëè÷åñòâî ñèìâîëîâ â ñòðîêå èëè -1, åñëè ñòðîêà - çàâåðøàåòñÿ íóëåì - color öâåò òåêñòà 0x00RRGGBB - params ïàðàìåòðû-ôëàãè: - 1 æèðíûé - 2 êóðñèâ - 4 ïîä÷åðêíóòûé - 8 ïåðå÷åðêíóòûé - 16 ïðèìåíèòü ñãëàæèâàíèå - 32 âûâîä â 32-áèòíûé áóôåð - âîçìîæíî èñïîëüçîâàíèå ôëàãîâ â ëþáûõ ñî÷åòàíèÿõ ------------------------------------------------------------------------------- -MODULE RasterWorks - îáåðòêà áèáëèîòåêè Rasterworks.obj ------------------------------------------------------------------------------- -MODULE libimg - îáåðòêà áèáëèîòåêè libimg.obj ------------------------------------------------------------------------------- \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/KOSLib866.txt b/programs/develop/oberon07/Docs/KOSLib866.txt deleted file mode 100644 index 7b501634ae..0000000000 --- a/programs/develop/oberon07/Docs/KOSLib866.txt +++ /dev/null @@ -1,566 +0,0 @@ -============================================================================== - - ¨¡«¨®â¥ª  (KolibriOS) - ------------------------------------------------------------------------------- -MODULE Out - ª®­á®«ì­ë© ¢ë¢®¤ - - PROCEDURE Open - ä®à¬ «ì­® ®âªà뢠¥â ª®­á®«ì­ë© ¢ë¢®¤ - - PROCEDURE Int(x, width: INTEGER) - ¢ë¢®¤ 楫®£® ç¨á«  x; - width - ª®«¨ç¥á⢮ §­ ª®¬¥áâ, ¨á¯®«ì§ã¥¬ëå ¤«ï ¢ë¢®¤  - - PROCEDURE Real(x: REAL; width: INTEGER) - ¢ë¢®¤ ¢¥é¥á⢥­­®£® ç¨á«  x ¢ ¯« ¢ î饬 ä®à¬ â¥; - width - ª®«¨ç¥á⢮ §­ ª®¬¥áâ, ¨á¯®«ì§ã¥¬ëå ¤«ï ¢ë¢®¤  - - PROCEDURE Char(x: CHAR) - ¢ë¢®¤ ᨬ¢®«  x - - PROCEDURE FixReal(x: REAL; width, p: INTEGER) - ¢ë¢®¤ ¢¥é¥á⢥­­®£® ç¨á«  x ¢ 䨪á¨à®¢ ­­®¬ ä®à¬ â¥; - width - ª®«¨ç¥á⢮ §­ ª®¬¥áâ, ¨á¯®«ì§ã¥¬ëå ¤«ï ¢ë¢®¤ ; - p - ª®«¨ç¥á⢮ §­ ª®¢ ¯®á«¥ ¤¥áïâ¨ç­®© â®çª¨ - - PROCEDURE Ln - ¯¥à¥å®¤ ­  á«¥¤ãîéãî áâபã - - PROCEDURE String(s: ARRAY OF CHAR) - ¢ë¢®¤ áâப¨ s - ------------------------------------------------------------------------------- -MODULE In - ª®­á®«ì­ë© ¢¢®¤ - - VAR Done: BOOLEAN - ¯à¨­¨¬ ¥â §­ ç¥­¨¥ TRUE ¢ á«ãç ¥ ãᯥ譮£® ¢ë¯®«­¥­¨ï - ®¯¥à æ¨¨ ¢¢®¤ , ¨­ ç¥ FALSE - - PROCEDURE Open - ä®à¬ «ì­® ®âªà뢠¥â ª®­á®«ì­ë© ¢¢®¤, - â ª¦¥ ¯à¨á¢ ¨¢ ¥â ¯¥à¥¬¥­­®© Done §­ ç¥­¨¥ TRUE - - PROCEDURE Int(VAR x: INTEGER) - ¢¢®¤ ç¨á«  ⨯  INTEGER - - PROCEDURE Char(VAR x: CHAR) - ¢¢®¤ ᨬ¢®«  - - PROCEDURE Real(VAR x: REAL) - ¢¢®¤ ç¨á«  ⨯  REAL - - PROCEDURE String(VAR s: ARRAY OF CHAR) - ¢¢®¤ áâப¨ - - PROCEDURE Ln - ®¦¨¤ ­¨¥ ­ ¦ â¨ï ENTER - ------------------------------------------------------------------------------- -MODULE Console - ¤®¯®«­¨â¥«ì­ë¥ ¯à®æ¥¤ãàë ª®­á®«ì­®£® ¢ë¢®¤  - - CONST - - ‘«¥¤ãî騥 ª®­áâ ­âë ®¯à¥¤¥«ïîâ 梥⠪®­á®«ì­®£® ¢ë¢®¤  - - Black = 0 Blue = 1 Green = 2 - Cyan = 3 Red = 4 Magenta = 5 - Brown = 6 LightGray = 7 DarkGray = 8 - LightBlue = 9 LightGreen = 10 LightCyan = 11 - LightRed = 12 LightMagenta = 13 Yellow = 14 - White = 15 - - PROCEDURE Cls - ®ç¨á⪠ ®ª­  ª®­á®«¨ - - PROCEDURE SetColor(FColor, BColor: INTEGER) - ãáâ ­®¢ª  æ¢¥â  ª®­á®«ì­®£® ¢ë¢®¤ : FColor - 梥â ⥪áâ , - BColor - 梥â ä®­ , ¢®§¬®¦­ë¥ §­ ç¥­¨ï - ¢ë襯¥à¥ç¨á«¥­­ë¥ - ª®­áâ ­âë - - PROCEDURE SetCursor(x, y: INTEGER) - ãáâ ­®¢ª  ªãàá®à  ª®­á®«¨ ¢ ¯®§¨æ¨î (x, y) - - PROCEDURE GetCursor(VAR x, y: INTEGER) - § ¯¨á뢠¥â ¢ ¯ à ¬¥âàë ⥪ã騥 ª®®à¤¨­ âë ªãàá®à  ª®­á®«¨ - - PROCEDURE GetCursorX(): INTEGER - ¢®§¢à é ¥â ⥪ãéãî x-ª®®à¤¨­ âã ªãàá®à  ª®­á®«¨ - - PROCEDURE GetCursorY(): INTEGER - ¢®§¢à é ¥â ⥪ãéãî y-ª®®à¤¨­ âã ªãàá®à  ª®­á®«¨ - ------------------------------------------------------------------------------- -MODULE ConsoleLib - ®¡¥à⪠ ¡¨¡«¨®â¥ª¨ console.obj - ------------------------------------------------------------------------------- -MODULE Math - ¬ â¥¬ â¨ç¥áª¨¥ ä㭪樨 - - CONST - - pi = 3.141592653589793E+00 - e = 2.718281828459045E+00 - - - PROCEDURE IsNan(x: REAL): BOOLEAN - ¢®§¢à é ¥â TRUE, ¥á«¨ x - ­¥ ç¨á«® - - PROCEDURE IsInf(x: REAL): BOOLEAN - ¢®§¢à é ¥â TRUE, ¥á«¨ x - ¡¥áª®­¥ç­®áâì - - PROCEDURE sqrt(x: REAL): REAL - ª¢ ¤à â­ë© ª®à¥­ì x - - PROCEDURE exp(x: REAL): REAL - íªá¯®­¥­â  x - - PROCEDURE ln(x: REAL): REAL - ­ âãà «ì­ë© «®£ à¨ä¬ x - - PROCEDURE sin(x: REAL): REAL - ᨭãá x - - PROCEDURE cos(x: REAL): REAL - ª®á¨­ãá x - - PROCEDURE tan(x: REAL): REAL - â ­£¥­á x - - PROCEDURE arcsin(x: REAL): REAL -  àªá¨­ãá x - - PROCEDURE arccos(x: REAL): REAL -  àªª®á¨­ãá x - - PROCEDURE arctan(x: REAL): REAL -  àªâ ­£¥­á x - - PROCEDURE arctan2(y, x: REAL): REAL -  àªâ ­£¥­á y/x - - PROCEDURE power(base, exponent: REAL): REAL - ¢®§¢¥¤¥­¨¥ ç¨á«  base ¢ á⥯¥­ì exponent - - PROCEDURE log(base, x: REAL): REAL - «®£ à¨ä¬ x ¯® ®á­®¢ ­¨î base - - PROCEDURE sinh(x: REAL): REAL - £¨¯¥à¡®«¨ç¥áª¨© ᨭãá x - - PROCEDURE cosh(x: REAL): REAL - £¨¯¥à¡®«¨ç¥áª¨© ª®á¨­ãá x - - PROCEDURE tanh(x: REAL): REAL - £¨¯¥à¡®«¨ç¥áª¨© â ­£¥­á x - - PROCEDURE arsinh(x: REAL): REAL - ®¡à â­ë© £¨¯¥à¡®«¨ç¥áª¨© ᨭãá x - - PROCEDURE arcosh(x: REAL): REAL - ®¡à â­ë© £¨¯¥à¡®«¨ç¥áª¨© ª®á¨­ãá x - - PROCEDURE artanh(x: REAL): REAL - ®¡à â­ë© £¨¯¥à¡®«¨ç¥áª¨© â ­£¥­á x - - PROCEDURE round(x: REAL): REAL - ®ªà㣫¥­¨¥ x ¤® ¡«¨¦ ©è¥£® 楫®£® - - PROCEDURE frac(x: REAL): REAL; - ¤à®¡­ ï ç áâì ç¨á«  x - - PROCEDURE floor(x: REAL): REAL - ­ ¨¡®«ì襥 楫®¥ ç¨á«® (¯à¥¤áâ ¢«¥­¨¥ ª ª REAL), - ­¥ ¡®«ìè¥ x: floor(1.2) = 1.0 - - PROCEDURE ceil(x: REAL): REAL - ­ ¨¬¥­ì襥 楫®¥ ç¨á«® (¯à¥¤áâ ¢«¥­¨¥ ª ª REAL), - ­¥ ¬¥­ìè¥ x: ceil(1.2) = 2.0 - - PROCEDURE sgn(x: REAL): INTEGER - ¥á«¨ x > 0 ¢®§¢à é ¥â 1 - ¥á«¨ x < 0 ¢®§¢à é ¥â -1 - ¥á«¨ x = 0 ¢®§¢à é ¥â 0 - - PROCEDURE fact(n: INTEGER): REAL - ä ªâ®à¨ « n - ------------------------------------------------------------------------------- -MODULE Debug - ¢ë¢®¤ ­  ¤®áªã ®â« ¤ª¨ - ˆ­â¥àä¥©á ª ª ¬®¤ã«ì Out - - PROCEDURE Open - ®âªà뢠¥â ¤®áªã ®â« ¤ª¨ - ------------------------------------------------------------------------------- -MODULE File - à ¡®â  á ä ©«®¢®© á¨á⥬®© - - TYPE - - FNAME = ARRAY 520 OF CHAR - - FS = POINTER TO rFS - - rFS = RECORD (* ¨­ä®à¬ æ¨®­­ ï áâàãªâãà  ä ©«  *) - subfunc, pos, hpos, bytes, buffer: INTEGER; - name: FNAME - END - - FD = POINTER TO rFD - - rFD = RECORD (* áâàãªâãà  ¡«®ª  ¤ ­­ëå ¢å®¤  ª â «®£  *) - attr: INTEGER; - ntyp: CHAR; - reserved: ARRAY 3 OF CHAR; - time_create, date_create, - time_access, date_access, - time_modif, date_modif, - size, hsize: INTEGER; - name: FNAME - END - - CONST - - SEEK_BEG = 0 - SEEK_CUR = 1 - SEEK_END = 2 - - PROCEDURE Load(FName: ARRAY OF CHAR; VAR size: INTEGER): INTEGER; - ‡ £à㦠¥â ¢ ¯ ¬ïâì ä ©« á ¨¬¥­¥¬ FName, § ¯¨á뢠¥â ¢ ¯ à ¬¥âà - size à §¬¥à ä ©« , ¢®§¢à é ¥â  ¤à¥á § £à㦥­­®£® ä ©«  - ¨«¨ 0 (®è¨¡ª ). ਠ­¥®¡å®¤¨¬®áâ¨, à á¯ ª®¢ë¢ ¥â - ä ©« (kunpack). - - PROCEDURE GetFileInfo(FName: ARRAY OF CHAR; VAR Info: rFD): BOOLEAN - ‡ ¯¨á뢠¥â áâàãªâãàã ¡«®ª  ¤ ­­ëå ¢å®¤  ª â «®£  ¤«ï ä ©«  - ¨«¨ ¯ ¯ª¨ á ¨¬¥­¥¬ FName ¢ ¯ à ¬¥âà Info. - ਠ®è¨¡ª¥ ¢®§¢à é ¥â FALSE. - - PROCEDURE Exists(FName: ARRAY OF CHAR): BOOLEAN - ¢®§¢à é ¥â TRUE, ¥á«¨ ä ©« á ¨¬¥­¥¬ FName áãé¥áâ¢ã¥â - - PROCEDURE Close(VAR F: FS) - ®á¢®¡®¦¤ ¥â ¯ ¬ïâì, ¢ë¤¥«¥­­ãî ¤«ï ¨­ä®à¬ æ¨®­­®© áâàãªâãàë - ä ©«  F ¨ ¯à¨á¢ ¨¢ ¥â F §­ ç¥­¨¥ NIL - - PROCEDURE Open(FName: ARRAY OF CHAR): FS - ¢®§¢à é ¥â 㪠§ â¥«ì ­  ¨­ä®à¬ æ¨®­­ãî áâàãªâãàã ä ©«  á - ¨¬¥­¥¬ FName, ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â NIL - - PROCEDURE Delete(FName: ARRAY OF CHAR): BOOLEAN - 㤠«ï¥â ä ©« á ¨¬¥­¥¬ FName, ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â FALSE - - PROCEDURE Seek(F: FS; Offset, Origin: INTEGER): INTEGER - ãáâ ­ ¢«¨¢ ¥â ¯®§¨æ¨î ç⥭¨ï-§ ¯¨á¨ ä ©«  F ­  Offset, - ®â­®á¨â¥«ì­® Origin = (SEEK_BEG - ­ ç «® ä ©« , - SEEK_CUR - ⥪ãé ï ¯®§¨æ¨ï, SEEK_END - ª®­¥æ ä ©« ), - ¢®§¢à é ¥â ¯®§¨æ¨î ®â­®á¨â¥«ì­® ­ ç «  ä ©« , ­ ¯à¨¬¥à: - Seek(F, 0, SEEK_END) - ãáâ ­ ¢«¨¢ ¥â ¯®§¨æ¨î ­  ª®­¥æ ä ©«  ¨ ¢®§¢à é ¥â ¤«¨­ã - ä ©« ; ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â -1 - - PROCEDURE Read(F: FS; Buffer, Count: INTEGER): INTEGER - —¨â ¥â ¤ ­­ë¥ ¨§ ä ©«  ¢ ¯ ¬ïâì. F - 㪠§ â¥«ì ­  - ¨­ä®à¬ æ¨®­­ãî áâàãªâãàã ä ©« , Buffer -  ¤à¥á ®¡« á⨠- ¯ ¬ïâ¨, Count - ª®«¨ç¥á⢮ ¡ ©â, ª®â®à®¥ âॡã¥âáï ¯à®ç¨â âì - ¨§ ä ©« ; ¢®§¢à é ¥â ª®«¨ç¥á⢮ ¡ ©â, ª®â®à®¥ ¡ë«® ¯à®ç¨â ­® - ¨ ᮮ⢥âáâ¢ãî騬 ®¡à §®¬ ¨§¬¥­ï¥â ¯®§¨æ¨î ç⥭¨ï/§ ¯¨á¨ ¢ - ¨­ä®à¬ æ¨®­­®© áâàãªâãॠF. - - PROCEDURE Write(F: FS; Buffer, Count: INTEGER): INTEGER - ‡ ¯¨á뢠¥â ¤ ­­ë¥ ¨§ ¯ ¬ï⨠¢ ä ©«. F - 㪠§ â¥«ì ­  - ¨­ä®à¬ æ¨®­­ãî áâàãªâãàã ä ©« , Buffer -  ¤à¥á ®¡« á⨠- ¯ ¬ïâ¨, Count - ª®«¨ç¥á⢮ ¡ ©â, ª®â®à®¥ âॡã¥âáï § ¯¨á âì - ¢ ä ©«; ¢®§¢à é ¥â ª®«¨ç¥á⢮ ¡ ©â, ª®â®à®¥ ¡ë«® § ¯¨á ­® ¨ - ᮮ⢥âáâ¢ãî騬 ®¡à §®¬ ¨§¬¥­ï¥â ¯®§¨æ¨î ç⥭¨ï/§ ¯¨á¨ ¢ - ¨­ä®à¬ æ¨®­­®© áâàãªâãॠF. - - PROCEDURE Create(FName: ARRAY OF CHAR): FS - ᮧ¤ ¥â ­®¢ë© ä ©« á ¨¬¥­¥¬ FName (¯®«­®¥ ¨¬ï), ¢®§¢à é ¥â - 㪠§ â¥«ì ­  ¨­ä®à¬ æ¨®­­ãî áâàãªâãàã ä ©« , - ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â NIL - - PROCEDURE CreateDir(DirName: ARRAY OF CHAR): BOOLEAN - ᮧ¤ ¥â ¯ ¯ªã á ¨¬¥­¥¬ DirName, ¢á¥ ¯à®¬¥¦ãâ®ç­ë¥ ¯ ¯ª¨ - ¤®«¦­ë áãé¥á⢮¢ âì, ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â FALSE - - PROCEDURE DeleteDir(DirName: ARRAY OF CHAR): BOOLEAN - 㤠«ï¥â ¯ãáâãî ¯ ¯ªã á ¨¬¥­¥¬ DirName, - ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â FALSE - - PROCEDURE DirExists(DirName: ARRAY OF CHAR): BOOLEAN - ¢®§¢à é ¥â TRUE, ¥á«¨ ¯ ¯ª  á ¨¬¥­¥¬ DirName áãé¥áâ¢ã¥â - ------------------------------------------------------------------------------- -MODULE Read - ç⥭¨¥ ®á­®¢­ëå ⨯®¢ ¤ ­­ëå ¨§ ä ©«  F - - à®æ¥¤ãàë ¢®§¢à é îâ TRUE ¢ á«ãç ¥ ãᯥ譮© ®¯¥à æ¨¨ ç⥭¨ï ¨ - ᮮ⢥âáâ¢ãî騬 ®¡à §®¬ ¨§¬¥­ïîâ ¯®§¨æ¨î ç⥭¨ï/§ ¯¨á¨ ¢ - ¨­ä®à¬ æ¨®­­®© áâàãªâãॠF - - PROCEDURE Char(F: File.FS; VAR x: CHAR): BOOLEAN - - PROCEDURE Int(F: File.FS; VAR x: INTEGER): BOOLEAN - - PROCEDURE Real(F: File.FS; VAR x: REAL): BOOLEAN - - PROCEDURE Boolean(F: File.FS; VAR x: BOOLEAN): BOOLEAN - - PROCEDURE Set(F: File.FS; VAR x: SET): BOOLEAN - - PROCEDURE WChar(F: File.FS; VAR x: WCHAR): BOOLEAN - ------------------------------------------------------------------------------- -MODULE Write - § ¯¨áì ®á­®¢­ëå ⨯®¢ ¤ ­­ëå ¢ ä ©« F - - à®æ¥¤ãàë ¢®§¢à é îâ TRUE ¢ á«ãç ¥ ãᯥ譮© ®¯¥à æ¨¨ § ¯¨á¨ ¨ - ᮮ⢥âáâ¢ãî騬 ®¡à §®¬ ¨§¬¥­ïîâ ¯®§¨æ¨î ç⥭¨ï/§ ¯¨á¨ ¢ - ¨­ä®à¬ æ¨®­­®© áâàãªâãॠF - - PROCEDURE Char(F: File.FS; x: CHAR): BOOLEAN - - PROCEDURE Int(F: File.FS; x: INTEGER): BOOLEAN - - PROCEDURE Real(F: File.FS; x: REAL): BOOLEAN - - PROCEDURE Boolean(F: File.FS; x: BOOLEAN): BOOLEAN - - PROCEDURE Set(F: File.FS; x: SET): BOOLEAN - - PROCEDURE WChar(F: File.FS; x: WCHAR): BOOLEAN - ------------------------------------------------------------------------------- -MODULE DateTime - ¤ â , ¢à¥¬ï - - CONST ERR = -7.0E5 - - PROCEDURE Now(VAR Year, Month, Day, Hour, Min, Sec: INTEGER) - § ¯¨á뢠¥â ¢ ¯ à ¬¥âàë ª®¬¯®­¥­âë ⥪ã饩 á¨á⥬­®© ¤ âë ¨ - ¢à¥¬¥­¨ - - PROCEDURE Encode(Year, Month, Day, Hour, Min, Sec: INTEGER): REAL - ¢®§¢à é ¥â ¤ âã, ¯®«ã祭­ãî ¨§ ª®¬¯®­¥­â®¢ - Year, Month, Day, Hour, Min, Sec; - ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â ª®­áâ ­âã ERR = -7.0E5 - - PROCEDURE Decode(Date: REAL; VAR Year, Month, Day, - Hour, Min, Sec: INTEGER): BOOLEAN - ¨§¢«¥ª ¥â ª®¬¯®­¥­âë - Year, Month, Day, Hour, Min, Sec ¨§ ¤ âë Date; - ¯à¨ ®è¨¡ª¥ ¢®§¢à é ¥â FALSE - ------------------------------------------------------------------------------- -MODULE Args - ¯ à ¬¥âàë ¯à®£à ¬¬ë - - VAR argc: INTEGER - ª®«¨ç¥á⢮ ¯ à ¬¥â஢ ¯à®£à ¬¬ë, ¢ª«îç ï ¨¬ï - ¨á¯®«­ï¥¬®£® ä ©«  - - PROCEDURE GetArg(n: INTEGER; VAR s: ARRAY OF CHAR) - § ¯¨á뢠¥â ¢ áâபã s n-© ¯ à ¬¥âà ¯à®£à ¬¬ë, - ­ã¬¥à æ¨ï ¯ à ¬¥â஢ ®â 0 ¤® argc - 1, - ­ã«¥¢®© ¯ à ¬¥âà -- ¨¬ï ¨á¯®«­ï¥¬®£® ä ©«  - ------------------------------------------------------------------------------- -MODULE KOSAPI - - PROCEDURE sysfunc1(arg1: INTEGER): INTEGER - PROCEDURE sysfunc2(arg1, arg2: INTEGER): INTEGER - ... - PROCEDURE sysfunc7(arg1, arg2, ..., arg7: INTEGER): INTEGER - Ž¡¥à⪨ ¤«ï ä㭪権 API ï¤à  KolibriOS. - arg1 .. arg7 ᮮ⢥âáâ¢ãîâ ॣ¨áâà ¬ - eax, ebx, ecx, edx, esi, edi, ebp; - ¢®§¢à é îâ §­ ç¥­¨¥ ॣ¨áâà  eax ¯®á«¥ á¨á⥬­®£® ¢ë§®¢ . - - PROCEDURE sysfunc22(arg1, arg2: INTEGER; VAR res2: INTEGER): INTEGER - Ž¡¥à⪠ ¤«ï ä㭪権 API ï¤à  KolibriOS. - arg1 - ॣ¨áâà eax, arg2 - ॣ¨áâà ebx, - res2 - §­ ç¥­¨¥ ॣ¨áâà  ebx ¯®á«¥ á¨á⥬­®£® ¢ë§®¢ ; - ¢®§¢à é ¥â §­ ç¥­¨¥ ॣ¨áâà  eax ¯®á«¥ á¨á⥬­®£® ¢ë§®¢ . - - PROCEDURE malloc(size: INTEGER): INTEGER - ‚뤥«ï¥â ¡«®ª ¯ ¬ïâ¨. - size - à §¬¥à ¡«®ª  ¢ ¡ ©â å, - ¢®§¢à é ¥â  ¤à¥á ¢ë¤¥«¥­­®£® ¡«®ª  - - PROCEDURE free(ptr: INTEGER): INTEGER - Žá¢®¡®¦¤ ¥â à ­¥¥ ¢ë¤¥«¥­­ë© ¡«®ª ¯ ¬ïâ¨ á  ¤à¥á®¬ ptr, - ¢®§¢à é ¥â 0 - - PROCEDURE realloc(ptr, size: INTEGER): INTEGER - ¥à¥à á¯à¥¤¥«ï¥â ¡«®ª ¯ ¬ïâ¨, - ptr -  ¤à¥á à ­¥¥ ¢ë¤¥«¥­­®£® ¡«®ª , - size - ­®¢ë© à §¬¥à, - ¢®§¢à é ¥â 㪠§ â¥«ì ­  ¯¥à¥à á¯à¥¤¥«¥­­ë© ¡«®ª, - 0 ¯à¨ ®è¨¡ª¥ - - PROCEDURE GetCommandLine(): INTEGER - ‚®§¢à é ¥â  ¤à¥á áâப¨ ¯ à ¬¥â஢ - - PROCEDURE GetName(): INTEGER - ‚®§¢à é ¥â  ¤à¥á áâப¨ á ¨¬¥­¥¬ ¯à®£à ¬¬ë - - PROCEDURE LoadLib(name: ARRAY OF CHAR): INTEGER - ‡ £à㦠¥â DLL á ¯®«­ë¬ ¨¬¥­¥¬ name. ‚®§¢à é ¥â  ¤à¥á â ¡«¨æë - íªá¯®àâ . ਠ®è¨¡ª¥ ¢®§¢à é ¥â 0. - - PROCEDURE GetProcAdr(name: ARRAY OF CHAR; lib: INTEGER): INTEGER - name - ¨¬ï ¯à®æ¥¤ãàë - lib -  ¤à¥á â ¡«¨æë íªá¯®àâ  DLL - ‚®§¢à é ¥â  ¤à¥á ¯à®æ¥¤ãàë. ਠ®è¨¡ª¥ ¢®§¢à é ¥â 0. - ------------------------------------------------------------------------------- -MODULE ColorDlg - à ¡®â  á ¤¨ «®£®¬ "Color Dialog" - - TYPE - - Dialog = POINTER TO RECORD (* áâàãªâãà  ¤¨ «®£  *) - status: INTEGER (* á®áâ®ï­¨¥ ¤¨ «®£ : - 0 - ¯®«ì§®¢ â¥«ì ­ ¦ « Cancel - 1 - ¯®«ì§®¢ â¥«ì ­ ¦ « OK - 2 - ¤¨ «®£ ®âªàëâ *) - - color: INTEGER (* ¢ë¡à ­­ë© 梥â *) - END - - PROCEDURE Create(draw_window: DRAW_WINDOW): Dialog - ᮧ¤ âì ¤¨ «®£ - draw_window - ¯à®æ¥¤ãà  ¯¥à¥à¨á®¢ª¨ ®á­®¢­®£® ®ª­  - (TYPE DRAW_WINDOW = PROCEDURE); - ¯à®æ¥¤ãà  ¢®§¢à é ¥â 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  - - PROCEDURE Show(cd: Dialog) - ¯®ª § âì ¤¨ «®£ - cd - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£ , ª®â®àë© ¡ë« ᮧ¤ ­ à ­¥¥ - ¯à®æ¥¤ãன Create - - PROCEDURE Destroy(VAR cd: Dialog) - ã­¨ç⮦¨âì ¤¨ «®£ - cd - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  - ------------------------------------------------------------------------------- -MODULE OpenDlg - à ¡®â  á ¤¨ «®£®¬ "Open Dialog" - - TYPE - - Dialog = POINTER TO RECORD (* áâàãªâãà  ¤¨ «®£  *) - status: INTEGER (* á®áâ®ï­¨¥ ¤¨ «®£ : - 0 - ¯®«ì§®¢ â¥«ì ­ ¦ « Cancel - 1 - ¯®«ì§®¢ â¥«ì ­ ¦ « OK - 2 - ¤¨ «®£ ®âªàëâ *) - - FileName: ARRAY 4096 OF CHAR (* ¨¬ï ¢ë¡à ­­®£® ä ©«  *) - FilePath: ARRAY 4096 OF CHAR (* ¯®«­®¥ ¨¬ï ¢ë¡à ­­®£® - ä ©«  *) - END - - PROCEDURE Create(draw_window: DRAW_WINDOW; type: INTEGER; def_path, - filter: ARRAY OF CHAR): Dialog - ᮧ¤ âì ¤¨ «®£ - draw_window - ¯à®æ¥¤ãà  ¯¥à¥à¨á®¢ª¨ ®á­®¢­®£® ®ª­  - (TYPE DRAW_WINDOW = PROCEDURE) - type - ⨯ ¤¨ «®£  - 0 - ®âªàëâì - 1 - á®åà ­¨âì - 2 - ¢ë¡à âì ¯ ¯ªã - def_path - ¯ãâì ¯® 㬮«ç ­¨î, ¯ ¯ª  def_path ¡ã¤¥â ®âªàëâ  - ¯à¨ ¯¥à¢®¬ § ¯ã᪥ ¤¨ «®£  - filter - ¢ áâப¥ § ¯¨á ­® ¯¥à¥ç¨á«¥­¨¥ à áè¨à¥­¨© ä ©«®¢, - ª®â®àë¥ ¡ã¤ãâ ¯®ª § ­ë ¢ ¤¨ «®£®¢®¬ ®ª­¥, à áè¨à¥­¨ï - à §¤¥«ïîâáï ᨬ¢®«®¬ "|", ­ ¯à¨¬¥à: "ASM|TXT|INI" - ¯à®æ¥¤ãà  ¢®§¢à é ¥â 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  - - PROCEDURE Show(od: Dialog; Width, Height: INTEGER) - ¯®ª § âì ¤¨ «®£ - od - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£ , ª®â®àë© ¡ë« ᮧ¤ ­ à ­¥¥ - ¯à®æ¥¤ãன Create - Width ¨ Height - è¨à¨­  ¨ ¢ëá®â  ¤¨ «®£®¢®£® ®ª­  - - PROCEDURE Destroy(VAR od: Dialog) - ã­¨ç⮦¨âì ¤¨ «®£ - od - 㪠§ â¥«ì ­  áâàãªâãàã ¤¨ «®£  - ------------------------------------------------------------------------------- -MODULE kfonts - à ¡®â  á kf-èà¨äâ ¬¨ - - CONST - - bold = 1 - italic = 2 - underline = 4 - strike_through = 8 - smoothing = 16 - bpp32 = 32 - - TYPE - - TFont = POINTER TO TFont_desc (* 㪠§ â¥«ì ­  èà¨äâ *) - - PROCEDURE LoadFont(file_name: ARRAY OF CHAR): TFont - § £à㧨âì èà¨äâ ¨§ ä ©«  - file_name ¨¬ï kf-ä ©«  - १-â: 㪠§ â¥«ì ­  èà¨äâ/NIL (®è¨¡ª ) - - PROCEDURE SetSize(Font: TFont; font_size: INTEGER): BOOLEAN - ãáâ ­®¢¨âì à §¬¥à èà¨äâ  - Font 㪠§ â¥«ì ­  èà¨äâ - font_size à §¬¥à èà¨äâ  - १-â: TRUE/FALSE (®è¨¡ª ) - - PROCEDURE Enabled(Font: TFont; font_size: INTEGER): BOOLEAN - ¯à®¢¥à¨âì, ¥áâì «¨ èà¨äâ, § ¤ ­­®£® à §¬¥à  - Font 㪠§ â¥«ì ­  èà¨äâ - font_size à §¬¥à èà¨äâ  - १-â: TRUE/FALSE (èà¨äâ  ­¥â) - - PROCEDURE Destroy(VAR Font: TFont) - ¢ë£à㧨âì èà¨äâ, ®á¢®¡®¤¨âì ¤¨­ ¬¨ç¥áªãî ¯ ¬ïâì - Font 㪠§ â¥«ì ­  èà¨äâ - à¨á¢ ¨¢ ¥â ¯¥à¥¬¥­­®© Font §­ ç¥­¨¥ NIL - - PROCEDURE TextHeight(Font: TFont): INTEGER - ¯®«ãç¨âì ¢ëá®âã áâப¨ ⥪áâ  - Font 㪠§ â¥«ì ­  èà¨äâ - १-â: ¢ëá®â  áâப¨ ⥪áâ  ¢ ¯¨ªá¥«ïå - - PROCEDURE TextWidth(Font: TFont; - str, length, params: INTEGER): INTEGER - ¯®«ãç¨âì è¨à¨­ã áâப¨ ⥪áâ  - Font 㪠§ â¥«ì ­  èà¨äâ - str  ¤à¥á áâப¨ ⥪áâ  ¢ ª®¤¨à®¢ª¥ Win-1251 - length ª®«¨ç¥á⢮ ᨬ¢®«®¢ ¢ áâப¥ ¨«¨ -1, ¥á«¨ áâப  - § ¢¥àè ¥âáï ­ã«¥¬ - params ¯ à ¬¥âàë-ä« £¨ á¬. ­¨¦¥ - १-â: è¨à¨­  áâப¨ ⥪áâ  ¢ ¯¨ªá¥«ïå - - PROCEDURE TextOut(Font: TFont; - canvas, x, y, str, length, color, params: INTEGER) - ¢ë¢¥á⨠⥪áâ ¢ ¡ãä¥à - ¤«ï ¢ë¢®¤  ¡ãä¥à  ¢ ®ª­®, ¨á¯®«ì§®¢ âì ä.65 ¨«¨ - ä.7 (¥á«¨ ¡ãä¥à 24-¡¨â­ë©) - Font 㪠§ â¥«ì ­  èà¨äâ - canvas  ¤à¥á £à ä¨ç¥áª®£® ¡ãä¥à  - áâàãªâãà  ¡ãä¥à : - Xsize dd - Ysize dd - picture rb Xsize * Ysize * 4 (32 ¡¨â ) - ¨«¨ Xsize * Ysize * 3 (24 ¡¨â ) - x, y ª®®à¤¨­ âë ⥪áâ  ®â­®á¨â¥«ì­® «¥¢®£® ¢¥àå­¥£® - 㣫  ¡ãä¥à  - str  ¤à¥á áâப¨ ⥪áâ  ¢ ª®¤¨à®¢ª¥ Win-1251 - length ª®«¨ç¥á⢮ ᨬ¢®«®¢ ¢ áâப¥ ¨«¨ -1, ¥á«¨ áâப  - § ¢¥àè ¥âáï ­ã«¥¬ - color 梥â ⥪áâ  0x00RRGGBB - params ¯ à ¬¥âàë-ä« £¨: - 1 ¦¨à­ë© - 2 ªãàᨢ - 4 ¯®¤ç¥àª­ãâë© - 8 ¯¥à¥ç¥àª­ãâë© - 16 ¯à¨¬¥­¨âì ᣫ ¦¨¢ ­¨¥ - 32 ¢ë¢®¤ ¢ 32-¡¨â­ë© ¡ãä¥à - ¢®§¬®¦­® ¨á¯®«ì§®¢ ­¨¥ ä« £®¢ ¢ «î¡ëå á®ç¥â ­¨ïå ------------------------------------------------------------------------------- -MODULE RasterWorks - ®¡¥à⪠ ¡¨¡«¨®â¥ª¨ Rasterworks.obj ------------------------------------------------------------------------------- -MODULE libimg - ®¡¥à⪠ ¡¨¡«¨®â¥ª¨ libimg.obj ------------------------------------------------------------------------------- \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/WinLib.txt b/programs/develop/oberon07/Docs/WinLib.txt new file mode 100644 index 0000000000..be342ad92b --- /dev/null +++ b/programs/develop/oberon07/Docs/WinLib.txt @@ -0,0 +1,312 @@ +============================================================================== + + Библиотека (Windows) + +------------------------------------------------------------------------------ +MODULE Out - конÑольный вывод + + PROCEDURE Open + открывает конÑольный вывод + + PROCEDURE Int(x, width: INTEGER) + вывод целого чиÑла x; + width - количеÑтво знакомеÑÑ‚, иÑпользуемых Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð° + + PROCEDURE Real(x: REAL; width: INTEGER) + вывод вещеÑтвенного чиÑла x в плавающем формате; + width - количеÑтво знакомеÑÑ‚, иÑпользуемых Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð° + + PROCEDURE Char(x: CHAR) + вывод Ñимвола x + + PROCEDURE FixReal(x: REAL; width, p: INTEGER) + вывод вещеÑтвенного чиÑла x в фикÑированном формате; + width - количеÑтво знакомеÑÑ‚, иÑпользуемых Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð°; + p - количеÑтво знаков поÑле деÑÑтичной точки + + PROCEDURE Ln + переход на Ñледующую Ñтроку + + PROCEDURE String(s: ARRAY OF CHAR) + вывод Ñтроки s (ASCII) + + PROCEDURE StringW(s: ARRAY OF WCHAR) + вывод Ñтроки s (UTF-16) + +------------------------------------------------------------------------------ +MODULE In - конÑольный ввод + + VAR Done: BOOLEAN + принимает значение TRUE в Ñлучае уÑпешного Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ + операции ввода и FALSE в противном Ñлучае + + PROCEDURE Open + открывает конÑольный ввод, + также приÑваивает переменной Done значение TRUE + + PROCEDURE Int(VAR x: INTEGER) + ввод чиÑла типа INTEGER + + PROCEDURE Char(VAR x: CHAR) + ввод Ñимвола + + PROCEDURE Real(VAR x: REAL) + ввод чиÑла типа REAL + + PROCEDURE String(VAR s: ARRAY OF CHAR) + ввод Ñтроки + + PROCEDURE Ln + ожидание Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ENTER + +------------------------------------------------------------------------------ +MODULE Console - дополнительные процедуры конÑольного вывода + + CONST + + Следующие конÑтанты определÑÑŽÑ‚ цвет конÑольного вывода + + Black = 0 Blue = 1 Green = 2 + Cyan = 3 Red = 4 Magenta = 5 + Brown = 6 LightGray = 7 DarkGray = 8 + LightBlue = 9 LightGreen = 10 LightCyan = 11 + LightRed = 12 LightMagenta = 13 Yellow = 14 + White = 15 + + PROCEDURE Cls + очиÑтка окна конÑоли + + PROCEDURE SetColor(FColor, BColor: INTEGER) + уÑтановка цвета конÑольного вывода: FColor - цвет текÑта, + BColor - цвет фона, возможные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ - вышеперечиÑленные + конÑтанты + + PROCEDURE SetCursor(x, y: INTEGER) + уÑтановка курÑора конÑоли в позицию (x, y) + + PROCEDURE GetCursor(VAR x, y: INTEGER) + запиÑывает в параметры текущие координаты курÑора конÑоли + + PROCEDURE GetCursorX(): INTEGER + возвращает текущую x-координату курÑора конÑоли + + PROCEDURE GetCursorY(): INTEGER + возвращает текущую y-координату курÑора конÑоли + +------------------------------------------------------------------------------ +MODULE Math - математичеÑкие функции + + CONST + + pi = 3.141592653589793E+00 + e = 2.718281828459045E+00 + + PROCEDURE IsNan(x: REAL): BOOLEAN + возвращает TRUE, еÑли x - не чиÑло + + PROCEDURE IsInf(x: REAL): BOOLEAN + возвращает TRUE, еÑли x - беÑконечноÑÑ‚ÑŒ + + PROCEDURE sqrt(x: REAL): REAL + квадратный корень x + + PROCEDURE exp(x: REAL): REAL + ÑкÑпонента x + + PROCEDURE ln(x: REAL): REAL + натуральный логарифм x + + PROCEDURE sin(x: REAL): REAL + ÑÐ¸Ð½ÑƒÑ x + + PROCEDURE cos(x: REAL): REAL + коÑÐ¸Ð½ÑƒÑ x + + PROCEDURE tan(x: REAL): REAL + Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ x + + PROCEDURE arcsin(x: REAL): REAL + аркÑÐ¸Ð½ÑƒÑ x + + PROCEDURE arccos(x: REAL): REAL + арккоÑÐ¸Ð½ÑƒÑ x + + PROCEDURE arctan(x: REAL): REAL + Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ x + + PROCEDURE arctan2(y, x: REAL): REAL + Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ y/x + + PROCEDURE power(base, exponent: REAL): REAL + возведение чиÑла base в Ñтепень exponent + + PROCEDURE log(base, x: REAL): REAL + логарифм x по оÑнованию base + + PROCEDURE sinh(x: REAL): REAL + гиперболичеÑкий ÑÐ¸Ð½ÑƒÑ x + + PROCEDURE cosh(x: REAL): REAL + гиперболичеÑкий коÑÐ¸Ð½ÑƒÑ x + + PROCEDURE tanh(x: REAL): REAL + гиперболичеÑкий Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ x + + PROCEDURE arsinh(x: REAL): REAL + обратный гиперболичеÑкий ÑÐ¸Ð½ÑƒÑ x + + PROCEDURE arcosh(x: REAL): REAL + обратный гиперболичеÑкий коÑÐ¸Ð½ÑƒÑ x + + PROCEDURE artanh(x: REAL): REAL + обратный гиперболичеÑкий Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ x + + PROCEDURE round(x: REAL): REAL + округление x до ближайшего целого + + PROCEDURE frac(x: REAL): REAL; + Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ чиÑла x + + PROCEDURE floor(x: REAL): REAL + наибольшее целое чиÑло (предÑтавление как REAL), + не больше x: floor(1.2) = 1.0 + + PROCEDURE ceil(x: REAL): REAL + наименьшее целое чиÑло (предÑтавление как REAL), + не меньше x: ceil(1.2) = 2.0 + + PROCEDURE sgn(x: REAL): INTEGER + еÑли x > 0 возвращает 1 + еÑли x < 0 возвращает -1 + еÑли x = 0 возвращает 0 + + PROCEDURE fact(n: INTEGER): REAL + факториал n + +------------------------------------------------------------------------------ +MODULE File - работа Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð¾Ð¹ ÑиÑтемой + + CONST + + OPEN_R = 0 + OPEN_W = 1 + OPEN_RW = 2 + + SEEK_BEG = 0 + SEEK_CUR = 1 + SEEK_END = 2 + + PROCEDURE Create(FName: ARRAY OF CHAR): INTEGER + Ñоздает новый файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName (полное Ð¸Ð¼Ñ Ñ Ð¿ÑƒÑ‚ÐµÐ¼), + открывет файл Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи и возвращает идентификатор файла + (целое чиÑло), в Ñлучае ошибки, возвращает -1 + + PROCEDURE Open(FName: ARRAY OF CHAR; Mode: INTEGER): INTEGER + открывает ÑущеÑтвующий файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName (полное Ð¸Ð¼Ñ Ñ + путем) в режиме Mode = (OPEN_R (только чтение), OPEN_W + (только запиÑÑŒ), OPEN_RW (чтение и запиÑÑŒ)), возвращает + идентификатор файла (целое чиÑло), в Ñлучае ошибки, + возвращает -1 + + PROCEDURE Read(F, Buffer, Count: INTEGER): INTEGER + Читает данные из файла в памÑÑ‚ÑŒ. F - чиÑловой идентификатор + файла, Buffer - Ð°Ð´Ñ€ÐµÑ Ð¾Ð±Ð»Ð°Ñти памÑти, Count - количеÑтво байт, + которое требуетÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚ÑŒ из файла; возвращает количеÑтво + байт, которое было прочитано из файла + + PROCEDURE Write(F, Buffer, Count: INTEGER): INTEGER + ЗапиÑывает данные из памÑти в файл. F - чиÑловой идентификатор + файла, Buffer - Ð°Ð´Ñ€ÐµÑ Ð¾Ð±Ð»Ð°Ñти памÑти, Count - количеÑтво байт, + которое требуетÑÑ Ð·Ð°Ð¿Ð¸Ñать в файл; возвращает количеÑтво байт, + которое было запиÑано в файл + + PROCEDURE Seek(F, Offset, Origin: INTEGER): INTEGER + уÑтанавливает позицию чтениÑ-запиÑи файла Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ F + на Offset, отноÑительно Origin = (SEEK_BEG - начало файла, + SEEK_CUR - Ñ‚ÐµÐºÑƒÑ‰Ð°Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ, SEEK_END - конец файла), + возвращает позицию отноÑительно начала файла, например: + Seek(F, 0, 2) - уÑтанавливает позицию на конец файла и + возвращает длину файла; при ошибке возвращает -1 + + PROCEDURE Close(F: INTEGER) + закрывает ранее открытый файл Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ F + + PROCEDURE Delete(FName: ARRAY OF CHAR): BOOLEAN + удалÑет файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName (полное Ð¸Ð¼Ñ Ñ Ð¿ÑƒÑ‚ÐµÐ¼), + возвращает TRUE, еÑли файл уÑпешно удален + + PROCEDURE Exists(FName: ARRAY OF CHAR): BOOLEAN + возвращает TRUE, еÑли файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName (полное имÑ) + ÑущеÑтвует + + PROCEDURE Load(FName: ARRAY OF CHAR; VAR Size: INTEGER): INTEGER + загружает в памÑÑ‚ÑŒ ÑущеÑтвующий файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ FName (полное Ð¸Ð¼Ñ Ñ + путем), возвращает Ð°Ð´Ñ€ÐµÑ Ð¿Ð°Ð¼Ñти, куда был загружен файл, + запиÑывает размер файла в параметр Size; + при ошибке возвращает 0 + + PROCEDURE CreateDir(DirName: ARRAY OF CHAR): BOOLEAN + Ñоздает папку Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ DirName, вÑе промежуточные папки + должны ÑущеÑтвовать. Ð’ Ñлучае ошибки, возвращает FALSE + + PROCEDURE RemoveDir(DirName: ARRAY OF CHAR): BOOLEAN + удалÑет пуÑтую папку Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ DirName. Ð’ Ñлучае ошибки, + возвращает FALSE + + PROCEDURE ExistsDir(DirName: ARRAY OF CHAR): BOOLEAN + возвращает TRUE, еÑли папка Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ DirName ÑущеÑтвует + +------------------------------------------------------------------------------ +MODULE DateTime - дата, Ð²Ñ€ÐµÐ¼Ñ + + CONST ERR = -7.0E5 + + PROCEDURE Now(VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER) + возвращает в параметрах компоненты текущей ÑиÑтемной даты и + времени + + PROCEDURE NowEncode(): REAL; + возвращает текущую ÑиÑтемную дату и + Ð²Ñ€ÐµÐ¼Ñ (предÑтавление REAL) + + PROCEDURE Encode(Year, Month, Day, + Hour, Min, Sec, MSec: INTEGER): REAL + возвращает дату, полученную из компонентов + Year, Month, Day, Hour, Min, Sec, MSec; + при ошибке возвращает конÑтанту ERR = -7.0E5 + + PROCEDURE Decode(Date: REAL; VAR Year, Month, Day, + Hour, Min, Sec, MSec: INTEGER): BOOLEAN + извлекает компоненты + Year, Month, Day, Hour, Min, Sec, MSec из даты Date; + при ошибке возвращает FALSE + +------------------------------------------------------------------------------ +MODULE Args - параметры программы + + VAR argc: INTEGER + количеÑтво параметров программы, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¸Ð¼Ñ + иÑполнÑемого файла + + PROCEDURE GetArg(n: INTEGER; VAR s: ARRAY OF CHAR) + запиÑывает в Ñтроку s n-й параметр программы, + Ð½ÑƒÐ¼ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð² от 0 до argc - 1, + нулевой параметр -- Ð¸Ð¼Ñ Ð¸ÑполнÑемого файла + +------------------------------------------------------------------------------ +MODULE Utils - разное + + PROCEDURE Utf8To16(source: ARRAY OF CHAR; + VAR dest: ARRAY OF CHAR): INTEGER; + преобразует Ñимволы Ñтроки source из кодировки UTF-8 в + кодировку UTF-16, результат запиÑывает в Ñтроку dest, + возвращает количеÑтво 16-битных Ñимволов, запиÑанных в dest + + PROCEDURE PutSeed(seed: INTEGER) + Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð³ÐµÐ½ÐµÑ€Ð°Ñ‚Ð¾Ñ€Ð° Ñлучайных чиÑел целым чиÑлом seed + + PROCEDURE Rnd(range: INTEGER): INTEGER + Целые Ñлучайные чиÑла в диапазоне 0 <= x < range + +------------------------------------------------------------------------------ +MODULE WINAPI - привÑзки к некоторым API-функциÑм Windows \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/x86.txt b/programs/develop/oberon07/Docs/x86.txt new file mode 100644 index 0000000000..e26976fda6 --- /dev/null +++ b/programs/develop/oberon07/Docs/x86.txt @@ -0,0 +1,358 @@ + КомпилÑтор Ñзыка Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Oberon-07/16 Ð´Ð»Ñ i486 + Windows/Linux/KolibriOS. +------------------------------------------------------------------------------ + + Параметры командной Ñтроки + + Вход - текÑтовые файлы модулей Ñ Ñ€Ð°Ñширением ".ob07", кодировка ANSI или +UTF-8 Ñ BOM-Ñигнатурой. + Выход - иÑпонÑемый файл формата PE32, ELF или MENUET01/MSCOFF. + Параметры: + 1) Ð¸Ð¼Ñ Ð³Ð»Ð°Ð²Ð½Ð¾Ð³Ð¾ Ð¼Ð¾Ð´ÑƒÐ»Ñ + 2) тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ + "win32con" - Windows console + "win32gui" - Windows GUI + "win32dll" - Windows DLL + "linux32exe" - Linux ELF-EXEC + "linux32so" - Linux ELF-SO + "kosexe" - KolibriOS + "kosdll" - KolibriOS DLL + + 3) необÑзательные параметры-ключи + -out Ð¸Ð¼Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð¸Ñ€ÑƒÑŽÑ‰ÐµÐ³Ð¾ файла; по умолчанию, + Ñовпадает Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ главного модулÑ, но Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼ раÑширением + (ÑоответÑтвует типу иÑполнÑемого файла) + -stk размер ÑÑ‚Ñка в мегабайтах (по умолчанию 2 Мб, + допуÑтимо от 1 до 32 Мб) + -nochk <"ptibcwra"> отключить проверки при выполнении (Ñм. ниже) + -ver верÑÐ¸Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹ (только Ð´Ð»Ñ kosdll) + + параметр -nochk задаетÑÑ Ð² виде Ñтроки из Ñимволов: + "p" - указатели + "t" - типы + "i" - индекÑÑ‹ + "b" - неÑвное приведение INTEGER к BYTE + "c" - диапазон аргумента функции CHR + "w" - диапазон аргумента функции WCHR + "r" - Ñквивалентно "bcw" + "a" - вÑе проверки + + ПорÑдок Ñимволов может быть любым. Ðаличие в Ñтроке того или иного + Ñимвола отключает ÑоответÑтвующую проверку. + + Ðапример: -nochk it - отключить проверку индекÑов и охрану типа. + -nochk a - отключить вÑе отключаемые проверки. + + Ðапример: + + Compiler.exe "C:\example.ob07" win32con -out "C:\example.exe" -stk 1 + Compiler.exe "C:\example.ob07" win32dll -out "C:\example.dll" + Compiler.exe "C:\example.ob07" win32gui -out "C:\example.exe" -stk 4 + Compiler.exe "C:\example.ob07" win32con -out "C:\example.exe" -nochk pti + Compiler.kex "/tmp0/1/example.ob07" kosexe -out "/tmp0/1/example.kex" -stk 4 + Compiler.kex "/tmp0/1/example.ob07" kosdll -out "/tmp0/1/mydll.obj" -ver 2.7 + Compiler.exe "C:\example.ob07" linux32exe -out "C:\example" -stk 1 -nochk a + + Ð’ Ñлучае уÑпешной компилÑции, компилÑтор передает код Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ 0, иначе 1. +При работе компилÑтора в KolibriOS, код Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð½Ðµ передаетÑÑ. + +------------------------------------------------------------------------------ + ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ Ð¾Ñ‚ оригинала + +1. РаÑширен пÑевдомодуль SYSTEM +2. Ð’ идентификаторах допуÑкаетÑÑ Ñимвол "_" +3. Добавлены ÑиÑтемные флаги +4. УÑовершенÑтвован оператор CASE (добавлены конÑтантные Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð² + метках вариантов и необÑÐ·Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð²ÐµÑ‚ÐºÐ° ELSE) +5. РаÑширен набор Ñтандартных процедур +6. Семантика охраны/проверки типа уточнена Ð´Ð»Ñ Ð½ÑƒÐ»ÐµÐ²Ð¾Ð³Ð¾ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ +7. Добавлены одноÑтрочные комментарии (начинаютÑÑ Ñ Ð¿Ð°Ñ€Ñ‹ Ñимволов "//") +8. Разрешено наÑледование от типа-ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ +9. Добавлен ÑинтакÑÐ¸Ñ Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð° процедур из внешних библиотек +10. "Строки" можно заключать также в одиночные кавычки: 'Ñтрока' +11. Добавлен тип WCHAR + +------------------------------------------------------------------------------ + ОÑобенноÑти реализации + +1. ОÑновные типы + + Тип Диапазон значений Размер, байт + + INTEGER -2147483648 .. 2147483647 4 + REAL 4.94E-324 .. 1.70E+308 8 + CHAR Ñимвол ASCII (0X .. 0FFX) 1 + BOOLEAN FALSE, TRUE 1 + SET множеÑтво из целых чиÑел {0 .. 31} 4 + BYTE 0 .. 255 1 + WCHAR Ñимвол юникода (0X .. 0FFFFX) 2 + +2. МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° идентификаторов - 1024 Ñимволов +3. МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° Ñтроковых конÑтант - 1024 Ñимволов (UTF-8) +4. МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð½Ð¾ÑÑ‚ÑŒ открытых маÑÑивов - 5 +5. Процедура NEW заполнÑет нулÑми выделенный блок памÑти +6. Глобальные и локальные переменные инициализируютÑÑ Ð½ÑƒÐ»Ñми +7. Ð’ отличие от многих Oberon-реализаций, Ñборщик муÑора и динамичеÑÐºÐ°Ñ + модульноÑÑ‚ÑŒ отÑутÑтвуют +8. Тип BYTE в выражениÑÑ… вÑегда приводитÑÑ Ðº INTEGER +9. Контроль Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ выражений не производитÑÑ +10. Ошибки времени выполнениÑ: + + 1 ASSERT(x), при x = FALSE + 2 разыменование нулевого ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ + 3 целочиÑленное деление на неположительное чиÑло + 4 вызов процедуры через процедурную переменную Ñ Ð½ÑƒÐ»ÐµÐ²Ñ‹Ð¼ значением + 5 ошибка охраны типа + 6 нарушение границ маÑÑива + 7 непредуÑмотренное значение Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð² операторе CASE + 8 ошибка ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð°ÑÑивов v := x, еÑли LEN(v) < LEN(x) + 9 CHR(x), еÑли (x < 0) OR (x > 255) +10 WCHR(x), еÑли (x < 0) OR (x > 65535) +11 неÑвное приведение x:INTEGER к v:BYTE, еÑли (x < 0) OR (x > 255) + +------------------------------------------------------------------------------ + ПÑевдомодуль SYSTEM + + ПÑевдомодуль SYSTEM Ñодержит низкоуровневые и небезопаÑные процедуры, +ошибки при иÑпользовании процедур пÑÐµÐ²Ð´Ð¾Ð¼Ð¾Ð´ÑƒÐ»Ñ SYSTEM могут привеÑти к +повреждению данных времени Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ аварийному завершению программы. + + PROCEDURE ADR(v: любой тип): INTEGER + v - Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸Ð»Ð¸ процедура; + возвращает Ð°Ð´Ñ€ÐµÑ v + + PROCEDURE SADR(x: ÑÑ‚Ñ€Ð¾ÐºÐ¾Ð²Ð°Ñ ÐºÐ¾Ð½Ñтанта (CHAR UTF-8)): INTEGER + возвращает Ð°Ð´Ñ€ÐµÑ x + + PROCEDURE WSADR(x: ÑÑ‚Ñ€Ð¾ÐºÐ¾Ð²Ð°Ñ ÐºÐ¾Ð½Ñтанта (WCHAR)): INTEGER + возвращает Ð°Ð´Ñ€ÐµÑ x + + PROCEDURE SIZE(T): INTEGER + возвращает размер типа T + + PROCEDURE TYPEID(T): INTEGER + T - тип-запиÑÑŒ или тип-указатель, + возвращает номер типа в таблице типов-запиÑей + + PROCEDURE INF(): REAL + возвращает Ñпециальное вещеÑтвенное значение "беÑконечноÑÑ‚ÑŒ" + + PROCEDURE GET(a: INTEGER; + VAR v: любой оÑновной тип, PROCEDURE, POINTER) + v := ПамÑÑ‚ÑŒ[a] + + PROCEDURE PUT(a: INTEGER; x: любой оÑновной тип, PROCEDURE, POINTER) + ПамÑÑ‚ÑŒ[a] := x; + ЕÑли x: BYTE или x: WCHAR, то значение x будет раÑширено + до 32 бит, Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи байтов иÑпользовать SYSTEM.PUT8, + Ð´Ð»Ñ WCHAR -- SYSTEM.PUT16 + + PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + ПамÑÑ‚ÑŒ[a] := младшие 8 бит (x) + + PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + ПамÑÑ‚ÑŒ[a] := младшие 16 бит (x) + + PROCEDURE MOVE(Source, Dest, n: INTEGER) + Копирует n байт памÑти из Source в Dest, + облаÑти Source и Dest не могут перекрыватьÑÑ + + PROCEDURE COPY(VAR Source: любой тип; VAR Dest: любой тип; n: INTEGER) + Копирует n байт памÑти из Source в Dest. + Эквивалентно + SYSTEM.MOVE(SYSTEM.ADR(Source), SYSTEM.ADR(Dest), n) + + PROCEDURE CODE(byte1, byte2,... : INTEGER) + Ð’Ñтавка машинного кода, + byte1, byte2 ... - конÑтанты в диапазоне 0..255, + например: + SYSTEM.CODE(08BH, 045H, 008H) (* mov eax, dword [ebp + 08h] *) + + + Функции пÑÐµÐ²Ð´Ð¾Ð¼Ð¾Ð´ÑƒÐ»Ñ SYSTEM Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать в конÑтантных выражениÑÑ…. + +------------------------------------------------------------------------------ + СиÑтемные флаги + + При объÑвлении процедурных типов и глобальных процедур, поÑле ключевого +Ñлова PROCEDURE может быть указан флаг ÑÐ¾Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð¾ вызове: [stdcall], +[ccall], [ccall16], [windows], [linux]. Ðапример: + + PROCEDURE [ccall] MyProc (x, y, z: INTEGER): INTEGER; + + ЕÑли указан флаг [ccall16], то принимаетÑÑ Ñоглашение ccall, но перед +вызовом указатель ÑÑ‚Ñка будет выравнен по границе 16 байт. + Флаг [windows] - Ñиноним Ð´Ð»Ñ [stdcall], [linux] - Ñиноним Ð´Ð»Ñ [ccall16]. + Знак "-" поÑле имени флага ([stdcall-], [linux-], ...) означает, что +результат процедуры можно игнорировать (не допуÑкаетÑÑ Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð° REAL). + + При объÑвлении типов-запиÑей, поÑле ключевого Ñлова RECORD может быть +указан флаг [noalign]. Флаг [noalign] означает отÑутÑтвие Ð²Ñ‹Ñ€Ð°Ð²Ð½Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð»ÐµÐ¹ +запиÑи. ЗапиÑи Ñ ÑиÑтемным флагом не могут иметь базовый тип и не могут быть +базовыми типами Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… запиÑей. + Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑиÑтемных флагов, требуетÑÑ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ SYSTEM. + +------------------------------------------------------------------------------ + Оператор CASE + + СинтакÑÐ¸Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ‚Ð¾Ñ€Ð° CASE: + + CaseStatement = + CASE Expression OF Сase {"|" Сase} + [ELSE StatementSequence] END. + Case = [CaseLabelList ":" StatementSequence]. + CaseLabelList = CaseLabels {"," CaseLabels}. + CaseLabels = ConstExpression [".." ConstExpression]. + + Ðапример: + + CASE x OF + |-1: DoSomething1 + | 1: DoSomething2 + | 0: DoSomething3 + ELSE + DoSomething4 + END + + Ð’ метках вариантов можно иÑпользовать конÑтантные выражениÑ, ветка ELSE +необÑзательна. ЕÑли значение x не ÑоответÑтвует ни одному варианту и ELSE +отÑутÑтвует, то программа прерываетÑÑ Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹ времени выполнениÑ. + +------------------------------------------------------------------------------ + Тип WCHAR + + Тип WCHAR добавлен в Ñзык Ð´Ð»Ñ ÑƒÐ´Ð¾Ð±Ð½Ð¾Ð¹ поддежки юникода. Ð”Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð² WCHAR и +ARRAY OF WCHAR допуÑкаютÑÑ Ð²Ñе те же операции, как Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð² CHAR и +ARRAY OF CHAR, за иÑключением вÑтроенной процедуры CHR, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÑ‚ +только тип CHAR. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° WCHAR, Ñледует иÑпользовать +процедуру WCHR вмеÑто CHR. Ð”Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð¹ работы Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼, необходимо ÑохранÑÑ‚ÑŒ +иÑходный код в кодировке UTF-8 c BOM. + +------------------------------------------------------------------------------ + Проверка и охрана типа нулевого ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ + + Оригинальное Ñообщение о Ñзыке не определÑет поведение программы при +выполнении охраны p(T) и проверки типа p IS T при p = NIL. Во многих +Oberon-реализациÑÑ… выполнение такой операции приводит к ошибке времени +выполнениÑ. Ð’ данной реализации охрана типа нулевого ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ приводит к +ошибке, а проверка типа дает результат FALSE. Ð’ Ñ€Ñде Ñлучаев Ñто позволÑет +значительно Ñократить чаÑтоту Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¾Ñ…Ñ€Ð°Ð½Ñ‹ типа. + +------------------------------------------------------------------------------ + Дополнительные Ñтандартные процедуры + + DISPOSE (VAR v: любой_указатель) + ОÑвобождает памÑÑ‚ÑŒ, выделенную процедурой NEW Ð´Ð»Ñ + динамичеÑкой переменной v^, и приÑваивает переменной v + значение NIL. + + COPY (x: ARRAY OF CHAR/WCHAR; VAR v: ARRAY OF CHAR/WCHAR); + v := x; + ЕÑли LEN(v) < LEN(x), то Ñтрока x будет Ñкопирована + не полноÑтью + + LSR (x, n: INTEGER): INTEGER + ЛогичеÑкий Ñдвиг x на n бит вправо. + + MIN (a, b: INTEGER): INTEGER + Минимум из двух значений. + + MAX (a, b: INTEGER): INTEGER + МакÑимум из двух значений. + + BITS (x: INTEGER): SET + Интерпретирует x как значение типа SET. + ВыполнÑетÑÑ Ð½Ð° Ñтапе компилÑции. + + LENGTH (s: ARRAY OF CHAR/WCHAR): INTEGER + Длина 0X-завершенной Ñтроки s, без учета Ñимвола 0X. + ЕÑли Ñимвол 0X отÑутÑтвует, Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÑ‚ длину + маÑÑива s. s не может быть конÑтантой. + + WCHR (n: INTEGER): WCHAR + Преобразование типа, аналогично CHR(n: INTEGER): CHAR + +------------------------------------------------------------------------------ + Импортированные процедуры + + СинтакÑÐ¸Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°: + + PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type; + + - callconv -- Ñоглашение о вызове + - "library" -- Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° динамичеÑкой библиотеки + - "function" -- Ð¸Ð¼Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€ÑƒÐµÐ¼Ð¾Ð¹ процедуры + + например: + + PROCEDURE [windows, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); + + PROCEDURE [stdcall, "Console.obj", "con_exit"] exit (bCloseWindow: BOOLEAN); + + Ð’ конце объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть добавлено (необÑзательно) "END proc_name;" + + ОбъÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ñ… процедур должны раÑполагатьÑÑ Ð² глобальной + облаÑти видимоÑти Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¿Ð¾Ñле объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ñ…, вмеÑте Ñ Ð¾Ð±ÑŠÑвлением + "обычных" процедур, от которых импортированные отличаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ отÑутÑтвием + тела процедуры. Ð’ оÑтальном, к таким процедурам применимы те же правила: + их можно вызвать, приÑвоить процедурной переменной или получить адреÑ. + + Так как Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð° вÑегда имеет Ñвное указание ÑÐ¾Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð¾ + вызове, то ÑовмеÑтимый процедурный тип тоже должен быть объÑвлен Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸ÐµÐ¼ + ÑÐ¾Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð¾ вызове: + + VAR + ExitProcess: PROCEDURE [windows] (code: INTEGER); + con_exit: PROCEDURE [stdcall] (bCloseWindow: BOOLEAN); + + Ð’ KolibriOS импортировать процедуры можно только из библиотек, размещенных + в /rd/1/lib. Импортировать и вызывать функции инициализации библиотек + (lib_init, START) при Ñтом не нужно. + + Ð”Ð»Ñ Linux, импортированные процедуры не реализованы. + +------------------------------------------------------------------------------ + Скрытые параметры процедур + + Ðекоторые процедуры могут иметь Ñкрытые параметры, они отÑутÑтвуют в ÑпиÑке +формальных параметров, но учитываютÑÑ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñтором при транÑлÑции вызовов. +Это возможно в Ñледующих ÑлучаÑÑ…: + +1. Процедура имеет формальный параметр открытый маÑÑив: + PROCEDURE Proc (x: ARRAY OF ARRAY OF REAL); + Вызов транÑлируетÑÑ Ñ‚Ð°Ðº: + Proc(LEN(x), LEN(x[0]), SYSTEM.ADR(x)) +2. Процедура имеет формальный параметр-переменную типа RECORD: + PROCEDURE Proc (VAR x: Rec); + Вызов транÑлируетÑÑ Ñ‚Ð°Ðº: + Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) + +------------------------------------------------------------------------------ + Модуль RTL + + Ð’Ñе программы неÑвно иÑпользуют модуль RTL. КомпилÑтор транÑлирует +некоторые операции (проверка и охрана типа, Ñравнение Ñтрок, ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ð± +ошибках времени Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ др.) как вызовы процедур Ñтого модулÑ. Ðе +Ñледует вызывать Ñти процедуры Ñвно. + Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ð± ошибках времени Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð²Ð¾Ð´ÑÑ‚ÑÑ Ð² диалоговых окнах +(Windows), в терминал (Linux), на доÑку отладки (KolibriOS). + +------------------------------------------------------------------------------ + Модуль API + + СущеÑтвуют неÑколько реализаций Ð¼Ð¾Ð´ÑƒÐ»Ñ API (Ð´Ð»Ñ Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð½Ñ‹Ñ… ОС). + Как и модуль RTL, модуль API не предназначен Ð´Ð»Ñ Ð¿Ñ€Ñмого иÑпользованиÑ. +Он обеÑпечивает ÑвÑзь RTL Ñ ÐžÐ¡. + +------------------------------------------------------------------------------ + Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¸ÑполнÑемых файлов DLL + + РазрешаетÑÑ ÑкÑпортировать только процедуры. Ð”Ð»Ñ Ñтого, процедура должна +находитьÑÑ Ð² главном модуле программы, и ее Ð¸Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ быть отмечено Ñимволом +ÑкÑпорта ("*"). KolibriOS DLL вÑегда ÑкÑпортируют идентификаторы "version" +(верÑÐ¸Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹) и "lib_init" - Ð°Ð´Ñ€ÐµÑ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ инициализации DLL: + + PROCEDURE [stdcall] lib_init (): INTEGER + +Эта процедура должна быть вызвана перед иÑпользованием DLL. +Процедура вÑегда возвращает 1. \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/x86_64.txt b/programs/develop/oberon07/Docs/x86_64.txt new file mode 100644 index 0000000000..9655412ac4 --- /dev/null +++ b/programs/develop/oberon07/Docs/x86_64.txt @@ -0,0 +1,346 @@ + КомпилÑтор Ñзыка Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Oberon-07/16 Ð´Ð»Ñ x86_64 + Windows/Linux +------------------------------------------------------------------------------ + + Параметры командной Ñтроки + + Вход - текÑтовые файлы модулей Ñ Ñ€Ð°Ñширением ".ob07", кодировка ANSI или +UTF-8 Ñ BOM-Ñигнатурой. + Выход - иÑпонÑемый файл формата PE32+ или ELF64. + Параметры: + 1) Ð¸Ð¼Ñ Ð³Ð»Ð°Ð²Ð½Ð¾Ð³Ð¾ Ð¼Ð¾Ð´ÑƒÐ»Ñ + 2) тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ + "win64con" - Windows64 console + "win64gui" - Windows64 GUI + "win64dll" - Windows64 DLL + "linux64exe" - Linux ELF64-EXEC + "linux64so" - Linux ELF64-SO + + 3) необÑзательные параметры-ключи + -out Ð¸Ð¼Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð¸Ñ€ÑƒÑŽÑ‰ÐµÐ³Ð¾ файла; по умолчанию, + Ñовпадает Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ главного модулÑ, но Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼ раÑширением + (ÑоответÑтвует типу иÑполнÑемого файла) + -stk размер ÑÑ‚Ñка в мегабайтах (по умолчанию 2 Мб, + допуÑтимо от 1 до 32 Мб) + -nochk <"ptibcwra"> отключить проверки при выполнении + + параметр -nochk задаетÑÑ Ð² виде Ñтроки из Ñимволов: + "p" - указатели + "t" - типы + "i" - индекÑÑ‹ + "b" - неÑвное приведение INTEGER к BYTE + "c" - диапазон аргумента функции CHR + "w" - диапазон аргумента функции WCHR + "r" - Ñквивалентно "bcw" + "a" - вÑе проверки + + ПорÑдок Ñимволов может быть любым. Ðаличие в Ñтроке того или иного + Ñимвола отключает ÑоответÑтвующую проверку. + + Ðапример: -nochk it - отключить проверку индекÑов и охрану типа. + -nochk a - отключить вÑе отключаемые проверки. + + Ðапример: + + Compiler.exe "C:\example.ob07" win64con -out "C:\example.exe" -stk 1 + Compiler.exe "C:\example.ob07" win64dll -out "C:\example.dll" -nochk pti + Compiler "source/Compiler.ob07" linux64exe -out "source/Compiler" -nochk a + + Ð’ Ñлучае уÑпешной компилÑции, компилÑтор передает код Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ 0, иначе 1. + +------------------------------------------------------------------------------ + ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ Ð¾Ñ‚ оригинала + +1. РаÑширен пÑевдомодуль SYSTEM +2. Ð’ идентификаторах допуÑкаетÑÑ Ñимвол "_" +3. Добавлены ÑиÑтемные флаги +4. УÑовершенÑтвован оператор CASE (добавлены конÑтантные Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð² + метках вариантов и необÑÐ·Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð²ÐµÑ‚ÐºÐ° ELSE) +5. РаÑширен набор Ñтандартных процедур +6. Семантика охраны/проверки типа уточнена Ð´Ð»Ñ Ð½ÑƒÐ»ÐµÐ²Ð¾Ð³Ð¾ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ +7. Добавлены одноÑтрочные комментарии (начинаютÑÑ Ñ Ð¿Ð°Ñ€Ñ‹ Ñимволов "//") +8. Разрешено наÑледование от типа-ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ +9. Добавлен ÑинтакÑÐ¸Ñ Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð° процедур из внешних библиотек +10. "Строки" можно заключать также в одиночные кавычки: 'Ñтрока' +11. Добавлен тип WCHAR + +------------------------------------------------------------------------------ + ОÑобенноÑти реализации + +1. ОÑновные типы + + Тип Диапазон значений Размер, байт + + INTEGER -9223372036854775808 .. 9223372036854775807 8 + REAL 4.94E-324 .. 1.70E+308 8 + CHAR Ñимвол ASCII (0X .. 0FFX) 1 + BOOLEAN FALSE, TRUE 1 + SET множеÑтво из целых чиÑел {0 .. 63} 8 + BYTE 0 .. 255 1 + WCHAR Ñимвол юникода (0X .. 0FFFFX) 2 + +2. МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° идентификаторов - 1024 Ñимволов +3. МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° Ñтроковых конÑтант - 1024 Ñимволов (UTF-8) +4. МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð½Ð¾ÑÑ‚ÑŒ открытых маÑÑивов - 5 +5. Процедура NEW заполнÑет нулÑми выделенный блок памÑти +6. Глобальные и локальные переменные инициализируютÑÑ Ð½ÑƒÐ»Ñми +7. Ð’ отличие от многих Oberon-реализаций, Ñборщик муÑора и динамичеÑÐºÐ°Ñ + модульноÑÑ‚ÑŒ отÑутÑтвуют +8. Тип BYTE в выражениÑÑ… вÑегда приводитÑÑ Ðº INTEGER +9. Контроль Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ выражений не производитÑÑ +10. Ошибки времени выполнениÑ: + + 1 ASSERT(x), при x = FALSE + 2 разыменование нулевого ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ + 3 целочиÑленное деление на неположительное чиÑло + 4 вызов процедуры через процедурную переменную Ñ Ð½ÑƒÐ»ÐµÐ²Ñ‹Ð¼ значением + 5 ошибка охраны типа + 6 нарушение границ маÑÑива + 7 непредуÑмотренное значение Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð² операторе CASE + 8 ошибка ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð°ÑÑивов v := x, еÑли LEN(v) < LEN(x) + 9 CHR(x), еÑли (x < 0) OR (x > 255) +10 WCHR(x), еÑли (x < 0) OR (x > 65535) +11 неÑвное приведение x:INTEGER к v:BYTE, еÑли (x < 0) OR (x > 255) + +------------------------------------------------------------------------------ + ПÑевдомодуль SYSTEM + + ПÑевдомодуль SYSTEM Ñодержит низкоуровневые и небезопаÑные процедуры, +ошибки при иÑпользовании процедур пÑÐµÐ²Ð´Ð¾Ð¼Ð¾Ð´ÑƒÐ»Ñ SYSTEM могут привеÑти к +повреждению данных времени Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ аварийному завершению программы. + + PROCEDURE ADR(v: любой тип): INTEGER + v - Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸Ð»Ð¸ процедура; + возвращает Ð°Ð´Ñ€ÐµÑ v + + PROCEDURE SADR(x: ÑÑ‚Ñ€Ð¾ÐºÐ¾Ð²Ð°Ñ ÐºÐ¾Ð½Ñтанта (CHAR UTF-8)): INTEGER + возвращает Ð°Ð´Ñ€ÐµÑ x + + PROCEDURE WSADR(x: ÑÑ‚Ñ€Ð¾ÐºÐ¾Ð²Ð°Ñ ÐºÐ¾Ð½Ñтанта (WCHAR)): INTEGER + возвращает Ð°Ð´Ñ€ÐµÑ x + + PROCEDURE SIZE(T): INTEGER + возвращает размер типа T + + PROCEDURE TYPEID(T): INTEGER + T - тип-запиÑÑŒ или тип-указатель, + возвращает номер типа в таблице типов-запиÑей + + PROCEDURE INF(): REAL + возвращает Ñпециальное вещеÑтвенное значение "беÑконечноÑÑ‚ÑŒ" + + PROCEDURE GET(a: INTEGER; + VAR v: любой оÑновной тип, PROCEDURE, POINTER) + v := ПамÑÑ‚ÑŒ[a] + + PROCEDURE PUT(a: INTEGER; x: любой оÑновной тип, PROCEDURE, POINTER) + ПамÑÑ‚ÑŒ[a] := x; + ЕÑли x: BYTE или x: WCHAR, то значение x будет раÑширено + до 64 бит, Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи байтов иÑпользовать SYSTEM.PUT8, + Ð´Ð»Ñ WCHAR -- SYSTEM.PUT16 + + PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + ПамÑÑ‚ÑŒ[a] := младшие 8 бит (x) + + PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + ПамÑÑ‚ÑŒ[a] := младшие 16 бит (x) + + PROCEDURE PUT32(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + ПамÑÑ‚ÑŒ[a] := младшие 32 бит (x) + + PROCEDURE MOVE(Source, Dest, n: INTEGER) + Копирует n байт памÑти из Source в Dest, + облаÑти Source и Dest не могут перекрыватьÑÑ + + PROCEDURE COPY(VAR Source: любой тип; VAR Dest: любой тип; n: INTEGER) + Копирует n байт памÑти из Source в Dest. + Эквивалентно + SYSTEM.MOVE(SYSTEM.ADR(Source), SYSTEM.ADR(Dest), n) + + PROCEDURE CODE(byte1, byte2,... : BYTE) + Ð’Ñтавка машинного кода, + byte1, byte2 ... - конÑтанты в диапазоне 0..255, + например: + + SYSTEM.CODE(048H,08BH,045H,010H) (* mov rax,qword[rbp+16] *) + + Также, в модуле SYSTEM определен тип CARD32 (4 байта). Ð”Ð»Ñ Ñ‚Ð¸Ð¿Ð° CARD32 не +допуÑкаютÑÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ðµ Ñвные операции, за иÑключением приÑваиваниÑ. + + Функции пÑÐµÐ²Ð´Ð¾Ð¼Ð¾Ð´ÑƒÐ»Ñ SYSTEM Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать в конÑтантных выражениÑÑ…. + +------------------------------------------------------------------------------ + СиÑтемные флаги + + При объÑвлении процедурных типов и глобальных процедур, поÑле ключевого +Ñлова PROCEDURE может быть указан флаг ÑÐ¾Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð¾ вызове: [win64], [systemv], +[windows], [linux]. +Ðапример: + + PROCEDURE [win64] MyProc (x, y, z: INTEGER): INTEGER; + + Флаг [windows] - Ñиноним Ð´Ð»Ñ [win64], [linux] - Ñиноним Ð´Ð»Ñ [systemv]. + Знак "-" поÑле имени флага ([win64-], [linux-], ...) означает, что +результат процедуры можно игнорировать (не допуÑкаетÑÑ Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð° REAL). + ЕÑли флаг не указан, то принимаетÑÑ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÐµÐµ Ñоглашение о вызове. +[win64] и [systemv] иÑпользуютÑÑ Ð´Ð»Ñ ÑвÑзи Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¾Ð¹ ÑиÑтемой и внешними +приложениÑми. + + При объÑвлении типов-запиÑей, поÑле ключевого Ñлова RECORD может быть +указан флаг [noalign]. Флаг [noalign] означает отÑутÑтвие Ð²Ñ‹Ñ€Ð°Ð²Ð½Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð»ÐµÐ¹ +запиÑи. ЗапиÑи Ñ ÑиÑтемным флагом не могут иметь базовый тип и не могут быть +базовыми типами Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… запиÑей. + Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑиÑтемных флагов, требуетÑÑ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ SYSTEM. + +------------------------------------------------------------------------------ + Оператор CASE + + СинтакÑÐ¸Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ‚Ð¾Ñ€Ð° CASE: + + CaseStatement = + CASE Expression OF Сase {"|" Сase} + [ELSE StatementSequence] END. + Case = [CaseLabelList ":" StatementSequence]. + CaseLabelList = CaseLabels {"," CaseLabels}. + CaseLabels = ConstExpression [".." ConstExpression]. + + Ðапример: + + CASE x OF + |-1: DoSomething1 + | 1: DoSomething2 + | 0: DoSomething3 + ELSE + DoSomething4 + END + + Ð’ метках вариантов можно иÑпользовать конÑтантные выражениÑ, ветка ELSE +необÑзательна. ЕÑли значение x не ÑоответÑтвует ни одному варианту и ELSE +отÑутÑтвует, то программа прерываетÑÑ Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹ времени выполнениÑ. + +------------------------------------------------------------------------------ + Тип WCHAR + + Тип WCHAR добавлен в Ñзык Ð´Ð»Ñ ÑƒÐ´Ð¾Ð±Ð½Ð¾Ð¹ поддежки юникода. Ð”Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð² WCHAR и +ARRAY OF WCHAR допуÑкаютÑÑ Ð²Ñе те же операции, как Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð² CHAR и +ARRAY OF CHAR, за иÑключением вÑтроенной процедуры CHR, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÑ‚ +только тип CHAR. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° WCHAR, Ñледует иÑпользовать +процедуру WCHR вмеÑто CHR. Ð”Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ð¹ работы Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼, необходимо ÑохранÑÑ‚ÑŒ +иÑходный код в кодировке UTF-8 c BOM. + +------------------------------------------------------------------------------ + Проверка и охрана типа нулевого ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ + + Оригинальное Ñообщение о Ñзыке не определÑет поведение программы при +выполнении охраны p(T) и проверки типа p IS T при p = NIL. Во многих +Oberon-реализациÑÑ… выполнение такой операции приводит к ошибке времени +выполнениÑ. Ð’ данной реализации охрана типа нулевого ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ приводит к +ошибке, а проверка типа дает результат FALSE. Ð’ Ñ€Ñде Ñлучаев Ñто позволÑет +значительно Ñократить чаÑтоту Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¾Ñ…Ñ€Ð°Ð½Ñ‹ типа. + +------------------------------------------------------------------------------ + Дополнительные Ñтандартные процедуры + + DISPOSE (VAR v: любой_указатель) + ОÑвобождает памÑÑ‚ÑŒ, выделенную процедурой NEW Ð´Ð»Ñ + динамичеÑкой переменной v^, и приÑваивает переменной v + значение NIL. + + COPY (x: ARRAY OF CHAR/WCHAR; VAR v: ARRAY OF CHAR/WCHAR); + v := x; + ЕÑли LEN(v) < LEN(x), то Ñтрока x будет Ñкопирована + не полноÑтью + + LSR (x, n: INTEGER): INTEGER + ЛогичеÑкий Ñдвиг x на n бит вправо. + + MIN (a, b: INTEGER): INTEGER + Минимум из двух значений. + + MAX (a, b: INTEGER): INTEGER + МакÑимум из двух значений. + + BITS (x: INTEGER): SET + Интерпретирует x как значение типа SET. + ВыполнÑетÑÑ Ð½Ð° Ñтапе компилÑции. + + LENGTH (s: ARRAY OF CHAR/WCHAR): INTEGER + Длина 0X-завершенной Ñтроки s, без учета Ñимвола 0X. + ЕÑли Ñимвол 0X отÑутÑтвует, Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÑ‚ длину + маÑÑива s. s не может быть конÑтантой. + + WCHR (n: INTEGER): WCHAR + Преобразование типа, аналогично CHR(n: INTEGER): CHAR + +------------------------------------------------------------------------------ + Импортированные процедуры + + СинтакÑÐ¸Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°: + + PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type; + + - callconv -- Ñоглашение о вызове + - "library" -- Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° динамичеÑкой библиотеки + - "function" -- Ð¸Ð¼Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€ÑƒÐµÐ¼Ð¾Ð¹ процедуры + + например: + + PROCEDURE [win64, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); + + + Ð’ конце объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть добавлено (необÑзательно) "END proc_name;" + + ОбъÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ñ… процедур должны раÑполагатьÑÑ Ð² глобальной + облаÑти видимоÑти Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¿Ð¾Ñле объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ñ…, вмеÑте Ñ Ð¾Ð±ÑŠÑвлением + "обычных" процедур, от которых импортированные отличаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ отÑутÑтвием + тела процедуры. Ð’ оÑтальном, к таким процедурам применимы те же правила: + их можно вызвать, приÑвоить процедурной переменной или получить адреÑ. + + Так как Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð° вÑегда имеет Ñвное указание ÑÐ¾Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð¾ + вызове, то ÑовмеÑтимый процедурный тип тоже должен быть объÑвлен Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸ÐµÐ¼ + ÑÐ¾Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð¾ вызове: + + VAR + ExitProcess: PROCEDURE [win64] (code: INTEGER); + + Ð”Ð»Ñ Linux, импортированные процедуры не реализованы. + +------------------------------------------------------------------------------ + Скрытые параметры процедур + + Ðекоторые процедуры могут иметь Ñкрытые параметры, они отÑутÑтвуют в ÑпиÑке +формальных параметров, но учитываютÑÑ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñтором при транÑлÑции вызовов. +Это возможно в Ñледующих ÑлучаÑÑ…: + +1. Процедура имеет формальный параметр открытый маÑÑив: + PROCEDURE Proc (x: ARRAY OF ARRAY OF REAL); + Вызов транÑлируетÑÑ Ñ‚Ð°Ðº: + Proc(LEN(x), LEN(x[0]), SYSTEM.ADR(x)) +2. Процедура имеет формальный параметр-переменную типа RECORD: + PROCEDURE Proc (VAR x: Rec); + Вызов транÑлируетÑÑ Ñ‚Ð°Ðº: + Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) + +------------------------------------------------------------------------------ + Модуль RTL + + Ð’Ñе программы неÑвно иÑпользуют модуль RTL. КомпилÑтор транÑлирует +некоторые операции (проверка и охрана типа, Ñравнение Ñтрок, ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ð± +ошибках времени Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ др.) как вызовы процедур Ñтого модулÑ. Ðе +Ñледует вызывать Ñти процедуры Ñвно. + Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ð± ошибках времени Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð²Ð¾Ð´ÑÑ‚ÑÑ Ð² диалоговых окнах +(Windows), в терминал (Linux). + +------------------------------------------------------------------------------ + Модуль API + + СущеÑтвуют неÑколько реализаций Ð¼Ð¾Ð´ÑƒÐ»Ñ API (Ð´Ð»Ñ Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð½Ñ‹Ñ… ОС). + Как и модуль RTL, модуль API не предназначен Ð´Ð»Ñ Ð¿Ñ€Ñмого иÑпользованиÑ. +Он обеÑпечивает ÑвÑзь RTL Ñ ÐžÐ¡. + +------------------------------------------------------------------------------ + Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¸ÑполнÑемых файлов DLL + + РазрешаетÑÑ ÑкÑпортировать только процедуры. Ð”Ð»Ñ Ñтого, процедура должна +находитьÑÑ Ð² главном модуле программы, ее Ð¸Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ быть отмечено Ñимволом +ÑкÑпорта ("*") и должно быть указано Ñоглашение о вызове. \ No newline at end of file diff --git a/programs/develop/oberon07/GitHub.url b/programs/develop/oberon07/GitHub.url new file mode 100644 index 0000000000..590f82c508 --- /dev/null +++ b/programs/develop/oberon07/GitHub.url @@ -0,0 +1,2 @@ +[InternetShortcut] +URL=https://github.com/AntKrotov/oberon-07-compiler diff --git a/programs/develop/oberon07/LICENSE b/programs/develop/oberon07/LICENSE new file mode 100644 index 0000000000..e56a7ff740 --- /dev/null +++ b/programs/develop/oberon07/LICENSE @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2018-2020, Anton Krotov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/programs/develop/oberon07/Lib/KolibriOS/API.ob07 b/programs/develop/oberon07/Lib/KolibriOS/API.ob07 index 1786326c47..4f99171320 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/API.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/API.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018, Anton Krotov + Copyright (c) 2018, 2020, Anton Krotov All rights reserved. *) @@ -318,4 +318,13 @@ PROCEDURE GetTickCount* (): INTEGER; END GetTickCount; -END API. +PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; + RETURN 0 +END dllentry; + + +PROCEDURE sofinit*; +END sofinit; + + +END API. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Args.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Args.ob07 index 20856c87af..889059d0a4 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Args.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Args.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -97,4 +97,4 @@ END GetArg; BEGIN ParamParse -END Args. +END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 b/programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 index 5cf255ce9c..e993d375cb 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -102,4 +102,4 @@ END Load; BEGIN Load -END ColorDlg. +END ColorDlg. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Console.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Console.ob07 index ee5c5d1f94..7d80c4fb01 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Console.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Console.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify diff --git a/programs/develop/oberon07/Lib/KolibriOS/ConsoleLib.ob07 b/programs/develop/oberon07/Lib/KolibriOS/ConsoleLib.ob07 index 74ee3f3d43..74346a692c 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/ConsoleLib.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/ConsoleLib.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -100,4 +100,4 @@ END main; BEGIN main -END ConsoleLib. +END ConsoleLib. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/DateTime.ob07 b/programs/develop/oberon07/Lib/KolibriOS/DateTime.ob07 index e44bde1510..12291065f6 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/DateTime.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/DateTime.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -138,4 +138,4 @@ BEGIN Msec := 0 END Now; -END DateTime. +END DateTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Debug.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Debug.ob07 index b341b83fc0..daaf40ece1 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Debug.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Debug.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -289,4 +289,4 @@ BEGIN res := KOSAPI.sysfunc2(70, sys.ADR(info)) END Open; -END Debug. +END Debug. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/File.ob07 b/programs/develop/oberon07/Lib/KolibriOS/File.ob07 index ff61c5863c..d25a8d6938 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/File.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/File.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -313,4 +313,4 @@ BEGIN END DeleteDir; -END File. +END File. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 b/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 index 10a9def866..775291cddb 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -57,6 +57,8 @@ VAR eol*: ARRAY 3 OF CHAR; + maxreal*: REAL; + PROCEDURE [stdcall, "Console.obj", "con_init"] con_init (wnd_width, wnd_height, scr_width, scr_height, title: INTEGER); @@ -453,6 +455,42 @@ PROCEDURE UnixTime* (): INTEGER; END UnixTime; +PROCEDURE d2s* (x: REAL): INTEGER; +VAR + h, l, s, e: INTEGER; + +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), l); + SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + + s := ASR(h, 31) MOD 2; + e := (h DIV 100000H) MOD 2048; + IF e <= 896 THEN + h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; + REPEAT + h := h DIV 2; + INC(e) + UNTIL e = 897; + e := 896; + l := (h MOD 8) * 20000000H; + h := h DIV 8 + ELSIF (1151 <= e) & (e < 2047) THEN + e := 1151; + h := 0; + l := 0 + ELSIF e = 2047 THEN + e := 1151; + IF (h MOD 100000H # 0) OR (l # 0) THEN + h := 80000H; + l := 0 + END + END; + DEC(e, 896) + + RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 +END d2s; + + PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; BEGIN SYSTEM.GET(SYSTEM.ADR(x), a); @@ -463,9 +501,11 @@ END splitf; BEGIN eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; + maxreal := 1.9; + PACK(maxreal, 1023); Console := API.import; IF Console THEN con_init(-1, -1, -1, -1, SYSTEM.SADR("Oberon-07 for KolibriOS")) END; ParamParse -END HOST. +END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/In.ob07 b/programs/develop/oberon07/Lib/KolibriOS/In.ob07 index 6401c6dc18..50af0cb957 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/In.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/In.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify diff --git a/programs/develop/oberon07/Lib/KolibriOS/KOSAPI.ob07 b/programs/develop/oberon07/Lib/KolibriOS/KOSAPI.ob07 index de4a9d9b99..84a881bbaf 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/KOSAPI.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/KOSAPI.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -427,4 +427,4 @@ BEGIN END _init; -END KOSAPI. +END KOSAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 index b49668351d..b1fe62acc0 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2013, 2014, 2018, 2019 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -381,4 +381,4 @@ BEGIN END fact; -END Math. +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 93d0dbc7b8..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 @@ -104,4 +104,4 @@ PROCEDURE LinkStatus* (num: INTEGER): INTEGER; END LinkStatus; -END NetDevices. +END NetDevices. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 b/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 index 6240eb2b26..9bffd20f21 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -150,4 +150,4 @@ END Load; BEGIN Load -END OpenDlg. +END OpenDlg. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Out.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Out.ob07 index 04de78c75e..02cc14e017 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Out.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Out.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -264,4 +264,4 @@ END FixReal; PROCEDURE Open*; END Open; -END Out. +END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 b/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 index 3aa6c454e1..0929a5678a 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -16,34 +16,14 @@ CONST maxint* = 7FFFFFFFH; minint* = 80000000H; - DLL_PROCESS_ATTACH = 1; - DLL_THREAD_ATTACH = 2; - DLL_THREAD_DETACH = 3; - DLL_PROCESS_DETACH = 0; - WORD = bit_depth DIV 8; MAX_SET = bit_depth - 1; -TYPE - - DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); - PROC = PROCEDURE; - - VAR name: INTEGER; types: INTEGER; - bits: ARRAY MAX_SET + 1 OF INTEGER; - - dll: RECORD - process_detach, - thread_detach, - thread_attach: DLL_ENTRY - END; - - fini: PROC; PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER); @@ -97,7 +77,6 @@ VAR i, n, k: INTEGER; BEGIN - k := LEN(A) - 1; n := A[0]; i := 0; @@ -106,7 +85,6 @@ BEGIN INC(i) END; A[k] := n - END _rot; @@ -128,14 +106,16 @@ BEGIN END _set; -PROCEDURE [stdcall] _set1* (a: INTEGER): INTEGER; +PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *) BEGIN - IF ASR(a, 5) = 0 THEN - SYSTEM.GET(SYSTEM.ADR(bits[0]) + a * WORD, a) - ELSE - a := 0 - END - RETURN a + SYSTEM.CODE( + 031H, 0C0H, (* xor eax, eax *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *) + 083H, 0F9H, 01FH, (* cmp ecx, 31 *) + 077H, 003H, (* ja L *) + 00FH, 0ABH, 0C8H (* bts eax, ecx *) + (* L: *) + ) END _set1; @@ -315,7 +295,6 @@ VAR c: CHAR; BEGIN - res := strncmp(str1, str2, MIN(len1, len2)); IF res = minint THEN IF len1 > len2 THEN @@ -349,7 +328,6 @@ VAR c: WCHAR; BEGIN - res := strncmpw(str1, str2, MIN(len1, len2)); IF res = minint THEN IF len1 > len2 THEN @@ -398,7 +376,6 @@ VAR c: CHAR; BEGIN - i := 0; REPEAT str[i] := CHR(x MOD 10 + ORD("0")); @@ -422,6 +399,7 @@ END IntToStr; PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR n1, n2, i, j: INTEGER; + BEGIN n1 := LENGTH(s1); n2 := LENGTH(s2); @@ -437,7 +415,6 @@ BEGIN END; s1[j] := 0X - END append; @@ -446,20 +423,18 @@ VAR s, temp: ARRAY 1024 OF CHAR; BEGIN - - s := ""; CASE err OF - | 1: append(s, "assertion failure") - | 2: append(s, "NIL dereference") - | 3: append(s, "division by zero") - | 4: append(s, "NIL procedure call") - | 5: append(s, "type guard error") - | 6: append(s, "index out of range") - | 7: append(s, "invalid CASE") - | 8: append(s, "array assignment error") - | 9: append(s, "CHR out of range") - |10: append(s, "WCHR out of range") - |11: append(s, "BYTE out of range") + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" END; append(s, API.eol); @@ -513,36 +488,16 @@ END _guard; PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - CASE fdwReason OF - |DLL_PROCESS_ATTACH: - res := 1 - |DLL_THREAD_ATTACH: - res := 0; - IF dll.thread_attach # NIL THEN - dll.thread_attach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_THREAD_DETACH: - res := 0; - IF dll.thread_detach # NIL THEN - dll.thread_detach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_PROCESS_DETACH: - res := 0; - IF dll.process_detach # NIL THEN - dll.process_detach(hinstDLL, fdwReason, lpvReserved) - END - ELSE - res := 0 - END - - RETURN res + RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) END _dllentry; +PROCEDURE [stdcall] _sofinit*; +BEGIN + API.sofinit +END _sofinit; + + PROCEDURE [stdcall] _exit* (code: INTEGER); BEGIN API.exit(code) @@ -571,42 +526,8 @@ BEGIN END END; - j := 1; - FOR i := 0 TO MAX_SET DO - bits[i] := j; - j := LSL(j, 1) - END; - - name := modname; - - dll.process_detach := NIL; - dll.thread_detach := NIL; - dll.thread_attach := NIL; - - fini := NIL + name := modname END _init; -PROCEDURE [stdcall] _sofinit*; -BEGIN - IF fini # NIL THEN - fini - END -END _sofinit; - - -PROCEDURE SetDll* (process_detach, thread_detach, thread_attach: DLL_ENTRY); -BEGIN - dll.process_detach := process_detach; - dll.thread_detach := thread_detach; - dll.thread_attach := thread_attach -END SetDll; - - -PROCEDURE SetFini* (ProcFini: PROC); -BEGIN - fini := ProcFini -END SetFini; - - -END RTL. +END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/RasterWorks.ob07 b/programs/develop/oberon07/Lib/KolibriOS/RasterWorks.ob07 index dc814845ca..5c804aa180 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/RasterWorks.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/RasterWorks.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 KolibriOS team This program is free software: you can redistribute it and/or modify @@ -121,4 +121,4 @@ END main; BEGIN main -END RasterWorks. +END RasterWorks. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Read.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Read.ob07 index 85bb58d801..c2e86e37d7 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Read.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Read.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -43,4 +43,4 @@ PROCEDURE WChar*(F: File.FS; VAR x: WCHAR): BOOLEAN; RETURN File.Read(F, sys.ADR(x), sys.SIZE(WCHAR)) = sys.SIZE(WCHAR) END WChar; -END Read. +END Read. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/UnixTime.ob07 b/programs/develop/oberon07/Lib/KolibriOS/UnixTime.ob07 index 138e4297fa..0e6ed5bd6d 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/UnixTime.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/UnixTime.ob07 @@ -1,64 +1,64 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2019, Anton Krotov - All rights reserved. -*) - -MODULE UnixTime; - - -VAR - - days: ARRAY 12, 31, 2 OF INTEGER; - - -PROCEDURE init; -VAR - i, j, k, n0, n1: INTEGER; -BEGIN - - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - days[i, j, 0] := 0; - days[i, j, 1] := 0; - END - END; - - days[ 1, 28, 0] := -1; - - FOR k := 0 TO 1 DO - days[ 1, 29, k] := -1; - days[ 1, 30, k] := -1; - days[ 3, 30, k] := -1; - days[ 5, 30, k] := -1; - days[ 8, 30, k] := -1; - days[10, 30, k] := -1; - END; - - n0 := 0; - n1 := 0; - FOR i := 0 TO 11 DO - FOR j := 0 TO 30 DO - IF days[i, j, 0] = 0 THEN - days[i, j, 0] := n0; - INC(n0) - END; - IF days[i, j, 1] = 0 THEN - days[i, j, 1] := n1; - INC(n1) - END - END - END - -END init; - - -PROCEDURE time* (year, month, day, hour, min, sec: INTEGER): INTEGER; - RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec -END time; - - -BEGIN - init -END UnixTime. +(* + BSD 2-Clause License + + Copyright (c) 2018-2019, Anton Krotov + All rights reserved. +*) + +MODULE UnixTime; + + +VAR + + days: ARRAY 12, 31, 2 OF INTEGER; + + +PROCEDURE init; +VAR + i, j, k, n0, n1: INTEGER; +BEGIN + + FOR i := 0 TO 11 DO + FOR j := 0 TO 30 DO + days[i, j, 0] := 0; + days[i, j, 1] := 0; + END + END; + + days[ 1, 28, 0] := -1; + + FOR k := 0 TO 1 DO + days[ 1, 29, k] := -1; + days[ 1, 30, k] := -1; + days[ 3, 30, k] := -1; + days[ 5, 30, k] := -1; + days[ 8, 30, k] := -1; + days[10, 30, k] := -1; + END; + + n0 := 0; + n1 := 0; + FOR i := 0 TO 11 DO + FOR j := 0 TO 30 DO + IF days[i, j, 0] = 0 THEN + days[i, j, 0] := n0; + INC(n0) + END; + IF days[i, j, 1] = 0 THEN + days[i, j, 1] := n1; + INC(n1) + END + END + END + +END init; + + +PROCEDURE time* (year, month, day, hour, min, sec: INTEGER): INTEGER; + RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec +END time; + + +BEGIN + init +END UnixTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Vector.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Vector.ob07 index 0792204a98..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 @@ -118,4 +118,4 @@ BEGIN END destroy; -END Vector. +END Vector. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/Write.ob07 b/programs/develop/oberon07/Lib/KolibriOS/Write.ob07 index 7a9823f25b..6730d799d7 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/Write.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/Write.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -43,4 +43,4 @@ PROCEDURE WChar*(F: File.FS; x: WCHAR): BOOLEAN; RETURN File.Write(F, sys.ADR(x), sys.SIZE(WCHAR)) = sys.SIZE(WCHAR) END WChar; -END Write. +END Write. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/kfonts.ob07 b/programs/develop/oberon07/Lib/KolibriOS/kfonts.ob07 index 67c1080406..8ef267a004 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/kfonts.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/kfonts.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 Anton Krotov This program is free software: you can redistribute it and/or modify @@ -489,4 +489,4 @@ BEGIN RETURN Font END LoadFont; -END kfonts. +END kfonts. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 b/programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 index 9c5a516a96..425f74034a 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 +++ b/programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 @@ -1,4 +1,4 @@ -(* +(* Copyright 2016, 2018 KolibriOS team This program is free software: you can redistribute it and/or modify @@ -432,4 +432,4 @@ END main; BEGIN main -END libimg. +END libimg. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/API.ob07 b/programs/develop/oberon07/Lib/Linux32/API.ob07 index 42a337fd01..0415cdbd01 100644 --- a/programs/develop/oberon07/Lib/Linux32/API.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/API.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) @@ -13,11 +13,13 @@ IMPORT SYSTEM; CONST RTLD_LAZY* = 1; + BIT_DEPTH* = 32; TYPE TP* = ARRAY 2 OF INTEGER; + SOFINI* = PROCEDURE; VAR @@ -46,6 +48,8 @@ VAR clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; time* : PROCEDURE [linux] (ptr: INTEGER): INTEGER; + fini: SOFINI; + PROCEDURE putc* (c: CHAR); VAR @@ -103,6 +107,7 @@ END GetProcAdr; PROCEDURE init* (sp, code: INTEGER); BEGIN + fini := NIL; SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER) * 2, dlopen); SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER), dlsym); MainParam := sp; @@ -142,4 +147,23 @@ BEGIN END exit_thread; -END API. +PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; + RETURN 0 +END dllentry; + + +PROCEDURE sofinit*; +BEGIN + IF fini # NIL THEN + fini + END +END sofinit; + + +PROCEDURE SetFini* (ProcFini: SOFINI); +BEGIN + fini := ProcFini +END SetFini; + + +END API. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/HOST.ob07 b/programs/develop/oberon07/Lib/Linux32/HOST.ob07 index a2f43bc83c..2851c0cab9 100644 --- a/programs/develop/oberon07/Lib/Linux32/HOST.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/HOST.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) @@ -26,6 +26,8 @@ VAR eol*: ARRAY 2 OF CHAR; + maxreal*: REAL; + PROCEDURE ExitProcess* (code: INTEGER); BEGIN @@ -148,6 +150,42 @@ PROCEDURE UnixTime* (): INTEGER; END UnixTime; +PROCEDURE d2s* (x: REAL): INTEGER; +VAR + h, l, s, e: INTEGER; + +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), l); + SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + + s := ASR(h, 31) MOD 2; + e := (h DIV 100000H) MOD 2048; + IF e <= 896 THEN + h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; + REPEAT + h := h DIV 2; + INC(e) + UNTIL e = 897; + e := 896; + l := (h MOD 8) * 20000000H; + h := h DIV 8 + ELSIF (1151 <= e) & (e < 2047) THEN + e := 1151; + h := 0; + l := 0 + ELSIF e = 2047 THEN + e := 1151; + IF (h MOD 100000H # 0) OR (l # 0) THEN + h := 80000H; + l := 0 + END + END; + DEC(e, 896) + + RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 +END d2s; + + PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; VAR res: INTEGER; @@ -164,5 +202,7 @@ END splitf; BEGIN eol := 0AX; + maxreal := 1.9; + PACK(maxreal, 1023); SYSTEM.GET(API.MainParam, argc) -END HOST. +END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 b/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 index d38c8b3f47..31348bcadf 100644 --- a/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2019, Anton Krotov + Copyright (c) 2019-2020, Anton Krotov All rights reserved. *) @@ -13,6 +13,7 @@ IMPORT SYSTEM, API; TYPE TP* = API.TP; + SOFINI* = API.SOFINI; VAR @@ -69,12 +70,17 @@ BEGIN END GetEnv; +PROCEDURE SetFini* (ProcFini: SOFINI); +BEGIN + API.SetFini(ProcFini) +END SetFini; + + PROCEDURE init; VAR ptr: INTEGER; BEGIN - IF API.MainParam # 0 THEN envc := -1; SYSTEM.GET(API.MainParam, argc); @@ -134,4 +140,4 @@ END syscall; BEGIN init -END LINAPI. +END LINAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/Libdl.ob07 b/programs/develop/oberon07/Lib/Linux32/Libdl.ob07 new file mode 100644 index 0000000000..f8a5781d87 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux32/Libdl.ob07 @@ -0,0 +1,65 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE Libdl; + +IMPORT SYSTEM, API; + + +CONST + + LAZY* = 1; + NOW* = 2; + BINDING_MASK* = 3; + NOLOAD* = 4; + LOCAL* = 0; + GLOBAL* = 256; + NODELETE* = 4096; + + +VAR + + _close: PROCEDURE [linux] (handle: INTEGER): INTEGER; + _error: PROCEDURE [linux] (): INTEGER; + + +PROCEDURE open* (file: ARRAY OF CHAR; mode: INTEGER): INTEGER; + RETURN API.dlopen(SYSTEM.ADR(file[0]), mode) +END open; + + +PROCEDURE sym* (handle: INTEGER; name: ARRAY OF CHAR): INTEGER; + RETURN API.dlsym(handle, SYSTEM.ADR(name[0])) +END sym; + + +PROCEDURE close* (handle: INTEGER): INTEGER; + RETURN _close(handle) +END close; + + +PROCEDURE error* (): INTEGER; + RETURN _error() +END error; + + +PROCEDURE init; +VAR + lib: INTEGER; + +BEGIN + lib := open("libdl.so.2", LAZY); + SYSTEM.PUT(SYSTEM.ADR(_close), sym(lib, "dlclose")); + ASSERT(_close # NIL); + SYSTEM.PUT(SYSTEM.ADR(_error), sym(lib, "dlerror")); + ASSERT(_error # NIL) +END init; + + +BEGIN + init +END Libdl. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/Math.ob07 b/programs/develop/oberon07/Lib/Linux32/Math.ob07 new file mode 100644 index 0000000000..25950952bf --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux32/Math.ob07 @@ -0,0 +1,384 @@ +(* + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE Math; + +IMPORT SYSTEM; + + +CONST + + pi* = 3.141592653589793; + e* = 2.718281828459045; + + +PROCEDURE IsNan* (x: REAL): BOOLEAN; +VAR + h, l: SET; + +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), l); + SYSTEM.GET(SYSTEM.ADR(x) + 4, h) + RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) +END IsNan; + + +PROCEDURE IsInf* (x: REAL): BOOLEAN; + RETURN ABS(x) = SYSTEM.INF() +END IsInf; + + +PROCEDURE Max (a, b: REAL): REAL; +VAR + res: REAL; + +BEGIN + IF a > b THEN + res := a + ELSE + res := b + END + RETURN res +END Max; + + +PROCEDURE Min (a, b: REAL): REAL; +VAR + res: REAL; + +BEGIN + IF a < b THEN + res := a + ELSE + res := b + END + RETURN res +END Min; + + +PROCEDURE SameValue (a, b: REAL): BOOLEAN; +VAR + eps: REAL; + res: BOOLEAN; + +BEGIN + eps := Max(Min(ABS(a), ABS(b)) * 1.0E-12, 1.0E-12); + IF a > b THEN + res := (a - b) <= eps + ELSE + res := (b - a) <= eps + END + RETURN res +END SameValue; + + +PROCEDURE IsZero (x: REAL): BOOLEAN; + RETURN ABS(x) <= 1.0E-12 +END IsZero; + + +PROCEDURE [stdcall] sqrt* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0FAH, (* fsqrt *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END sqrt; + + +PROCEDURE [stdcall] sin* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0FEH, (* fsin *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END sin; + + +PROCEDURE [stdcall] cos* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0FFH, (* fcos *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END cos; + + +PROCEDURE [stdcall] tan* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0FBH, (* fsincos *) + 0DEH, 0F9H, (* fdivp st1, st *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END tan; + + +PROCEDURE [stdcall] arctan2* (y, x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) + 0D9H, 0F3H, (* fpatan *) + 0C9H, (* leave *) + 0C2H, 010H, 000H (* ret 10h *) + ) + RETURN 0.0 +END arctan2; + + +PROCEDURE [stdcall] ln* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0D9H, 0EDH, (* fldln2 *) + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0F1H, (* fyl2x *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END ln; + + +PROCEDURE [stdcall] log* (base, x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0D9H, 0E8H, (* fld1 *) + 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) + 0D9H, 0F1H, (* fyl2x *) + 0D9H, 0E8H, (* fld1 *) + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0F1H, (* fyl2x *) + 0DEH, 0F9H, (* fdivp st1, st *) + 0C9H, (* leave *) + 0C2H, 010H, 000H (* ret 10h *) + ) + RETURN 0.0 +END log; + + +PROCEDURE [stdcall] exp* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0EAH, (* fldl2e *) + 0DEH, 0C9H, 0D9H, 0C0H, + 0D9H, 0FCH, 0DCH, 0E9H, + 0D9H, 0C9H, 0D9H, 0F0H, + 0D9H, 0E8H, 0DEH, 0C1H, + 0D9H, 0FDH, 0DDH, 0D9H, + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END exp; + + +PROCEDURE [stdcall] round* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 07DH, 0F4H, 0D9H, + 07DH, 0F6H, 066H, 081H, + 04DH, 0F6H, 000H, 003H, + 0D9H, 06DH, 0F6H, 0D9H, + 0FCH, 0D9H, 06DH, 0F4H, + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END round; + + +PROCEDURE [stdcall] frac* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 050H, + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0C0H, 0D9H, 03CH, + 024H, 0D9H, 07CH, 024H, + 002H, 066H, 081H, 04CH, + 024H, 002H, 000H, 00FH, + 0D9H, 06CH, 024H, 002H, + 0D9H, 0FCH, 0D9H, 02CH, + 024H, 0DEH, 0E9H, + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END frac; + + +PROCEDURE arcsin* (x: REAL): REAL; + RETURN arctan2(x, sqrt(1.0 - x * x)) +END arcsin; + + +PROCEDURE arccos* (x: REAL): REAL; + RETURN arctan2(sqrt(1.0 - x * x), x) +END arccos; + + +PROCEDURE arctan* (x: REAL): REAL; + RETURN arctan2(x, 1.0) +END arctan; + + +PROCEDURE sinh* (x: REAL): REAL; +BEGIN + x := exp(x) + RETURN (x - 1.0 / x) * 0.5 +END sinh; + + +PROCEDURE cosh* (x: REAL): REAL; +BEGIN + x := exp(x) + RETURN (x + 1.0 / x) * 0.5 +END cosh; + + +PROCEDURE tanh* (x: REAL): REAL; +BEGIN + IF x > 15.0 THEN + x := 1.0 + ELSIF x < -15.0 THEN + x := -1.0 + ELSE + x := exp(2.0 * x); + x := (x - 1.0) / (x + 1.0) + END + + RETURN x +END tanh; + + +PROCEDURE arsinh* (x: REAL): REAL; + RETURN ln(x + sqrt(x * x + 1.0)) +END arsinh; + + +PROCEDURE arcosh* (x: REAL): REAL; + RETURN ln(x + sqrt(x * x - 1.0)) +END arcosh; + + +PROCEDURE artanh* (x: REAL): REAL; +VAR + res: REAL; + +BEGIN + IF SameValue(x, 1.0) THEN + res := SYSTEM.INF() + ELSIF SameValue(x, -1.0) THEN + res := -SYSTEM.INF() + ELSE + res := 0.5 * ln((1.0 + x) / (1.0 - x)) + END + RETURN res +END artanh; + + +PROCEDURE floor* (x: REAL): REAL; +VAR + f: REAL; + +BEGIN + f := frac(x); + x := x - f; + IF f < 0.0 THEN + x := x - 1.0 + END + RETURN x +END floor; + + +PROCEDURE ceil* (x: REAL): REAL; +VAR + f: REAL; + +BEGIN + f := frac(x); + x := x - f; + IF f > 0.0 THEN + x := x + 1.0 + END + RETURN x +END ceil; + + +PROCEDURE power* (base, exponent: REAL): REAL; +VAR + res: REAL; + +BEGIN + IF exponent = 0.0 THEN + res := 1.0 + ELSIF (base = 0.0) & (exponent > 0.0) THEN + res := 0.0 + ELSE + res := exp(exponent * ln(base)) + END + RETURN res +END power; + + +PROCEDURE sgn* (x: REAL): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF x > 0.0 THEN + res := 1 + ELSIF x < 0.0 THEN + res := -1 + ELSE + res := 0 + END + + RETURN res +END sgn; + + +PROCEDURE fact* (n: INTEGER): REAL; +VAR + res: REAL; + +BEGIN + res := 1.0; + WHILE n > 1 DO + res := res * FLT(n); + DEC(n) + END + + RETURN res +END fact; + + +END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/Out.ob07 b/programs/develop/oberon07/Lib/Linux32/Out.ob07 new file mode 100644 index 0000000000..1bb3f23255 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux32/Out.ob07 @@ -0,0 +1,277 @@ +(* + Copyright 2013, 2014, 2017, 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE Out; + +IMPORT sys := SYSTEM, API; + +CONST + + d = 1.0 - 5.0E-12; + +VAR + + Realp: PROCEDURE (x: REAL; width: INTEGER); + + +PROCEDURE Char*(x: CHAR); +BEGIN + API.putc(x) +END Char; + + +PROCEDURE String*(s: ARRAY OF CHAR); +VAR + i: INTEGER; + +BEGIN + i := 0; + WHILE (i < LEN(s)) & (s[i] # 0X) DO + Char(s[i]); + INC(i) + END +END String; + + +PROCEDURE WriteInt(x, n: INTEGER); +VAR i: INTEGER; a: ARRAY 16 OF CHAR; neg: BOOLEAN; +BEGIN + i := 0; + IF n < 1 THEN + n := 1 + END; + IF x < 0 THEN + x := -x; + DEC(n); + neg := TRUE + END; + REPEAT + a[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10; + INC(i) + UNTIL x = 0; + WHILE n > i DO + Char(" "); + DEC(n) + END; + IF neg THEN + Char("-") + END; + REPEAT + DEC(i); + Char(a[i]) + UNTIL i = 0 +END WriteInt; + +PROCEDURE IsNan(AValue: REAL): BOOLEAN; +VAR h, l: SET; +BEGIN + sys.GET(sys.ADR(AValue), l); + sys.GET(sys.ADR(AValue) + 4, h) + RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) +END IsNan; + +PROCEDURE IsInf(x: REAL): BOOLEAN; + RETURN ABS(x) = sys.INF() +END IsInf; + +PROCEDURE Int*(x, width: INTEGER); +VAR i: INTEGER; +BEGIN + IF x # 80000000H THEN + WriteInt(x, width) + ELSE + FOR i := 12 TO width DO + Char(20X) + END; + String("-2147483648") + END +END Int; + +PROCEDURE OutInf(x: REAL; width: INTEGER); +VAR s: ARRAY 5 OF CHAR; i: INTEGER; +BEGIN + IF IsNan(x) THEN + s := "Nan"; + INC(width) + ELSIF IsInf(x) & (x > 0.0) THEN + s := "+Inf" + ELSIF IsInf(x) & (x < 0.0) THEN + s := "-Inf" + END; + FOR i := 1 TO width - 4 DO + Char(" ") + END; + String(s) +END OutInf; + +PROCEDURE Ln*; +BEGIN + Char(0AX) +END Ln; + +PROCEDURE _FixReal(x: REAL; width, p: INTEGER); +VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; +BEGIN + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSIF p < 0 THEN + Realp(x, width) + ELSE + len := 0; + minus := FALSE; + IF x < 0.0 THEN + minus := TRUE; + INC(len); + x := ABS(x) + END; + e := 0; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + + IF e >= 0 THEN + len := len + e + p + 1; + IF x > 9.0 + d THEN + INC(len) + END; + IF p > 0 THEN + INC(len) + END; + ELSE + len := len + p + 2 + END; + FOR i := 1 TO width - len DO + Char(" ") + END; + IF minus THEN + Char("-") + END; + y := x; + WHILE (y < 1.0) & (y # 0.0) DO + y := y * 10.0; + DEC(e) + END; + IF e < 0 THEN + IF x - FLT(FLOOR(x)) > d THEN + Char("1"); + x := 0.0 + ELSE + Char("0"); + x := x * 10.0 + END + ELSE + WHILE e >= 0 DO + IF x - FLT(FLOOR(x)) > d THEN + IF x > 9.0 THEN + String("10") + ELSE + Char(CHR(FLOOR(x) + ORD("0") + 1)) + END; + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(e) + END + END; + IF p > 0 THEN + Char(".") + END; + WHILE p > 0 DO + IF x - FLT(FLOOR(x)) > d THEN + Char(CHR(FLOOR(x) + ORD("0") + 1)); + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(p) + END + END +END _FixReal; + +PROCEDURE Real*(x: REAL; width: INTEGER); +VAR e, n, i: INTEGER; minus: BOOLEAN; +BEGIN + Realp := Real; + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSE + e := 0; + n := 0; + IF width > 23 THEN + n := width - 23; + width := 23 + ELSIF width < 9 THEN + width := 9 + END; + width := width - 5; + IF x < 0.0 THEN + x := -x; + minus := TRUE + ELSE + minus := FALSE + END; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + WHILE (x < 1.0) & (x # 0.0) DO + x := x * 10.0; + DEC(e) + END; + IF x > 9.0 + d THEN + x := 1.0; + INC(e) + END; + FOR i := 1 TO n DO + Char(" ") + END; + IF minus THEN + x := -x + END; + _FixReal(x, width, width - 3); + Char("E"); + IF e >= 0 THEN + Char("+") + ELSE + Char("-"); + e := ABS(e) + END; + IF e < 100 THEN + Char("0") + END; + IF e < 10 THEN + Char("0") + END; + Int(e, 0) + END +END Real; + +PROCEDURE FixReal*(x: REAL; width, p: INTEGER); +BEGIN + Realp := Real; + _FixReal(x, width, p) +END FixReal; + +PROCEDURE Open*; +END Open; + +END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/RTL.ob07 b/programs/develop/oberon07/Lib/Linux32/RTL.ob07 index 3aa6c454e1..0929a5678a 100644 --- a/programs/develop/oberon07/Lib/Linux32/RTL.ob07 +++ b/programs/develop/oberon07/Lib/Linux32/RTL.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -16,34 +16,14 @@ CONST maxint* = 7FFFFFFFH; minint* = 80000000H; - DLL_PROCESS_ATTACH = 1; - DLL_THREAD_ATTACH = 2; - DLL_THREAD_DETACH = 3; - DLL_PROCESS_DETACH = 0; - WORD = bit_depth DIV 8; MAX_SET = bit_depth - 1; -TYPE - - DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); - PROC = PROCEDURE; - - VAR name: INTEGER; types: INTEGER; - bits: ARRAY MAX_SET + 1 OF INTEGER; - - dll: RECORD - process_detach, - thread_detach, - thread_attach: DLL_ENTRY - END; - - fini: PROC; PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER); @@ -97,7 +77,6 @@ VAR i, n, k: INTEGER; BEGIN - k := LEN(A) - 1; n := A[0]; i := 0; @@ -106,7 +85,6 @@ BEGIN INC(i) END; A[k] := n - END _rot; @@ -128,14 +106,16 @@ BEGIN END _set; -PROCEDURE [stdcall] _set1* (a: INTEGER): INTEGER; +PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *) BEGIN - IF ASR(a, 5) = 0 THEN - SYSTEM.GET(SYSTEM.ADR(bits[0]) + a * WORD, a) - ELSE - a := 0 - END - RETURN a + SYSTEM.CODE( + 031H, 0C0H, (* xor eax, eax *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *) + 083H, 0F9H, 01FH, (* cmp ecx, 31 *) + 077H, 003H, (* ja L *) + 00FH, 0ABH, 0C8H (* bts eax, ecx *) + (* L: *) + ) END _set1; @@ -315,7 +295,6 @@ VAR c: CHAR; BEGIN - res := strncmp(str1, str2, MIN(len1, len2)); IF res = minint THEN IF len1 > len2 THEN @@ -349,7 +328,6 @@ VAR c: WCHAR; BEGIN - res := strncmpw(str1, str2, MIN(len1, len2)); IF res = minint THEN IF len1 > len2 THEN @@ -398,7 +376,6 @@ VAR c: CHAR; BEGIN - i := 0; REPEAT str[i] := CHR(x MOD 10 + ORD("0")); @@ -422,6 +399,7 @@ END IntToStr; PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR n1, n2, i, j: INTEGER; + BEGIN n1 := LENGTH(s1); n2 := LENGTH(s2); @@ -437,7 +415,6 @@ BEGIN END; s1[j] := 0X - END append; @@ -446,20 +423,18 @@ VAR s, temp: ARRAY 1024 OF CHAR; BEGIN - - s := ""; CASE err OF - | 1: append(s, "assertion failure") - | 2: append(s, "NIL dereference") - | 3: append(s, "division by zero") - | 4: append(s, "NIL procedure call") - | 5: append(s, "type guard error") - | 6: append(s, "index out of range") - | 7: append(s, "invalid CASE") - | 8: append(s, "array assignment error") - | 9: append(s, "CHR out of range") - |10: append(s, "WCHR out of range") - |11: append(s, "BYTE out of range") + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" END; append(s, API.eol); @@ -513,36 +488,16 @@ END _guard; PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - CASE fdwReason OF - |DLL_PROCESS_ATTACH: - res := 1 - |DLL_THREAD_ATTACH: - res := 0; - IF dll.thread_attach # NIL THEN - dll.thread_attach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_THREAD_DETACH: - res := 0; - IF dll.thread_detach # NIL THEN - dll.thread_detach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_PROCESS_DETACH: - res := 0; - IF dll.process_detach # NIL THEN - dll.process_detach(hinstDLL, fdwReason, lpvReserved) - END - ELSE - res := 0 - END - - RETURN res + RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) END _dllentry; +PROCEDURE [stdcall] _sofinit*; +BEGIN + API.sofinit +END _sofinit; + + PROCEDURE [stdcall] _exit* (code: INTEGER); BEGIN API.exit(code) @@ -571,42 +526,8 @@ BEGIN END END; - j := 1; - FOR i := 0 TO MAX_SET DO - bits[i] := j; - j := LSL(j, 1) - END; - - name := modname; - - dll.process_detach := NIL; - dll.thread_detach := NIL; - dll.thread_attach := NIL; - - fini := NIL + name := modname END _init; -PROCEDURE [stdcall] _sofinit*; -BEGIN - IF fini # NIL THEN - fini - END -END _sofinit; - - -PROCEDURE SetDll* (process_detach, thread_detach, thread_attach: DLL_ENTRY); -BEGIN - dll.process_detach := process_detach; - dll.thread_detach := thread_detach; - dll.thread_attach := thread_attach -END SetDll; - - -PROCEDURE SetFini* (ProcFini: PROC); -BEGIN - fini := ProcFini -END SetFini; - - -END RTL. +END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/API.ob07 b/programs/develop/oberon07/Lib/Linux64/API.ob07 new file mode 100644 index 0000000000..8d845678d2 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/API.ob07 @@ -0,0 +1,169 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE API; + +IMPORT SYSTEM; + + +CONST + + RTLD_LAZY* = 1; + BIT_DEPTH* = 64; + + +TYPE + + TP* = ARRAY 2 OF INTEGER; + SOFINI* = PROCEDURE; + + +VAR + + eol*: ARRAY 2 OF CHAR; + MainParam*: INTEGER; + + libc*, librt*: INTEGER; + + dlopen* : PROCEDURE [linux] (filename, flag: INTEGER): INTEGER; + dlsym* : PROCEDURE [linux] (handle, symbol: INTEGER): INTEGER; + + stdout*, + stdin*, + stderr* : INTEGER; + + malloc* : PROCEDURE [linux] (size: INTEGER): INTEGER; + free* : PROCEDURE [linux] (ptr: INTEGER); + _exit* : PROCEDURE [linux] (code: INTEGER); + puts* : PROCEDURE [linux] (pStr: INTEGER); + fwrite*, + fread* : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; + fopen* : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; + fclose* : PROCEDURE [linux] (file: INTEGER): INTEGER; + + clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; + time* : PROCEDURE [linux] (ptr: INTEGER): INTEGER; + + fini: SOFINI; + + +PROCEDURE putc* (c: CHAR); +VAR + res: INTEGER; + +BEGIN + res := fwrite(SYSTEM.ADR(c), 1, 1, stdout) +END putc; + + +PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); +BEGIN + puts(lpCaption); + puts(lpText) +END DebugMsg; + + +PROCEDURE _NEW* (size: INTEGER): INTEGER; +VAR + res, ptr, words: INTEGER; + +BEGIN + res := malloc(size); + IF res # 0 THEN + ptr := res; + words := size DIV SYSTEM.SIZE(INTEGER); + WHILE words > 0 DO + SYSTEM.PUT(ptr, 0); + INC(ptr, SYSTEM.SIZE(INTEGER)); + DEC(words) + END + END + + RETURN res +END _NEW; + + +PROCEDURE _DISPOSE* (p: INTEGER): INTEGER; +BEGIN + free(p) + RETURN 0 +END _DISPOSE; + + +PROCEDURE GetProcAdr (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); +VAR + sym: INTEGER; + +BEGIN + sym := dlsym(lib, SYSTEM.ADR(name[0])); + ASSERT(sym # 0); + SYSTEM.PUT(VarAdr, sym) +END GetProcAdr; + + +PROCEDURE init* (sp, code: INTEGER); +BEGIN + fini := NIL; + SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER) * 2, dlopen); + SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER), dlsym); + MainParam := sp; + eol := 0AX; + + libc := dlopen(SYSTEM.SADR("libc.so.6"), RTLD_LAZY); + GetProcAdr(libc, "malloc", SYSTEM.ADR(malloc)); + GetProcAdr(libc, "free", SYSTEM.ADR(free)); + GetProcAdr(libc, "exit", SYSTEM.ADR(_exit)); + GetProcAdr(libc, "stdout", SYSTEM.ADR(stdout)); + GetProcAdr(libc, "stdin", SYSTEM.ADR(stdin)); + GetProcAdr(libc, "stderr", SYSTEM.ADR(stderr)); + SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); + SYSTEM.GET(stdin - SYSTEM.SIZE(INTEGER), stdin); + SYSTEM.GET(stderr - SYSTEM.SIZE(INTEGER), stderr); + GetProcAdr(libc, "puts", SYSTEM.ADR(puts)); + GetProcAdr(libc, "fwrite", SYSTEM.ADR(fwrite)); + GetProcAdr(libc, "fread", SYSTEM.ADR(fread)); + GetProcAdr(libc, "fopen", SYSTEM.ADR(fopen)); + GetProcAdr(libc, "fclose", SYSTEM.ADR(fclose)); + GetProcAdr(libc, "time", SYSTEM.ADR(time)); + + librt := dlopen(SYSTEM.SADR("librt.so.1"), RTLD_LAZY); + GetProcAdr(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) +END init; + + +PROCEDURE exit* (code: INTEGER); +BEGIN + _exit(code) +END exit; + + +PROCEDURE exit_thread* (code: INTEGER); +BEGIN + _exit(code) +END exit_thread; + + +PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; + RETURN 0 +END dllentry; + + +PROCEDURE sofinit*; +BEGIN + IF fini # NIL THEN + fini + END +END sofinit; + + +PROCEDURE SetFini* (ProcFini: SOFINI); +BEGIN + fini := ProcFini +END SetFini; + + +END API. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/HOST.ob07 b/programs/develop/oberon07/Lib/Linux64/HOST.ob07 new file mode 100644 index 0000000000..96bf051d5e --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/HOST.ob07 @@ -0,0 +1,208 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE HOST; + +IMPORT SYSTEM, API, RTL; + + +CONST + + slash* = "/"; + OS* = "LINUX"; + + bit_depth* = RTL.bit_depth; + maxint* = RTL.maxint; + minint* = RTL.minint; + + +VAR + + argc: INTEGER; + + eol*: ARRAY 2 OF CHAR; + + maxreal*: REAL; + + +PROCEDURE ExitProcess* (code: INTEGER); +BEGIN + API.exit(code) +END ExitProcess; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +VAR + i, len, ptr: INTEGER; + c: CHAR; + +BEGIN + i := 0; + len := LEN(s) - 1; + IF (n < argc) & (len > 0) THEN + SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); + REPEAT + SYSTEM.GET(ptr, c); + s[i] := c; + INC(i); + INC(ptr) + UNTIL (c = 0X) OR (i = len) + END; + s[i] := 0X +END GetArg; + + +PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); +VAR + n: INTEGER; + +BEGIN + GetArg(0, path); + n := LENGTH(path) - 1; + WHILE path[n] # slash DO + DEC(n) + END; + path[n + 1] := 0X +END GetCurrentDirectory; + + +PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + res := API.fread(SYSTEM.ADR(Buffer[0]), 1, bytes, F); + IF res <= 0 THEN + res := -1 + END + + RETURN res +END FileRead; + + +PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + res := API.fwrite(SYSTEM.ADR(Buffer[0]), 1, bytes, F); + IF res <= 0 THEN + res := -1 + END + + RETURN res +END FileWrite; + + +PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; + RETURN API.fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("wb")) +END FileCreate; + + +PROCEDURE FileClose* (File: INTEGER); +BEGIN + File := API.fclose(File) +END FileClose; + + +PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; + RETURN API.fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("rb")) +END FileOpen; + + +PROCEDURE OutChar* (c: CHAR); +BEGIN + API.putc(c) +END OutChar; + + +PROCEDURE GetTickCount* (): INTEGER; +VAR + tp: API.TP; + res: INTEGER; + +BEGIN + IF API.clock_gettime(0, tp) = 0 THEN + res := tp[0] * 100 + tp[1] DIV 10000000 + ELSE + res := 0 + END + + RETURN res +END GetTickCount; + + +PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; + RETURN path[0] # slash +END isRelative; + + +PROCEDURE now* (VAR year, month, day, hour, min, sec: INTEGER); +END now; + + +PROCEDURE UnixTime* (): INTEGER; + RETURN API.time(0) +END UnixTime; + + +PROCEDURE d2s* (x: REAL): INTEGER; +VAR + h, l, s, e: INTEGER; + +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), l); + SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + + s := ASR(h, 31) MOD 2; + e := (h DIV 100000H) MOD 2048; + IF e <= 896 THEN + h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; + REPEAT + h := h DIV 2; + INC(e) + UNTIL e = 897; + e := 896; + l := (h MOD 8) * 20000000H; + h := h DIV 8 + ELSIF (1151 <= e) & (e < 2047) THEN + e := 1151; + h := 0; + l := 0 + ELSIF e = 2047 THEN + e := 1151; + IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN + h := 80000H; + l := 0 + END + END; + DEC(e, 896) + + RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 +END d2s; + + +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + a := 0; + b := 0; + SYSTEM.MOVE(SYSTEM.ADR(x), SYSTEM.ADR(a), 4); + SYSTEM.MOVE(SYSTEM.ADR(x) + 4, SYSTEM.ADR(b), 4); + SYSTEM.GET(SYSTEM.ADR(x), res) + RETURN res +END splitf; + + +BEGIN + eol := 0AX; + maxreal := 1.9; + PACK(maxreal, 1023); + SYSTEM.GET(API.MainParam, argc) +END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 b/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 new file mode 100644 index 0000000000..c7931e2315 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 @@ -0,0 +1,138 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE LINAPI; + +IMPORT SYSTEM, API; + + +TYPE + + TP* = API.TP; + SOFINI* = API.SOFINI; + + +VAR + + argc*, envc*: INTEGER; + + libc*, librt*: INTEGER; + + stdout*, + stdin*, + stderr* : INTEGER; + + malloc* : PROCEDURE [linux] (size: INTEGER): INTEGER; + free* : PROCEDURE [linux] (ptr: INTEGER); + exit* : PROCEDURE [linux] (code: INTEGER); + puts* : PROCEDURE [linux] (pStr: INTEGER); + fwrite*, + fread* : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; + fopen* : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; + fclose* : PROCEDURE [linux] (file: INTEGER): INTEGER; + time* : PROCEDURE [linux] (ptr: INTEGER): INTEGER; + + clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +VAR + i, len, ptr: INTEGER; + c: CHAR; + +BEGIN + i := 0; + len := LEN(s) - 1; + IF (0 <= n) & (n <= argc + envc) & (n # argc) & (len > 0) THEN + SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); + REPEAT + SYSTEM.GET(ptr, c); + s[i] := c; + INC(i); + INC(ptr) + UNTIL (c = 0X) OR (i = len) + END; + s[i] := 0X +END GetArg; + + +PROCEDURE GetEnv* (n: INTEGER; VAR s: ARRAY OF CHAR); +BEGIN + IF (0 <= n) & (n < envc) THEN + GetArg(n + argc + 1, s) + ELSE + s[0] := 0X + END +END GetEnv; + + +PROCEDURE SetFini* (ProcFini: SOFINI); +BEGIN + API.SetFini(ProcFini) +END SetFini; + + +PROCEDURE init; +VAR + ptr: INTEGER; + +BEGIN + IF API.MainParam # 0 THEN + envc := -1; + SYSTEM.GET(API.MainParam, argc); + REPEAT + SYSTEM.GET(API.MainParam + (envc + argc + 3) * SYSTEM.SIZE(INTEGER), ptr); + INC(envc) + UNTIL ptr = 0 + ELSE + envc := 0; + argc := 0 + END; + + libc := API.libc; + + stdout := API.stdout; + stdin := API.stdin; + stderr := API.stderr; + + malloc := API.malloc; + free := API.free; + exit := API._exit; + puts := API.puts; + fwrite := API.fwrite; + fread := API.fread; + fopen := API.fopen; + fclose := API.fclose; + time := API.time; + + librt := API.librt; + + clock_gettime := API.clock_gettime +END init; + + +PROCEDURE [stdcall64-] syscall* (rax, rdi, rsi, rdx, r10, r8, r9: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 048H, 08BH, 045H, 010H, (* mov rax, qword [rbp + 16] *) + 048H, 08BH, 07DH, 018H, (* mov rdi, qword [rbp + 24] *) + 048H, 08BH, 075H, 020H, (* mov rsi, qword [rbp + 32] *) + 048H, 08BH, 055H, 028H, (* mov rdx, qword [rbp + 40] *) + 04CH, 08BH, 055H, 030H, (* mov r10, qword [rbp + 48] *) + 04CH, 08BH, 045H, 038H, (* mov r8, qword [rbp + 56] *) + 04CH, 08BH, 04DH, 040H, (* mov r9, qword [rbp + 64] *) + 00FH, 005H, (* syscall *) + 0C9H, (* leave *) + 0C2H, 038H, 000H (* ret 56 *) + ) + RETURN 0 +END syscall; + + +BEGIN + init +END LINAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/Libdl.ob07 b/programs/develop/oberon07/Lib/Linux64/Libdl.ob07 new file mode 100644 index 0000000000..f8a5781d87 --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/Libdl.ob07 @@ -0,0 +1,65 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE Libdl; + +IMPORT SYSTEM, API; + + +CONST + + LAZY* = 1; + NOW* = 2; + BINDING_MASK* = 3; + NOLOAD* = 4; + LOCAL* = 0; + GLOBAL* = 256; + NODELETE* = 4096; + + +VAR + + _close: PROCEDURE [linux] (handle: INTEGER): INTEGER; + _error: PROCEDURE [linux] (): INTEGER; + + +PROCEDURE open* (file: ARRAY OF CHAR; mode: INTEGER): INTEGER; + RETURN API.dlopen(SYSTEM.ADR(file[0]), mode) +END open; + + +PROCEDURE sym* (handle: INTEGER; name: ARRAY OF CHAR): INTEGER; + RETURN API.dlsym(handle, SYSTEM.ADR(name[0])) +END sym; + + +PROCEDURE close* (handle: INTEGER): INTEGER; + RETURN _close(handle) +END close; + + +PROCEDURE error* (): INTEGER; + RETURN _error() +END error; + + +PROCEDURE init; +VAR + lib: INTEGER; + +BEGIN + lib := open("libdl.so.2", LAZY); + SYSTEM.PUT(SYSTEM.ADR(_close), sym(lib, "dlclose")); + ASSERT(_close # NIL); + SYSTEM.PUT(SYSTEM.ADR(_error), sym(lib, "dlerror")); + ASSERT(_error # NIL) +END init; + + +BEGIN + init +END Libdl. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/Math.ob07 b/programs/develop/oberon07/Lib/Linux64/Math.ob07 new file mode 100644 index 0000000000..ab80d79ebf --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/Math.ob07 @@ -0,0 +1,311 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE Math; + +IMPORT SYSTEM; + + +CONST + + e *= 2.71828182845904523; + pi *= 3.14159265358979324; + ln2 *= 0.693147180559945309; + + eps = 1.0E-16; + MaxCosArg = 1000000.0 * pi; + + +VAR + + Exp: ARRAY 710 OF REAL; + + +PROCEDURE [stdcall64] sqrt* (x: REAL): REAL; +BEGIN + ASSERT(x >= 0.0); + SYSTEM.CODE( + 0F2H, 0FH, 51H, 45H, 10H, (* sqrtsd xmm0, qword[rbp + 10h] *) + 05DH, (* pop rbp *) + 0C2H, 08H, 00H (* ret 8 *) + ) + + RETURN 0.0 +END sqrt; + + +PROCEDURE exp* (x: REAL): REAL; +CONST + e25 = 1.284025416687741484; (* exp(0.25) *) + +VAR + a, s, res: REAL; + neg: BOOLEAN; + n: INTEGER; + +BEGIN + neg := x < 0.0; + IF neg THEN + x := -x + END; + + IF x < FLT(LEN(Exp)) THEN + res := Exp[FLOOR(x)]; + x := x - FLT(FLOOR(x)); + WHILE x >= 0.25 DO + res := res * e25; + x := x - 0.25 + END + ELSE + res := SYSTEM.INF(); + x := 0.0 + END; + + n := 0; + a := 1.0; + s := 1.0; + + REPEAT + INC(n); + a := a * x / FLT(n); + s := s + a + UNTIL a < eps; + + IF neg THEN + res := 1.0 / (res * s) + ELSE + res := res * s + END + + RETURN res +END exp; + + +PROCEDURE ln* (x: REAL): REAL; +VAR + a, x2, res: REAL; + n: INTEGER; + +BEGIN + ASSERT(x > 0.0); + UNPK(x, n); + + x := (x - 1.0) / (x + 1.0); + x2 := x * x; + res := x + FLT(n) * (ln2 * 0.5); + n := 1; + + REPEAT + INC(n, 2); + x := x * x2; + a := x / FLT(n); + res := res + a + UNTIL a < eps + + RETURN res * 2.0 +END ln; + + +PROCEDURE power* (base, exponent: REAL): REAL; +BEGIN + ASSERT(base > 0.0) + RETURN exp(exponent * ln(base)) +END power; + + +PROCEDURE log* (base, x: REAL): REAL; +BEGIN + ASSERT(base > 0.0); + ASSERT(x > 0.0) + RETURN ln(x) / ln(base) +END log; + + +PROCEDURE cos* (x: REAL): REAL; +VAR + a, res: REAL; + n: INTEGER; + +BEGIN + x := ABS(x); + ASSERT(x <= MaxCosArg); + + x := x - FLT( FLOOR(x / (2.0 * pi)) ) * (2.0 * pi); + x := x * x; + res := 0.0; + a := 1.0; + n := -1; + + REPEAT + INC(n, 2); + res := res + a; + a := -a * x / FLT(n*n + n) + UNTIL ABS(a) < eps + + RETURN res +END cos; + + +PROCEDURE sin* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) <= MaxCosArg); + x := cos(x) + RETURN sqrt(1.0 - x * x) +END sin; + + +PROCEDURE tan* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) <= MaxCosArg); + x := cos(x) + RETURN sqrt(1.0 - x * x) / x +END tan; + + +PROCEDURE arcsin* (x: REAL): REAL; + + + PROCEDURE arctan (x: REAL): REAL; + VAR + z, p, k: REAL; + + BEGIN + p := x / (x * x + 1.0); + z := p * x; + x := 0.0; + k := 0.0; + + REPEAT + k := k + 2.0; + x := x + p; + p := p * k * z / (k + 1.0) + UNTIL p < eps + + RETURN x + END arctan; + + +BEGIN + ASSERT(ABS(x) <= 1.0); + + IF ABS(x) >= 0.707 THEN + x := 0.5 * pi - arctan(sqrt(1.0 - x * x) / x) + ELSE + x := arctan(x / sqrt(1.0 - x * x)) + END + + RETURN x +END arcsin; + + +PROCEDURE arccos* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) <= 1.0) + RETURN 0.5 * pi - arcsin(x) +END arccos; + + +PROCEDURE arctan* (x: REAL): REAL; + RETURN arcsin(x / sqrt(1.0 + x * x)) +END arctan; + + +PROCEDURE sinh* (x: REAL): REAL; +BEGIN + x := exp(x) + RETURN (x - 1.0 / x) * 0.5 +END sinh; + + +PROCEDURE cosh* (x: REAL): REAL; +BEGIN + x := exp(x) + RETURN (x + 1.0 / x) * 0.5 +END cosh; + + +PROCEDURE tanh* (x: REAL): REAL; +BEGIN + IF x > 15.0 THEN + x := 1.0 + ELSIF x < -15.0 THEN + x := -1.0 + ELSE + x := exp(2.0 * x); + x := (x - 1.0) / (x + 1.0) + END + + RETURN x +END tanh; + + +PROCEDURE arsinh* (x: REAL): REAL; + RETURN ln(x + sqrt(x * x + 1.0)) +END arsinh; + + +PROCEDURE arcosh* (x: REAL): REAL; +BEGIN + ASSERT(x >= 1.0) + RETURN ln(x + sqrt(x * x - 1.0)) +END arcosh; + + +PROCEDURE artanh* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) < 1.0) + RETURN 0.5 * ln((1.0 + x) / (1.0 - x)) +END artanh; + + +PROCEDURE sgn* (x: REAL): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF x > 0.0 THEN + res := 1 + ELSIF x < 0.0 THEN + res := -1 + ELSE + res := 0 + END + + RETURN res +END sgn; + + +PROCEDURE fact* (n: INTEGER): REAL; +VAR + res: REAL; + +BEGIN + res := 1.0; + WHILE n > 1 DO + res := res * FLT(n); + DEC(n) + END + + RETURN res +END fact; + + +PROCEDURE init; +VAR + i: INTEGER; + +BEGIN + Exp[0] := 1.0; + FOR i := 1 TO LEN(Exp) - 1 DO + Exp[i] := Exp[i - 1] * e + END +END init; + + +BEGIN + init +END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/Out.ob07 b/programs/develop/oberon07/Lib/Linux64/Out.ob07 new file mode 100644 index 0000000000..48d4e84c6c --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/Out.ob07 @@ -0,0 +1,276 @@ +(* + Copyright 2013, 2014, 2017, 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE Out; + +IMPORT sys := SYSTEM, API; + +CONST + + d = 1.0 - 5.0E-12; + +VAR + + Realp: PROCEDURE (x: REAL; width: INTEGER); + + +PROCEDURE Char*(x: CHAR); +BEGIN + API.putc(x) +END Char; + + +PROCEDURE String*(s: ARRAY OF CHAR); +VAR + i: INTEGER; + +BEGIN + i := 0; + WHILE (i < LEN(s)) & (s[i] # 0X) DO + Char(s[i]); + INC(i) + END +END String; + + +PROCEDURE WriteInt(x, n: INTEGER); +VAR i: INTEGER; a: ARRAY 24 OF CHAR; neg: BOOLEAN; +BEGIN + i := 0; + IF n < 1 THEN + n := 1 + END; + IF x < 0 THEN + x := -x; + DEC(n); + neg := TRUE + END; + REPEAT + a[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10; + INC(i) + UNTIL x = 0; + WHILE n > i DO + Char(" "); + DEC(n) + END; + IF neg THEN + Char("-") + END; + REPEAT + DEC(i); + Char(a[i]) + UNTIL i = 0 +END WriteInt; + +PROCEDURE IsNan(AValue: REAL): BOOLEAN; +VAR s: SET; +BEGIN + sys.GET(sys.ADR(AValue), s) + RETURN (s * {52..62} = {52..62}) & ((s * {32..51} # {}) OR (s * {0..31} # {})) +END IsNan; + +PROCEDURE IsInf(x: REAL): BOOLEAN; + RETURN ABS(x) = sys.INF() +END IsInf; + +PROCEDURE Int*(x, width: INTEGER); +VAR i: INTEGER; +BEGIN + IF x # 80000000H THEN + WriteInt(x, width) + ELSE + FOR i := 12 TO width DO + Char(20X) + END; + String("-2147483648") + END +END Int; + +PROCEDURE OutInf(x: REAL; width: INTEGER); +VAR s: ARRAY 5 OF CHAR; i: INTEGER; +BEGIN + IF IsNan(x) THEN + s := "Nan"; + INC(width) + ELSIF IsInf(x) & (x > 0.0) THEN + s := "+Inf" + ELSIF IsInf(x) & (x < 0.0) THEN + s := "-Inf" + END; + FOR i := 1 TO width - 4 DO + Char(" ") + END; + String(s) +END OutInf; + +PROCEDURE Ln*; +BEGIN + Char(0AX) +END Ln; + +PROCEDURE _FixReal(x: REAL; width, p: INTEGER); +VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; +BEGIN + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSIF p < 0 THEN + Realp(x, width) + ELSE + len := 0; + minus := FALSE; + IF x < 0.0 THEN + minus := TRUE; + INC(len); + x := ABS(x) + END; + e := 0; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + + IF e >= 0 THEN + len := len + e + p + 1; + IF x > 9.0 + d THEN + INC(len) + END; + IF p > 0 THEN + INC(len) + END; + ELSE + len := len + p + 2 + END; + FOR i := 1 TO width - len DO + Char(" ") + END; + IF minus THEN + Char("-") + END; + y := x; + WHILE (y < 1.0) & (y # 0.0) DO + y := y * 10.0; + DEC(e) + END; + IF e < 0 THEN + IF x - FLT(FLOOR(x)) > d THEN + Char("1"); + x := 0.0 + ELSE + Char("0"); + x := x * 10.0 + END + ELSE + WHILE e >= 0 DO + IF x - FLT(FLOOR(x)) > d THEN + IF x > 9.0 THEN + String("10") + ELSE + Char(CHR(FLOOR(x) + ORD("0") + 1)) + END; + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(e) + END + END; + IF p > 0 THEN + Char(".") + END; + WHILE p > 0 DO + IF x - FLT(FLOOR(x)) > d THEN + Char(CHR(FLOOR(x) + ORD("0") + 1)); + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(p) + END + END +END _FixReal; + +PROCEDURE Real*(x: REAL; width: INTEGER); +VAR e, n, i: INTEGER; minus: BOOLEAN; +BEGIN + Realp := Real; + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSE + e := 0; + n := 0; + IF width > 23 THEN + n := width - 23; + width := 23 + ELSIF width < 9 THEN + width := 9 + END; + width := width - 5; + IF x < 0.0 THEN + x := -x; + minus := TRUE + ELSE + minus := FALSE + END; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + WHILE (x < 1.0) & (x # 0.0) DO + x := x * 10.0; + DEC(e) + END; + IF x > 9.0 + d THEN + x := 1.0; + INC(e) + END; + FOR i := 1 TO n DO + Char(" ") + END; + IF minus THEN + x := -x + END; + _FixReal(x, width, width - 3); + Char("E"); + IF e >= 0 THEN + Char("+") + ELSE + Char("-"); + e := ABS(e) + END; + IF e < 100 THEN + Char("0") + END; + IF e < 10 THEN + Char("0") + END; + Int(e, 0) + END +END Real; + +PROCEDURE FixReal*(x: REAL; width, p: INTEGER); +BEGIN + Realp := Real; + _FixReal(x, width, p) +END FixReal; + +PROCEDURE Open*; +END Open; + +END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/RTL.ob07 b/programs/develop/oberon07/Lib/Linux64/RTL.ob07 new file mode 100644 index 0000000000..94a94eafda --- /dev/null +++ b/programs/develop/oberon07/Lib/Linux64/RTL.ob07 @@ -0,0 +1,516 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018-2020, Anton Krotov + All rights reserved. +*) + +MODULE RTL; + +IMPORT SYSTEM, API; + + +CONST + + bit_depth* = 64; + maxint* = 7FFFFFFFFFFFFFFFH; + minint* = 8000000000000000H; + + WORD = bit_depth DIV 8; + MAX_SET = bit_depth - 1; + + +VAR + + name: INTEGER; + types: INTEGER; + sets: ARRAY (MAX_SET + 1) * (MAX_SET + 1) OF INTEGER; + + +PROCEDURE [stdcall64] _move* (bytes, dest, source: INTEGER); +BEGIN + SYSTEM.CODE( + 048H, 08BH, 045H, 010H, (* mov rax, qword [rbp + 16] *) + 048H, 085H, 0C0H, (* test rax, rax *) + 07EH, 020H, (* jle L *) + 0FCH, (* cld *) + 057H, (* push rdi *) + 056H, (* push rsi *) + 048H, 08BH, 075H, 020H, (* mov rsi, qword [rbp + 32] *) + 048H, 08BH, 07DH, 018H, (* mov rdi, qword [rbp + 24] *) + 048H, 089H, 0C1H, (* mov rcx, rax *) + 048H, 0C1H, 0E9H, 003H, (* shr rcx, 3 *) + 0F3H, 048H, 0A5H, (* rep movsd *) + 048H, 089H, 0C1H, (* mov rcx, rax *) + 048H, 083H, 0E1H, 007H, (* and rcx, 7 *) + 0F3H, 0A4H, (* rep movsb *) + 05EH, (* pop rsi *) + 05FH (* pop rdi *) + (* L: *) + ) +END _move; + + +PROCEDURE [stdcall64] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + IF len_src > len_dst THEN + res := FALSE + ELSE + _move(len_src * base_size, dst, src); + res := TRUE + END + + RETURN res +END _arrcpy; + + +PROCEDURE [stdcall64] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); +BEGIN + _move(MIN(len_dst, len_src) * chr_size, dst, src) +END _strcpy; + + +PROCEDURE [stdcall64] _rot* (VAR A: ARRAY OF INTEGER); +VAR + i, n, k: INTEGER; + +BEGIN + k := LEN(A) - 1; + n := A[0]; + i := 0; + WHILE i < k DO + A[i] := A[i + 1]; + INC(i) + END; + A[k] := n +END _rot; + + +PROCEDURE [stdcall64] _set* (b, a: INTEGER): INTEGER; +BEGIN + IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN + SYSTEM.GET((MIN(b, MAX_SET) * (MAX_SET + 1) + MAX(a, 0)) * WORD + SYSTEM.ADR(sets[0]), a) + ELSE + a := 0 + END + + RETURN a +END _set; + + +PROCEDURE [stdcall64] _set1* (a: INTEGER); (* {a} -> rax *) +BEGIN + SYSTEM.CODE( + 048H, 031H, 0C0H, (* xor rax, rax *) + 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) (* rcx <- a *) + 048H, 083H, 0F9H, 03FH, (* cmp rcx, 63 *) + 077H, 004H, (* ja L *) + 048H, 00FH, 0ABH, 0C8H (* bts rax, rcx *) + (* L: *) + ) +END _set1; + + +PROCEDURE [stdcall64] _divmod* (y, x: INTEGER); (* (x div y) -> rax; (x mod y) -> rdx *) +BEGIN + SYSTEM.CODE( + 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) (* rax <- x *) + 048H, 031H, 0D2H, (* xor rdx, rdx *) + 048H, 085H, 0C0H, (* test rax, rax *) + 074H, 022H, (* je L2 *) + 07FH, 003H, (* jg L1 *) + 048H, 0F7H, 0D2H, (* not rdx *) + (* L1: *) + 049H, 089H, 0C0H, (* mov r8, rax *) + 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) (* rcx <- y *) + 048H, 0F7H, 0F9H, (* idiv rcx *) + 048H, 085H, 0D2H, (* test rdx, rdx *) + 074H, 00EH, (* je L2 *) + 049H, 031H, 0C8H, (* xor r8, rcx *) + 04DH, 085H, 0C0H, (* test r8, r8 *) + 07DH, 006H, (* jge L2 *) + 048H, 0FFH, 0C8H, (* dec rax *) + 048H, 001H, 0CAH (* add rdx, rcx *) + (* L2: *) + ) +END _divmod; + + +PROCEDURE [stdcall64] _new* (t, size: INTEGER; VAR ptr: INTEGER); +BEGIN + ptr := API._NEW(size); + IF ptr # 0 THEN + SYSTEM.PUT(ptr, t); + INC(ptr, WORD) + END +END _new; + + +PROCEDURE [stdcall64] _dispose* (VAR ptr: INTEGER); +BEGIN + IF ptr # 0 THEN + ptr := API._DISPOSE(ptr - WORD) + END +END _dispose; + + +PROCEDURE [stdcall64] _length* (len, str: INTEGER); +BEGIN + SYSTEM.CODE( + 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) + 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) + 048H, 0FFH, 0C8H, (* dec rax *) + (* L1: *) + 048H, 0FFH, 0C0H, (* inc rax *) + 080H, 038H, 000H, (* cmp byte [rax], 0 *) + 074H, 005H, (* jz L2 *) + 0E2H, 0F6H, (* loop L1 *) + 048H, 0FFH, 0C0H, (* inc rax *) + (* L2: *) + 048H, 02BH, 045H, 018H (* sub rax, qword [rbp + 24] *) + ) +END _length; + + +PROCEDURE [stdcall64] _lengthw* (len, str: INTEGER); +BEGIN + SYSTEM.CODE( + 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) + 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) + 048H, 083H, 0E8H, 002H, (* sub rax, 2 *) + (* L1: *) + 048H, 083H, 0C0H, 002H, (* add rax, 2 *) + 066H, 083H, 038H, 000H, (* cmp word [rax], 0 *) + 074H, 006H, (* jz L2 *) + 0E2H, 0F4H, (* loop L1 *) + 048H, 083H, 0C0H, 002H, (* add rax, 2 *) + (* L2: *) + 048H, 02BH, 045H, 018H, (* sub rax, qword [rbp + 24] *) + 048H, 0D1H, 0E8H (* shr rax, 1 *) + ) +END _lengthw; + + +PROCEDURE [stdcall64] strncmp (a, b, n: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 048H, 08BH, 04DH, 010H, (* mov rcx, qword[rbp + 16]; rcx <- a *) + 048H, 08BH, 055H, 018H, (* mov rdx, qword[rbp + 24]; rdx <- b *) + 04CH, 08BH, 045H, 020H, (* mov r8, qword[rbp + 32]; r8 <- n *) + 04DH, 031H, 0C9H, (* xor r9, r9 *) + 04DH, 031H, 0D2H, (* xor r10, r10 *) + 048H, 0B8H, 000H, 000H, + 000H, 000H, 000H, 000H, + 000H, 080H, (* movabs rax, minint *) + (* L1: *) + 04DH, 085H, 0C0H, (* test r8, r8 *) + 07EH, 024H, (* jle L3 *) + 044H, 08AH, 009H, (* mov r9b, byte[rcx] *) + 044H, 08AH, 012H, (* mov r10b, byte[rdx] *) + 048H, 0FFH, 0C1H, (* inc rcx *) + 048H, 0FFH, 0C2H, (* inc rdx *) + 049H, 0FFH, 0C8H, (* dec r8 *) + 04DH, 039H, 0D1H, (* cmp r9, r10 *) + 074H, 008H, (* je L2 *) + 04CH, 089H, 0C8H, (* mov rax, r9 *) + 04CH, 029H, 0D0H, (* sub rax, r10 *) + 0EBH, 008H, (* jmp L3 *) + (* L2: *) + 04DH, 085H, 0C9H, (* test r9, r9 *) + 075H, 0DAH, (* jne L1 *) + 048H, 031H, 0C0H, (* xor rax, rax *) + (* L3: *) + 05DH, (* pop rbp *) + 0C2H, 018H, 000H (* ret 24 *) + ) + RETURN 0 +END strncmp; + + +PROCEDURE [stdcall64] strncmpw (a, b, n: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 048H, 08BH, 04DH, 010H, (* mov rcx, qword[rbp + 16]; rcx <- a *) + 048H, 08BH, 055H, 018H, (* mov rdx, qword[rbp + 24]; rdx <- b *) + 04CH, 08BH, 045H, 020H, (* mov r8, qword[rbp + 32]; r8 <- n *) + 04DH, 031H, 0C9H, (* xor r9, r9 *) + 04DH, 031H, 0D2H, (* xor r10, r10 *) + 048H, 0B8H, 000H, 000H, + 000H, 000H, 000H, 000H, + 000H, 080H, (* movabs rax, minint *) + (* L1: *) + 04DH, 085H, 0C0H, (* test r8, r8 *) + 07EH, 028H, (* jle L3 *) + 066H, 044H, 08BH, 009H, (* mov r9w, word[rcx] *) + 066H, 044H, 08BH, 012H, (* mov r10w, word[rdx] *) + 048H, 083H, 0C1H, 002H, (* add rcx, 2 *) + 048H, 083H, 0C2H, 002H, (* add rdx, 2 *) + 049H, 0FFH, 0C8H, (* dec r8 *) + 04DH, 039H, 0D1H, (* cmp r9, r10 *) + 074H, 008H, (* je L2 *) + 04CH, 089H, 0C8H, (* mov rax, r9 *) + 04CH, 029H, 0D0H, (* sub rax, r10 *) + 0EBH, 008H, (* jmp L3 *) + (* L2: *) + 04DH, 085H, 0C9H, (* test r9, r9 *) + 075H, 0D6H, (* jne L1 *) + 048H, 031H, 0C0H, (* xor rax, rax *) + (* L3: *) + 05DH, (* pop rbp *) + 0C2H, 018H, 000H (* ret 24 *) + ) + RETURN 0 +END strncmpw; + + +PROCEDURE [stdcall64] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: CHAR; + +BEGIN + res := strncmp(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmp; + + +PROCEDURE [stdcall64] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: WCHAR; + +BEGIN + res := strncmpw(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2 * 2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1 * 2, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmpw; + + +PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); +VAR + c: CHAR; + i: INTEGER; + +BEGIN + i := 0; + REPEAT + SYSTEM.GET(pchar, c); + s[i] := c; + INC(pchar); + INC(i) + UNTIL c = 0X +END PCharToStr; + + +PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); +VAR + i, a, b: INTEGER; + c: CHAR; + +BEGIN + i := 0; + REPEAT + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10; + INC(i) + UNTIL x = 0; + + a := 0; + b := i - 1; + WHILE a < b DO + c := str[a]; + str[a] := str[b]; + str[b] := c; + INC(a); + DEC(b) + END; + str[i] := 0X +END IntToStr; + + +PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); +VAR + n1, n2, i, j: INTEGER; + +BEGIN + n1 := LENGTH(s1); + n2 := LENGTH(s2); + + ASSERT(n1 + n2 < LEN(s1)); + + i := 0; + j := n1; + WHILE i < n2 DO + s1[j] := s2[i]; + INC(i); + INC(j) + END; + + s1[j] := 0X +END append; + + +PROCEDURE [stdcall64] _error* (module, err, line: INTEGER); +VAR + s, temp: ARRAY 1024 OF CHAR; + +BEGIN + CASE err OF + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" + END; + + append(s, API.eol); + + 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); + + API.exit_thread(0) +END _error; + + +PROCEDURE [stdcall64] _isrec* (t0, t1, r: INTEGER): INTEGER; +BEGIN + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 +END _isrec; + + +PROCEDURE [stdcall64] _is* (t0, p: INTEGER): INTEGER; +BEGIN + IF p # 0 THEN + SYSTEM.GET(p - WORD, p); + SYSTEM.GET(t0 + p + types, p) + END + + RETURN p MOD 2 +END _is; + + +PROCEDURE [stdcall64] _guardrec* (t0, t1: INTEGER): INTEGER; +BEGIN + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 +END _guardrec; + + +PROCEDURE [stdcall64] _guard* (t0, p: INTEGER): INTEGER; +BEGIN + SYSTEM.GET(p, p); + IF p # 0 THEN + SYSTEM.GET(p - WORD, p); + SYSTEM.GET(t0 + p + types, p) + ELSE + p := 1 + END + + RETURN p MOD 2 +END _guard; + + +PROCEDURE [stdcall64] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; + RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) +END _dllentry; + + +PROCEDURE [stdcall64] _sofinit*; +BEGIN + API.sofinit +END _sofinit; + + +PROCEDURE [stdcall64] _exit* (code: INTEGER); +BEGIN + API.exit(code) +END _exit; + + +PROCEDURE [stdcall64] _init* (modname: INTEGER; tcount, _types: INTEGER; code, param: INTEGER); +VAR + t0, t1, i, j: INTEGER; + +BEGIN + API.init(param, code); + + types := API._NEW(tcount * tcount + SYSTEM.SIZE(INTEGER)); + ASSERT(types # 0); + FOR i := 0 TO tcount - 1 DO + FOR j := 0 TO tcount - 1 DO + t0 := i; t1 := j; + + WHILE (t1 # 0) & (t1 # t0) DO + SYSTEM.GET(_types + t1 * WORD, t1) + END; + + SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) + END + END; + + FOR i := 0 TO MAX_SET DO + FOR j := 0 TO i DO + sets[i * (MAX_SET + 1) + j] := LSR(ASR(minint, i - j), MAX_SET - i) + END + END; + + name := modname +END _init; + + +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 ec9ce7a93a..0eaf6c9a7a 100644 --- a/programs/develop/oberon07/Lib/Windows32/API.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/API.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -14,6 +14,16 @@ CONST SectionAlignment = 1000H; + DLL_PROCESS_ATTACH = 1; + DLL_THREAD_ATTACH = 2; + DLL_THREAD_DETACH = 3; + DLL_PROCESS_DETACH = 0; + + +TYPE + + DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); + VAR @@ -21,6 +31,10 @@ VAR base*: INTEGER; heap: INTEGER; + process_detach, + thread_detach, + thread_attach: DLL_ENTRY; + PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] ExitProcess (code: INTEGER); PROCEDURE [windows-, "kernel32.dll", "ExitThread"] ExitThread (code: INTEGER); @@ -51,6 +65,9 @@ END _DISPOSE; PROCEDURE init* (reserved, code: INTEGER); BEGIN + process_detach := NIL; + thread_detach := NIL; + thread_attach := NIL; eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; base := code - SectionAlignment; heap := GetProcessHeap() @@ -69,4 +86,45 @@ BEGIN END exit_thread; -END API. +PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + res := 0; + + CASE fdwReason OF + |DLL_PROCESS_ATTACH: + res := 1 + |DLL_THREAD_ATTACH: + IF thread_attach # NIL THEN + thread_attach(hinstDLL, fdwReason, lpvReserved) + END + |DLL_THREAD_DETACH: + IF thread_detach # NIL THEN + thread_detach(hinstDLL, fdwReason, lpvReserved) + END + |DLL_PROCESS_DETACH: + IF process_detach # NIL THEN + process_detach(hinstDLL, fdwReason, lpvReserved) + END + ELSE + END + + RETURN res +END dllentry; + + +PROCEDURE sofinit*; +END sofinit; + + +PROCEDURE SetDll* (_process_detach, _thread_detach, _thread_attach: DLL_ENTRY); +BEGIN + process_detach := _process_detach; + thread_detach := _thread_detach; + thread_attach := _thread_attach +END SetDll; + + +END API. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Args.ob07 b/programs/develop/oberon07/Lib/Windows32/Args.ob07 new file mode 100644 index 0000000000..7777687a4b --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/Args.ob07 @@ -0,0 +1,101 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE Args; + +IMPORT SYSTEM, WINAPI; + + +CONST + + MAX_PARAM = 1024; + + +VAR + + Params: ARRAY MAX_PARAM, 2 OF INTEGER; + argc*: INTEGER; + + +PROCEDURE GetChar (adr: INTEGER): CHAR; +VAR + res: CHAR; + +BEGIN + SYSTEM.GET(adr, res) + RETURN res +END GetChar; + + +PROCEDURE ParamParse; +VAR + p, count, cond: INTEGER; + c: CHAR; + + + PROCEDURE ChangeCond (A, B, C: INTEGER; VAR cond: INTEGER; c: CHAR): INTEGER; + BEGIN + IF (c <= 20X) & (c # 0X) THEN + cond := A + ELSIF c = 22X THEN + cond := B + ELSIF c = 0X THEN + cond := 6 + ELSE + cond := C + END + + RETURN cond + END ChangeCond; + + +BEGIN + p := WINAPI.GetCommandLine(); + cond := 0; + count := 0; + WHILE (count < MAX_PARAM) & (cond # 6) DO + c := GetChar(p); + CASE cond OF + |0: IF ChangeCond(0, 4, 1, cond, c) = 1 THEN Params[count, 0] := p END + |1: IF ChangeCond(0, 3, 1, cond, c) IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END + |3: IF ChangeCond(3, 1, 3, cond, c) = 6 THEN Params[count, 1] := p - 1; INC(count) END + |4: IF ChangeCond(5, 0, 5, cond, c) = 5 THEN Params[count, 0] := p END + |5: IF ChangeCond(5, 1, 5, cond, c) = 6 THEN Params[count, 1] := p - 1; INC(count) END + |6: + END; + INC(p) + END; + argc := count +END ParamParse; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +VAR + i, j, len: INTEGER; + c: CHAR; + +BEGIN + j := 0; + IF n < argc THEN + i := Params[n, 0]; + len := LEN(s) - 1; + WHILE (j < len) & (i <= Params[n, 1]) DO + c := GetChar(i); + IF c # '"' THEN + s[j] := c; + INC(j) + END; + INC(i) + END + END; + s[j] := 0X +END GetArg; + + +BEGIN + ParamParse +END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Console.ob07 b/programs/develop/oberon07/Lib/Windows32/Console.ob07 new file mode 100644 index 0000000000..3cbfdb0a34 --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/Console.ob07 @@ -0,0 +1,100 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE Console; + +IMPORT SYSTEM, WINAPI, In, Out; + + +CONST + + Black* = 0; Blue* = 1; Green* = 2; Cyan* = 3; + Red* = 4; Magenta* = 5; Brown* = 6; LightGray* = 7; + DarkGray* = 8; LightBlue* = 9; LightGreen* = 10; LightCyan* = 11; + LightRed* = 12; LightMagenta* = 13; Yellow* = 14; White* = 15; + + +VAR + + hConsoleOutput: INTEGER; + + +PROCEDURE SetCursor* (X, Y: INTEGER); +BEGIN + WINAPI.SetConsoleCursorPosition(hConsoleOutput, X + Y * 65536) +END SetCursor; + + +PROCEDURE GetCursor* (VAR X, Y: INTEGER); +VAR + ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; + +BEGIN + WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); + X := ORD(ScrBufInfo.dwCursorPosition.X); + Y := ORD(ScrBufInfo.dwCursorPosition.Y) +END GetCursor; + + +PROCEDURE Cls*; +VAR + fill: INTEGER; + ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; + +BEGIN + WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); + fill := ORD(ScrBufInfo.dwSize.X) * ORD(ScrBufInfo.dwSize.Y); + WINAPI.FillConsoleOutputCharacter(hConsoleOutput, 20H, fill, 0, SYSTEM.ADR(fill)); + WINAPI.FillConsoleOutputAttribute(hConsoleOutput, ORD(ScrBufInfo.wAttributes), fill, 0, SYSTEM.ADR(fill)); + SetCursor(0, 0) +END Cls; + + +PROCEDURE SetColor* (FColor, BColor: INTEGER); +BEGIN + IF (FColor IN {0..15}) & (BColor IN {0..15}) THEN + WINAPI.SetConsoleTextAttribute(hConsoleOutput, LSL(BColor, 4) + FColor) + END +END SetColor; + + +PROCEDURE GetCursorX* (): INTEGER; +VAR + ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; + +BEGIN + WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo) + RETURN ORD(ScrBufInfo.dwCursorPosition.X) +END GetCursorX; + + +PROCEDURE GetCursorY* (): INTEGER; +VAR + ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; + +BEGIN + WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo) + RETURN ORD(ScrBufInfo.dwCursorPosition.Y) +END GetCursorY; + + +PROCEDURE open*; +BEGIN + WINAPI.AllocConsole; + hConsoleOutput := WINAPI.GetStdHandle(-11); + In.Open; + Out.Open +END open; + + +PROCEDURE exit* (b: BOOLEAN); +BEGIN + WINAPI.FreeConsole +END exit; + + +END Console. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 b/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 new file mode 100644 index 0000000000..0a31732893 --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 @@ -0,0 +1,174 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE DateTime; + +IMPORT WINAPI; + + +CONST + + ERR* = -7.0E5; + + +VAR + + DateTable: ARRAY 120000, 3 OF INTEGER; + MonthsTable: ARRAY 13, 4 OF INTEGER; + + +PROCEDURE Encode* (Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): REAL; +VAR + d, bis: INTEGER; + res: REAL; + +BEGIN + res := ERR; + IF (Year >= 1) & (Year <= 9999) & (Month >= 1) & (Month <= 12) & + (Day >= 1) & (Day <= 31) & (Hour >= 0) & (Hour <= 23) & + (Min >= 0) & (Min <= 59) & (Sec >= 0) & (Sec <= 59) & + (MSec >= 0) & (MSec <= 999) THEN + + bis := ORD((Year MOD 4 = 0) & (Year MOD 100 # 0) OR (Year MOD 400 = 0)); + + IF Day <= MonthsTable[Month][2 + bis] THEN + DEC(Year); + d := Year * 365 + (Year DIV 4) - (Year DIV 100) + (Year DIV 400) + + MonthsTable[Month][bis] + Day - 693594; + res := FLT(d) + FLT(Hour * 3600000 + Min * 60000 + Sec * 1000 + MSec) / 86400000.0 + END + END + RETURN res +END Encode; + + +PROCEDURE Decode* (Date: REAL; VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + d, t: INTEGER; + L, R, M: INTEGER; + +BEGIN + res := (Date >= -693593.0) & (Date < 2958466.0); + IF res THEN + d := FLOOR(Date); + t := FLOOR((Date - FLT(d)) * 86400000.0); + INC(d, 693593); + + L := 0; + R := LEN(DateTable) - 1; + M := (L + R) DIV 2; + + WHILE R - L > 1 DO + IF d > DateTable[M][0] THEN + L := M; + M := (L + R) DIV 2 + ELSIF d < DateTable[M][0] THEN + R := M; + M := (L + R) DIV 2 + ELSE + L := M; + R := M + END + END; + + Year := DateTable[L][1]; + Month := DateTable[L][2]; + Day := d - DateTable[L][0] + 1; + + Hour := t DIV 3600000; t := t MOD 3600000; + Min := t DIV 60000; t := t MOD 60000; + Sec := t DIV 1000; + MSec := t MOD 1000 + END + + RETURN res +END Decode; + + +PROCEDURE Now* (VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER); +VAR + T: WINAPI.TSystemTime; + +BEGIN + WINAPI.GetLocalTime(T); + Year := ORD(T.Year); + Month := ORD(T.Month); + Day := ORD(T.Day); + Hour := ORD(T.Hour); + Min := ORD(T.Min); + Sec := ORD(T.Sec); + MSec := ORD(T.MSec) +END Now; + + +PROCEDURE NowEncode* (): REAL; +VAR + Year, Month, Day, Hour, Min, Sec, MSec: INTEGER; + +BEGIN + Now(Year, Month, Day, Hour, Min, Sec, MSec) + RETURN Encode(Year, Month, Day, Hour, Min, Sec, MSec) +END NowEncode; + + +PROCEDURE init; +VAR + day, year, month, i: INTEGER; + Months: ARRAY 13 OF INTEGER; + +BEGIN + Months[1] := 31; Months[2] := 28; Months[3] := 31; Months[4] := 30; + Months[5] := 31; Months[6] := 30; Months[7] := 31; Months[8] := 31; + Months[9] := 30; Months[10] := 31; Months[11] := 30; Months[12] := 31; + + day := 0; + year := 1; + month := 1; + i := 0; + + WHILE year <= 10000 DO + DateTable[i][0] := day; + DateTable[i][1] := year; + DateTable[i][2] := month; + INC(day, Months[month]); + IF (month = 2) & ((year MOD 4 = 0) & (year MOD 100 # 0) OR (year MOD 400 = 0)) THEN + INC(day) + END; + INC(month); + IF month > 12 THEN + month := 1; + INC(year) + END; + INC(i) + END; + + MonthsTable[1][0] := 0; + FOR i := 2 TO 12 DO + MonthsTable[i][0] := MonthsTable[i - 1][0] + Months[i - 1] + END; + + FOR i := 1 TO 12 DO + MonthsTable[i][2] := Months[i] + END; + + Months[2] := 29; + MonthsTable[1][1] := 0; + FOR i := 2 TO 12 DO + MonthsTable[i][1] := MonthsTable[i - 1][1] + Months[i - 1] + END; + + FOR i := 1 TO 12 DO + MonthsTable[i][3] := Months[i] + END + +END init; + + +BEGIN + init +END DateTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/File.ob07 b/programs/develop/oberon07/Lib/Windows32/File.ob07 new file mode 100644 index 0000000000..9f3470636b --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/File.ob07 @@ -0,0 +1,142 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE File; + +IMPORT SYSTEM, WINAPI; + + +CONST + + OPEN_R* = 0; OPEN_W* = 1; OPEN_RW* = 2; + SEEK_BEG* = 0; SEEK_CUR* = 1; SEEK_END* = 2; + + +PROCEDURE Exists* (FName: ARRAY OF CHAR): BOOLEAN; +VAR + FindData: WINAPI.TWin32FindData; + Handle: INTEGER; + +BEGIN + Handle := WINAPI.FindFirstFile(SYSTEM.ADR(FName[0]), FindData); + IF Handle # -1 THEN + WINAPI.FindClose(Handle); + IF 4 IN FindData.dwFileAttributes THEN + Handle := -1 + END + END + + RETURN Handle # -1 +END Exists; + + +PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; + RETURN WINAPI.DeleteFile(SYSTEM.ADR(FName[0])) # 0 +END Delete; + + +PROCEDURE Create* (FName: ARRAY OF CHAR): INTEGER; + RETURN WINAPI.CreateFile(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) +END Create; + + +PROCEDURE Close* (F: INTEGER); +BEGIN + WINAPI.CloseHandle(F) +END Close; + + +PROCEDURE Open* (FName: ARRAY OF CHAR; Mode: INTEGER): INTEGER; +VAR + ofstr: WINAPI.OFSTRUCT; +BEGIN + RETURN WINAPI.OpenFile(SYSTEM.ADR(FName[0]), ofstr, Mode) +END Open; + + +PROCEDURE Seek* (F, Offset, Origin: INTEGER): INTEGER; + RETURN WINAPI.SetFilePointer(F, Offset, 0, Origin) +END Seek; + + +PROCEDURE Read* (F, Buffer, Count: INTEGER): INTEGER; +VAR + res, n: INTEGER; + +BEGIN + IF WINAPI.ReadFile(F, Buffer, Count, SYSTEM.ADR(n), NIL) = 0 THEN + res := -1 + ELSE + res := n + END + + RETURN res +END Read; + + +PROCEDURE Write* (F, Buffer, Count: INTEGER): INTEGER; +VAR + res, n: INTEGER; + +BEGIN + IF WINAPI.WriteFile(F, Buffer, Count, SYSTEM.ADR(n), NIL) = 0 THEN + res := -1 + ELSE + res := n + END + + RETURN res +END Write; + + +PROCEDURE Load* (FName: ARRAY OF CHAR; VAR Size: INTEGER): INTEGER; +VAR + res, n, F: INTEGER; + +BEGIN + res := 0; + F := Open(FName, OPEN_R); + + IF F # -1 THEN + Size := Seek(F, 0, SEEK_END); + n := Seek(F, 0, SEEK_BEG); + res := WINAPI.GlobalAlloc(64, Size); + IF (res = 0) OR (Read(F, res, Size) # Size) THEN + IF res # 0 THEN + WINAPI.GlobalFree(Size); + res := 0; + Size := 0 + END + END; + Close(F) + END + + RETURN res +END Load; + + +PROCEDURE RemoveDir* (DirName: ARRAY OF CHAR): BOOLEAN; + RETURN WINAPI.RemoveDirectory(SYSTEM.ADR(DirName[0])) # 0 +END RemoveDir; + + +PROCEDURE ExistsDir* (DirName: ARRAY OF CHAR): BOOLEAN; +VAR + Code: SET; + +BEGIN + Code := WINAPI.GetFileAttributes(SYSTEM.ADR(DirName[0])) + RETURN (Code # {0..31}) & (4 IN Code) +END ExistsDir; + + +PROCEDURE CreateDir* (DirName: ARRAY OF CHAR): BOOLEAN; + RETURN WINAPI.CreateDirectory(SYSTEM.ADR(DirName[0]), NIL) # 0 +END CreateDir; + + +END File. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/HOST.ob07 b/programs/develop/oberon07/Lib/Windows32/HOST.ob07 index 8e5568d8f1..e63f9b6d72 100644 --- a/programs/develop/oberon07/Lib/Windows32/HOST.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/HOST.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -82,6 +82,8 @@ VAR eol*: ARRAY 3 OF CHAR; + maxreal*: REAL; + PROCEDURE [windows-, "kernel32.dll", "GetTickCount"] _GetTickCount (): INTEGER; @@ -310,6 +312,42 @@ PROCEDURE UnixTime* (): INTEGER; END UnixTime; +PROCEDURE d2s* (x: REAL): INTEGER; +VAR + h, l, s, e: INTEGER; + +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), l); + SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + + s := ASR(h, 31) MOD 2; + e := (h DIV 100000H) MOD 2048; + IF e <= 896 THEN + h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; + REPEAT + h := h DIV 2; + INC(e) + UNTIL e = 897; + e := 896; + l := (h MOD 8) * 20000000H; + h := h DIV 8 + ELSIF (1151 <= e) & (e < 2047) THEN + e := 1151; + h := 0; + l := 0 + ELSIF e = 2047 THEN + e := 1151; + IF (h MOD 100000H # 0) OR (l # 0) THEN + h := 80000H; + l := 0 + END + END; + DEC(e, 896) + + RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 +END d2s; + + PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; VAR res: INTEGER; @@ -326,6 +364,8 @@ END splitf; BEGIN eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; + maxreal := 1.9; + PACK(maxreal, 1023); hConsoleOutput := _GetStdHandle(-11); ParamParse -END HOST. +END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/In.ob07 b/programs/develop/oberon07/Lib/Windows32/In.ob07 new file mode 100644 index 0000000000..02aa8c426d --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/In.ob07 @@ -0,0 +1,289 @@ +(* + Copyright 2013, 2017, 2018 Anton Krotov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE In; + +IMPORT sys := SYSTEM, WINAPI; + +TYPE + + STRING = ARRAY 260 OF CHAR; + +VAR + + Done*: BOOLEAN; + hConsoleInput: INTEGER; + +PROCEDURE digit(ch: CHAR): BOOLEAN; + RETURN (ch >= "0") & (ch <= "9") +END digit; + +PROCEDURE CheckInt(s: STRING; VAR first, last: INTEGER; VAR neg: BOOLEAN; Point: BOOLEAN): BOOLEAN; +VAR i: INTEGER; +BEGIN + i := 0; + neg := FALSE; + WHILE (s[i] <= 20X) & (s[i] # 0X) DO + INC(i) + END; + IF s[i] = "-" THEN + neg := TRUE; + INC(i) + ELSIF s[i] = "+" THEN + INC(i) + END; + first := i; + WHILE digit(s[i]) DO + INC(i) + END; + last := i + RETURN ((s[i] <= 20X) OR (Point & (s[i] = "."))) & digit(s[first]) +END CheckInt; + +PROCEDURE IsMinInt(str: STRING; pos: INTEGER): BOOLEAN; +VAR i: INTEGER; min: STRING; +BEGIN + i := 0; + min := "2147483648"; + WHILE (min[i] # 0X) & (str[i] # 0X) & (min[i] = str[i + pos]) DO + INC(i) + END + RETURN i = 10 +END IsMinInt; + +PROCEDURE StrToInt(str: STRING; VAR err: BOOLEAN): INTEGER; +CONST maxINT = 7FFFFFFFH; +VAR i, n, res: INTEGER; flag, neg: BOOLEAN; +BEGIN + res := 0; + flag := CheckInt(str, i, n, neg, FALSE); + err := ~flag; + IF flag & neg & IsMinInt(str, i) THEN + flag := FALSE; + neg := FALSE; + res := 80000000H + END; + WHILE flag & digit(str[i]) DO + IF res > maxINT DIV 10 THEN + err := TRUE; + flag := FALSE; + res := 0 + ELSE + res := res * 10; + IF res > maxINT - (ORD(str[i]) - ORD("0")) THEN + err := TRUE; + flag := FALSE; + res := 0 + ELSE + res := res + (ORD(str[i]) - ORD("0")); + INC(i) + END + END + END; + IF neg THEN + res := -res + END + RETURN res +END StrToInt; + +PROCEDURE Space(s: STRING): BOOLEAN; +VAR i: INTEGER; +BEGIN + i := 0; + WHILE (s[i] # 0X) & (s[i] <= 20X) DO + INC(i) + END + RETURN s[i] = 0X +END Space; + +PROCEDURE CheckReal(s: STRING; VAR n: INTEGER; VAR neg: BOOLEAN): BOOLEAN; +VAR i: INTEGER; Res: BOOLEAN; +BEGIN + Res := CheckInt(s, n, i, neg, TRUE); + IF Res THEN + IF s[i] = "." THEN + INC(i); + WHILE digit(s[i]) DO + INC(i) + END; + IF (s[i] = "D") OR (s[i] = "E") OR (s[i] = "d") OR (s[i] = "e") THEN + INC(i); + IF (s[i] = "+") OR (s[i] = "-") THEN + INC(i) + END; + Res := digit(s[i]); + WHILE digit(s[i]) DO + INC(i) + END + END + END + END + RETURN Res & (s[i] <= 20X) +END CheckReal; + +PROCEDURE StrToFloat(str: STRING; VAR err: BOOLEAN): REAL; +CONST maxDBL = 1.69E308; maxINT = 7FFFFFFFH; +VAR i, scale: INTEGER; res, m, d: REAL; minus, neg: BOOLEAN; + + PROCEDURE part1(VAR res, d: REAL; VAR i: INTEGER; str: STRING): BOOLEAN; + BEGIN + res := 0.0; + d := 1.0; + WHILE digit(str[i]) DO + res := res * 10.0 + FLT(ORD(str[i]) - ORD("0")); + INC(i) + END; + IF str[i] = "." THEN + INC(i); + WHILE digit(str[i]) DO + d := d / 10.0; + res := res + FLT(ORD(str[i]) - ORD("0")) * d; + INC(i) + END + END + RETURN str[i] # 0X + END part1; + + PROCEDURE part2(VAR i, scale: INTEGER; VAR m, res: REAL; VAR minus, err: BOOLEAN; str: STRING): BOOLEAN; + BEGIN + INC(i); + m := 10.0; + minus := FALSE; + IF str[i] = "+" THEN + INC(i) + ELSIF str[i] = "-" THEN + minus := TRUE; + INC(i); + m := 0.1 + END; + scale := 0; + err := FALSE; + WHILE ~err & digit(str[i]) DO + IF scale > maxINT DIV 10 THEN + err := TRUE; + res := 0.0 + ELSE + scale := scale * 10; + IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN + err := TRUE; + res := 0.0 + ELSE + scale := scale + (ORD(str[i]) - ORD("0")); + INC(i) + END + END + END + RETURN ~err + END part2; + + PROCEDURE part3 (VAR err, minus: BOOLEAN; VAR scale: INTEGER; VAR res, m: REAL); + VAR i: INTEGER; + BEGIN + err := FALSE; + IF scale = maxINT THEN + err := TRUE; + res := 0.0 + END; + i := 1; + WHILE ~err & (i <= scale) DO + IF ~minus & (res > maxDBL / m) THEN + err := TRUE; + res := 0.0 + ELSE + res := res * m; + INC(i) + END + END + END part3; + +BEGIN + IF CheckReal(str, i, neg) THEN + IF part1(res, d, i, str) & part2(i, scale, m, res, minus, err, str) THEN + part3(err, minus, scale, res, m) + END; + IF neg THEN + res := -res + END + ELSE + res := 0.0; + err := TRUE + END + RETURN res +END StrToFloat; + +PROCEDURE String*(VAR s: ARRAY OF CHAR); +VAR count, i: INTEGER; str: STRING; +BEGIN + WINAPI.ReadConsole(hConsoleInput, sys.ADR(str[0]), 256, sys.ADR(count), 0); + IF (str[count - 1] = 0AX) & (str[count - 2] = 0DX) THEN + DEC(count, 2) + END; + str[256] := 0X; + str[count] := 0X; + i := 0; + WHILE (i < LEN(s) - 1) & (i < LEN(str)) & (str[i] # 0X) DO + s[i] := str[i]; + INC(i) + END; + s[i] := 0X; + Done := TRUE +END String; + +PROCEDURE Char*(VAR x: CHAR); +VAR str: STRING; +BEGIN + String(str); + x := str[0]; + Done := TRUE +END Char; + +PROCEDURE Ln*; +VAR str: STRING; +BEGIN + String(str); + Done := TRUE +END Ln; + +PROCEDURE Real*(VAR x: REAL); +VAR str: STRING; err: BOOLEAN; +BEGIN + err := FALSE; + REPEAT + String(str) + UNTIL ~Space(str); + x := StrToFloat(str, err); + Done := ~err +END Real; + +PROCEDURE Int*(VAR x: INTEGER); +VAR str: STRING; err: BOOLEAN; +BEGIN + err := FALSE; + REPEAT + String(str) + UNTIL ~Space(str); + x := StrToInt(str, err); + Done := ~err +END Int; + +PROCEDURE Open*; +BEGIN + hConsoleInput := WINAPI.GetStdHandle(-10); + Done := TRUE +END Open; + +END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Math.ob07 b/programs/develop/oberon07/Lib/Windows32/Math.ob07 new file mode 100644 index 0000000000..b1fe62acc0 --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/Math.ob07 @@ -0,0 +1,384 @@ +(* + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE Math; + +IMPORT SYSTEM; + + +CONST + + pi* = 3.141592653589793; + e* = 2.718281828459045; + + +PROCEDURE IsNan* (x: REAL): BOOLEAN; +VAR + h, l: SET; + +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), l); + SYSTEM.GET(SYSTEM.ADR(x) + 4, h) + RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) +END IsNan; + + +PROCEDURE IsInf* (x: REAL): BOOLEAN; + RETURN ABS(x) = SYSTEM.INF() +END IsInf; + + +PROCEDURE Max (a, b: REAL): REAL; +VAR + res: REAL; + +BEGIN + IF a > b THEN + res := a + ELSE + res := b + END + RETURN res +END Max; + + +PROCEDURE Min (a, b: REAL): REAL; +VAR + res: REAL; + +BEGIN + IF a < b THEN + res := a + ELSE + res := b + END + RETURN res +END Min; + + +PROCEDURE SameValue (a, b: REAL): BOOLEAN; +VAR + eps: REAL; + res: BOOLEAN; + +BEGIN + eps := Max(Min(ABS(a), ABS(b)) * 1.0E-12, 1.0E-12); + IF a > b THEN + res := (a - b) <= eps + ELSE + res := (b - a) <= eps + END + RETURN res +END SameValue; + + +PROCEDURE IsZero (x: REAL): BOOLEAN; + RETURN ABS(x) <= 1.0E-12 +END IsZero; + + +PROCEDURE [stdcall] sqrt* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0FAH, (* fsqrt *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END sqrt; + + +PROCEDURE [stdcall] sin* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0FEH, (* fsin *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END sin; + + +PROCEDURE [stdcall] cos* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0FFH, (* fcos *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END cos; + + +PROCEDURE [stdcall] tan* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0FBH, (* fsincos *) + 0DEH, 0F9H, (* fdivp st1, st *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END tan; + + +PROCEDURE [stdcall] arctan2* (y, x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) + 0D9H, 0F3H, (* fpatan *) + 0C9H, (* leave *) + 0C2H, 010H, 000H (* ret 10h *) + ) + RETURN 0.0 +END arctan2; + + +PROCEDURE [stdcall] ln* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0D9H, 0EDH, (* fldln2 *) + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0F1H, (* fyl2x *) + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END ln; + + +PROCEDURE [stdcall] log* (base, x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0D9H, 0E8H, (* fld1 *) + 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) + 0D9H, 0F1H, (* fyl2x *) + 0D9H, 0E8H, (* fld1 *) + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0F1H, (* fyl2x *) + 0DEH, 0F9H, (* fdivp st1, st *) + 0C9H, (* leave *) + 0C2H, 010H, 000H (* ret 10h *) + ) + RETURN 0.0 +END log; + + +PROCEDURE [stdcall] exp* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0EAH, (* fldl2e *) + 0DEH, 0C9H, 0D9H, 0C0H, + 0D9H, 0FCH, 0DCH, 0E9H, + 0D9H, 0C9H, 0D9H, 0F0H, + 0D9H, 0E8H, 0DEH, 0C1H, + 0D9H, 0FDH, 0DDH, 0D9H, + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END exp; + + +PROCEDURE [stdcall] round* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 07DH, 0F4H, 0D9H, + 07DH, 0F6H, 066H, 081H, + 04DH, 0F6H, 000H, 003H, + 0D9H, 06DH, 0F6H, 0D9H, + 0FCH, 0D9H, 06DH, 0F4H, + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END round; + + +PROCEDURE [stdcall] frac* (x: REAL): REAL; +BEGIN + SYSTEM.CODE( + 050H, + 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) + 0D9H, 0C0H, 0D9H, 03CH, + 024H, 0D9H, 07CH, 024H, + 002H, 066H, 081H, 04CH, + 024H, 002H, 000H, 00FH, + 0D9H, 06CH, 024H, 002H, + 0D9H, 0FCH, 0D9H, 02CH, + 024H, 0DEH, 0E9H, + 0C9H, (* leave *) + 0C2H, 008H, 000H (* ret 08h *) + ) + RETURN 0.0 +END frac; + + +PROCEDURE arcsin* (x: REAL): REAL; + RETURN arctan2(x, sqrt(1.0 - x * x)) +END arcsin; + + +PROCEDURE arccos* (x: REAL): REAL; + RETURN arctan2(sqrt(1.0 - x * x), x) +END arccos; + + +PROCEDURE arctan* (x: REAL): REAL; + RETURN arctan2(x, 1.0) +END arctan; + + +PROCEDURE sinh* (x: REAL): REAL; +BEGIN + x := exp(x) + RETURN (x - 1.0 / x) * 0.5 +END sinh; + + +PROCEDURE cosh* (x: REAL): REAL; +BEGIN + x := exp(x) + RETURN (x + 1.0 / x) * 0.5 +END cosh; + + +PROCEDURE tanh* (x: REAL): REAL; +BEGIN + IF x > 15.0 THEN + x := 1.0 + ELSIF x < -15.0 THEN + x := -1.0 + ELSE + x := exp(2.0 * x); + x := (x - 1.0) / (x + 1.0) + END + + RETURN x +END tanh; + + +PROCEDURE arsinh* (x: REAL): REAL; + RETURN ln(x + sqrt(x * x + 1.0)) +END arsinh; + + +PROCEDURE arcosh* (x: REAL): REAL; + RETURN ln(x + sqrt(x * x - 1.0)) +END arcosh; + + +PROCEDURE artanh* (x: REAL): REAL; +VAR + res: REAL; + +BEGIN + IF SameValue(x, 1.0) THEN + res := SYSTEM.INF() + ELSIF SameValue(x, -1.0) THEN + res := -SYSTEM.INF() + ELSE + res := 0.5 * ln((1.0 + x) / (1.0 - x)) + END + RETURN res +END artanh; + + +PROCEDURE floor* (x: REAL): REAL; +VAR + f: REAL; + +BEGIN + f := frac(x); + x := x - f; + IF f < 0.0 THEN + x := x - 1.0 + END + RETURN x +END floor; + + +PROCEDURE ceil* (x: REAL): REAL; +VAR + f: REAL; + +BEGIN + f := frac(x); + x := x - f; + IF f > 0.0 THEN + x := x + 1.0 + END + RETURN x +END ceil; + + +PROCEDURE power* (base, exponent: REAL): REAL; +VAR + res: REAL; + +BEGIN + IF exponent = 0.0 THEN + res := 1.0 + ELSIF (base = 0.0) & (exponent > 0.0) THEN + res := 0.0 + ELSE + res := exp(exponent * ln(base)) + END + RETURN res +END power; + + +PROCEDURE sgn* (x: REAL): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF x > 0.0 THEN + res := 1 + ELSIF x < 0.0 THEN + res := -1 + ELSE + res := 0 + END + + RETURN res +END sgn; + + +PROCEDURE fact* (n: INTEGER): REAL; +VAR + res: REAL; + +BEGIN + res := 1.0; + WHILE n > 1 DO + res := res * FLT(n); + DEC(n) + END + + RETURN res +END fact; + + +END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Out.ob07 b/programs/develop/oberon07/Lib/Windows32/Out.ob07 new file mode 100644 index 0000000000..6e6950c00b --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/Out.ob07 @@ -0,0 +1,280 @@ +(* + Copyright 2013, 2014, 2017, 2018 Anton Krotov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE Out; + +IMPORT sys := SYSTEM, WINAPI; + +CONST + + d = 1.0 - 5.0E-12; + +VAR + + hConsoleOutput: INTEGER; + Realp: PROCEDURE (x: REAL; width: INTEGER); + + +PROCEDURE String*(s: ARRAY OF CHAR); +VAR count: INTEGER; +BEGIN + WINAPI.WriteFile(hConsoleOutput, sys.ADR(s[0]), LENGTH(s), sys.ADR(count), NIL) +END String; + +PROCEDURE StringW*(s: ARRAY OF WCHAR); +VAR count: INTEGER; +BEGIN + WINAPI.WriteConsoleW(hConsoleOutput, sys.ADR(s[0]), LENGTH(s), sys.ADR(count), 0) +END StringW; + +PROCEDURE Char*(x: CHAR); +VAR count: INTEGER; +BEGIN + WINAPI.WriteFile(hConsoleOutput, sys.ADR(x), 1, sys.ADR(count), NIL) +END Char; + +PROCEDURE WriteInt(x, n: INTEGER); +VAR i: INTEGER; a: ARRAY 16 OF CHAR; neg: BOOLEAN; +BEGIN + i := 0; + IF n < 1 THEN + n := 1 + END; + IF x < 0 THEN + x := -x; + DEC(n); + neg := TRUE + END; + REPEAT + a[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10; + INC(i) + UNTIL x = 0; + WHILE n > i DO + Char(" "); + DEC(n) + END; + IF neg THEN + Char("-") + END; + REPEAT + DEC(i); + Char(a[i]) + UNTIL i = 0 +END WriteInt; + +PROCEDURE IsNan(AValue: REAL): BOOLEAN; +VAR h, l: SET; +BEGIN + sys.GET(sys.ADR(AValue), l); + sys.GET(sys.ADR(AValue) + 4, h) + RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) +END IsNan; + +PROCEDURE IsInf(x: REAL): BOOLEAN; + RETURN ABS(x) = sys.INF() +END IsInf; + +PROCEDURE Int*(x, width: INTEGER); +VAR i: INTEGER; +BEGIN + IF x # 80000000H THEN + WriteInt(x, width) + ELSE + FOR i := 12 TO width DO + Char(20X) + END; + String("-2147483648") + END +END Int; + +PROCEDURE OutInf(x: REAL; width: INTEGER); +VAR s: ARRAY 5 OF CHAR; i: INTEGER; +BEGIN + IF IsNan(x) THEN + s := "Nan"; + INC(width) + ELSIF IsInf(x) & (x > 0.0) THEN + s := "+Inf" + ELSIF IsInf(x) & (x < 0.0) THEN + s := "-Inf" + END; + FOR i := 1 TO width - 4 DO + Char(" ") + END; + String(s) +END OutInf; + +PROCEDURE Ln*; +BEGIN + Char(0DX); + Char(0AX) +END Ln; + +PROCEDURE _FixReal(x: REAL; width, p: INTEGER); +VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; +BEGIN + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSIF p < 0 THEN + Realp(x, width) + ELSE + len := 0; + minus := FALSE; + IF x < 0.0 THEN + minus := TRUE; + INC(len); + x := ABS(x) + END; + e := 0; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + + IF e >= 0 THEN + len := len + e + p + 1; + IF x > 9.0 + d THEN + INC(len) + END; + IF p > 0 THEN + INC(len) + END; + ELSE + len := len + p + 2 + END; + FOR i := 1 TO width - len DO + Char(" ") + END; + IF minus THEN + Char("-") + END; + y := x; + WHILE (y < 1.0) & (y # 0.0) DO + y := y * 10.0; + DEC(e) + END; + IF e < 0 THEN + IF x - FLT(FLOOR(x)) > d THEN + Char("1"); + x := 0.0 + ELSE + Char("0"); + x := x * 10.0 + END + ELSE + WHILE e >= 0 DO + IF x - FLT(FLOOR(x)) > d THEN + IF x > 9.0 THEN + String("10") + ELSE + Char(CHR(FLOOR(x) + ORD("0") + 1)) + END; + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(e) + END + END; + IF p > 0 THEN + Char(".") + END; + WHILE p > 0 DO + IF x - FLT(FLOOR(x)) > d THEN + Char(CHR(FLOOR(x) + ORD("0") + 1)); + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(p) + END + END +END _FixReal; + +PROCEDURE Real*(x: REAL; width: INTEGER); +VAR e, n, i: INTEGER; minus: BOOLEAN; +BEGIN + Realp := Real; + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSE + e := 0; + n := 0; + IF width > 23 THEN + n := width - 23; + width := 23 + ELSIF width < 9 THEN + width := 9 + END; + width := width - 5; + IF x < 0.0 THEN + x := -x; + minus := TRUE + ELSE + minus := FALSE + END; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + WHILE (x < 1.0) & (x # 0.0) DO + x := x * 10.0; + DEC(e) + END; + IF x > 9.0 + d THEN + x := 1.0; + INC(e) + END; + FOR i := 1 TO n DO + Char(" ") + END; + IF minus THEN + x := -x + END; + _FixReal(x, width, width - 3); + Char("E"); + IF e >= 0 THEN + Char("+") + ELSE + Char("-"); + e := ABS(e) + END; + IF e < 100 THEN + Char("0") + END; + IF e < 10 THEN + Char("0") + END; + Int(e, 0) + END +END Real; + +PROCEDURE FixReal*(x: REAL; width, p: INTEGER); +BEGIN + Realp := Real; + _FixReal(x, width, p) +END FixReal; + +PROCEDURE Open*; +BEGIN + hConsoleOutput := WINAPI.GetStdHandle(-11) +END Open; + +END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/RTL.ob07 b/programs/develop/oberon07/Lib/Windows32/RTL.ob07 index 3aa6c454e1..0929a5678a 100644 --- a/programs/develop/oberon07/Lib/Windows32/RTL.ob07 +++ b/programs/develop/oberon07/Lib/Windows32/RTL.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -16,34 +16,14 @@ CONST maxint* = 7FFFFFFFH; minint* = 80000000H; - DLL_PROCESS_ATTACH = 1; - DLL_THREAD_ATTACH = 2; - DLL_THREAD_DETACH = 3; - DLL_PROCESS_DETACH = 0; - WORD = bit_depth DIV 8; MAX_SET = bit_depth - 1; -TYPE - - DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); - PROC = PROCEDURE; - - VAR name: INTEGER; types: INTEGER; - bits: ARRAY MAX_SET + 1 OF INTEGER; - - dll: RECORD - process_detach, - thread_detach, - thread_attach: DLL_ENTRY - END; - - fini: PROC; PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER); @@ -97,7 +77,6 @@ VAR i, n, k: INTEGER; BEGIN - k := LEN(A) - 1; n := A[0]; i := 0; @@ -106,7 +85,6 @@ BEGIN INC(i) END; A[k] := n - END _rot; @@ -128,14 +106,16 @@ BEGIN END _set; -PROCEDURE [stdcall] _set1* (a: INTEGER): INTEGER; +PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *) BEGIN - IF ASR(a, 5) = 0 THEN - SYSTEM.GET(SYSTEM.ADR(bits[0]) + a * WORD, a) - ELSE - a := 0 - END - RETURN a + SYSTEM.CODE( + 031H, 0C0H, (* xor eax, eax *) + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *) + 083H, 0F9H, 01FH, (* cmp ecx, 31 *) + 077H, 003H, (* ja L *) + 00FH, 0ABH, 0C8H (* bts eax, ecx *) + (* L: *) + ) END _set1; @@ -315,7 +295,6 @@ VAR c: CHAR; BEGIN - res := strncmp(str1, str2, MIN(len1, len2)); IF res = minint THEN IF len1 > len2 THEN @@ -349,7 +328,6 @@ VAR c: WCHAR; BEGIN - res := strncmpw(str1, str2, MIN(len1, len2)); IF res = minint THEN IF len1 > len2 THEN @@ -398,7 +376,6 @@ VAR c: CHAR; BEGIN - i := 0; REPEAT str[i] := CHR(x MOD 10 + ORD("0")); @@ -422,6 +399,7 @@ END IntToStr; PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); VAR n1, n2, i, j: INTEGER; + BEGIN n1 := LENGTH(s1); n2 := LENGTH(s2); @@ -437,7 +415,6 @@ BEGIN END; s1[j] := 0X - END append; @@ -446,20 +423,18 @@ VAR s, temp: ARRAY 1024 OF CHAR; BEGIN - - s := ""; CASE err OF - | 1: append(s, "assertion failure") - | 2: append(s, "NIL dereference") - | 3: append(s, "division by zero") - | 4: append(s, "NIL procedure call") - | 5: append(s, "type guard error") - | 6: append(s, "index out of range") - | 7: append(s, "invalid CASE") - | 8: append(s, "array assignment error") - | 9: append(s, "CHR out of range") - |10: append(s, "WCHR out of range") - |11: append(s, "BYTE out of range") + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" END; append(s, API.eol); @@ -513,36 +488,16 @@ END _guard; PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - CASE fdwReason OF - |DLL_PROCESS_ATTACH: - res := 1 - |DLL_THREAD_ATTACH: - res := 0; - IF dll.thread_attach # NIL THEN - dll.thread_attach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_THREAD_DETACH: - res := 0; - IF dll.thread_detach # NIL THEN - dll.thread_detach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_PROCESS_DETACH: - res := 0; - IF dll.process_detach # NIL THEN - dll.process_detach(hinstDLL, fdwReason, lpvReserved) - END - ELSE - res := 0 - END - - RETURN res + RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) END _dllentry; +PROCEDURE [stdcall] _sofinit*; +BEGIN + API.sofinit +END _sofinit; + + PROCEDURE [stdcall] _exit* (code: INTEGER); BEGIN API.exit(code) @@ -571,42 +526,8 @@ BEGIN END END; - j := 1; - FOR i := 0 TO MAX_SET DO - bits[i] := j; - j := LSL(j, 1) - END; - - name := modname; - - dll.process_detach := NIL; - dll.thread_detach := NIL; - dll.thread_attach := NIL; - - fini := NIL + name := modname END _init; -PROCEDURE [stdcall] _sofinit*; -BEGIN - IF fini # NIL THEN - fini - END -END _sofinit; - - -PROCEDURE SetDll* (process_detach, thread_detach, thread_attach: DLL_ENTRY); -BEGIN - dll.process_detach := process_detach; - dll.thread_detach := thread_detach; - dll.thread_attach := thread_attach -END SetDll; - - -PROCEDURE SetFini* (ProcFini: PROC); -BEGIN - fini := ProcFini -END SetFini; - - -END RTL. +END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/UnixTime.ob07 b/programs/develop/oberon07/Lib/Windows32/UnixTime.ob07 new file mode 100644 index 0000000000..0e6ed5bd6d --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/UnixTime.ob07 @@ -0,0 +1,64 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018-2019, Anton Krotov + All rights reserved. +*) + +MODULE UnixTime; + + +VAR + + days: ARRAY 12, 31, 2 OF INTEGER; + + +PROCEDURE init; +VAR + i, j, k, n0, n1: INTEGER; +BEGIN + + FOR i := 0 TO 11 DO + FOR j := 0 TO 30 DO + days[i, j, 0] := 0; + days[i, j, 1] := 0; + END + END; + + days[ 1, 28, 0] := -1; + + FOR k := 0 TO 1 DO + days[ 1, 29, k] := -1; + days[ 1, 30, k] := -1; + days[ 3, 30, k] := -1; + days[ 5, 30, k] := -1; + days[ 8, 30, k] := -1; + days[10, 30, k] := -1; + END; + + n0 := 0; + n1 := 0; + FOR i := 0 TO 11 DO + FOR j := 0 TO 30 DO + IF days[i, j, 0] = 0 THEN + days[i, j, 0] := n0; + INC(n0) + END; + IF days[i, j, 1] = 0 THEN + days[i, j, 1] := n1; + INC(n1) + END + END + END + +END init; + + +PROCEDURE time* (year, month, day, hour, min, sec: INTEGER): INTEGER; + RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec +END time; + + +BEGIN + init +END UnixTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Utils.ob07 b/programs/develop/oberon07/Lib/Windows32/Utils.ob07 new file mode 100644 index 0000000000..0f85e9808e --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/Utils.ob07 @@ -0,0 +1,76 @@ +(* + Copyright 2013, 2017, 2018, 2020 Anton Krotov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE Utils; + +IMPORT WINAPI; + +PROCEDURE PutSeed*(seed: INTEGER); +BEGIN + WINAPI.srand(seed) +END PutSeed; + +PROCEDURE Rnd*(range : INTEGER): INTEGER; + RETURN WINAPI.rand() MOD range +END Rnd; + +PROCEDURE Utf8To16*(source: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR): INTEGER; +VAR i, j, L, u, N: INTEGER; +BEGIN + L := LEN(source); + N := LEN(dest); + N := N - N MOD 2 - 1; + i := 0; + j := 0; + WHILE (i < L) & (j < N) & (source[i] # 0X) DO + CASE source[i] OF + |00X..7FX: u := ORD(source[i]); + |0C1X..0DFX: + u := LSL(ORD(source[i]) - 0C0H, 6); + IF i + 1 < L THEN + u := u + ROR(LSL(ORD(source[i + 1]), 26), 26); + INC(i) + END + |0E1X..0EFX: + u := LSL(ORD(source[i]) - 0E0H, 12); + IF i + 1 < L THEN + u := u + ROR(LSL(ORD(source[i + 1]), 26), 20); + INC(i) + END; + IF i + 1 < L THEN + u := u + ROR(LSL(ORD(source[i + 1]), 26), 26); + INC(i) + END +(* |0F1X..0F7X: + |0F9X..0FBX: + |0FDX:*) + ELSE + END; + INC(i); + dest[j] := CHR(u MOD 256); + INC(j); + dest[j] := CHR(u DIV 256); + INC(j); + END; + IF j < N THEN + dest[j] := 0X; + dest[j + 1] := 0X + END + RETURN j DIV 2 +END Utf8To16; + +END Utils. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 b/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 new file mode 100644 index 0000000000..f6043431ad --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 @@ -0,0 +1,241 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE WINAPI; + +IMPORT SYSTEM, API; + + +CONST + + OFS_MAXPATHNAME* = 128; + + +TYPE + + DLL_ENTRY* = API.DLL_ENTRY; + + STRING = ARRAY 260 OF CHAR; + + TCoord* = RECORD + + X*, Y*: WCHAR + + END; + + TSmallRect* = RECORD + + Left*, Top*, Right*, Bottom*: WCHAR + + END; + + TConsoleScreenBufferInfo* = RECORD + + dwSize*: TCoord; + dwCursorPosition*: TCoord; + wAttributes*: WCHAR; + srWindow*: TSmallRect; + dwMaximumWindowSize*: TCoord + + END; + + TSystemTime* = RECORD + + Year*, + Month*, + DayOfWeek*, + Day*, + Hour*, + Min*, + Sec*, + MSec*: WCHAR + + END; + + PSecurityAttributes* = POINTER TO TSecurityAttributes; + + TSecurityAttributes* = RECORD + + nLength*: INTEGER; + lpSecurityDescriptor*: INTEGER; + bInheritHandle*: INTEGER + + END; + + TFileTime* = RECORD + + dwLowDateTime*, + dwHighDateTime*: INTEGER + + END; + + TWin32FindData* = RECORD + + dwFileAttributes*: SET; + ftCreationTime*: TFileTime; + ftLastAccessTime*: TFileTime; + ftLastWriteTime*: TFileTime; + nFileSizeHigh*: INTEGER; + nFileSizeLow*: INTEGER; + dwReserved0*: INTEGER; + dwReserved1*: INTEGER; + cFileName*: STRING; + cAlternateFileName*: ARRAY 14 OF CHAR + + END; + + OFSTRUCT* = RECORD + + cBytes*: CHAR; + fFixedDisk*: CHAR; + nErrCode*: WCHAR; + Reserved1*: WCHAR; + Reserved2*: WCHAR; + szPathName*: ARRAY OFS_MAXPATHNAME OF CHAR + + END; + + POverlapped* = POINTER TO OVERLAPPED; + + OVERLAPPED* = RECORD + + Internal*: INTEGER; + InternalHigh*: INTEGER; + Offset*: INTEGER; + OffsetHigh*: INTEGER; + hEvent*: INTEGER + + END; + + +PROCEDURE [windows-, "kernel32.dll", "SetConsoleCursorPosition"] + SetConsoleCursorPosition* (hConsoleOutput, dwCursorPosition: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetConsoleScreenBufferInfo"] + GetConsoleScreenBufferInfo* (hConsoleOutput: INTEGER; ConsoleScreenBufferInfo: TConsoleScreenBufferInfo): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "FillConsoleOutputCharacterA"] + FillConsoleOutputCharacter* (hConsoleOutput, cCaracter, nLength, dwWriteCoord, lpNumberOfCharsWritten: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "FillConsoleOutputAttribute"] + FillConsoleOutputAttribute* (hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "SetConsoleTextAttribute"] + SetConsoleTextAttribute* (hConsoleOutput, wAttributes: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] + GetStdHandle* (nStdHandle: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetLocalTime"] + GetLocalTime* (T: TSystemTime); + +PROCEDURE [windows-, "kernel32.dll", "RemoveDirectoryA"] + RemoveDirectory* (lpPathName: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetFileAttributesA"] + GetFileAttributes* (lpPathName: INTEGER): SET; + +PROCEDURE [windows-, "kernel32.dll", "CreateDirectoryA"] + CreateDirectory* (lpPathName: INTEGER; lpSecurityAttributes: PSecurityAttributes): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "FindFirstFileA"] + FindFirstFile* (lpFileName: INTEGER; lpFindFileData: TWin32FindData): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "DeleteFileA"] + DeleteFile* (lpFileName: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "FindClose"] + FindClose* (hFindFile: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "CloseHandle"] + CloseHandle* (hObject: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "CreateFileA"] + CreateFile* ( + lpFileName, dwDesiredAccess, dwShareMode: INTEGER; + lpSecurityAttributes: PSecurityAttributes; + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "OpenFile"] + OpenFile* (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "SetFilePointer"] + SetFilePointer* (hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "ReadFile"] + ReadFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "WriteFile"] + WriteFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "ReadConsoleA"] + ReadConsole* (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetCommandLineA"] + GetCommandLine* (): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GlobalAlloc"] + GlobalAlloc* (uFlags, dwBytes: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GlobalFree"] + GlobalFree* (hMem: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "WriteConsoleW"] + WriteConsoleW* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] + ExitProcess* (code: INTEGER); + +PROCEDURE [windows-, "kernel32.dll", "WriteConsoleA"] + WriteConsole* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetTickCount"] + GetTickCount* (): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "Sleep"] + Sleep* (dwMilliseconds: INTEGER); + +PROCEDURE [windows-, "kernel32.dll", "FreeLibrary"] + FreeLibrary* (hLibModule: INTEGER): INTEGER; + +PROCEDURE [ccall, "msvcrt.dll", "rand"] + rand* (): INTEGER; + +PROCEDURE [ccall, "msvcrt.dll", "srand"] + srand* (seed: INTEGER); + +PROCEDURE [windows-, "user32.dll", "MessageBoxA"] + MessageBoxA* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; + +PROCEDURE [windows-, "user32.dll", "MessageBoxW"] + MessageBox* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; + +PROCEDURE [windows-, "user32.dll", "CreateWindowExA"] + CreateWindowEx* ( + dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, + nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetProcAddress"] + GetProcAddress* (hModule, name: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "LoadLibraryA"] + LoadLibraryA* (name: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "AllocConsole"] + AllocConsole* (): BOOLEAN; + +PROCEDURE [windows-, "kernel32.dll", "FreeConsole"] + FreeConsole* (): BOOLEAN; + + +PROCEDURE SetDllEntry* (process_detach, thread_detach, thread_attach: DLL_ENTRY); +BEGIN + API.SetDll(process_detach, thread_detach, thread_attach) +END SetDllEntry; + + +END WINAPI. diff --git a/programs/develop/oberon07/Lib/Windows64/API.ob07 b/programs/develop/oberon07/Lib/Windows64/API.ob07 new file mode 100644 index 0000000000..0eaf6c9a7a --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/API.ob07 @@ -0,0 +1,130 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018-2020, Anton Krotov + All rights reserved. +*) + +MODULE API; + +IMPORT SYSTEM; + + +CONST + + SectionAlignment = 1000H; + + DLL_PROCESS_ATTACH = 1; + DLL_THREAD_ATTACH = 2; + DLL_THREAD_DETACH = 3; + DLL_PROCESS_DETACH = 0; + + +TYPE + + DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); + + +VAR + + eol*: ARRAY 3 OF CHAR; + base*: INTEGER; + heap: INTEGER; + + process_detach, + thread_detach, + thread_attach: DLL_ENTRY; + + +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 DebugMsg* (lpText, lpCaption: INTEGER); +BEGIN + MessageBoxA(0, lpText, lpCaption, 16) +END DebugMsg; + + +PROCEDURE _NEW* (size: INTEGER): INTEGER; + RETURN HeapAlloc(heap, 8, size) +END _NEW; + + +PROCEDURE _DISPOSE* (p: INTEGER): INTEGER; +BEGIN + HeapFree(heap, 0, p) + RETURN 0 +END _DISPOSE; + + +PROCEDURE init* (reserved, code: INTEGER); +BEGIN + process_detach := NIL; + thread_detach := NIL; + thread_attach := NIL; + eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; + base := code - SectionAlignment; + heap := GetProcessHeap() +END init; + + +PROCEDURE exit* (code: INTEGER); +BEGIN + ExitProcess(code) +END exit; + + +PROCEDURE exit_thread* (code: INTEGER); +BEGIN + ExitThread(code) +END exit_thread; + + +PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + res := 0; + + CASE fdwReason OF + |DLL_PROCESS_ATTACH: + res := 1 + |DLL_THREAD_ATTACH: + IF thread_attach # NIL THEN + thread_attach(hinstDLL, fdwReason, lpvReserved) + END + |DLL_THREAD_DETACH: + IF thread_detach # NIL THEN + thread_detach(hinstDLL, fdwReason, lpvReserved) + END + |DLL_PROCESS_DETACH: + IF process_detach # NIL THEN + process_detach(hinstDLL, fdwReason, lpvReserved) + END + ELSE + END + + RETURN res +END dllentry; + + +PROCEDURE sofinit*; +END sofinit; + + +PROCEDURE SetDll* (_process_detach, _thread_detach, _thread_attach: DLL_ENTRY); +BEGIN + process_detach := _process_detach; + thread_detach := _thread_detach; + thread_attach := _thread_attach +END SetDll; + + +END API. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Console.ob07 b/programs/develop/oberon07/Lib/Windows64/Console.ob07 new file mode 100644 index 0000000000..042b0317ab --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/Console.ob07 @@ -0,0 +1,100 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE Console; + +IMPORT SYSTEM, WINAPI, In, Out; + + +CONST + + Black* = 0; Blue* = 1; Green* = 2; Cyan* = 3; + Red* = 4; Magenta* = 5; Brown* = 6; LightGray* = 7; + DarkGray* = 8; LightBlue* = 9; LightGreen* = 10; LightCyan* = 11; + LightRed* = 12; LightMagenta* = 13; Yellow* = 14; White* = 15; + + +VAR + + hConsoleOutput: INTEGER; + + +PROCEDURE SetCursor* (X, Y: INTEGER); +BEGIN + WINAPI.SetConsoleCursorPosition(hConsoleOutput, X + Y * 65536) +END SetCursor; + + +PROCEDURE GetCursor* (VAR X, Y: INTEGER); +VAR + ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; + +BEGIN + WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); + X := ORD(ScrBufInfo.dwCursorPosition.X); + Y := ORD(ScrBufInfo.dwCursorPosition.Y) +END GetCursor; + + +PROCEDURE Cls*; +VAR + fill: INTEGER; + ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; + +BEGIN + WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); + fill := ORD(ScrBufInfo.dwSize.X) * ORD(ScrBufInfo.dwSize.Y); + WINAPI.FillConsoleOutputCharacter(hConsoleOutput, 20H, fill, 0, SYSTEM.ADR(fill)); + WINAPI.FillConsoleOutputAttribute(hConsoleOutput, ORD(ScrBufInfo.wAttributes), fill, 0, SYSTEM.ADR(fill)); + SetCursor(0, 0) +END Cls; + + +PROCEDURE SetColor* (FColor, BColor: INTEGER); +BEGIN + IF (FColor IN {0..15}) & (BColor IN {0..15}) THEN + WINAPI.SetConsoleTextAttribute(hConsoleOutput, LSL(BColor, 4) + FColor) + END +END SetColor; + + +PROCEDURE GetCursorX* (): INTEGER; +VAR + ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; + +BEGIN + WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo) + RETURN ORD(ScrBufInfo.dwCursorPosition.X) +END GetCursorX; + + +PROCEDURE GetCursorY* (): INTEGER; +VAR + ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; + +BEGIN + WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo) + RETURN ORD(ScrBufInfo.dwCursorPosition.Y) +END GetCursorY; + + +PROCEDURE open*; +BEGIN + WINAPI.AllocConsole; + hConsoleOutput := WINAPI.GetStdHandle(-11); + In.Open; + Out.Open +END open; + + +PROCEDURE exit* (b: BOOLEAN); +BEGIN + WINAPI.FreeConsole +END exit; + + +END Console. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 b/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 new file mode 100644 index 0000000000..bd849fb704 --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 @@ -0,0 +1,174 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE DateTime; + +IMPORT WINAPI; + + +CONST + + ERR* = -7.0E5; + + +VAR + + DateTable: ARRAY 120000, 3 OF INTEGER; + MonthsTable: ARRAY 13, 4 OF INTEGER; + + +PROCEDURE Encode* (Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): REAL; +VAR + d, bis: INTEGER; + res: REAL; + +BEGIN + res := ERR; + IF (Year >= 1) & (Year <= 9999) & (Month >= 1) & (Month <= 12) & + (Day >= 1) & (Day <= 31) & (Hour >= 0) & (Hour <= 23) & + (Min >= 0) & (Min <= 59) & (Sec >= 0) & (Sec <= 59) & + (MSec >= 0) & (MSec <= 999) THEN + + bis := ORD((Year MOD 4 = 0) & (Year MOD 100 # 0) OR (Year MOD 400 = 0)); + + IF Day <= MonthsTable[Month][2 + bis] THEN + DEC(Year); + d := Year * 365 + (Year DIV 4) - (Year DIV 100) + (Year DIV 400) + + MonthsTable[Month][bis] + Day - 693594; + res := FLT(d) + FLT(Hour * 3600000 + Min * 60000 + Sec * 1000 + MSec) / 86400000.0 + END + END + RETURN res +END Encode; + + +PROCEDURE Decode* (Date: REAL; VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + d, t: INTEGER; + L, R, M: INTEGER; + +BEGIN + res := (Date >= -693593.0) & (Date < 2958466.0); + IF res THEN + d := FLOOR(Date); + t := FLOOR((Date - FLT(d)) * 86400000.0); + INC(d, 693593); + + L := 0; + R := LEN(DateTable) - 1; + M := (L + R) DIV 2; + + WHILE R - L > 1 DO + IF d > DateTable[M][0] THEN + L := M; + M := (L + R) DIV 2 + ELSIF d < DateTable[M][0] THEN + R := M; + M := (L + R) DIV 2 + ELSE + L := M; + R := M + END + END; + + Year := DateTable[L][1]; + Month := DateTable[L][2]; + Day := d - DateTable[L][0] + 1; + + Hour := t DIV 3600000; t := t MOD 3600000; + Min := t DIV 60000; t := t MOD 60000; + Sec := t DIV 1000; + MSec := t MOD 1000 + END + + RETURN res +END Decode; + + +PROCEDURE Now* (VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER); +VAR + T: WINAPI.TSystemTime; + +BEGIN + WINAPI.GetLocalTime(T); + Year := ORD(T.Year); + Month := ORD(T.Month); + Day := ORD(T.Day); + Hour := ORD(T.Hour); + Min := ORD(T.Min); + Sec := ORD(T.Sec); + MSec := ORD(T.MSec) +END Now; + + +PROCEDURE NowEncode* (): REAL; +VAR + Year, Month, Day, Hour, Min, Sec, MSec: INTEGER; + +BEGIN + Now(Year, Month, Day, Hour, Min, Sec, MSec) + RETURN Encode(Year, Month, Day, Hour, Min, Sec, MSec) +END NowEncode; + + +PROCEDURE init; +VAR + day, year, month, i: INTEGER; + Months: ARRAY 13 OF INTEGER; + +BEGIN + Months[1] := 31; Months[2] := 28; Months[3] := 31; Months[4] := 30; + Months[5] := 31; Months[6] := 30; Months[7] := 31; Months[8] := 31; + Months[9] := 30; Months[10] := 31; Months[11] := 30; Months[12] := 31; + + day := 0; + year := 1; + month := 1; + i := 0; + + WHILE year <= 10000 DO + DateTable[i][0] := day; + DateTable[i][1] := year; + DateTable[i][2] := month; + INC(day, Months[month]); + IF (month = 2) & ((year MOD 4 = 0) & (year MOD 100 # 0) OR (year MOD 400 = 0)) THEN + INC(day) + END; + INC(month); + IF month > 12 THEN + month := 1; + INC(year) + END; + INC(i) + END; + + MonthsTable[1][0] := 0; + FOR i := 2 TO 12 DO + MonthsTable[i][0] := MonthsTable[i - 1][0] + Months[i - 1] + END; + + FOR i := 1 TO 12 DO + MonthsTable[i][2] := Months[i] + END; + + Months[2] := 29; + MonthsTable[1][1] := 0; + FOR i := 2 TO 12 DO + MonthsTable[i][1] := MonthsTable[i - 1][1] + Months[i - 1] + END; + + FOR i := 1 TO 12 DO + MonthsTable[i][3] := Months[i] + END + +END init; + + +BEGIN + init +END DateTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/HOST.ob07 b/programs/develop/oberon07/Lib/Windows64/HOST.ob07 new file mode 100644 index 0000000000..ee6b7bf778 --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/HOST.ob07 @@ -0,0 +1,371 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018-2020, Anton Krotov + All rights reserved. +*) + +MODULE HOST; + +IMPORT SYSTEM, RTL; + + +CONST + + slash* = "\"; + OS* = "WINDOWS"; + + bit_depth* = RTL.bit_depth; + maxint* = RTL.maxint; + minint* = RTL.minint; + + MAX_PARAM = 1024; + + OFS_MAXPATHNAME = 128; + + +TYPE + + POverlapped = POINTER TO OVERLAPPED; + + OVERLAPPED = RECORD + + Internal: INTEGER; + InternalHigh: INTEGER; + Offset: INTEGER; + OffsetHigh: INTEGER; + hEvent: INTEGER + + END; + + OFSTRUCT = RECORD + + cBytes: CHAR; + fFixedDisk: CHAR; + nErrCode: WCHAR; + Reserved1: WCHAR; + Reserved2: WCHAR; + szPathName: ARRAY OFS_MAXPATHNAME OF CHAR + + END; + + PSecurityAttributes = POINTER TO TSecurityAttributes; + + TSecurityAttributes = RECORD + + nLength: INTEGER; + lpSecurityDescriptor: INTEGER; + bInheritHandle: INTEGER + + END; + + TSystemTime = RECORD + + Year, + Month, + DayOfWeek, + Day, + Hour, + Min, + Sec, + MSec: WCHAR + + END; + + +VAR + + hConsoleOutput: INTEGER; + + Params: ARRAY MAX_PARAM, 2 OF INTEGER; + argc: INTEGER; + + eol*: ARRAY 3 OF CHAR; + + maxreal*: REAL; + + +PROCEDURE [windows-, "kernel32.dll", "GetTickCount"] + _GetTickCount (): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] + _GetStdHandle (nStdHandle: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetCommandLineA"] + _GetCommandLine (): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "ReadFile"] + _ReadFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "WriteFile"] + _WriteFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "CloseHandle"] + _CloseHandle (hObject: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "CreateFileA"] + _CreateFile ( + lpFileName, dwDesiredAccess, dwShareMode: INTEGER; + lpSecurityAttributes: PSecurityAttributes; + dwCreationDisposition, dwFlagsAndAttributes, + hTemplateFile: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "OpenFile"] + _OpenFile (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetCurrentDirectoryA"] + _GetCurrentDirectory (nBufferLength, lpBuffer: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetSystemTime"] + _GetSystemTime (T: TSystemTime); + +PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] + _ExitProcess (code: INTEGER); + + +PROCEDURE ExitProcess* (code: INTEGER); +BEGIN + _ExitProcess(code) +END ExitProcess; + + +PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); +VAR + n: INTEGER; + +BEGIN + n := _GetCurrentDirectory(LEN(path), SYSTEM.ADR(path[0])); + path[n] := slash; + path[n + 1] := 0X +END GetCurrentDirectory; + + +PROCEDURE GetChar (adr: INTEGER): CHAR; +VAR + res: CHAR; + +BEGIN + SYSTEM.GET(adr, res) + RETURN res +END GetChar; + + +PROCEDURE ParamParse; +VAR + p, count, cond: INTEGER; + c: CHAR; + + + PROCEDURE ChangeCond (A, B, C: INTEGER; VAR cond: INTEGER; c: CHAR); + BEGIN + IF (c <= 20X) & (c # 0X) THEN + cond := A + ELSIF c = 22X THEN + cond := B + ELSIF c = 0X THEN + cond := 6 + ELSE + cond := C + END + END ChangeCond; + + +BEGIN + p := _GetCommandLine(); + cond := 0; + count := 0; + WHILE (count < MAX_PARAM) & (cond # 6) DO + c := GetChar(p); + CASE cond OF + |0: ChangeCond(0, 4, 1, cond, c); IF cond = 1 THEN Params[count, 0] := p END + |1: ChangeCond(0, 3, 1, cond, c); IF cond IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END + |3: ChangeCond(3, 1, 3, cond, c); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END + |4: ChangeCond(5, 0, 5, cond, c); IF cond = 5 THEN Params[count, 0] := p END + |5: ChangeCond(5, 1, 5, cond, c); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END + |6: + END; + INC(p) + END; + argc := count +END ParamParse; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +VAR + i, j, len: INTEGER; + c: CHAR; + +BEGIN + j := 0; + IF n < argc THEN + len := LEN(s) - 1; + i := Params[n, 0]; + WHILE (j < len) & (i <= Params[n, 1]) DO + c := GetChar(i); + IF c # 22X THEN + s[j] := c; + INC(j) + END; + INC(i) + END + END; + s[j] := 0X +END GetArg; + + +PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; +VAR + res, n: INTEGER; + +BEGIN + IF _ReadFile(F, SYSTEM.ADR(Buffer[0]), bytes, n, NIL) = 0 THEN + res := -1 + ELSE + res := n + END + + RETURN res +END FileRead; + + +PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; +VAR + res, n: INTEGER; + +BEGIN + IF _WriteFile(F, SYSTEM.ADR(Buffer[0]), bytes, n, NIL) = 0 THEN + res := -1 + ELSE + res := n + END + + RETURN res +END FileWrite; + + +PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; + RETURN _CreateFile(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) +END FileCreate; + + +PROCEDURE FileClose* (F: INTEGER); +BEGIN + _CloseHandle(F) +END FileClose; + + +PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; +VAR + ofstr: OFSTRUCT; + res: INTEGER; + +BEGIN + res := _OpenFile(SYSTEM.ADR(FName[0]), ofstr, 0); + IF res = 0FFFFFFFFH THEN + res := -1 + END + + RETURN res +END FileOpen; + + +PROCEDURE OutChar* (c: CHAR); +VAR + count: INTEGER; +BEGIN + _WriteFile(hConsoleOutput, SYSTEM.ADR(c), 1, count, NIL) +END OutChar; + + +PROCEDURE GetTickCount* (): INTEGER; + RETURN _GetTickCount() DIV 10 +END GetTickCount; + + +PROCEDURE letter (c: CHAR): BOOLEAN; + RETURN ("a" <= c) & (c <= "z") OR ("A" <= c) & (c <= "Z") +END letter; + + +PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; + RETURN ~(letter(path[0]) & (path[1] = ":")) +END isRelative; + + +PROCEDURE now* (VAR year, month, day, hour, min, sec: INTEGER); +VAR + T: TSystemTime; + +BEGIN + _GetSystemTime(T); + year := ORD(T.Year); + month := ORD(T.Month); + day := ORD(T.Day); + hour := ORD(T.Hour); + min := ORD(T.Min); + sec := ORD(T.Sec) +END now; + + +PROCEDURE UnixTime* (): INTEGER; + RETURN 0 +END UnixTime; + + +PROCEDURE d2s* (x: REAL): INTEGER; +VAR + h, l, s, e: INTEGER; + +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), l); + SYSTEM.GET(SYSTEM.ADR(x) + 4, h); + + s := ASR(h, 31) MOD 2; + e := (h DIV 100000H) MOD 2048; + IF e <= 896 THEN + h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; + REPEAT + h := h DIV 2; + INC(e) + UNTIL e = 897; + e := 896; + l := (h MOD 8) * 20000000H; + h := h DIV 8 + ELSIF (1151 <= e) & (e < 2047) THEN + e := 1151; + h := 0; + l := 0 + ELSIF e = 2047 THEN + e := 1151; + IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN + h := 80000H; + l := 0 + END + END; + DEC(e, 896) + + RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 +END d2s; + + +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + a := 0; + b := 0; + SYSTEM.MOVE(SYSTEM.ADR(x), SYSTEM.ADR(a), 4); + SYSTEM.MOVE(SYSTEM.ADR(x) + 4, SYSTEM.ADR(b), 4); + SYSTEM.GET(SYSTEM.ADR(x), res) + RETURN res +END splitf; + + +BEGIN + eol[0] := 0DX; eol[1] := 0AX; eol[2] := 0X; + maxreal := 1.9; + PACK(maxreal, 1023); + hConsoleOutput := _GetStdHandle(-11); + ParamParse +END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/In.ob07 b/programs/develop/oberon07/Lib/Windows64/In.ob07 new file mode 100644 index 0000000000..dd4b518601 --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/In.ob07 @@ -0,0 +1,295 @@ +(* + Copyright 2013, 2017, 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE In; + +IMPORT sys := SYSTEM; + +TYPE + + STRING = ARRAY 260 OF CHAR; + +VAR + + Done*: BOOLEAN; + hConsoleInput: INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] + GetStdHandle (nStdHandle: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "ReadConsoleA"] + ReadConsole (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER): INTEGER; + +PROCEDURE digit(ch: CHAR): BOOLEAN; + RETURN (ch >= "0") & (ch <= "9") +END digit; + +PROCEDURE CheckInt(s: STRING; VAR first, last: INTEGER; VAR neg: BOOLEAN; Point: BOOLEAN): BOOLEAN; +VAR i: INTEGER; +BEGIN + i := 0; + neg := FALSE; + WHILE (s[i] <= 20X) & (s[i] # 0X) DO + INC(i) + END; + IF s[i] = "-" THEN + neg := TRUE; + INC(i) + ELSIF s[i] = "+" THEN + INC(i) + END; + first := i; + WHILE digit(s[i]) DO + INC(i) + END; + last := i + RETURN ((s[i] <= 20X) OR (Point & (s[i] = "."))) & digit(s[first]) +END CheckInt; + +PROCEDURE IsMinInt(str: STRING; pos: INTEGER): BOOLEAN; +VAR i: INTEGER; min: STRING; +BEGIN + i := 0; + min := "2147483648"; + WHILE (min[i] # 0X) & (str[i] # 0X) & (min[i] = str[i + pos]) DO + INC(i) + END + RETURN i = 10 +END IsMinInt; + +PROCEDURE StrToInt(str: STRING; VAR err: BOOLEAN): INTEGER; +CONST maxINT = 7FFFFFFFH; +VAR i, n, res: INTEGER; flag, neg: BOOLEAN; +BEGIN + res := 0; + flag := CheckInt(str, i, n, neg, FALSE); + err := ~flag; + IF flag & neg & IsMinInt(str, i) THEN + flag := FALSE; + neg := FALSE; + res := 80000000H + END; + WHILE flag & digit(str[i]) DO + IF res > maxINT DIV 10 THEN + err := TRUE; + flag := FALSE; + res := 0 + ELSE + res := res * 10; + IF res > maxINT - (ORD(str[i]) - ORD("0")) THEN + err := TRUE; + flag := FALSE; + res := 0 + ELSE + res := res + (ORD(str[i]) - ORD("0")); + INC(i) + END + END + END; + IF neg THEN + res := -res + END + RETURN res +END StrToInt; + +PROCEDURE Space(s: STRING): BOOLEAN; +VAR i: INTEGER; +BEGIN + i := 0; + WHILE (s[i] # 0X) & (s[i] <= 20X) DO + INC(i) + END + RETURN s[i] = 0X +END Space; + +PROCEDURE CheckReal(s: STRING; VAR n: INTEGER; VAR neg: BOOLEAN): BOOLEAN; +VAR i: INTEGER; Res: BOOLEAN; +BEGIN + Res := CheckInt(s, n, i, neg, TRUE); + IF Res THEN + IF s[i] = "." THEN + INC(i); + WHILE digit(s[i]) DO + INC(i) + END; + IF (s[i] = "D") OR (s[i] = "E") OR (s[i] = "d") OR (s[i] = "e") THEN + INC(i); + IF (s[i] = "+") OR (s[i] = "-") THEN + INC(i) + END; + Res := digit(s[i]); + WHILE digit(s[i]) DO + INC(i) + END + END + END + END + RETURN Res & (s[i] <= 20X) +END CheckReal; + +PROCEDURE StrToFloat(str: STRING; VAR err: BOOLEAN): REAL; +CONST maxDBL = 1.69E308; maxINT = 7FFFFFFFH; +VAR i, scale: INTEGER; res, m, d: REAL; minus, neg: BOOLEAN; + + PROCEDURE part1(VAR res, d: REAL; VAR i: INTEGER; str: STRING): BOOLEAN; + BEGIN + res := 0.0; + d := 1.0; + WHILE digit(str[i]) DO + res := res * 10.0 + FLT(ORD(str[i]) - ORD("0")); + INC(i) + END; + IF str[i] = "." THEN + INC(i); + WHILE digit(str[i]) DO + d := d / 10.0; + res := res + FLT(ORD(str[i]) - ORD("0")) * d; + INC(i) + END + END + RETURN str[i] # 0X + END part1; + + PROCEDURE part2(VAR i, scale: INTEGER; VAR m, res: REAL; VAR minus, err: BOOLEAN; str: STRING): BOOLEAN; + BEGIN + INC(i); + m := 10.0; + minus := FALSE; + IF str[i] = "+" THEN + INC(i) + ELSIF str[i] = "-" THEN + minus := TRUE; + INC(i); + m := 0.1 + END; + scale := 0; + err := FALSE; + WHILE ~err & digit(str[i]) DO + IF scale > maxINT DIV 10 THEN + err := TRUE; + res := 0.0 + ELSE + scale := scale * 10; + IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN + err := TRUE; + res := 0.0 + ELSE + scale := scale + (ORD(str[i]) - ORD("0")); + INC(i) + END + END + END + RETURN ~err + END part2; + + PROCEDURE part3 (VAR err, minus: BOOLEAN; VAR scale: INTEGER; VAR res, m: REAL); + VAR i: INTEGER; + BEGIN + err := FALSE; + IF scale = maxINT THEN + err := TRUE; + res := 0.0 + END; + i := 1; + WHILE ~err & (i <= scale) DO + IF ~minus & (res > maxDBL / m) THEN + err := TRUE; + res := 0.0 + ELSE + res := res * m; + INC(i) + END + END + END part3; + +BEGIN + IF CheckReal(str, i, neg) THEN + IF part1(res, d, i, str) & part2(i, scale, m, res, minus, err, str) THEN + part3(err, minus, scale, res, m) + END; + IF neg THEN + res := -res + END + ELSE + res := 0.0; + err := TRUE + END + RETURN res +END StrToFloat; + +PROCEDURE String*(VAR s: ARRAY OF CHAR); +VAR count, i: INTEGER; str: STRING; +BEGIN + ReadConsole(hConsoleInput, sys.ADR(str[0]), 256, sys.ADR(count), 0); + IF (str[count - 1] = 0AX) & (str[count - 2] = 0DX) THEN + DEC(count, 2) + END; + str[256] := 0X; + str[count] := 0X; + i := 0; + WHILE (i < LEN(s) - 1) & (i < LEN(str)) & (str[i] # 0X) DO + s[i] := str[i]; + INC(i) + END; + s[i] := 0X; + Done := TRUE +END String; + +PROCEDURE Char*(VAR x: CHAR); +VAR str: STRING; +BEGIN + String(str); + x := str[0]; + Done := TRUE +END Char; + +PROCEDURE Ln*; +VAR str: STRING; +BEGIN + String(str); + Done := TRUE +END Ln; + +PROCEDURE Real*(VAR x: REAL); +VAR str: STRING; err: BOOLEAN; +BEGIN + err := FALSE; + REPEAT + String(str) + UNTIL ~Space(str); + x := StrToFloat(str, err); + Done := ~err +END Real; + +PROCEDURE Int*(VAR x: INTEGER); +VAR str: STRING; err: BOOLEAN; +BEGIN + err := FALSE; + REPEAT + String(str) + UNTIL ~Space(str); + x := StrToInt(str, err); + Done := ~err +END Int; + +PROCEDURE Open*; +BEGIN + hConsoleInput := GetStdHandle(-10); + Done := TRUE +END Open; + +END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Math.ob07 b/programs/develop/oberon07/Lib/Windows64/Math.ob07 new file mode 100644 index 0000000000..ab80d79ebf --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/Math.ob07 @@ -0,0 +1,311 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019, Anton Krotov + All rights reserved. +*) + +MODULE Math; + +IMPORT SYSTEM; + + +CONST + + e *= 2.71828182845904523; + pi *= 3.14159265358979324; + ln2 *= 0.693147180559945309; + + eps = 1.0E-16; + MaxCosArg = 1000000.0 * pi; + + +VAR + + Exp: ARRAY 710 OF REAL; + + +PROCEDURE [stdcall64] sqrt* (x: REAL): REAL; +BEGIN + ASSERT(x >= 0.0); + SYSTEM.CODE( + 0F2H, 0FH, 51H, 45H, 10H, (* sqrtsd xmm0, qword[rbp + 10h] *) + 05DH, (* pop rbp *) + 0C2H, 08H, 00H (* ret 8 *) + ) + + RETURN 0.0 +END sqrt; + + +PROCEDURE exp* (x: REAL): REAL; +CONST + e25 = 1.284025416687741484; (* exp(0.25) *) + +VAR + a, s, res: REAL; + neg: BOOLEAN; + n: INTEGER; + +BEGIN + neg := x < 0.0; + IF neg THEN + x := -x + END; + + IF x < FLT(LEN(Exp)) THEN + res := Exp[FLOOR(x)]; + x := x - FLT(FLOOR(x)); + WHILE x >= 0.25 DO + res := res * e25; + x := x - 0.25 + END + ELSE + res := SYSTEM.INF(); + x := 0.0 + END; + + n := 0; + a := 1.0; + s := 1.0; + + REPEAT + INC(n); + a := a * x / FLT(n); + s := s + a + UNTIL a < eps; + + IF neg THEN + res := 1.0 / (res * s) + ELSE + res := res * s + END + + RETURN res +END exp; + + +PROCEDURE ln* (x: REAL): REAL; +VAR + a, x2, res: REAL; + n: INTEGER; + +BEGIN + ASSERT(x > 0.0); + UNPK(x, n); + + x := (x - 1.0) / (x + 1.0); + x2 := x * x; + res := x + FLT(n) * (ln2 * 0.5); + n := 1; + + REPEAT + INC(n, 2); + x := x * x2; + a := x / FLT(n); + res := res + a + UNTIL a < eps + + RETURN res * 2.0 +END ln; + + +PROCEDURE power* (base, exponent: REAL): REAL; +BEGIN + ASSERT(base > 0.0) + RETURN exp(exponent * ln(base)) +END power; + + +PROCEDURE log* (base, x: REAL): REAL; +BEGIN + ASSERT(base > 0.0); + ASSERT(x > 0.0) + RETURN ln(x) / ln(base) +END log; + + +PROCEDURE cos* (x: REAL): REAL; +VAR + a, res: REAL; + n: INTEGER; + +BEGIN + x := ABS(x); + ASSERT(x <= MaxCosArg); + + x := x - FLT( FLOOR(x / (2.0 * pi)) ) * (2.0 * pi); + x := x * x; + res := 0.0; + a := 1.0; + n := -1; + + REPEAT + INC(n, 2); + res := res + a; + a := -a * x / FLT(n*n + n) + UNTIL ABS(a) < eps + + RETURN res +END cos; + + +PROCEDURE sin* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) <= MaxCosArg); + x := cos(x) + RETURN sqrt(1.0 - x * x) +END sin; + + +PROCEDURE tan* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) <= MaxCosArg); + x := cos(x) + RETURN sqrt(1.0 - x * x) / x +END tan; + + +PROCEDURE arcsin* (x: REAL): REAL; + + + PROCEDURE arctan (x: REAL): REAL; + VAR + z, p, k: REAL; + + BEGIN + p := x / (x * x + 1.0); + z := p * x; + x := 0.0; + k := 0.0; + + REPEAT + k := k + 2.0; + x := x + p; + p := p * k * z / (k + 1.0) + UNTIL p < eps + + RETURN x + END arctan; + + +BEGIN + ASSERT(ABS(x) <= 1.0); + + IF ABS(x) >= 0.707 THEN + x := 0.5 * pi - arctan(sqrt(1.0 - x * x) / x) + ELSE + x := arctan(x / sqrt(1.0 - x * x)) + END + + RETURN x +END arcsin; + + +PROCEDURE arccos* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) <= 1.0) + RETURN 0.5 * pi - arcsin(x) +END arccos; + + +PROCEDURE arctan* (x: REAL): REAL; + RETURN arcsin(x / sqrt(1.0 + x * x)) +END arctan; + + +PROCEDURE sinh* (x: REAL): REAL; +BEGIN + x := exp(x) + RETURN (x - 1.0 / x) * 0.5 +END sinh; + + +PROCEDURE cosh* (x: REAL): REAL; +BEGIN + x := exp(x) + RETURN (x + 1.0 / x) * 0.5 +END cosh; + + +PROCEDURE tanh* (x: REAL): REAL; +BEGIN + IF x > 15.0 THEN + x := 1.0 + ELSIF x < -15.0 THEN + x := -1.0 + ELSE + x := exp(2.0 * x); + x := (x - 1.0) / (x + 1.0) + END + + RETURN x +END tanh; + + +PROCEDURE arsinh* (x: REAL): REAL; + RETURN ln(x + sqrt(x * x + 1.0)) +END arsinh; + + +PROCEDURE arcosh* (x: REAL): REAL; +BEGIN + ASSERT(x >= 1.0) + RETURN ln(x + sqrt(x * x - 1.0)) +END arcosh; + + +PROCEDURE artanh* (x: REAL): REAL; +BEGIN + ASSERT(ABS(x) < 1.0) + RETURN 0.5 * ln((1.0 + x) / (1.0 - x)) +END artanh; + + +PROCEDURE sgn* (x: REAL): INTEGER; +VAR + res: INTEGER; + +BEGIN + IF x > 0.0 THEN + res := 1 + ELSIF x < 0.0 THEN + res := -1 + ELSE + res := 0 + END + + RETURN res +END sgn; + + +PROCEDURE fact* (n: INTEGER): REAL; +VAR + res: REAL; + +BEGIN + res := 1.0; + WHILE n > 1 DO + res := res * FLT(n); + DEC(n) + END + + RETURN res +END fact; + + +PROCEDURE init; +VAR + i: INTEGER; + +BEGIN + Exp[0] := 1.0; + FOR i := 1 TO LEN(Exp) - 1 DO + Exp[i] := Exp[i - 1] * e + END +END init; + + +BEGIN + init +END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Out.ob07 b/programs/develop/oberon07/Lib/Windows64/Out.ob07 new file mode 100644 index 0000000000..d75f9051e3 --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/Out.ob07 @@ -0,0 +1,308 @@ +(* + Copyright 2013, 2014, 2017, 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*) + +MODULE Out; + +IMPORT sys := SYSTEM; + +CONST + + d = 1.0 - 5.0E-12; + +TYPE + + POverlapped* = POINTER TO OVERLAPPED; + + OVERLAPPED* = RECORD + + Internal*: INTEGER; + InternalHigh*: INTEGER; + Offset*: INTEGER; + OffsetHigh*: INTEGER; + hEvent*: INTEGER + + END; + +VAR + + hConsoleOutput: INTEGER; + Realp: PROCEDURE (x: REAL; width: INTEGER); + + +PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] + GetStdHandle (nStdHandle: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "WriteFile"] + WriteFile (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "WriteConsoleW"] + WriteConsoleW (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; + + +PROCEDURE Char*(x: CHAR); +VAR count: INTEGER; +BEGIN + WriteFile(hConsoleOutput, sys.ADR(x), 1, sys.ADR(count), NIL) +END Char; + +PROCEDURE StringW*(s: ARRAY OF WCHAR); +VAR count: INTEGER; +BEGIN + WriteConsoleW(hConsoleOutput, sys.ADR(s[0]), LENGTH(s), sys.ADR(count), 0) +END StringW; + +PROCEDURE String*(s: ARRAY OF CHAR); +VAR len, i: INTEGER; +BEGIN + len := LENGTH(s); + FOR i := 0 TO len - 1 DO + Char(s[i]) + END +END String; + +PROCEDURE WriteInt(x, n: INTEGER); +VAR i: INTEGER; a: ARRAY 32 OF CHAR; neg: BOOLEAN; +BEGIN + i := 0; + IF n < 1 THEN + n := 1 + END; + IF x < 0 THEN + x := -x; + DEC(n); + neg := TRUE + END; + REPEAT + a[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10; + INC(i) + UNTIL x = 0; + WHILE n > i DO + Char(" "); + DEC(n) + END; + IF neg THEN + Char("-") + END; + REPEAT + DEC(i); + Char(a[i]) + UNTIL i = 0 +END WriteInt; + +PROCEDURE IsNan(AValue: REAL): BOOLEAN; +VAR s: SET; +BEGIN + sys.GET(sys.ADR(AValue), s) + RETURN (s * {52..62} = {52..62}) & ((s * {32..51} # {}) OR (s * {0..31} # {})) +END IsNan; + +PROCEDURE IsInf(x: REAL): BOOLEAN; + RETURN ABS(x) = sys.INF() +END IsInf; + +PROCEDURE Int*(x, width: INTEGER); +VAR i, minInt: INTEGER; +BEGIN + minInt := 1; + minInt := ROR(minInt, 1); + IF x # minInt THEN + WriteInt(x, width) + ELSE + FOR i := 21 TO width DO + Char(20X) + END; + String("-9223372036854775808") + END +END Int; + +PROCEDURE OutInf(x: REAL; width: INTEGER); +VAR s: ARRAY 5 OF CHAR; i: INTEGER; +BEGIN + IF IsNan(x) THEN + s := "Nan"; + INC(width) + ELSIF IsInf(x) & (x > 0.0) THEN + s := "+Inf" + ELSIF IsInf(x) & (x < 0.0) THEN + s := "-Inf" + END; + FOR i := 1 TO width - 4 DO + Char(" ") + END; + String(s) +END OutInf; + +PROCEDURE Ln*; +BEGIN + Char(0DX); + Char(0AX) +END Ln; + +PROCEDURE _FixReal(x: REAL; width, p: INTEGER); +VAR e, len, i: INTEGER; y: REAL; minus: BOOLEAN; +BEGIN + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSIF p < 0 THEN + Realp(x, width) + ELSE + len := 0; + minus := FALSE; + IF x < 0.0 THEN + minus := TRUE; + INC(len); + x := ABS(x) + END; + e := 0; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + + IF e >= 0 THEN + len := len + e + p + 1; + IF x > 9.0 + d THEN + INC(len) + END; + IF p > 0 THEN + INC(len) + END; + ELSE + len := len + p + 2 + END; + FOR i := 1 TO width - len DO + Char(" ") + END; + IF minus THEN + Char("-") + END; + y := x; + WHILE (y < 1.0) & (y # 0.0) DO + y := y * 10.0; + DEC(e) + END; + IF e < 0 THEN + IF x - FLT(FLOOR(x)) > d THEN + Char("1"); + x := 0.0 + ELSE + Char("0"); + x := x * 10.0 + END + ELSE + WHILE e >= 0 DO + IF x - FLT(FLOOR(x)) > d THEN + IF x > 9.0 THEN + String("10") + ELSE + Char(CHR(FLOOR(x) + ORD("0") + 1)) + END; + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(e) + END + END; + IF p > 0 THEN + Char(".") + END; + WHILE p > 0 DO + IF x - FLT(FLOOR(x)) > d THEN + Char(CHR(FLOOR(x) + ORD("0") + 1)); + x := 0.0 + ELSE + Char(CHR(FLOOR(x) + ORD("0"))); + x := (x - FLT(FLOOR(x))) * 10.0 + END; + DEC(p) + END + END +END _FixReal; + +PROCEDURE Real*(x: REAL; width: INTEGER); +VAR e, n, i: INTEGER; minus: BOOLEAN; +BEGIN + Realp := Real; + IF IsNan(x) OR IsInf(x) THEN + OutInf(x, width) + ELSE + e := 0; + n := 0; + IF width > 23 THEN + n := width - 23; + width := 23 + ELSIF width < 9 THEN + width := 9 + END; + width := width - 5; + IF x < 0.0 THEN + x := -x; + minus := TRUE + ELSE + minus := FALSE + END; + WHILE x >= 10.0 DO + x := x / 10.0; + INC(e) + END; + WHILE (x < 1.0) & (x # 0.0) DO + x := x * 10.0; + DEC(e) + END; + IF x > 9.0 + d THEN + x := 1.0; + INC(e) + END; + FOR i := 1 TO n DO + Char(" ") + END; + IF minus THEN + x := -x + END; + _FixReal(x, width, width - 3); + Char("E"); + IF e >= 0 THEN + Char("+") + ELSE + Char("-"); + e := ABS(e) + END; + IF e < 100 THEN + Char("0") + END; + IF e < 10 THEN + Char("0") + END; + Int(e, 0) + END +END Real; + +PROCEDURE FixReal*(x: REAL; width, p: INTEGER); +BEGIN + Realp := Real; + _FixReal(x, width, p) +END FixReal; + +PROCEDURE Open*; +BEGIN + hConsoleOutput := GetStdHandle(-11) +END Open; + +END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/RTL.ob07 b/programs/develop/oberon07/Lib/Windows64/RTL.ob07 new file mode 100644 index 0000000000..94a94eafda --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/RTL.ob07 @@ -0,0 +1,516 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018-2020, Anton Krotov + All rights reserved. +*) + +MODULE RTL; + +IMPORT SYSTEM, API; + + +CONST + + bit_depth* = 64; + maxint* = 7FFFFFFFFFFFFFFFH; + minint* = 8000000000000000H; + + WORD = bit_depth DIV 8; + MAX_SET = bit_depth - 1; + + +VAR + + name: INTEGER; + types: INTEGER; + sets: ARRAY (MAX_SET + 1) * (MAX_SET + 1) OF INTEGER; + + +PROCEDURE [stdcall64] _move* (bytes, dest, source: INTEGER); +BEGIN + SYSTEM.CODE( + 048H, 08BH, 045H, 010H, (* mov rax, qword [rbp + 16] *) + 048H, 085H, 0C0H, (* test rax, rax *) + 07EH, 020H, (* jle L *) + 0FCH, (* cld *) + 057H, (* push rdi *) + 056H, (* push rsi *) + 048H, 08BH, 075H, 020H, (* mov rsi, qword [rbp + 32] *) + 048H, 08BH, 07DH, 018H, (* mov rdi, qword [rbp + 24] *) + 048H, 089H, 0C1H, (* mov rcx, rax *) + 048H, 0C1H, 0E9H, 003H, (* shr rcx, 3 *) + 0F3H, 048H, 0A5H, (* rep movsd *) + 048H, 089H, 0C1H, (* mov rcx, rax *) + 048H, 083H, 0E1H, 007H, (* and rcx, 7 *) + 0F3H, 0A4H, (* rep movsb *) + 05EH, (* pop rsi *) + 05FH (* pop rdi *) + (* L: *) + ) +END _move; + + +PROCEDURE [stdcall64] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + IF len_src > len_dst THEN + res := FALSE + ELSE + _move(len_src * base_size, dst, src); + res := TRUE + END + + RETURN res +END _arrcpy; + + +PROCEDURE [stdcall64] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); +BEGIN + _move(MIN(len_dst, len_src) * chr_size, dst, src) +END _strcpy; + + +PROCEDURE [stdcall64] _rot* (VAR A: ARRAY OF INTEGER); +VAR + i, n, k: INTEGER; + +BEGIN + k := LEN(A) - 1; + n := A[0]; + i := 0; + WHILE i < k DO + A[i] := A[i + 1]; + INC(i) + END; + A[k] := n +END _rot; + + +PROCEDURE [stdcall64] _set* (b, a: INTEGER): INTEGER; +BEGIN + IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN + SYSTEM.GET((MIN(b, MAX_SET) * (MAX_SET + 1) + MAX(a, 0)) * WORD + SYSTEM.ADR(sets[0]), a) + ELSE + a := 0 + END + + RETURN a +END _set; + + +PROCEDURE [stdcall64] _set1* (a: INTEGER); (* {a} -> rax *) +BEGIN + SYSTEM.CODE( + 048H, 031H, 0C0H, (* xor rax, rax *) + 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) (* rcx <- a *) + 048H, 083H, 0F9H, 03FH, (* cmp rcx, 63 *) + 077H, 004H, (* ja L *) + 048H, 00FH, 0ABH, 0C8H (* bts rax, rcx *) + (* L: *) + ) +END _set1; + + +PROCEDURE [stdcall64] _divmod* (y, x: INTEGER); (* (x div y) -> rax; (x mod y) -> rdx *) +BEGIN + SYSTEM.CODE( + 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) (* rax <- x *) + 048H, 031H, 0D2H, (* xor rdx, rdx *) + 048H, 085H, 0C0H, (* test rax, rax *) + 074H, 022H, (* je L2 *) + 07FH, 003H, (* jg L1 *) + 048H, 0F7H, 0D2H, (* not rdx *) + (* L1: *) + 049H, 089H, 0C0H, (* mov r8, rax *) + 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) (* rcx <- y *) + 048H, 0F7H, 0F9H, (* idiv rcx *) + 048H, 085H, 0D2H, (* test rdx, rdx *) + 074H, 00EH, (* je L2 *) + 049H, 031H, 0C8H, (* xor r8, rcx *) + 04DH, 085H, 0C0H, (* test r8, r8 *) + 07DH, 006H, (* jge L2 *) + 048H, 0FFH, 0C8H, (* dec rax *) + 048H, 001H, 0CAH (* add rdx, rcx *) + (* L2: *) + ) +END _divmod; + + +PROCEDURE [stdcall64] _new* (t, size: INTEGER; VAR ptr: INTEGER); +BEGIN + ptr := API._NEW(size); + IF ptr # 0 THEN + SYSTEM.PUT(ptr, t); + INC(ptr, WORD) + END +END _new; + + +PROCEDURE [stdcall64] _dispose* (VAR ptr: INTEGER); +BEGIN + IF ptr # 0 THEN + ptr := API._DISPOSE(ptr - WORD) + END +END _dispose; + + +PROCEDURE [stdcall64] _length* (len, str: INTEGER); +BEGIN + SYSTEM.CODE( + 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) + 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) + 048H, 0FFH, 0C8H, (* dec rax *) + (* L1: *) + 048H, 0FFH, 0C0H, (* inc rax *) + 080H, 038H, 000H, (* cmp byte [rax], 0 *) + 074H, 005H, (* jz L2 *) + 0E2H, 0F6H, (* loop L1 *) + 048H, 0FFH, 0C0H, (* inc rax *) + (* L2: *) + 048H, 02BH, 045H, 018H (* sub rax, qword [rbp + 24] *) + ) +END _length; + + +PROCEDURE [stdcall64] _lengthw* (len, str: INTEGER); +BEGIN + SYSTEM.CODE( + 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) + 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) + 048H, 083H, 0E8H, 002H, (* sub rax, 2 *) + (* L1: *) + 048H, 083H, 0C0H, 002H, (* add rax, 2 *) + 066H, 083H, 038H, 000H, (* cmp word [rax], 0 *) + 074H, 006H, (* jz L2 *) + 0E2H, 0F4H, (* loop L1 *) + 048H, 083H, 0C0H, 002H, (* add rax, 2 *) + (* L2: *) + 048H, 02BH, 045H, 018H, (* sub rax, qword [rbp + 24] *) + 048H, 0D1H, 0E8H (* shr rax, 1 *) + ) +END _lengthw; + + +PROCEDURE [stdcall64] strncmp (a, b, n: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 048H, 08BH, 04DH, 010H, (* mov rcx, qword[rbp + 16]; rcx <- a *) + 048H, 08BH, 055H, 018H, (* mov rdx, qword[rbp + 24]; rdx <- b *) + 04CH, 08BH, 045H, 020H, (* mov r8, qword[rbp + 32]; r8 <- n *) + 04DH, 031H, 0C9H, (* xor r9, r9 *) + 04DH, 031H, 0D2H, (* xor r10, r10 *) + 048H, 0B8H, 000H, 000H, + 000H, 000H, 000H, 000H, + 000H, 080H, (* movabs rax, minint *) + (* L1: *) + 04DH, 085H, 0C0H, (* test r8, r8 *) + 07EH, 024H, (* jle L3 *) + 044H, 08AH, 009H, (* mov r9b, byte[rcx] *) + 044H, 08AH, 012H, (* mov r10b, byte[rdx] *) + 048H, 0FFH, 0C1H, (* inc rcx *) + 048H, 0FFH, 0C2H, (* inc rdx *) + 049H, 0FFH, 0C8H, (* dec r8 *) + 04DH, 039H, 0D1H, (* cmp r9, r10 *) + 074H, 008H, (* je L2 *) + 04CH, 089H, 0C8H, (* mov rax, r9 *) + 04CH, 029H, 0D0H, (* sub rax, r10 *) + 0EBH, 008H, (* jmp L3 *) + (* L2: *) + 04DH, 085H, 0C9H, (* test r9, r9 *) + 075H, 0DAH, (* jne L1 *) + 048H, 031H, 0C0H, (* xor rax, rax *) + (* L3: *) + 05DH, (* pop rbp *) + 0C2H, 018H, 000H (* ret 24 *) + ) + RETURN 0 +END strncmp; + + +PROCEDURE [stdcall64] strncmpw (a, b, n: INTEGER): INTEGER; +BEGIN + SYSTEM.CODE( + 048H, 08BH, 04DH, 010H, (* mov rcx, qword[rbp + 16]; rcx <- a *) + 048H, 08BH, 055H, 018H, (* mov rdx, qword[rbp + 24]; rdx <- b *) + 04CH, 08BH, 045H, 020H, (* mov r8, qword[rbp + 32]; r8 <- n *) + 04DH, 031H, 0C9H, (* xor r9, r9 *) + 04DH, 031H, 0D2H, (* xor r10, r10 *) + 048H, 0B8H, 000H, 000H, + 000H, 000H, 000H, 000H, + 000H, 080H, (* movabs rax, minint *) + (* L1: *) + 04DH, 085H, 0C0H, (* test r8, r8 *) + 07EH, 028H, (* jle L3 *) + 066H, 044H, 08BH, 009H, (* mov r9w, word[rcx] *) + 066H, 044H, 08BH, 012H, (* mov r10w, word[rdx] *) + 048H, 083H, 0C1H, 002H, (* add rcx, 2 *) + 048H, 083H, 0C2H, 002H, (* add rdx, 2 *) + 049H, 0FFH, 0C8H, (* dec r8 *) + 04DH, 039H, 0D1H, (* cmp r9, r10 *) + 074H, 008H, (* je L2 *) + 04CH, 089H, 0C8H, (* mov rax, r9 *) + 04CH, 029H, 0D0H, (* sub rax, r10 *) + 0EBH, 008H, (* jmp L3 *) + (* L2: *) + 04DH, 085H, 0C9H, (* test r9, r9 *) + 075H, 0D6H, (* jne L1 *) + 048H, 031H, 0C0H, (* xor rax, rax *) + (* L3: *) + 05DH, (* pop rbp *) + 0C2H, 018H, 000H (* ret 24 *) + ) + RETURN 0 +END strncmpw; + + +PROCEDURE [stdcall64] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: CHAR; + +BEGIN + res := strncmp(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmp; + + +PROCEDURE [stdcall64] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: WCHAR; + +BEGIN + res := strncmpw(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2 * 2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1 * 2, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmpw; + + +PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); +VAR + c: CHAR; + i: INTEGER; + +BEGIN + i := 0; + REPEAT + SYSTEM.GET(pchar, c); + s[i] := c; + INC(pchar); + INC(i) + UNTIL c = 0X +END PCharToStr; + + +PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); +VAR + i, a, b: INTEGER; + c: CHAR; + +BEGIN + i := 0; + REPEAT + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10; + INC(i) + UNTIL x = 0; + + a := 0; + b := i - 1; + WHILE a < b DO + c := str[a]; + str[a] := str[b]; + str[b] := c; + INC(a); + DEC(b) + END; + str[i] := 0X +END IntToStr; + + +PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); +VAR + n1, n2, i, j: INTEGER; + +BEGIN + n1 := LENGTH(s1); + n2 := LENGTH(s2); + + ASSERT(n1 + n2 < LEN(s1)); + + i := 0; + j := n1; + WHILE i < n2 DO + s1[j] := s2[i]; + INC(i); + INC(j) + END; + + s1[j] := 0X +END append; + + +PROCEDURE [stdcall64] _error* (module, err, line: INTEGER); +VAR + s, temp: ARRAY 1024 OF CHAR; + +BEGIN + CASE err OF + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" + END; + + append(s, API.eol); + + 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); + + API.exit_thread(0) +END _error; + + +PROCEDURE [stdcall64] _isrec* (t0, t1, r: INTEGER): INTEGER; +BEGIN + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 +END _isrec; + + +PROCEDURE [stdcall64] _is* (t0, p: INTEGER): INTEGER; +BEGIN + IF p # 0 THEN + SYSTEM.GET(p - WORD, p); + SYSTEM.GET(t0 + p + types, p) + END + + RETURN p MOD 2 +END _is; + + +PROCEDURE [stdcall64] _guardrec* (t0, t1: INTEGER): INTEGER; +BEGIN + SYSTEM.GET(t0 + t1 + types, t0) + RETURN t0 MOD 2 +END _guardrec; + + +PROCEDURE [stdcall64] _guard* (t0, p: INTEGER): INTEGER; +BEGIN + SYSTEM.GET(p, p); + IF p # 0 THEN + SYSTEM.GET(p - WORD, p); + SYSTEM.GET(t0 + p + types, p) + ELSE + p := 1 + END + + RETURN p MOD 2 +END _guard; + + +PROCEDURE [stdcall64] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; + RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) +END _dllentry; + + +PROCEDURE [stdcall64] _sofinit*; +BEGIN + API.sofinit +END _sofinit; + + +PROCEDURE [stdcall64] _exit* (code: INTEGER); +BEGIN + API.exit(code) +END _exit; + + +PROCEDURE [stdcall64] _init* (modname: INTEGER; tcount, _types: INTEGER; code, param: INTEGER); +VAR + t0, t1, i, j: INTEGER; + +BEGIN + API.init(param, code); + + types := API._NEW(tcount * tcount + SYSTEM.SIZE(INTEGER)); + ASSERT(types # 0); + FOR i := 0 TO tcount - 1 DO + FOR j := 0 TO tcount - 1 DO + t0 := i; t1 := j; + + WHILE (t1 # 0) & (t1 # t0) DO + SYSTEM.GET(_types + t1 * WORD, t1) + END; + + SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) + END + END; + + FOR i := 0 TO MAX_SET DO + FOR j := 0 TO i DO + sets[i * (MAX_SET + 1) + j] := LSR(ASR(minint, i - j), MAX_SET - i) + END + END; + + name := modname +END _init; + + +END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/UnixTime.ob07 b/programs/develop/oberon07/Lib/Windows64/UnixTime.ob07 new file mode 100644 index 0000000000..0e6ed5bd6d --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/UnixTime.ob07 @@ -0,0 +1,64 @@ +(* + BSD 2-Clause License + + Copyright (c) 2018-2019, Anton Krotov + All rights reserved. +*) + +MODULE UnixTime; + + +VAR + + days: ARRAY 12, 31, 2 OF INTEGER; + + +PROCEDURE init; +VAR + i, j, k, n0, n1: INTEGER; +BEGIN + + FOR i := 0 TO 11 DO + FOR j := 0 TO 30 DO + days[i, j, 0] := 0; + days[i, j, 1] := 0; + END + END; + + days[ 1, 28, 0] := -1; + + FOR k := 0 TO 1 DO + days[ 1, 29, k] := -1; + days[ 1, 30, k] := -1; + days[ 3, 30, k] := -1; + days[ 5, 30, k] := -1; + days[ 8, 30, k] := -1; + days[10, 30, k] := -1; + END; + + n0 := 0; + n1 := 0; + FOR i := 0 TO 11 DO + FOR j := 0 TO 30 DO + IF days[i, j, 0] = 0 THEN + days[i, j, 0] := n0; + INC(n0) + END; + IF days[i, j, 1] = 0 THEN + days[i, j, 1] := n1; + INC(n1) + END + END + END + +END init; + + +PROCEDURE time* (year, month, day, hour, min, sec: INTEGER): INTEGER; + RETURN ((year - 1970) * 365 + days[month - 1, day - 1, ORD(year DIV 4 = 0)] + (year - 1969) DIV 4) * 86400 + hour * 3600 + min * 60 + sec +END time; + + +BEGIN + init +END UnixTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 b/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 new file mode 100644 index 0000000000..86d166008f --- /dev/null +++ b/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 @@ -0,0 +1,170 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2020, Anton Krotov + All rights reserved. +*) + +MODULE WINAPI; + +IMPORT SYSTEM, API; + + +CONST + + OFS_MAXPATHNAME* = 128; + + +TYPE + + DLL_ENTRY* = API.DLL_ENTRY; + + STRING = ARRAY 260 OF CHAR; + + TCoord* = RECORD + + X*, Y*: WCHAR + + END; + + TSmallRect* = RECORD + + Left*, Top*, Right*, Bottom*: WCHAR + + END; + + TConsoleScreenBufferInfo* = RECORD + + dwSize*: TCoord; + dwCursorPosition*: TCoord; + wAttributes*: WCHAR; + srWindow*: TSmallRect; + dwMaximumWindowSize*: TCoord + + END; + + TSystemTime* = RECORD + + Year*, + Month*, + DayOfWeek*, + Day*, + Hour*, + Min*, + Sec*, + MSec*: WCHAR + + END; + + PSecurityAttributes* = POINTER TO TSecurityAttributes; + + TSecurityAttributes* = RECORD + + nLength*: INTEGER; + lpSecurityDescriptor*: INTEGER; + bInheritHandle*: INTEGER + + END; + + TFileTime* = RECORD + + dwLowDateTime*, + dwHighDateTime*: INTEGER + + END; + + OFSTRUCT* = RECORD + + cBytes*: CHAR; + fFixedDisk*: CHAR; + nErrCode*: WCHAR; + Reserved1*: WCHAR; + Reserved2*: WCHAR; + szPathName*: ARRAY OFS_MAXPATHNAME OF CHAR + + END; + + POverlapped* = POINTER TO OVERLAPPED; + + OVERLAPPED* = RECORD + + Internal*: INTEGER; + InternalHigh*: INTEGER; + Offset*: INTEGER; + OffsetHigh*: INTEGER; + hEvent*: INTEGER + + END; + + +PROCEDURE [windows-, "kernel32.dll", "SetConsoleCursorPosition"] + SetConsoleCursorPosition* (hConsoleOutput, dwCursorPosition: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetConsoleScreenBufferInfo"] + GetConsoleScreenBufferInfo* (hConsoleOutput: INTEGER; ConsoleScreenBufferInfo: TConsoleScreenBufferInfo): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "FillConsoleOutputCharacterA"] + FillConsoleOutputCharacter* (hConsoleOutput, cCaracter, nLength, dwWriteCoord, lpNumberOfCharsWritten: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "FillConsoleOutputAttribute"] + FillConsoleOutputAttribute* (hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "SetConsoleTextAttribute"] + SetConsoleTextAttribute* (hConsoleOutput, wAttributes: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] + GetStdHandle* (nStdHandle: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "CloseHandle"] + CloseHandle* (hObject: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "WriteFile"] + WriteFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "ReadFile"] + ReadFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetCommandLineA"] + GetCommandLine* (): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GlobalAlloc"] + GlobalAlloc* (uFlags, dwBytes: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GlobalFree"] + GlobalFree* (hMem: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] + ExitProcess* (code: INTEGER); + +PROCEDURE [windows-, "kernel32.dll", "GetTickCount"] + GetTickCount* (): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "Sleep"] + Sleep* (dwMilliseconds: INTEGER); + +PROCEDURE [windows-, "kernel32.dll", "FreeLibrary"] + FreeLibrary* (hLibModule: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "GetProcAddress"] + GetProcAddress* (hModule, name: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "LoadLibraryA"] + LoadLibraryA* (name: INTEGER): INTEGER; + +PROCEDURE [windows-, "kernel32.dll", "AllocConsole"] + AllocConsole* (): BOOLEAN; + +PROCEDURE [windows-, "kernel32.dll", "FreeConsole"] + FreeConsole* (): BOOLEAN; + +PROCEDURE [windows-, "kernel32.dll", "GetLocalTime"] + GetLocalTime* (T: TSystemTime); + + +PROCEDURE SetDllEntry* (process_detach, thread_detach, thread_attach: DLL_ENTRY); +BEGIN + API.SetDll(process_detach, thread_detach, thread_attach) +END SetDllEntry; + + +END WINAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Dialogs.ob07 b/programs/develop/oberon07/Samples/Dialogs.ob07 index d680c3ffde..9ba66c67d5 100644 --- a/programs/develop/oberon07/Samples/Dialogs.ob07 +++ b/programs/develop/oberon07/Samples/Dialogs.ob07 @@ -1,4 +1,4 @@ -MODULE Dialogs; +MODULE Dialogs; IMPORT KOSAPI, sys := SYSTEM, OpenDlg, ColorDlg; @@ -107,4 +107,4 @@ END main; BEGIN main -END Dialogs. +END Dialogs. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/HW.ob07 b/programs/develop/oberon07/Samples/HW.ob07 index 707071da17..3412f93b53 100644 --- a/programs/develop/oberon07/Samples/HW.ob07 +++ b/programs/develop/oberon07/Samples/HW.ob07 @@ -1,4 +1,4 @@ -MODULE HW; +MODULE HW; IMPORT sys := SYSTEM, KOSAPI; @@ -47,4 +47,4 @@ END Main; BEGIN Main("HW", "Hello, world!") -END HW. +END HW. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/HW_con.ob07 b/programs/develop/oberon07/Samples/HW_con.ob07 index e32bec396f..7f8f9e136c 100644 --- a/programs/develop/oberon07/Samples/HW_con.ob07 +++ b/programs/develop/oberon07/Samples/HW_con.ob07 @@ -1,4 +1,4 @@ -MODULE HW_con; +MODULE HW_con; IMPORT Out, In, Console, DateTime; @@ -60,4 +60,4 @@ BEGIN main; In.Ln; Console.exit(TRUE) -END HW_con. +END HW_con. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/AMD64.ob07 b/programs/develop/oberon07/Source/AMD64.ob07 index b93712817d..a4ae7285c8 100644 --- a/programs/develop/oberon07/Source/AMD64.ob07 +++ b/programs/develop/oberon07/Source/AMD64.ob07 @@ -1,14 +1,14 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) MODULE AMD64; -IMPORT IL, BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PATHS, PROG, - REG, C := CONSOLE, UTILS, mConst := CONSTANTS, S := STRINGS, PE32, ELF, X86; +IMPORT IL, BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PATHS, PROG, TARGETS, + REG, C := CONSOLE, UTILS, S := STRINGS, PE32, ELF, X86; CONST @@ -74,25 +74,25 @@ END OutByte; PROCEDURE OutByte2 (a, b: BYTE); BEGIN - OutByte(a); - OutByte(b) + X86.OutByte(a); + X86.OutByte(b) END OutByte2; PROCEDURE OutByte3 (a, b, c: BYTE); BEGIN - OutByte(a); - OutByte(b); - OutByte(c) + X86.OutByte(a); + X86.OutByte(b); + X86.OutByte(c) END OutByte3; PROCEDURE OutInt (n: INTEGER); BEGIN - OutByte(UTILS.Byte(n, 0)); - OutByte(UTILS.Byte(n, 1)); - OutByte(UTILS.Byte(n, 2)); - OutByte(UTILS.Byte(n, 3)) + X86.OutByte(n MOD 256); + X86.OutByte(UTILS.Byte(n, 1)); + X86.OutByte(UTILS.Byte(n, 2)); + X86.OutByte(UTILS.Byte(n, 3)) END OutInt; @@ -114,7 +114,7 @@ END long; PROCEDURE OutIntByte (n: INTEGER); BEGIN IF isByte(n) THEN - OutByte(UTILS.Byte(n, 0)) + OutByte(n MOD 256) ELSE OutInt(n) END @@ -154,74 +154,74 @@ END Rex; PROCEDURE lea (reg, offset, section: INTEGER); BEGIN Rex(0, reg); - OutByte2(8DH, 05H + 8 * (reg MOD 8)); // lea reg, [rip + offset] + OutByte2(8DH, 05H + 8 * (reg MOD 8)); (* lea reg, [rip + offset] *) X86.Reloc(section, offset) END lea; -PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); // op reg1, reg2 +PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *) BEGIN Rex(reg1, reg2); OutByte2(op, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8) END oprr; -PROCEDURE oprr2 (op1, op2: BYTE; reg1, reg2: INTEGER); // op reg1, reg2 +PROCEDURE oprr2 (op1, op2: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *) BEGIN Rex(reg1, reg2); OutByte3(op1, op2, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8) END oprr2; -PROCEDURE mov (reg1, reg2: INTEGER); // mov reg1, reg2 +PROCEDURE mov (reg1, reg2: INTEGER); (* mov reg1, reg2 *) BEGIN oprr(89H, reg1, reg2) END mov; -PROCEDURE xor (reg1, reg2: INTEGER); // xor reg1, reg2 +PROCEDURE xor (reg1, reg2: INTEGER); (* xor reg1, reg2 *) BEGIN oprr(31H, reg1, reg2) END xor; -PROCEDURE and (reg1, reg2: INTEGER); // and reg1, reg2 +PROCEDURE and (reg1, reg2: INTEGER); (* and reg1, reg2 *) BEGIN oprr(21H, reg1, reg2) END and; -PROCEDURE or (reg1, reg2: INTEGER); // and reg1, reg2 +PROCEDURE or (reg1, reg2: INTEGER); (* or reg1, reg2 *) BEGIN oprr(09H, reg1, reg2) END or; -PROCEDURE add (reg1, reg2: INTEGER); // add reg1, reg2 +PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *) BEGIN oprr(01H, reg1, reg2) END add; -PROCEDURE sub (reg1, reg2: INTEGER); // sub reg1, reg2 +PROCEDURE sub (reg1, reg2: INTEGER); (* sub reg1, reg2 *) BEGIN oprr(29H, reg1, reg2) END sub; -PROCEDURE xchg (reg1, reg2: INTEGER); // xchg reg1, reg2 +PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *) BEGIN oprr(87H, reg1, reg2) END xchg; -PROCEDURE cmprr (reg1, reg2: INTEGER); // cmp reg1, reg2 +PROCEDURE cmprr (reg1, reg2: INTEGER); (* cmp reg1, reg2 *) BEGIN oprr(39H, reg1, reg2) END cmprr; -PROCEDURE pop (reg: INTEGER); // pop reg +PROCEDURE pop (reg: INTEGER); (* pop reg *) BEGIN IF reg >= 8 THEN OutByte(41H) @@ -230,7 +230,7 @@ BEGIN END pop; -PROCEDURE push (reg: INTEGER); // push reg +PROCEDURE push (reg: INTEGER); (* push reg *) BEGIN IF reg >= 8 THEN OutByte(41H) @@ -242,14 +242,14 @@ END push; PROCEDURE decr (reg: INTEGER); BEGIN Rex(reg, 0); - OutByte2(0FFH, 0C8H + reg MOD 8) // dec reg1 + OutByte2(0FFH, 0C8H + reg MOD 8) (* dec reg1 *) END decr; PROCEDURE incr (reg: INTEGER); BEGIN Rex(reg, 0); - OutByte2(0FFH, 0C0H + reg MOD 8) // inc reg1 + OutByte2(0FFH, 0C0H + reg MOD 8) (* inc reg1 *) END incr; @@ -276,7 +276,7 @@ VAR BEGIN reg := GetAnyReg(); lea(reg, label, sIMP); - IF reg >= 8 THEN // call qword[reg] + IF reg >= 8 THEN (* call qword[reg] *) OutByte(41H) END; OutByte2(0FFH, 10H + reg MOD 8); @@ -337,14 +337,14 @@ VAR BEGIN Rex(reg, 0); - OutByte(0B8H + reg MOD 8); // movabs reg, n + OutByte(0B8H + reg MOD 8); (* movabs reg, n *) FOR i := 0 TO 7 DO OutByte(UTILS.Byte(n, i)) END END movabs; -PROCEDURE movrc (reg, n: INTEGER); // mov reg, n +PROCEDURE movrc (reg, n: INTEGER); (* mov reg, n *) BEGIN IF isLong(n) THEN movabs(reg, n) @@ -358,7 +358,7 @@ BEGIN END movrc; -PROCEDURE test (reg: INTEGER); // test reg, reg +PROCEDURE test (reg: INTEGER); (* test reg, reg *) BEGIN oprr(85H, reg, reg) END test; @@ -370,6 +370,7 @@ VAR BEGIN reg2 := GetAnyReg(); + ASSERT(reg2 # reg); movabs(reg2, n); oprr(reg, reg2); drop @@ -388,30 +389,46 @@ BEGIN END oprc; -PROCEDURE cmprc (reg, n: INTEGER); // cmp reg, n +PROCEDURE cmprc (reg, n: INTEGER); (* cmp reg, n *) BEGIN - oprc(0F8H, reg, n, cmprr) + IF n = 0 THEN + test(reg) + ELSE + oprc(0F8H, reg, n, cmprr) + END END cmprc; -PROCEDURE addrc (reg, n: INTEGER); // add reg, n +PROCEDURE addrc (reg, n: INTEGER); (* add reg, n *) BEGIN oprc(0C0H, reg, n, add) END addrc; -PROCEDURE subrc (reg, n: INTEGER); // sub reg, n +PROCEDURE subrc (reg, n: INTEGER); (* sub reg, n *) BEGIN oprc(0E8H, reg, n, sub) END subrc; -PROCEDURE andrc (reg, n: INTEGER); // and reg, n +PROCEDURE andrc (reg, n: INTEGER); (* and reg, n *) BEGIN oprc(0E0H, reg, n, and) END andrc; +PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *) +BEGIN + oprc(0C8H, reg, n, or) +END orrc; + + +PROCEDURE xorrc (reg, n: INTEGER); (* xor reg, n *) +BEGIN + oprc(0F0H, reg, n, xor) +END xorrc; + + PROCEDURE pushc (n: INTEGER); VAR reg2: INTEGER; @@ -423,147 +440,57 @@ BEGIN push(reg2); drop ELSE - OutByte(68H + short(n)); OutIntByte(n) // push n + OutByte(68H + short(n)); OutIntByte(n) (* push n *) END END pushc; -PROCEDURE not (reg: INTEGER); // not reg +PROCEDURE not (reg: INTEGER); (* not reg *) BEGIN Rex(reg, 0); OutByte2(0F7H, 0D0H + reg MOD 8) END not; -PROCEDURE neg (reg: INTEGER); // neg reg +PROCEDURE neg (reg: INTEGER); (* neg reg *) BEGIN Rex(reg, 0); OutByte2(0F7H, 0D8H + reg MOD 8) END neg; -PROCEDURE movzx (reg1, reg2, offs: INTEGER; word: BOOLEAN); // movzx reg1, byte/word[reg2 + offs] -VAR - b: BYTE; - +PROCEDURE movzx (reg1, reg2, offs: INTEGER; word: BOOLEAN); (* movzx reg1, byte/word[reg2 + offs] *) BEGIN Rex(reg2, reg1); - OutByte2(0FH, 0B6H + ORD(word)); - IF (offs = 0) & (reg2 # rbp) THEN - b := 0 - ELSE - b := 40H + long(offs) - END; - OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8); - IF reg2 = rsp THEN - OutByte(24H) - END; - IF b # 0 THEN - OutIntByte(offs) - END + X86.movzx(reg1, reg2, offs, word) END movzx; -PROCEDURE _movrm (reg1, reg2, offs, size: INTEGER; mr: BOOLEAN); -VAR - b: BYTE; - +PROCEDURE movmr32 (reg1, offs, reg2: INTEGER); (* mov dword[reg1+offs], reg2_32 *) BEGIN - IF size = 16 THEN - OutByte(66H) - END; - IF (reg1 >= 8) OR (reg2 >= 8) OR (size = 64) THEN - OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8) + 8 * ORD(size = 64)) - END; - OutByte(8BH - 2 * ORD(mr) - ORD(size = 8)); - IF (offs = 0) & (reg2 # rbp) THEN - b := 0 - ELSE - b := 40H + long(offs) - END; - OutByte(b + (reg1 MOD 8) * 8 + reg2 MOD 8); - IF reg2 = rsp THEN - OutByte(24H) - END; - IF b # 0 THEN - OutIntByte(offs) - END -END _movrm; - - -PROCEDURE movmr32 (reg1, offs, reg2: INTEGER); // mov dword[reg1+offs], reg2_32 -BEGIN - _movrm(reg2, reg1, offs, 32, TRUE) + X86._movrm(reg2, reg1, offs, 32, TRUE) END movmr32; -PROCEDURE movrm32 (reg1, reg2, offs: INTEGER); // mov reg1_32, dword[reg2+offs] +PROCEDURE movrm32 (reg1, reg2, offs: INTEGER); (* mov reg1_32, dword[reg2+offs] *) BEGIN - _movrm(reg1, reg2, offs, 32, FALSE) + X86._movrm(reg1, reg2, offs, 32, FALSE) END movrm32; -PROCEDURE movmr8 (reg1, offs, reg2: INTEGER); // mov byte[reg1+offs], reg2_8 +PROCEDURE movmr (reg1, offs, reg2: INTEGER); (* mov qword[reg1+offs], reg2 *) BEGIN - _movrm(reg2, reg1, offs, 8, TRUE) -END movmr8; - - -PROCEDURE movrm8 (reg1, reg2, offs: INTEGER); // mov reg1_8, byte[reg2+offs] -BEGIN - _movrm(reg1, reg2, offs, 8, FALSE) -END movrm8; - - -PROCEDURE movmr16 (reg1, offs, reg2: INTEGER); // mov word[reg1+offs], reg2_16 -BEGIN - _movrm(reg2, reg1, offs, 16, TRUE) -END movmr16; - - -PROCEDURE movrm16 (reg1, reg2, offs: INTEGER); // mov reg1_16, word[reg2+offs] -BEGIN - _movrm(reg1, reg2, offs, 16, FALSE) -END movrm16; - - -PROCEDURE movmr (reg1, offs, reg2: INTEGER); // mov qword[reg1+offs], reg2 -BEGIN - _movrm(reg2, reg1, offs, 64, TRUE) + X86._movrm(reg2, reg1, offs, 64, TRUE) END movmr; -PROCEDURE movrm (reg1, reg2, offs: INTEGER); // mov reg1, qword[reg2+offs] +PROCEDURE movrm (reg1, reg2, offs: INTEGER); (* mov reg1, qword[reg2+offs] *) BEGIN - _movrm(reg1, reg2, offs, 64, FALSE) + X86._movrm(reg1, reg2, offs, 64, FALSE) END movrm; -PROCEDURE pushm (reg, offs: INTEGER); // push qword[reg+offs] -VAR - b: BYTE; - -BEGIN - IF reg >= 8 THEN - OutByte(41H) - END; - OutByte(0FFH); - IF (offs = 0) & (reg # rbp) THEN - b := 30H - ELSE - b := 70H + long(offs) - END; - OutByte(b + reg MOD 8); - IF reg = rsp THEN - OutByte(24H) - END; - IF b # 30H THEN - OutIntByte(offs) - END -END pushm; - - -PROCEDURE comisd (xmm1, xmm2: INTEGER); // comisd xmm1, xmm2 +PROCEDURE comisd (xmm1, xmm2: INTEGER); (* comisd xmm1, xmm2 *) BEGIN OutByte(66H); IF (xmm1 >= 8) OR (xmm2 >= 8) THEN @@ -598,13 +525,13 @@ BEGIN END _movsdrm; -PROCEDURE movsdrm (xmm, reg, offs: INTEGER); // movsd xmm, qword[reg+offs] +PROCEDURE movsdrm (xmm, reg, offs: INTEGER); (* movsd xmm, qword[reg+offs] *) BEGIN _movsdrm(xmm, reg, offs, FALSE) END movsdrm; -PROCEDURE movsdmr (reg, offs, xmm: INTEGER); // movsd qword[reg+offs], xmm +PROCEDURE movsdmr (reg, offs, xmm: INTEGER); (* movsd qword[reg+offs], xmm *) BEGIN _movsdrm(xmm, reg, offs, TRUE) END movsdmr; @@ -620,19 +547,19 @@ BEGIN END opxx; -PROCEDURE jcc (cc, label: INTEGER); // jcc label +PROCEDURE jcc (cc, label: INTEGER); (* jcc label *) BEGIN X86.jcc(cc, label) END jcc; -PROCEDURE jmp (label: INTEGER); // jmp label +PROCEDURE jmp (label: INTEGER); (* jmp label *) BEGIN X86.jmp(label) END jmp; -PROCEDURE setcc (cc, reg: INTEGER); //setcc reg8 +PROCEDURE setcc (cc, reg: INTEGER); (* setcc reg8 *) BEGIN IF reg >= 8 THEN OutByte(41H) @@ -680,7 +607,6 @@ VAR reg: INTEGER; max: INTEGER; loop: INTEGER; - param2: INTEGER; BEGIN loop := 1; @@ -756,17 +682,7 @@ BEGIN leaf := FALSE |IL.opDIVR, IL.opMODR: - param2 := cur.param2; - IF param2 >= 1 THEN - param2 := UTILS.Log2(param2) - ELSIF param2 <= -1 THEN - param2 := UTILS.Log2(-param2) - ELSE - param2 := -1 - END; - IF param2 < 0 THEN - leaf := FALSE - END + leaf := UTILS.Log2(cur.param2) >= 0 ELSE @@ -912,9 +828,9 @@ BEGIN comisd(xmm - 1, xmm); cc := setnc END; - OutByte2(7AH, 3 + reg DIV 8); // jp L + OutByte2(7AH, 3 + reg DIV 8); (* jp L *) setcc(cc, reg); - //L: + (* L: *) END fcmp; @@ -969,7 +885,7 @@ BEGIN |IL.opWIN64CALLP: Win64Passing(param2) |IL.opSYSVCALLP: SysVPassing(param2) END; - OutByte2(0FFH, 0D0H); // call rax + OutByte2(0FFH, 0D0H); (* call rax *) REG.Restore(R); ASSERT(R.top = -1) @@ -989,6 +905,10 @@ BEGIN |IL.opERR: CallRTL(IL._error) + |IL.opONERR: + pushc(param2); + jmp(param1) + |IL.opPUSHC: pushc(param2) @@ -1117,9 +1037,9 @@ BEGIN n := param2; IF n > 4 THEN movrc(rcx, n); - // L: + (* L: *) pushc(0); - OutByte2(0E2H, 0FCH) // loop L + OutByte2(0E2H, 0FCH) (* loop L *) ELSE WHILE n > 0 DO pushc(0); @@ -1156,9 +1076,9 @@ BEGIN pop(rbp); IF param2 > 0 THEN - OutByte3(0C2H, (param2 * 8) MOD 256, (param2 * 8) DIV 256) // ret param2 + OutByte3(0C2H, (param2 * 8) MOD 256, (param2 * 8) DIV 256) (* ret param2 *) ELSE - OutByte(0C3H) // ret + X86.ret END; REG.Reset(R) @@ -1265,7 +1185,7 @@ BEGIN |IL.opLADR: n := param2 * 8; next := cmd.next(COMMAND); - IF next.opcode = IL.opSAVEF THEN + IF (next.opcode = IL.opSAVEF) OR (next.opcode = IL.opSAVEFI) THEN movsdmr(rbp, n, xmm); DEC(xmm); cmd := next @@ -1276,7 +1196,7 @@ BEGIN ELSE reg1 := GetAnyReg(); Rex(0, reg1); - OutByte2(8DH, 45H + long(n) + (reg1 MOD 8) * 8); // lea reg1, qword[rbp+n] + OutByte2(8DH, 45H + long(n) + (reg1 MOD 8) * 8); (* lea reg1, qword[rbp+n] *) OutIntByte(n) END @@ -1291,7 +1211,7 @@ BEGIN IF reg1 >= 8 THEN OutByte(41H) END; - OutByte3(0C6H, reg1 MOD 8, param2); // mov byte[reg1], param2 + OutByte3(0C6H, reg1 MOD 8, param2); (* mov byte[reg1], param2 *) drop |IL.opSAVE16C: @@ -1301,7 +1221,7 @@ BEGIN OutByte(41H) END; OutByte2(0C7H, reg1 MOD 8); - OutByte2(param2 MOD 256, param2 DIV 256); // mov word[reg1], param2 + OutByte2(param2 MOD 256, param2 DIV 256); (* mov word[reg1], param2 *) drop |IL.opSAVEC: @@ -1313,7 +1233,7 @@ BEGIN drop ELSE Rex(reg1, 0); - OutByte2(0C7H, reg1 MOD 8); // mov qword[reg1], param2 + OutByte2(0C7H, reg1 MOD 8); (* mov qword[reg1], param2 *) OutInt(param2) END; drop @@ -1346,17 +1266,17 @@ BEGIN |IL.opINCL, IL.opEXCL: BinOp(reg1, reg2); cmprc(reg1, 64); - OutByte2(73H, 04H); // jnb L + OutByte2(73H, 04H); (* jnb L *) Rex(reg2, reg1); - OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opEXCL), 8 * (reg1 MOD 8) + reg2 MOD 8); // bts/btr qword[reg2], reg1 - // L: + OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opEXCL), 8 * (reg1 MOD 8) + reg2 MOD 8); (* bts/btr qword[reg2], reg1 *) + (* L: *) drop; drop |IL.opINCLC, IL.opEXCLC: UnOp(reg1); Rex(reg1, 0); - OutByte2(0FH, 0BAH); // bts/btr qword[reg1], param2 + OutByte2(0FH, 0BAH); (* bts/btr qword[reg1], param2 *) OutByte2(28H + 8 * ORD(opcode = IL.opEXCLC) + reg1 MOD 8, param2); drop @@ -1384,26 +1304,19 @@ BEGIN drop ELSE UnOp(reg1); - IF param2 = 0 THEN - test(reg1) - ELSE - cmprc(reg1, param2) - END + cmprc(reg1, param2) END; 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 = IL.opJNE THEN - label := cmd.next(COMMAND).param1; - jcc(X86.inv0(cc), label); - cmd := cmd.next(COMMAND) - + next := cmd.next(COMMAND); + IF next.opcode = IL.opJE THEN + jcc(cc, next.param1); + cmd := next + ELSIF next.opcode = IL.opJNE THEN + jcc(X86.inv0(cc), next.param1); + cmd := next ELSE reg1 := GetAnyReg(); setcc(cc + 16, reg1); @@ -1447,6 +1360,11 @@ BEGIN test(reg1); jcc(je, param1) + |IL.opJG: + UnOp(reg1); + test(reg1); + jcc(jg, param1) + |IL.opJE: UnOp(reg1); test(reg1); @@ -1459,7 +1377,11 @@ BEGIN jcc(je, param1); drop - |IL.opIN: + |IL.opIN, IL.opINR: + IF opcode = IL.opINR THEN + reg2 := GetAnyReg(); + movrc(reg2, param2) + END; label := NewLabel(); L := NewLabel(); BinOp(reg1, reg2); @@ -1469,25 +1391,7 @@ BEGIN jmp(label); X86.SetLabel(L); Rex(reg2, reg1); - OutByte3(0FH, 0A3H, 0C0H + 8 * (reg1 MOD 8) + reg2 MOD 8); // bt reg2, reg1 - setcc(setc, reg1); - andrc(reg1, 1); - X86.SetLabel(label); - drop - - |IL.opINR: - label := NewLabel(); - L := NewLabel(); - UnOp(reg1); - reg2 := GetAnyReg(); - cmprc(reg1, 64); - jcc(jb, L); - xor(reg1, reg1); - jmp(label); - X86.SetLabel(L); - movrc(reg2, param2); - Rex(reg2, reg1); - OutByte3(0FH, 0A3H, 0C0H + 8 * (reg1 MOD 8) + reg2 MOD 8); // bt reg2, reg1 + OutByte3(0FH, 0A3H, 0C0H + 8 * (reg1 MOD 8) + reg2 MOD 8); (* bt reg2, reg1 *) setcc(setc, reg1); andrc(reg1, 1); X86.SetLabel(label); @@ -1496,7 +1400,7 @@ BEGIN |IL.opINL: UnOp(reg1); Rex(reg1, 0); - OutByte2(0FH, 0BAH); // bt reg1, param2 + OutByte2(0FH, 0BAH); (* bt reg1, param2 *) OutByte2(0E0H + reg1 MOD 8, param2); setcc(setc, reg1); andrc(reg1, 1) @@ -1516,9 +1420,9 @@ BEGIN |IL.opABS: UnOp(reg1); test(reg1); - OutByte2(7DH, 03H); // jge L + OutByte2(7DH, 03H); (* jge L *) neg(reg1) - // L: + (* L: *) |IL.opEQB, IL.opNEB: BinOp(reg1, reg2); @@ -1545,11 +1449,13 @@ BEGIN UnOp(reg1); andrc(reg1, param2) - |IL.opDIVSC, IL.opADDSL, IL.opADDSR: + |IL.opDIVSC: UnOp(reg1); - Rex(reg1, 0); - OutByte2(81H + short(param2), 0C8H + 28H * ORD(opcode = IL.opDIVSC) + reg1 MOD 8); // or/xor reg1, param2 - OutIntByte(param2) + xorrc(reg1, param2) + + |IL.opADDSL, IL.opADDSR: + UnOp(reg1); + orrc(reg1, param2) |IL.opSUBSL: UnOp(reg1); @@ -1646,7 +1552,7 @@ BEGIN |IL.opTYPEGD: UnOp(reg1); PushAll(0); - pushm(reg1, -8); + X86.pushm(reg1, -8); pushc(param2 * tcount); CallRTL(IL._guardrec); GetRegA @@ -1673,7 +1579,7 @@ BEGIN |IL.opINC, IL.opDEC: BinOp(reg1, reg2); - // add/sub qword[reg2], reg1 + (* add/sub qword[reg2], reg1 *) Rex(reg2, reg1); OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg2 MOD 8 + (reg1 MOD 8) * 8); drop; @@ -1684,15 +1590,15 @@ BEGIN IF isLong(param2) THEN reg2 := GetAnyReg(); movrc(reg2, param2); - // add qword[reg1], reg2 + (* add qword[reg1], reg2 *) Rex(reg1, reg2); OutByte2(01H, reg1 MOD 8 + (reg2 MOD 8) * 8); drop ELSIF ABS(param2) = 1 THEN Rex(reg1, 0); - OutByte2(0FFH, reg1 MOD 8 + 8 * ORD(param2 = -1)) // inc/dec qword[reg1] + OutByte2(0FFH, reg1 MOD 8 + 8 * ORD(param2 = -1)) (* inc/dec qword[reg1] *) ELSE - // add qword[reg1], param2 + (* add qword[reg1], param2 *) Rex(reg1, 0); OutByte2(81H + short(param2), reg1 MOD 8); OutIntByte(param2) @@ -1711,13 +1617,13 @@ BEGIN |IL.opSAVE8: BinOp(reg2, reg1); - movmr8(reg1, 0, reg2); + X86.movmr8(reg1, 0, reg2); drop; drop |IL.opSAVE16: BinOp(reg2, reg1); - movmr16(reg1, 0, reg2); + X86.movmr16(reg1, 0, reg2); drop; drop @@ -1727,35 +1633,24 @@ BEGIN drop; drop - |IL.opMIN: + |IL.opMAX, IL.opMIN: BinOp(reg1, reg2); cmprr(reg1, reg2); - OutByte2(7EH, 3); // jle L + OutByte2(7DH + ORD(opcode = IL.opMIN), 3); (* jge/jle L *) mov(reg1, reg2); - // L: + (* L: *) drop - |IL.opMAX: - BinOp(reg1, reg2); - cmprr(reg1, reg2); - OutByte2(7DH, 3); // jge L - mov(reg1, reg2); - // L: - drop - - |IL.opMINC: + |IL.opMAXC, IL.opMINC: UnOp(reg1); cmprc(reg1, param2); label := NewLabel(); - jcc(jle, label); - movrc(reg1, param2); - X86.SetLabel(label) - - |IL.opMAXC: - UnOp(reg1); - cmprc(reg1, param2); - label := NewLabel(); - jcc(jge, label); + IF opcode = IL.opMINC THEN + cc := jle + ELSE + cc := jge + END; + jcc(cc, label); movrc(reg1, param2); X86.SetLabel(label) @@ -1765,7 +1660,7 @@ BEGIN IF reg1 >= 8 THEN OutByte(41H) END; - OutByte3(0FH, 95H, reg1 MOD 8); // setne byte[reg1] + OutByte3(0FH, 95H, reg1 MOD 8); (* setne byte[reg1] *) drop; drop @@ -1774,13 +1669,9 @@ BEGIN IF reg1 >= 8 THEN OutByte(41H) END; - OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); // mov byte[reg1], 0/1 + OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *) drop - |IL.opODD: - UnOp(reg1); - andrc(reg1, 1) - |IL.opUMINUS: UnOp(reg1); neg(reg1) @@ -1810,15 +1701,39 @@ BEGIN END |IL.opADDL, IL.opADDR: - IF param2 # 0 THEN + IF (param2 # 0) & ~isLong(param2) THEN UnOp(reg1); - IF param2 = 1 THEN - incr(reg1) - ELSIF param2 = -1 THEN - decr(reg1) + next := cmd.next(COMMAND); + CASE next.opcode OF + |IL.opLOAD64: + movrm(reg1, reg1, param2); + cmd := next + |IL.opLOAD32: + movrm32(reg1, reg1, param2); + shiftrc(shl, reg1, 32); + shiftrc(shr, reg1, 32); + cmd := next + |IL.opLOAD16: + movzx(reg1, reg1, param2, TRUE); + cmd := next + |IL.opLOAD8: + movzx(reg1, reg1, param2, FALSE); + cmd := next + |IL.opLOAD64_PARAM: + X86.pushm(reg1, param2); + drop; + cmd := next ELSE - addrc(reg1, param2) + IF param2 = 1 THEN + incr(reg1) + ELSIF param2 = -1 THEN + decr(reg1) + ELSE + addrc(reg1, param2) + END END + ELSIF isLong(param2) THEN + addrc(reg1, param2) END |IL.opDIV: @@ -1827,40 +1742,15 @@ BEGIN GetRegA |IL.opDIVR: - 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 + n := UTILS.Log2(param2); + IF n > 0 THEN UnOp(reg1); - neg(reg1) - ELSE - IF n > 0 THEN - UnOp(reg1); - - IF a < 0 THEN - reg2 := GetAnyReg(); - mov(reg2, reg1); - shiftrc(sar, reg1, n); - sub(reg1, reg2); - drop - ELSE - shiftrc(sar, reg1, n) - END - - ELSE - PushAll(1); - pushc(param2); - CallRTL(IL._divmod); - GetRegA - END + shiftrc(sar, reg1, n) + ELSIF n < 0 THEN + PushAll(1); + pushc(param2); + CallRTL(IL._divmod); + GetRegA END |IL.opDIVL: @@ -1879,38 +1769,19 @@ BEGIN GetRegA |IL.opMODR: - a := param2; - IF a > 1 THEN - n := UTILS.Log2(a) - ELSIF a < -1 THEN - n := UTILS.Log2(-a) + n := UTILS.Log2(param2); + IF n > 0 THEN + UnOp(reg1); + andrc(reg1, param2 - 1); + ELSIF n < 0 THEN + PushAll(1); + pushc(param2); + CallRTL(IL._divmod); + mov(rax, rdx); + GetRegA ELSE - n := -1 - END; - - IF ABS(a) = 1 THEN UnOp(reg1); xor(reg1, reg1) - ELSE - IF n > 0 THEN - UnOp(reg1); - andrc(reg1, ABS(a) - 1); - - IF a < 0 THEN - test(reg1); - label := NewLabel(); - jcc(je, label); - addrc(reg1, a); - X86.SetLabel(label) - END - - ELSE - PushAll(1); - pushc(param2); - CallRTL(IL._divmod); - mov(rax, rdx); - GetRegA - END END |IL.opMODL: @@ -1925,38 +1796,56 @@ BEGIN |IL.opMUL: BinOp(reg1, reg2); - oprr2(0FH, 0AFH, reg2, reg1); // imul reg1, reg2 + oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *) drop |IL.opMULC: - UnOp(reg1); - - a := param2; - IF a > 1 THEN - n := UTILS.Log2(a) - ELSIF a < -1 THEN - n := UTILS.Log2(-a) + IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN + BinOp(reg1, reg2); + OutByte2(48H + 5 * (reg1 DIV 8) + 2 * (reg2 DIV 8), 8DH); (* lea reg1, [reg1 + reg2 * param2] *) + reg1 := reg1 MOD 8; + reg2 := reg2 MOD 8; + OutByte2(04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2)); + drop; + cmd := cmd.next(COMMAND) ELSE - n := -1 - END; + UnOp(reg1); - IF a = 1 THEN - - ELSIF a = -1 THEN - neg(reg1) - ELSIF a = 0 THEN - xor(reg1, reg1) - ELSE - IF n > 0 THEN - IF a < 0 THEN - neg(reg1) - END; - shiftrc(shl, reg1, n) + a := param2; + IF a > 1 THEN + n := UTILS.Log2(a) + ELSIF a < -1 THEN + n := UTILS.Log2(-a) ELSE - // imul reg1, a - Rex(reg1, reg1); - OutByte2(69H + short(a), 0C0H + (reg1 MOD 8) * 9); - OutIntByte(a) + n := -1 + END; + + IF a = 1 THEN + + ELSIF a = -1 THEN + neg(reg1) + ELSIF a = 0 THEN + xor(reg1, reg1) + ELSE + IF n > 0 THEN + IF a < 0 THEN + neg(reg1) + END; + shiftrc(shl, reg1, n) + ELSE + IF isLong(a) THEN + reg2 := GetAnyReg(); + movabs(reg2, a); + ASSERT(reg1 # reg2); + oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *) + drop + ELSE + (* imul reg1, a *) + Rex(reg1, reg1); + OutByte2(69H + short(a), 0C0H + (reg1 MOD 8) * 9); + OutIntByte(a) + END + END END END @@ -1990,24 +1879,30 @@ BEGIN |IL.opENDSW: |IL.opCASEL: - cmprc(rax, param1); - jcc(jl, param2) - - |IL.opCASER: - cmprc(rax, param1); - jcc(jg, param2) - - |IL.opCASELR: + GetRegA; cmprc(rax, param1); jcc(jl, param2); - jcc(jg, cmd.param3) + drop + + |IL.opCASER: + GetRegA; + cmprc(rax, param1); + jcc(jg, param2); + drop + + |IL.opCASELR: + GetRegA; + cmprc(rax, param1); + jcc(jl, param2); + jcc(jg, cmd.param3); + drop |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: BinOp(reg1, reg2); xchg(reg2, rcx); Rex(reg1, 0); OutByte(0D3H); - X86.shift(opcode, reg1 MOD 8); // shift reg1, cl + X86.shift(opcode, reg1 MOD 8); (* shift reg1, cl *) xchg(reg2, rcx); drop @@ -2018,7 +1913,7 @@ BEGIN xchg(reg1, rcx); Rex(reg2, 0); OutByte(0D3H); - X86.shift(opcode, reg2 MOD 8); // shift reg2, cl + X86.shift(opcode, reg2 MOD 8); (* shift reg2, cl *) xchg(reg1, rcx); drop; drop; @@ -2038,8 +1933,8 @@ BEGIN END; drop; drop; - _movrm(reg1, reg1, 0, param2 * 8, FALSE); - _movrm(reg1, reg2, 0, param2 * 8, TRUE) + X86._movrm(reg1, reg1, 0, param2 * 8, FALSE); + X86._movrm(reg1, reg2, 0, param2 * 8, TRUE) |IL.opCHKBYTE: BinOp(reg1, reg2); @@ -2055,14 +1950,11 @@ BEGIN BinOp(reg1, reg2); IF param2 # -1 THEN cmprr(reg2, reg1); - mov(reg1, reg2); - drop; - jcc(jb, param1) - ELSE - INCL(R.regs, reg1); - DEC(R.top); - R.stk[R.top] := reg2 - END + jcc(jb, param1); + END; + INCL(R.regs, reg1); + DEC(R.top); + R.stk[R.top] := reg2 |IL.opLENGTH: PushAll(2); @@ -2127,7 +2019,7 @@ BEGIN IF reg1 >= 8 THEN OutByte(41H) END; - OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1 MOD 8, param2 MOD 256); // add/sub byte[reg1], param2 MOD 256 + OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1 MOD 8, param2 MOD 256); (* add/sub byte[reg1], param2 MOD 256 *) drop |IL.opINCB, IL.opDECB: @@ -2135,7 +2027,7 @@ BEGIN IF (reg1 >= 8) OR (reg2 >= 8) THEN OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8)) END; - OutByte2(28H * ORD(opcode = IL.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); // add/sub byte[reg2], reg1_8 + OutByte2(28H * ORD(opcode = IL.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); (* add/sub byte[reg2], reg1_8 *) drop; drop @@ -2149,7 +2041,7 @@ BEGIN IF reg1 >= 8 THEN OutByte(41H) END; - OutByte2(8FH, reg1 MOD 8); // pop qword[reg1] + OutByte2(8FH, reg1 MOD 8); (* pop qword[reg1] *) drop |IL.opCLEANUP: @@ -2181,7 +2073,7 @@ BEGIN drop; NewNumber(UTILS.splitf(float, a, b)) - |IL.opSAVEF: + |IL.opSAVEF, IL.opSAVEFI: UnOp(reg1); movsdmr(reg1, 0, xmm); DEC(xmm); @@ -2216,35 +2108,35 @@ BEGIN |IL.opUMINF: reg1 := GetAnyReg(); lea(reg1, Numbers_Offs, sDATA); - OutByte3(66H, 40H + reg1 DIV 8 + (xmm DIV 8) * 4, 0FH); // xorpd xmm, xmmword[reg1] + 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 |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] + 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 |IL.opFLT: UnOp(reg1); INC(xmm); - OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); // cvtsi2sd xmm, reg1 + OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); (* cvtsi2sd xmm, reg1 *) OutByte2(2AH, 0C0H + (xmm MOD 8) * 8 + reg1 MOD 8); drop |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]; - OutByte3(081H, 024H, 024H); OutByte2(0FFH, 09FH); OutByte2(0FFH, 0FFH); // and dword[rsp],11111111111111111001111111111111b; - OutByte3(081H, 00CH, 024H); OutByte2(000H, 020H); OutByte2(000H, 000H); // or dword[rsp],00000000000000000010000000000000b; - OutByte2(00FH, 0AEH); OutByte2(014H, 024H); // ldmxcsr dword[rsp]; - OutByte(0F2H); Rex(xmm, reg1); OutByte(0FH); // cvtsd2si reg1, xmm + OutByte3(00FH, 0AEH, 05CH); OutByte2(024H, 004H); (* stmxcsr dword[rsp+4]; *) + OutByte2(00FH, 0AEH); OutByte2(01CH, 024H); (* stmxcsr dword[rsp]; *) + OutByte3(081H, 024H, 024H); OutByte2(0FFH, 09FH); OutByte2(0FFH, 0FFH); (* and dword[rsp],11111111111111111001111111111111b; *) + OutByte3(081H, 00CH, 024H); OutByte2(000H, 020H); OutByte2(000H, 000H); (* or dword[rsp],00000000000000000010000000000000b; *) + OutByte2(00FH, 0AEH); OutByte2(014H, 024H); (* ldmxcsr dword[rsp]; *) + OutByte(0F2H); Rex(xmm, reg1); OutByte(0FH); (* cvtsd2si reg1, xmm *) OutByte2(2DH, 0C0H + xmm MOD 8 + (reg1 MOD 8) * 8); - OutByte3(00FH, 0AEH, 054H); OutByte2(024H, 004H); // ldmxcsr dword[rsp+4]; + OutByte3(00FH, 0AEH, 054H); OutByte2(024H, 004H); (* ldmxcsr dword[rsp+4]; *) addrc(rsp, 8); DEC(xmm) @@ -2278,7 +2170,7 @@ BEGIN movrm(reg2, reg2, 0); push(reg1); - lea(reg1, Numbers_Offs + 40, sDATA); // {0..51, 63} + lea(reg1, Numbers_Offs + 40, sDATA); (* {0..51, 63} *) movrm(reg1, reg1, 0); and(reg2, reg1); pop(reg1); @@ -2299,7 +2191,7 @@ BEGIN IF ~regVar THEN reg2 := GetAnyReg(); Rex(0, reg2); - OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); // lea reg2, qword[rbp+n] + OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); (* lea reg2, qword[rbp+n] *) OutIntByte(n) END ELSE @@ -2324,14 +2216,14 @@ BEGIN movrm(reg1, reg2, 0); push(reg2); - lea(reg2, Numbers_Offs + 48, sDATA); // {52..61} + lea(reg2, Numbers_Offs + 48, sDATA); (* {52..61} *) movrm(reg2, reg2, 0); or(reg1, reg2); pop(reg2); Rex(reg1, 0); OutByte2(0FH, 0BAH); - OutByte2(0F0H + reg1 MOD 8, 3EH); // btr reg1, 62 + OutByte2(0F0H + reg1 MOD 8, 3EH); (* btr reg1, 62 *) movmr(reg2, 0, reg1); drop; drop @@ -2340,11 +2232,11 @@ BEGIN pushDA(stroffs + param2) |IL.opVADR_PARAM: - pushm(rbp, param2 * 8) + X86.pushm(rbp, param2 * 8) |IL.opLOAD64_PARAM: UnOp(reg1); - pushm(reg1, 0); + X86.pushm(reg1, 0); drop |IL.opLLOAD64_PARAM: @@ -2352,7 +2244,7 @@ BEGIN IF reg1 # -1 THEN push(reg1) ELSE - pushm(rbp, param2 * 8) + X86.pushm(rbp, param2 * 8) END |IL.opGLOAD64_PARAM: @@ -2405,7 +2297,7 @@ BEGIN movmr(rbp, n, reg2); drop ELSE - OutByte3(48H, 0C7H, 45H + long(n)); // mov qword[rbp+n],param2 + OutByte3(48H, 0C7H, 45H + long(n)); (* mov qword[rbp+n], param2 *) OutIntByte(n); OutInt(param2) END @@ -2424,7 +2316,7 @@ BEGIN reg2 := GetAnyReg(); lea(reg2, param1, sBSS); Rex(reg2, 0); - OutByte2(0C7H, reg2 MOD 8); // mov qword[reg2], param2 + OutByte2(0C7H, reg2 MOD 8); (* mov qword[reg2], param2 *) OutInt(param2); drop END @@ -2450,7 +2342,7 @@ BEGIN n := param1 * 8; Rex(0, reg2); OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8); - OutIntByte(n) // add qword[rbp+n],reg2 + OutIntByte(n) (* add qword[rbp+n], reg2 *) END; drop ELSIF ABS(param2) = 1 THEN @@ -2462,7 +2354,7 @@ BEGIN END ELSE n := param1 * 8; - OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); // inc/dec qword[rbp+n] + OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec qword[rbp+n] *) OutIntByte(n) END ELSE @@ -2472,7 +2364,7 @@ BEGIN n := param1 * 8; OutByte3(48H, 81H + short(param2), 45H + long(n)); OutIntByte(n); - OutIntByte(param2) // add qword[rbp+n],param2 + OutIntByte(param2) (* add qword[rbp+n], param2 *) END END @@ -2490,7 +2382,7 @@ BEGIN n := param1 * 8; OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB)); OutIntByte(n); - OutByte(param2) // add/sub byte[rbp+n],param2 + OutByte(param2) (* add/sub byte[rbp+n], param2 *) END |IL.opLADR_INC, IL.opLADR_DEC: @@ -2506,7 +2398,7 @@ BEGIN n := param2 * 8; Rex(0, reg1); OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8); - OutIntByte(n) // add/sub qword[rbp+n],reg1 + OutIntByte(n) (* add/sub qword[rbp+n], reg1 *) END; drop @@ -2526,7 +2418,7 @@ BEGIN OutByte(44H) END; OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8)); - OutIntByte(n) // add/sub byte[rbp+n], reg1_8 + OutIntByte(n) (* add/sub byte[rbp+n], reg1_8 *) END; drop @@ -2535,27 +2427,27 @@ BEGIN cmprc(reg1, 64); reg2 := GetVarReg(param2); IF reg2 # -1 THEN - OutByte2(73H, 4); // jnb L - oprr2(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), reg2, reg1) // bts/btr reg2, reg1 + OutByte2(73H, 4); (* jnb L *) + 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 + OutByte2(73H, 5 + 3 * ORD(~isByte(n))); (* jnb L *) Rex(0, reg1); OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8)); - OutIntByte(n) // bts/btr qword[rbp+n], reg1 + OutIntByte(n) (* bts/btr qword[rbp+n], reg1 *) END; - // L: + (* L: *) drop |IL.opLADR_INCLC, IL.opLADR_EXCLC: reg1 := GetVarReg(param1); IF reg1 # -1 THEN Rex(reg1, 0); - OutByte3(0FH, 0BAH, 0E8H); // bts/btr reg1, param2 + OutByte3(0FH, 0BAH, 0E8H); (* bts/btr reg1, 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 + OutByte3(48H, 0FH, 0BAH); (* bts/btr qword[rbp+n], param2 *) OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); OutIntByte(n); OutByte(param2) @@ -2586,7 +2478,7 @@ BEGIN entry := NewLabel(); X86.SetLabel(entry); - IF target = mConst.Target_iDLL64 THEN + IF target = TARGETS.Win64DLL THEN dllret := NewLabel(); push(r8); push(rdx); @@ -2596,7 +2488,7 @@ BEGIN jcc(je, dllret) END; - IF target = mConst.Target_iELF64 THEN + IF target = TARGETS.Linux64 THEN push(rsp) ELSE pushc(0) @@ -2604,12 +2496,12 @@ BEGIN lea(rax, entry, sCODE); push(rax); - pushDA(0); //TYPES + pushDA(0); (* TYPES *) pushc(tcount); - pushDA(ModName_Offs); //MODNAME + pushDA(ModName_Offs); (* MODNAME *) CallRTL(IL._init); - IF target IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iELF64} THEN + IF target IN {TARGETS.Win64C, TARGETS.Win64GUI, TARGETS.Linux64} THEN L := NewLabel(); pushc(0); push(rsp); @@ -2619,7 +2511,9 @@ BEGIN pop(rax); test(rax); jcc(je, L); + GetRegA; addrc(rax, 1024 * 1024 * stack_size - 8); + drop; mov(rsp, rax); X86.SetLabel(L) END @@ -2655,15 +2549,15 @@ VAR BEGIN - IF target = mConst.Target_iDLL64 THEN + IF target = TARGETS.Win64DLL THEN X86.SetLabel(dllret); - OutByte(0C3H) // ret - ELSIF target = mConst.Target_iELFSO64 THEN + X86.ret + ELSIF target = TARGETS.Linux64SO THEN sofinit := NewLabel(); - OutByte(0C3H); // ret + X86.ret; X86.SetLabel(sofinit); CallRTL(IL._sofinit); - OutByte(0C3H) // ret + X86.ret ELSE pushc(0); CallRTL(IL._exit) @@ -2724,8 +2618,8 @@ PROCEDURE rsave (reg, offs, size: INTEGER); BEGIN offs := offs * 8; CASE size OF - |1: movmr8(rbp, offs, reg) - |2: movmr16(rbp, offs, reg) + |1: X86.movmr8(rbp, offs, reg) + |2: X86.movmr16(rbp, offs, reg) |4: movmr32(rbp, offs, reg) |8: movmr(rbp, offs, reg) END @@ -2778,12 +2672,12 @@ BEGIN epilog(modname, target); BIN.fixup(prog); - IF target IN {mConst.Target_iConsole64, mConst.Target_iGUI64, mConst.Target_iDLL64} THEN - PE32.write(prog, outname, 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) + IF TARGETS.OS = TARGETS.osWIN64 THEN + PE32.write(prog, outname, target = TARGETS.Win64C, target = TARGETS.Win64DLL, TRUE) + ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN + ELF.write(prog, outname, sofinit, target = TARGETS.Linux64SO, TRUE) END END CodeGen; -END AMD64. +END AMD64. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/ARITH.ob07 b/programs/develop/oberon07/Source/ARITH.ob07 index 452e2b7b8c..2b10af2e1f 100644 --- a/programs/develop/oberon07/Source/ARITH.ob07 +++ b/programs/develop/oberon07/Source/ARITH.ob07 @@ -1,7 +1,7 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -75,15 +75,20 @@ BEGIN END Float; +PROCEDURE range* (i: VALUE; a, b: INTEGER): BOOLEAN; + RETURN (a <= i.int) & (i.int <= b) +END range; + + PROCEDURE check* (v: VALUE): BOOLEAN; VAR res: BOOLEAN; BEGIN CASE v.typ OF - |tINTEGER: res := (UTILS.target.minInt <= v.int) & (v.int <= UTILS.target.maxInt) - |tCHAR: res := (0 <= v.int) & (v.int <= 255) - |tWCHAR: res := (0 <= v.int) & (v.int <= 65535) + |tINTEGER: res := range(v, UTILS.target.minInt, UTILS.target.maxInt) + |tCHAR: res := range(v, 0, 255) + |tWCHAR: res := range(v, 0, 65535) |tREAL: res := (-UTILS.target.maxReal <= v.float) & (v.float <= UTILS.target.maxReal) END @@ -196,61 +201,15 @@ END hconv; PROCEDURE opFloat2 (VAR a: REAL; b: REAL; op: CHAR): BOOLEAN; -VAR - max: REAL; - res: BOOLEAN; - BEGIN - max := UTILS.maxreal; - CASE op OF - |"+": - IF (a < 0.0) & (b < 0.0) THEN - res := a > -max - b - ELSIF (a > 0.0) & (b > 0.0) THEN - res := a < max - b - ELSE - res := TRUE - END; - IF res THEN - a := a + b - END - - |"-": - IF (a < 0.0) & (b > 0.0) THEN - res := a > b - max - ELSIF (a > 0.0) & (b < 0.0) THEN - res := a < b + max - ELSE - res := TRUE - END; - IF res THEN - a := a - b - END - - |"*": - IF (ABS(a) > 1.0) & (ABS(b) > 1.0) THEN - res := ABS(a) < max / ABS(b) - ELSE - res := TRUE - END; - IF res THEN - a := a * b - END - - |"/": - IF ABS(b) < 1.0 THEN - res := ABS(a) < max * ABS(b) - ELSE - res := TRUE - END; - IF res THEN - a := a / b - END - + |"+": a := a + b + |"-": a := a - b + |"*": a := a * b + |"/": a := a / b END - RETURN res + RETURN (-UTILS.maxreal <= a) & (a <= UTILS.maxreal) (* +inf > UTILS.maxreal *) END opFloat2; @@ -407,13 +366,8 @@ VAR BEGIN ASSERT(x > 0); - n := 0; - WHILE ~ODD(x) DO - x := x DIV 2; - INC(n) - END; - - IF x # 1 THEN + n := UTILS.Log2(x); + IF n = -1 THEN n := 255 END @@ -521,7 +475,7 @@ BEGIN |"-": success := subInt(a.int, b.int) |"*": success := mulInt(a.int, b.int) |"/": success := FALSE - |"D": IF (b.int # -1) OR (a.int # UTILS.minint) THEN a.int := a.int DIV b.int ELSE success := FALSE END + |"D": a.int := a.int DIV b.int |"M": a.int := a.int MOD b.int |"L": a.int := _LSL(a.int, b.int) |"A": a.int := _ASR(a.int, b.int) @@ -670,11 +624,6 @@ BEGIN END opBoolean; -PROCEDURE range* (i: VALUE; a, b: INTEGER): BOOLEAN; - RETURN (a <= i.int) & (i.int <= b) -END range; - - PROCEDURE less (v, v2: VALUE; VAR error: INTEGER): BOOLEAN; VAR res: BOOLEAN; @@ -834,4 +783,4 @@ END init; BEGIN init -END ARITH. +END ARITH. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/AVLTREES.ob07 b/programs/develop/oberon07/Source/AVLTREES.ob07 index bb0cf0bfb3..64b1990b63 100644 --- a/programs/develop/oberon07/Source/AVLTREES.ob07 +++ b/programs/develop/oberon07/Source/AVLTREES.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -194,4 +194,4 @@ END destroy; BEGIN nodes := C.create() -END AVLTREES. +END AVLTREES. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/BIN.ob07 b/programs/develop/oberon07/Source/BIN.ob07 index 554624c4d8..14c94bc8b4 100644 --- a/programs/develop/oberon07/Source/BIN.ob07 +++ b/programs/develop/oberon07/Source/BIN.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -12,17 +12,12 @@ IMPORT LISTS, CHL := CHUNKLISTS, ARITH, UTILS; CONST - RCODE* = 1; - RDATA* = 2; - RBSS* = 3; - RIMP* = 4; + RCODE* = 0; PICCODE* = RCODE + 1; + RDATA* = 2; PICDATA* = RDATA + 1; + RBSS* = 4; PICBSS* = RBSS + 1; + RIMP* = 6; PICIMP* = RIMP + 1; - PICCODE* = 5; - PICDATA* = 6; - PICBSS* = 7; - PICIMP* = 8; - - IMPTAB* = 9; + IMPTAB* = 8; TYPE @@ -211,6 +206,13 @@ BEGIN END PutCode32LE; +PROCEDURE PutCode16LE* (program: PROGRAM; x: INTEGER); +BEGIN + CHL.PushByte(program.code, UTILS.Byte(x, 0)); + CHL.PushByte(program.code, UTILS.Byte(x, 1)) +END PutCode16LE; + + PROCEDURE SetLabel* (program: PROGRAM; label, offset: INTEGER); BEGIN CHL.SetInt(program.labels, label, offset) @@ -380,4 +382,4 @@ BEGIN END InitArray; -END BIN. +END BIN. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/CHUNKLISTS.ob07 b/programs/develop/oberon07/Source/CHUNKLISTS.ob07 index d020a3a71b..03b505c2f9 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-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) @@ -12,8 +12,8 @@ IMPORT LISTS, WR := WRITER; CONST - LENOFBYTECHUNK = 64000; - LENOFINTCHUNK = 16000; + LENOFBYTECHUNK = 65536; + LENOFINTCHUNK = 16384; TYPE @@ -283,4 +283,4 @@ PROCEDURE Length* (list: ANYLIST): INTEGER; END Length; -END CHUNKLISTS. +END CHUNKLISTS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/COLLECTIONS.ob07 b/programs/develop/oberon07/Source/COLLECTIONS.ob07 index 21b97ea336..f9b713a0b9 100644 --- a/programs/develop/oberon07/Source/COLLECTIONS.ob07 +++ b/programs/develop/oberon07/Source/COLLECTIONS.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -56,4 +56,4 @@ BEGIN END create; -END COLLECTIONS. +END COLLECTIONS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/CONSOLE.ob07 b/programs/develop/oberon07/Source/CONSOLE.ob07 index 372b190da4..b5916839c7 100644 --- a/programs/develop/oberon07/Source/CONSOLE.ob07 +++ b/programs/develop/oberon07/Source/CONSOLE.ob07 @@ -1,4 +1,4 @@ -(* +(* BSD 2-Clause License Copyright (c) 2018-2019, Anton Krotov @@ -79,4 +79,4 @@ BEGIN END Int2Ln; -END CONSOLE. +END CONSOLE. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/CONSTANTS.ob07 b/programs/develop/oberon07/Source/CONSTANTS.ob07 deleted file mode 100644 index f7006b5ab3..0000000000 --- a/programs/develop/oberon07/Source/CONSTANTS.ob07 +++ /dev/null @@ -1,49 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2019, Anton Krotov - All rights reserved. -*) - -MODULE CONSTANTS; - -CONST - - vMajor* = 1; - vMinor* = 13; - - FILE_EXT* = ".ob07"; - RTL_NAME* = "RTL"; - - MAX_GLOBAL_SIZE* = 1600000000; - - Target_iConsole* = 1; - Target_iGUI* = 2; - Target_iDLL* = 3; - Target_iKolibri* = 4; - Target_iObject* = 5; - Target_iConsole64* = 6; - Target_iGUI64* = 7; - Target_iDLL64* = 8; - Target_iELF32* = 9; - Target_iELFSO32* = 10; - Target_iELF64* = 11; - Target_iELFSO64* = 12; - Target_iMSP430* = 13; - - Target_sConsole* = "console"; - Target_sGUI* = "gui"; - Target_sDLL* = "dll"; - Target_sKolibri* = "kos"; - Target_sObject* = "obj"; - Target_sConsole64* = "console64"; - Target_sGUI64* = "gui64"; - Target_sDLL64* = "dll64"; - Target_sELF32* = "elfexe"; - Target_sELFSO32* = "elfso"; - Target_sELF64* = "elfexe64"; - Target_sELFSO64* = "elfso64"; - Target_sMSP430* = "msp430"; - - -END CONSTANTS. diff --git a/programs/develop/oberon07/Source/Compiler.ob07 b/programs/develop/oberon07/Source/Compiler.ob07 index ed4945902e..32b1aebac2 100644 --- a/programs/develop/oberon07/Source/Compiler.ob07 +++ b/programs/develop/oberon07/Source/Compiler.ob07 @@ -1,52 +1,14 @@ -(* +(* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2020, Anton Krotov All rights reserved. *) MODULE Compiler; -IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, PROG, C := CONSOLE, ERRORS, STRINGS, mConst := CONSTANTS, WRITER, MSP430; - - -PROCEDURE Target (s: ARRAY OF CHAR): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF s = mConst.Target_sConsole THEN - res := mConst.Target_iConsole - ELSIF s = mConst.Target_sGUI THEN - res := mConst.Target_iGUI - ELSIF s = mConst.Target_sDLL THEN - res := mConst.Target_iDLL - ELSIF s = mConst.Target_sKolibri THEN - res := mConst.Target_iKolibri - ELSIF s = mConst.Target_sObject THEN - res := mConst.Target_iObject - ELSIF s = mConst.Target_sConsole64 THEN - res := mConst.Target_iConsole64 - ELSIF s = mConst.Target_sGUI64 THEN - res := mConst.Target_iGUI64 - ELSIF s = mConst.Target_sDLL64 THEN - 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 - - RETURN res -END Target; +IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, PROG, C := CONSOLE, + ERRORS, STRINGS, WRITER, MSP430, THUMB, TARGETS; PROCEDURE keys (VAR options: PROG.OPTIONS; VAR out: PARS.PATH); @@ -168,6 +130,22 @@ BEGIN END keys; +PROCEDURE OutTargetItem (target: INTEGER; text: ARRAY OF CHAR); +VAR + width: INTEGER; + +BEGIN + width := 15; + width := width - LENGTH(TARGETS.Targets[target].ComLinePar) - 4; + C.String(" '"); C.String(TARGETS.Targets[target].ComLinePar); C.String("'"); + WHILE width > 0 DO + C.String(20X); + DEC(width) + END; + C.StringLn(text) +END OutTargetItem; + + PROCEDURE main; VAR path: PARS.PATH; @@ -180,7 +158,6 @@ VAR param: PARS.PATH; temp: PARS.PATH; target: INTEGER; - bit_depth: INTEGER; time: INTEGER; options: PROG.OPTIONS; @@ -196,32 +173,46 @@ BEGIN UTILS.GetArg(1, inname); C.Ln; - C.String("Akron Oberon Compiler v"); C.Int(mConst.vMajor); C.String("."); C.Int2(mConst.vMinor); + C.String("Akron Oberon Compiler v"); C.Int(UTILS.vMajor); C.String("."); C.Int2(UTILS.vMinor); C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit)"); - C.StringLn("Copyright (c) 2018-2019, Anton Krotov"); + C.StringLn("Copyright (c) 2018-2020, Anton Krotov"); IF inname = "" THEN C.Ln; C.StringLn("Usage: Compiler