2
0

CPC486.txt 80 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334
  1. MODULE LindevCPC486;
  2. (* THIS IS TEXT COPY OF CPC486.odc *)
  3. (* DO NOT EDIT *)
  4. IMPORT SYSTEM, DevCPM := LindevCPM, DevCPT := LindevCPT, DevCPE := LindevCPE,
  5. DevCPL486 := LindevCPL486;
  6. CONST
  7. initializeAll = FALSE; (* initialize all local variable to zero *)
  8. initializeOut = FALSE; (* initialize all OUT parameters to zero *)
  9. initializeDyn = FALSE; (* initialize all open array OUT parameters to zero *)
  10. initializeStr = FALSE; (* initialize rest of string value parameters to zero *)
  11. FpuControlRegister = 33EH; (* value for fpu control register initialization *)
  12. (* structure forms *)
  13. Undef = 0; Byte = 1; Bool = 2; Char8 = 3; Int8 = 4; Int16 = 5; Int32 = 6;
  14. Real32 = 7; Real64 = 8; Set = 9; String8 = 10; NilTyp = 11; NoTyp = 12;
  15. Pointer = 13; ProcTyp = 14; Comp = 15;
  16. Char16 = 16; String16 = 17; Int64 = 18; Guid = 23;
  17. VString16to8 = 29; VString8 = 30; VString16 = 31;
  18. intSet = {Int8..Int32, Int64}; realSet = {Real32, Real64};
  19. (* composite structure forms *)
  20. Basic = 1; Array = 2; DynArr = 3; Record = 4;
  21. (* item base modes (=object modes) *)
  22. Var = 1; VarPar = 2; Con = 3; Fld = 4; Typ = 5; LProc = 6; XProc = 7; CProc = 9; IProc = 10; TProc = 13;
  23. (* item modes for i386 *)
  24. Ind = 14; Abs = 15; Stk = 16; Cond = 17; Reg = 18; DInd = 19;
  25. (* symbol values and ops *)
  26. times = 1; slash = 2; div = 3; mod = 4;
  27. and = 5; plus = 6; minus = 7; or = 8; eql = 9;
  28. neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
  29. in = 15; is = 16; ash = 17; msk = 18; len = 19;
  30. conv = 20; abs = 21; cap = 22; odd = 23; not = 33;
  31. adr = 24; cc = 25; bit = 26; lsh = 27; rot = 28; val = 29;
  32. getrfn = 26; putrfn = 27;
  33. min = 34; max = 35; typ = 36;
  34. (* procedure flags (conval.setval) *)
  35. hasBody = 1; isRedef = 2; slNeeded = 3; imVar = 4; isGuarded = 30; isCallback = 31;
  36. (* attribute flags (attr.adr, struct.attribute, proc.conval.setval) *)
  37. newAttr = 16; absAttr = 17; limAttr = 18; empAttr = 19; extAttr = 20;
  38. false = 0; true = 1; nil = 0;
  39. (* registers *)
  40. AX = 0; CX = 1; DX = 2; BX = 3; SP = 4; BP = 5; SI = 6; DI = 7; AH = 4; CH = 5; DH = 6; BH = 7;
  41. stk = 31; mem = 30; con = 29; float = 28; high = 27; short = 26; deref = 25; wreg = {AX, BX, CX, DX, SI, DI};
  42. (* GenShiftOp *)
  43. ROL = 0; ROR = 8H; SHL = 20H; SHR = 28H; SAR = 38H;
  44. (* GenBitOp *)
  45. BT = 20H; BTS = 28H; BTR = 30H;
  46. (* GenFDOp *)
  47. FADD = 0; FMUL = 8H; FCOM = 10H; FCOMP = 18H; FSUB = 20H; FSUBR = 28H; FDIV = 30H; FDIVR = 38H;
  48. (* GenFMOp *)
  49. FABS = 1E1H; FCHS = 1E0H; FTST = 1E4H; FSTSW = 7E0H; FUCOM = 2E9H;
  50. (* GenCode *)
  51. SAHF = 9EH; WAIT = 9BH;
  52. (* condition codes *)
  53. ccB = 2; ccAE = 3; ccBE = 6; ccA = 7; (* unsigned *)
  54. ccL = 12; ccGE = 13; ccLE = 14; ccG = 15; (* signed *)
  55. ccE = 4; ccNE = 5; ccS = 8; ccNS = 9; ccO = 0; ccNO = 1;
  56. ccAlways = -1; ccNever = -2; ccCall = -3;
  57. (* sysflag *)
  58. untagged = 1; callback = 2; noAlign = 3; union = 7;
  59. interface = 10; ccall = -10; guarded = 10; noframe = 16;
  60. nilBit = 1; enumBits = 8; new = 1; iid = 2;
  61. stackArray = 120;
  62. (* system trap numbers *)
  63. withTrap = -1; caseTrap = -2; funcTrap = -3; typTrap = -4;
  64. recTrap = -5; ranTrap = -6; inxTrap = -7; copyTrap = -8;
  65. (* module visibility of objects *)
  66. internal = 0; external = 1; externalR = 2; inPar = 3; outPar = 4;
  67. (* pointer init limits *)
  68. MaxPtrs = 10; MaxPush = 4;
  69. Tag0Offset = 12;
  70. Mth0Offset = -4;
  71. ArrDOffs = 8;
  72. numPreIntProc = 2;
  73. stackAllocLimit = 2048;
  74. VAR
  75. imLevel*: ARRAY 64 OF BYTE;
  76. intHandler*: DevCPT.Object;
  77. inxchk, ovflchk, ranchk, typchk, ptrinit, hints: BOOLEAN;
  78. WReg, BReg, AllReg: SET; FReg: INTEGER;
  79. ptrTab: ARRAY MaxPtrs OF INTEGER;
  80. stkAllocLbl: DevCPL486.Label;
  81. procedureUsesFpu: BOOLEAN;
  82. PROCEDURE Init* (opt: SET);
  83. CONST chk = 0; achk = 1; hint = 29;
  84. BEGIN
  85. inxchk := chk IN opt; ovflchk := achk IN opt; ranchk := achk IN opt; typchk := chk IN opt; ptrinit := chk IN opt;
  86. hints := hint IN opt;
  87. stkAllocLbl := DevCPL486.NewLbl
  88. END Init;
  89. PROCEDURE Reversed (cond: BYTE): BYTE; (* reversed condition *)
  90. BEGIN
  91. IF cond = lss THEN RETURN gtr
  92. ELSIF cond = gtr THEN RETURN lss
  93. ELSIF cond = leq THEN RETURN geq
  94. ELSIF cond = geq THEN RETURN leq
  95. ELSE RETURN cond
  96. END
  97. END Reversed;
  98. PROCEDURE Inverted (cc: INTEGER): INTEGER; (* inverted sense of condition code *)
  99. BEGIN
  100. IF ODD(cc) THEN RETURN cc-1 ELSE RETURN cc+1 END
  101. END Inverted;
  102. PROCEDURE setCC* (VAR x: DevCPL486.Item; rel: BYTE; reversed, signed: BOOLEAN);
  103. BEGIN
  104. IF reversed THEN rel := Reversed(rel) END;
  105. CASE rel OF
  106. false: x.offset := ccNever
  107. | true: x.offset := ccAlways
  108. | eql: x.offset := ccE
  109. | neq: x.offset := ccNE
  110. | lss: IF signed THEN x.offset := ccL ELSE x.offset := ccB END
  111. | leq: IF signed THEN x.offset := ccLE ELSE x.offset := ccBE END
  112. | gtr: IF signed THEN x.offset := ccG ELSE x.offset := ccA END
  113. | geq: IF signed THEN x.offset := ccGE ELSE x.offset := ccAE END
  114. END;
  115. x.mode := Cond; x.form := Bool; x.reg := 0;
  116. IF reversed THEN x.reg := 1 END;
  117. IF signed THEN INC(x.reg, 2) END
  118. END setCC;
  119. PROCEDURE StackAlloc*; (* pre: len = CX bytes; post: len = CX words *)
  120. BEGIN
  121. DevCPL486.GenJump(ccCall, stkAllocLbl, FALSE)
  122. END StackAlloc;
  123. PROCEDURE^ CheckAv* (reg: INTEGER);
  124. PROCEDURE AdjustStack (val: INTEGER);
  125. VAR c, sp: DevCPL486.Item;
  126. BEGIN
  127. IF val < -stackAllocLimit THEN
  128. CheckAv(CX);
  129. DevCPL486.MakeConst(c, -val, Int32); DevCPL486.MakeReg(sp, CX, Int32); DevCPL486.GenMove(c, sp);
  130. StackAlloc
  131. ELSIF val # 0 THEN
  132. DevCPL486.MakeConst(c, val, Int32); DevCPL486.MakeReg(sp, SP, Int32); DevCPL486.GenAdd(c, sp, FALSE)
  133. END
  134. END AdjustStack;
  135. PROCEDURE DecStack (form: INTEGER);
  136. BEGIN
  137. IF form IN {Real64, Int64} THEN AdjustStack(-8) ELSE AdjustStack(-4) END
  138. END DecStack;
  139. PROCEDURE IncStack (form: INTEGER);
  140. BEGIN
  141. IF form IN {Real64, Int64} THEN AdjustStack(8) ELSE AdjustStack(4) END
  142. END IncStack;
  143. (*-----------------register handling------------------*)
  144. PROCEDURE SetReg* (reg: SET);
  145. BEGIN
  146. AllReg := reg; WReg := reg; BReg := reg * {0..3} + SYSTEM.LSH(reg * {0..3}, 4); FReg := 8
  147. END SetReg;
  148. PROCEDURE CheckReg*;
  149. VAR reg: SET;
  150. BEGIN
  151. reg := AllReg - WReg;
  152. IF reg # {} THEN
  153. DevCPM.err(-777); (* register not released *)
  154. IF AX IN reg THEN DevCPM.errorMes := DevCPM.errorMes + " AX" END;
  155. IF BX IN reg THEN DevCPM.errorMes := DevCPM.errorMes +" BX" END;
  156. IF CX IN reg THEN DevCPM.errorMes := DevCPM.errorMes + " CX" END;
  157. IF DX IN reg THEN DevCPM.errorMes := DevCPM.errorMes +" DX" END;
  158. IF SI IN reg THEN DevCPM.errorMes := DevCPM.errorMes + " SI" END;
  159. IF DI IN reg THEN DevCPM.errorMes := DevCPM.errorMes + " DI" END;
  160. WReg := AllReg; BReg := AllReg * {0..3} + SYSTEM.LSH(AllReg * {0..3}, 4)
  161. END;
  162. IF FReg < 8 THEN DevCPM.err(-778); FReg := 8 (* float register not released *)
  163. ELSIF FReg > 8 THEN DevCPM.err(-779); FReg := 8
  164. END
  165. END CheckReg;
  166. PROCEDURE CheckAv* (reg: INTEGER);
  167. BEGIN
  168. ASSERT(reg IN WReg)
  169. END CheckAv;
  170. PROCEDURE GetReg (VAR x: DevCPL486.Item; f: BYTE; hint, stop: SET);
  171. VAR n: INTEGER; s, s1: SET;
  172. BEGIN
  173. CASE f OF
  174. | Byte, Bool, Char8, Int8:
  175. s := BReg * {0..3} - stop;
  176. IF (high IN stop) OR (high IN hint) & (s - hint # {}) THEN n := 0;
  177. IF s = {} THEN DevCPM.err(215); WReg := wreg; BReg := {0..7}; s := {0..7} END;
  178. IF s - hint # {} THEN s := s - hint END;
  179. WHILE ~(n IN s) DO INC(n) END
  180. ELSE
  181. s := BReg - (stop * {0..3}) - SYSTEM.LSH(stop * {0..3}, 4); n := 0;
  182. IF s = {} THEN DevCPM.err(215); WReg := wreg; BReg := {0..7}; s := {0..7} END;
  183. s1 := s - (hint * {0..3}) - SYSTEM.LSH(hint * {0..3}, 4);
  184. IF s1 # {} THEN s := s1 END;
  185. WHILE ~(n IN s) & ~(n + 4 IN s) DO INC(n) END;
  186. IF ~(n IN s) THEN n := n + 4 END
  187. END;
  188. EXCL(BReg, n); EXCL(WReg, n MOD 4)
  189. | Int16, Int32, Set, String8, NilTyp, Pointer, ProcTyp, Comp, Char16, String16:
  190. s := WReg - stop;
  191. IF high IN stop THEN s := s * {0..3} END;
  192. IF s = {} THEN DevCPM.err(215); WReg := wreg; BReg := {0..7}; s := wreg END;
  193. s1 := s - hint;
  194. IF high IN hint THEN s1 := s1 * {0..3} END;
  195. IF s1 # {} THEN s := s1 END;
  196. IF 0 IN s THEN n := 0
  197. ELSIF 2 IN s THEN n := 2
  198. ELSIF 6 IN s THEN n := 6
  199. ELSIF 7 IN s THEN n := 7
  200. ELSIF 1 IN s THEN n := 1
  201. ELSE n := 3
  202. END;
  203. EXCL(WReg, n);
  204. IF n < 4 THEN EXCL(BReg, n); EXCL(BReg, n + 4) END
  205. | Real32, Real64:
  206. IF (FReg = 0) OR (float IN stop) THEN DevCPM.err(216); FReg := 99 END;
  207. DEC(FReg); n := 0
  208. END;
  209. DevCPL486.MakeReg(x, n, f);
  210. END GetReg;
  211. PROCEDURE FreeReg (n, f: INTEGER);
  212. BEGIN
  213. IF f <= Int8 THEN
  214. INCL(BReg, n);
  215. IF (n + 4) MOD 8 IN BReg THEN INCL(WReg, n MOD 4) END
  216. ELSIF f IN realSet THEN
  217. INC(FReg)
  218. ELSIF n IN AllReg THEN
  219. INCL(WReg, n);
  220. IF n < 4 THEN INCL(BReg, n); INCL(BReg, n + 4) END
  221. END
  222. END FreeReg;
  223. PROCEDURE FreeWReg (n: INTEGER);
  224. BEGIN
  225. IF n IN AllReg THEN
  226. INCL(WReg, n);
  227. IF n < 4 THEN INCL(BReg, n); INCL(BReg, n + 4) END
  228. END
  229. END FreeWReg;
  230. PROCEDURE Free* (VAR x: DevCPL486.Item);
  231. BEGIN
  232. CASE x.mode OF
  233. | Var, VarPar, Abs: IF x.scale # 0 THEN FreeWReg(x.index) END
  234. | Ind: FreeWReg(x.reg);
  235. IF x.scale # 0 THEN FreeWReg(x.index) END
  236. | Reg: FreeReg(x.reg, x.form);
  237. IF x.form = Int64 THEN FreeWReg(x.index) END
  238. ELSE
  239. END
  240. END Free;
  241. PROCEDURE FreeHi (VAR x: DevCPL486.Item); (* free hi byte of word reg *)
  242. BEGIN
  243. IF x.mode = Reg THEN
  244. IF x.form = Int64 THEN FreeWReg(x.index)
  245. ELSIF x.reg < 4 THEN INCL(BReg, x.reg + 4)
  246. END
  247. END
  248. END FreeHi;
  249. PROCEDURE Fits* (VAR x: DevCPL486.Item; stop: SET): BOOLEAN; (* x.mode = Reg *)
  250. BEGIN
  251. IF (short IN stop) & (x.form <= Int8) THEN RETURN FALSE END;
  252. IF x.form <= Int8 THEN RETURN ~(x.reg MOD 4 IN stop) & ((x.reg < 4) OR ~(high IN stop))
  253. ELSIF x.form IN realSet THEN RETURN ~(float IN stop)
  254. ELSIF x.form = Int64 THEN RETURN ~(x.reg IN stop) & ~(x.index IN stop)
  255. ELSE RETURN ~(x.reg IN stop) & ((x.reg < 4) OR ~(high IN stop))
  256. END
  257. END Fits;
  258. PROCEDURE Pop* (VAR r: DevCPL486.Item; f: BYTE; hint, stop: SET);
  259. VAR rh: DevCPL486.Item;
  260. BEGIN
  261. IF f = Int64 THEN
  262. GetReg(r, Int32, hint, stop); DevCPL486.GenPop(r);
  263. GetReg(rh, Int32, hint, stop); DevCPL486.GenPop(rh);
  264. r.form := Int64; r.index := rh.reg
  265. ELSE
  266. IF f < Int16 THEN INCL(stop, high) END;
  267. GetReg(r, f, hint, stop); DevCPL486.GenPop(r)
  268. END
  269. END Pop;
  270. PROCEDURE^ LoadLong (VAR x: DevCPL486.Item; hint, stop: SET);
  271. PROCEDURE Load* (VAR x: DevCPL486.Item; hint, stop: SET); (* = Assert(x, hint, stop + {mem, stk}) *)
  272. VAR r: DevCPL486.Item; f: BYTE;
  273. BEGIN
  274. f := x.typ.form;
  275. IF x.mode = Con THEN
  276. IF (short IN stop) & (x.form IN {Int8, Int16, Bool, Char8, Char16}) THEN f := Int32; x.form := Int32 END;
  277. IF con IN stop THEN
  278. IF f = Int64 THEN LoadLong(x, hint, stop)
  279. ELSE
  280. GetReg(r, f, hint, stop); DevCPL486.GenMove(x, r);
  281. x.mode := Reg; x.reg := r.reg; x.form := f
  282. END
  283. END
  284. ELSIF x.mode = Stk THEN
  285. IF f IN realSet THEN
  286. GetReg(r, f, hint, stop); DevCPL486.GenFLoad(x); IncStack(x.form)
  287. ELSE
  288. Pop(r, f, hint, stop)
  289. END;
  290. x.mode := Reg; x.reg := r.reg; x.index := r.index; x.form := f
  291. ELSIF (short IN stop) & (x.form IN {Int8, Int16, Bool, Char8, Char16}) THEN
  292. Free(x); GetReg(r, Int32, hint, stop); DevCPL486.GenExtMove(x, r);
  293. x.mode := Reg; x.reg := r.reg; x.form := Int32
  294. ELSIF (x.mode # Reg) OR ~Fits(x, stop) THEN
  295. IF f = Int64 THEN LoadLong(x, hint, stop)
  296. ELSE
  297. Free(x); GetReg(r, f, hint, stop);
  298. IF f IN realSet THEN DevCPL486.GenFLoad(x) ELSE DevCPL486.GenMove(x, r) END;
  299. x.mode := Reg; x.reg := r.reg; x.form := f
  300. END
  301. END
  302. END Load;
  303. PROCEDURE Push* (VAR x: DevCPL486.Item);
  304. VAR y: DevCPL486.Item;
  305. BEGIN
  306. IF x.form IN realSet THEN
  307. Load(x, {}, {}); DecStack(x.form);
  308. Free(x); x.mode := Stk;
  309. IF x.typ = DevCPT.intrealtyp THEN x.form := Int64 END;
  310. DevCPL486.GenFStore(x, TRUE)
  311. ELSIF x.form = Int64 THEN
  312. Free(x); x.form := Int32; y := x;
  313. IF x.mode = Reg THEN y.reg := x.index ELSE INC(y.offset, 4) END;
  314. DevCPL486.GenPush(y); DevCPL486.GenPush(x);
  315. x.mode := Stk; x.form := Int64
  316. ELSE
  317. IF x.form < Int16 THEN Load(x, {}, {high})
  318. ELSIF x.form = Int16 THEN Load(x, {}, {})
  319. END;
  320. Free(x); DevCPL486.GenPush(x); x.mode := Stk
  321. END
  322. END Push;
  323. PROCEDURE Assert* (VAR x: DevCPL486.Item; hint, stop: SET);
  324. VAR r: DevCPL486.Item;
  325. BEGIN
  326. IF (short IN stop) & (x.form IN {Int8, Int16, Bool, Char8, Char16}) & (x.mode # Con) THEN
  327. IF (wreg - stop = {}) & ~(stk IN stop) THEN Load(x, {}, {short}); Push(x)
  328. ELSE Load(x, hint, stop);
  329. END
  330. ELSE
  331. CASE x.mode OF
  332. | Var, VarPar: IF ~(mem IN stop) THEN RETURN END
  333. | Con: IF ~(con IN stop) THEN RETURN END
  334. | Ind: IF ~(mem IN stop) & ~(x.reg IN stop) & ((x.scale = 0) OR ~(x.index IN stop)) THEN RETURN END
  335. | Abs: IF ~(mem IN stop) & ((x.scale = 0) OR ~(x.index IN stop)) THEN RETURN END
  336. | Stk: IF ~(stk IN stop) THEN RETURN END
  337. | Reg: IF Fits(x, stop) THEN RETURN END
  338. ELSE RETURN
  339. END;
  340. IF ((float IN stop) OR ~(x.typ.form IN realSet) & (wreg - stop = {})) & ~(stk IN stop) THEN Push(x)
  341. ELSE Load(x, hint, stop)
  342. END
  343. END
  344. END Assert;
  345. (*------------------------------------------------*)
  346. PROCEDURE LoadR (VAR x: DevCPL486.Item);
  347. BEGIN
  348. IF x.mode # Reg THEN
  349. Free(x); DevCPL486.GenFLoad(x);
  350. IF x.mode = Stk THEN IncStack(x.form) END;
  351. GetReg(x, Real32, {}, {})
  352. END
  353. END LoadR;
  354. PROCEDURE PushR (VAR x: DevCPL486.Item);
  355. BEGIN
  356. IF x.mode # Reg THEN LoadR(x) END;
  357. DecStack(x.form);
  358. Free(x); x.mode := Stk; DevCPL486.GenFStore(x, TRUE)
  359. END PushR;
  360. PROCEDURE LoadW (VAR x: DevCPL486.Item; hint, stop: SET);
  361. VAR r: DevCPL486.Item;
  362. BEGIN
  363. IF x.mode = Stk THEN
  364. Pop(x, x.form, hint, stop)
  365. ELSE
  366. Free(x); GetReg(r, x.form, hint, stop);
  367. DevCPL486.GenMove(x, r);
  368. x.mode := Reg; x.reg := r.reg
  369. END
  370. END LoadW;
  371. PROCEDURE LoadL (VAR x: DevCPL486.Item; hint, stop: SET);
  372. VAR r: DevCPL486.Item;
  373. BEGIN
  374. IF x.mode = Stk THEN
  375. Pop(x, x.form, hint, stop);
  376. IF (x.form < Int32) OR (x.form = Char16) THEN
  377. r := x; x.form := Int32; DevCPL486.GenExtMove(r, x)
  378. END
  379. ELSE
  380. Free(x);
  381. IF (x.form < Int32) OR (x.form = Char16) THEN GetReg(r, Int32, hint, stop) ELSE GetReg(r, x.form, hint, stop) END;
  382. IF x.mode = Con THEN x.form := r.form END;
  383. IF x.form # r.form THEN DevCPL486.GenExtMove(x, r) ELSE DevCPL486.GenMove(x, r) END;
  384. x.mode := Reg; x.reg := r.reg; x.form := r.form
  385. END
  386. END LoadL;
  387. PROCEDURE LoadLong (VAR x: DevCPL486.Item; hint, stop: SET);
  388. VAR r, rh, c: DevCPL486.Item; offs: INTEGER;
  389. BEGIN
  390. IF x.form = Int64 THEN
  391. IF x.mode = Stk THEN
  392. Pop(x, x.form, hint, stop)
  393. ELSIF x.mode = Reg THEN
  394. FreeReg(x.reg, Int32); GetReg(r, Int32, hint, stop);
  395. FreeReg(x.index, Int32); GetReg(rh, Int32, hint, stop);
  396. x.form := Int32; DevCPL486.GenMove(x, r);
  397. x.reg := x.index; DevCPL486.GenMove(x, rh);
  398. x.reg := r.reg; x.index := rh.reg
  399. ELSE
  400. GetReg(rh, Int32, hint, stop + {AX});
  401. Free(x);
  402. GetReg(r, Int32, hint, stop);
  403. x.form := Int32; offs := x.offset;
  404. IF x.mode = Con THEN x.offset := x.scale ELSE INC(x.offset, 4) END;
  405. DevCPL486.GenMove(x, rh);
  406. x.offset := offs;
  407. DevCPL486.GenMove(x, r);
  408. x.mode := Reg; x.reg := r.reg; x.index := rh.reg
  409. END
  410. ELSE
  411. LoadL(x, hint, stop); GetReg(rh, Int32, hint, stop); DevCPL486.GenSignExt(x, rh);
  412. x.index := rh.reg
  413. END;
  414. x.form := Int64
  415. END LoadLong;
  416. (*------------------------------------------------*)
  417. PROCEDURE CopyReg* (VAR x, y: DevCPL486.Item; hint, stop: SET);
  418. BEGIN
  419. ASSERT(x.mode = Reg);
  420. GetReg(y, x.form, hint, stop);
  421. DevCPL486.GenMove(x, y)
  422. END CopyReg;
  423. PROCEDURE GetAdr* (VAR x: DevCPL486.Item; hint, stop: SET);
  424. VAR r: DevCPL486.Item;
  425. BEGIN
  426. IF x.mode = DInd THEN
  427. x.mode := Ind
  428. ELSIF (x.mode = Ind) & (x.offset = 0) & (x.scale = 0) & (x.reg IN wreg) THEN
  429. x.mode := Reg
  430. ELSE
  431. Free(x); GetReg(r, Pointer, hint, stop);
  432. IF x.mode = Con THEN DevCPL486.GenMove(x, r) ELSE DevCPL486.GenLoadAdr(x, r) END;
  433. x.mode := Reg; x.reg := r.reg; x.form := Pointer
  434. END;
  435. x.form := Pointer; x.typ := DevCPT.anyptrtyp;
  436. Assert(x, hint, stop)
  437. END GetAdr;
  438. PROCEDURE PushAdr (VAR x: DevCPL486.Item; niltest: BOOLEAN);
  439. VAR r, v: DevCPL486.Item;
  440. BEGIN
  441. IF (x.mode = Abs) & (x.scale = 0) THEN x.mode := Con; x.form := Pointer
  442. ELSIF niltest THEN
  443. GetAdr(x, {}, {mem, stk});
  444. DevCPL486.MakeReg(r, AX, Int32);
  445. v.mode := Ind; v.form := Int32; v.offset := 0; v.scale := 0; v.reg := x.reg;
  446. DevCPL486.GenTest(r, v)
  447. ELSIF x.mode = DInd THEN x.mode := Ind; x.form := Pointer
  448. ELSE GetAdr(x, {}, {})
  449. END;
  450. Free(x); DevCPL486.GenPush(x)
  451. END PushAdr;
  452. PROCEDURE LevelBase (VAR a: DevCPL486.Item; lev: INTEGER; hint, stop: SET);
  453. VAR n: BYTE;
  454. BEGIN
  455. a.mode := Ind; a.scale := 0; a.form := Int32; a.typ := DevCPT.int32typ;
  456. IF lev = DevCPL486.level THEN a.reg := BP
  457. ELSE
  458. a.reg := BX; n := SHORT(SHORT(imLevel[DevCPL486.level] - imLevel[lev]));
  459. WHILE n > 0 DO
  460. a.offset := -4; LoadL(a, hint, stop); a.mode := Ind; DEC(n)
  461. END
  462. END
  463. END LevelBase;
  464. PROCEDURE LenDesc (VAR x, len: DevCPL486.Item; typ: DevCPT.Struct); (* set len to LEN(x, -typ.n) *)
  465. BEGIN
  466. IF x.tmode = VarPar THEN
  467. LevelBase(len, x.obj.mnolev, {}, {}); len.offset := x.obj.adr;
  468. ELSE ASSERT((x.tmode = Ind) & (x.mode = Ind));
  469. len := x; len.offset := ArrDOffs; len.scale := 0; len.form := Int32
  470. END;
  471. INC(len.offset, typ.n * 4 + 4);
  472. IF typ.sysflag = stackArray THEN len.offset := -4 END
  473. END LenDesc;
  474. PROCEDURE Tag* (VAR x, tag: DevCPL486.Item);
  475. VAR typ: DevCPT.Struct;
  476. BEGIN
  477. typ := x.typ;
  478. IF typ.form = Pointer THEN typ := typ.BaseTyp END;
  479. IF (x.typ # DevCPT.sysptrtyp) & (typ.attribute = 0) & ~(DevCPM.oberon IN DevCPM.options) THEN (* final type *)
  480. DevCPL486.MakeConst(tag, 0, Pointer); tag.obj := DevCPE.TypeObj(typ)
  481. ELSIF x.typ.form = Pointer THEN
  482. ASSERT(x.mode = Reg);
  483. tag.mode := Ind; tag.reg := x.reg; tag.offset := -4;
  484. IF x.typ.sysflag = interface THEN tag.offset := 0 END
  485. ELSIF x.tmode = VarPar THEN
  486. LevelBase(tag, x.obj.mnolev, {}, {}); tag.offset := x.obj.adr + 4;
  487. Free(tag) (* ??? *)
  488. ELSIF x.tmode = Ind THEN
  489. ASSERT(x.mode = Ind);
  490. tag := x; tag.offset := -4
  491. ELSE
  492. DevCPL486.MakeConst(tag, 0, Pointer); tag.obj := DevCPE.TypeObj(x.typ)
  493. END;
  494. tag.scale := 0; tag.form := Pointer; tag.typ := DevCPT.sysptrtyp
  495. END Tag;
  496. PROCEDURE NumOfIntProc (typ: DevCPT.Struct): INTEGER;
  497. BEGIN
  498. WHILE (typ # NIL) & (typ.sysflag # interface) DO typ := typ.BaseTyp END;
  499. IF typ # NIL THEN RETURN typ.n
  500. ELSE RETURN 0
  501. END
  502. END NumOfIntProc;
  503. PROCEDURE ContainsIPtrs* (typ: DevCPT.Struct): BOOLEAN;
  504. VAR fld: DevCPT.Object;
  505. BEGIN
  506. WHILE typ.comp IN {DynArr, Array} DO typ := typ.BaseTyp END;
  507. IF (typ.form = Pointer) & (typ.sysflag = interface) THEN RETURN TRUE
  508. ELSIF (typ.comp = Record) & (typ.sysflag # union) THEN
  509. REPEAT
  510. fld := typ.link;
  511. WHILE (fld # NIL) & (fld.mode = Fld) DO
  512. IF (fld.sysflag = interface) & (fld.name^ = DevCPM.HdUtPtrName)
  513. OR ContainsIPtrs(fld.typ) THEN RETURN TRUE END;
  514. fld := fld.link
  515. END;
  516. typ := typ.BaseTyp
  517. UNTIL typ = NIL
  518. END;
  519. RETURN FALSE
  520. END ContainsIPtrs;
  521. PROCEDURE GuidFromString* (str: DevCPT.ConstExt; VAR x: DevCPL486.Item);
  522. VAR cv: DevCPT.Const;
  523. BEGIN
  524. IF ~DevCPM.ValidGuid(str^) THEN DevCPM.err(165) END;
  525. cv := DevCPT.NewConst();
  526. cv.intval := DevCPM.ConstNotAlloc; cv.intval2 := 16; cv.ext := str;
  527. DevCPL486.AllocConst(x, cv, Guid); x.typ := DevCPT.guidtyp
  528. END GuidFromString;
  529. PROCEDURE IPAddRef* (VAR x: DevCPL486.Item; offset: INTEGER; nilTest: BOOLEAN);
  530. VAR r, p, c: DevCPL486.Item; lbl: DevCPL486.Label;
  531. BEGIN
  532. ASSERT(x.mode IN {Reg, Ind, Abs});
  533. ASSERT({AX, CX, DX} - WReg = {});
  534. IF hints THEN
  535. IF nilTest THEN DevCPM.err(-701) ELSE DevCPM.err(-700) END
  536. END;
  537. IF x.mode # Reg THEN
  538. GetReg(r, Pointer, {}, {});
  539. p := x; INC(p.offset, offset); p.form := Pointer; DevCPL486.GenMove(p, r);
  540. ELSE r := x
  541. END;
  542. IF nilTest THEN
  543. DevCPL486.MakeConst(c, 0, Pointer); DevCPL486.GenComp(c, r);
  544. lbl := DevCPL486.NewLbl; DevCPL486.GenJump(ccE, lbl, TRUE)
  545. END;
  546. DevCPL486.GenPush(r); p := r;
  547. IF x.mode # Reg THEN Free(r) END;
  548. GetReg(r, Pointer, {}, {});
  549. p.mode := Ind; p.offset := 0; p.scale := 0; p.form := Pointer; DevCPL486.GenMove(p, r);
  550. p.offset := 4; p.reg := r.reg; Free(r); DevCPL486.GenCall(p);
  551. IF nilTest THEN DevCPL486.SetLabel(lbl) END;
  552. END IPAddRef;
  553. PROCEDURE IPRelease* (VAR x: DevCPL486.Item; offset: INTEGER; nilTest, nilSet: BOOLEAN);
  554. VAR r, p, c: DevCPL486.Item; lbl: DevCPL486.Label;
  555. BEGIN
  556. ASSERT(x.mode IN {Ind, Abs});
  557. ASSERT({AX, CX, DX} - WReg = {});
  558. IF hints THEN
  559. IF nilTest THEN DevCPM.err(-703) ELSE DevCPM.err(-702) END
  560. END;
  561. GetReg(r, Pointer, {}, {});
  562. p := x; INC(p.offset, offset); p.form := Pointer; DevCPL486.GenMove(p, r);
  563. DevCPL486.MakeConst(c, 0, Pointer);
  564. IF nilTest THEN
  565. DevCPL486.GenComp(c, r);
  566. lbl := DevCPL486.NewLbl; DevCPL486.GenJump(ccE, lbl, TRUE)
  567. END;
  568. IF nilSet THEN DevCPL486.GenMove(c, p) END;
  569. DevCPL486.GenPush(r);
  570. p.mode := Ind; p.reg := r.reg; p.offset := 0; p.scale := 0; DevCPL486.GenMove(p, r);
  571. p.offset := 8; Free(r); DevCPL486.GenCall(p);
  572. IF nilTest THEN DevCPL486.SetLabel(lbl) END;
  573. END IPRelease;
  574. PROCEDURE Prepare* (VAR x: DevCPL486.Item; hint, stop: SET);
  575. VAR n, i, lev: INTEGER; len, y: DevCPL486.Item; typ: DevCPT.Struct;
  576. BEGIN
  577. IF (x.mode IN {Var, VarPar, Ind, Abs}) & (x.scale # 0) THEN
  578. DevCPL486.MakeReg(y, x.index, Int32); typ := x.typ;
  579. WHILE typ.comp = DynArr DO (* complete dynamic array iterations *)
  580. LenDesc(x, len, typ); DevCPL486.GenMul(len, y, FALSE); typ := typ.BaseTyp;
  581. IF x.tmode = VarPar THEN Free(len) END; (* ??? *)
  582. END;
  583. n := x.scale; i := 0;
  584. WHILE (n MOD 2 = 0) & (i < 3) DO n := n DIV 2; INC(i) END;
  585. IF n > 1 THEN (* assure scale factor in {1, 2, 4, 8} *)
  586. DevCPL486.MakeConst(len, n, Int32); DevCPL486.GenMul(len, y, FALSE); x.scale := x.scale DIV n
  587. END
  588. END;
  589. CASE x.mode OF
  590. Var, VarPar:
  591. lev := x.obj.mnolev;
  592. IF lev <= 0 THEN
  593. x.mode := Abs
  594. ELSE
  595. LevelBase(y, lev, hint, stop);
  596. IF x.mode # VarPar THEN
  597. x.mode := Ind
  598. ELSIF (deref IN hint) & (x.offset = 0) & (x.scale = 0) THEN
  599. x.mode := DInd; x.offset := x.obj.adr
  600. ELSE
  601. y.offset := x.obj.adr; Load(y, hint, stop); x.mode := Ind
  602. END;
  603. x.reg := y.reg
  604. END;
  605. x.form := x.typ.form
  606. | LProc, XProc, IProc:
  607. x.mode := Con; x.offset := 0; x.form := ProcTyp
  608. | TProc, CProc:
  609. x.form := ProcTyp
  610. | Ind, Abs, Stk, Reg:
  611. IF ~(x.typ.form IN {String8, String16}) THEN x.form := x.typ.form END
  612. END
  613. END Prepare;
  614. PROCEDURE Field* (VAR x: DevCPL486.Item; field: DevCPT.Object);
  615. BEGIN
  616. INC(x.offset, field.adr); x.tmode := Con
  617. END Field;
  618. PROCEDURE DeRef* (VAR x: DevCPL486.Item);
  619. VAR btyp: DevCPT.Struct;
  620. BEGIN
  621. x.mode := Ind; x.tmode := Ind; x.scale := 0;
  622. btyp := x.typ.BaseTyp;
  623. IF btyp.untagged OR (btyp.sysflag = stackArray) THEN x.offset := 0
  624. ELSIF btyp.comp = DynArr THEN x.offset := ArrDOffs + btyp.size
  625. ELSIF btyp.comp = Array THEN x.offset := ArrDOffs + 4
  626. ELSE x.offset := 0
  627. END
  628. END DeRef;
  629. PROCEDURE Index* (VAR x, y: DevCPL486.Item; hint, stop: SET); (* x[y] *)
  630. VAR idx, len: DevCPL486.Item; btyp: DevCPT.Struct; elsize: INTEGER;
  631. BEGIN
  632. btyp := x.typ.BaseTyp; elsize := btyp.size;
  633. IF elsize = 0 THEN Free(y)
  634. ELSIF x.typ.comp = Array THEN
  635. len.mode := Con; len.obj := NIL;
  636. IF y.mode = Con THEN
  637. INC(x.offset, y.offset * elsize)
  638. ELSE
  639. Load(y, hint, stop + {mem, stk, short});
  640. IF inxchk THEN
  641. DevCPL486.MakeConst(len, x.typ.n, Int32);
  642. DevCPL486.GenComp(len, y); DevCPL486.GenAssert(ccB, inxTrap)
  643. END;
  644. IF x.scale = 0 THEN x.index := y.reg
  645. ELSE
  646. IF x.scale MOD elsize # 0 THEN
  647. IF (x.scale MOD 4 = 0) & (elsize MOD 4 = 0) THEN elsize := 4
  648. ELSIF (x.scale MOD 2 = 0) & (elsize MOD 2 = 0) THEN elsize := 2
  649. ELSE elsize := 1
  650. END;
  651. DevCPL486.MakeConst(len, btyp.size DIV elsize, Int32);
  652. DevCPL486.GenMul(len, y, FALSE)
  653. END;
  654. DevCPL486.MakeConst(len, x.scale DIV elsize, Int32);
  655. DevCPL486.MakeReg(idx, x.index, Int32);
  656. DevCPL486.GenMul(len, idx, FALSE); DevCPL486.GenAdd(y, idx, FALSE); Free(y)
  657. END;
  658. x.scale := elsize
  659. END;
  660. x.tmode := Con
  661. ELSE (* x.typ.comp = DynArr *)
  662. IF (btyp.comp = DynArr) & x.typ.untagged THEN DevCPM.err(137) END;
  663. LenDesc(x, len, x.typ);
  664. IF x.scale # 0 THEN
  665. DevCPL486.MakeReg(idx, x.index, Int32);
  666. DevCPL486.GenMul(len, idx, FALSE)
  667. END;
  668. IF (y.mode # Con) OR (y.offset # 0) THEN
  669. IF (y.mode # Con) OR (btyp.comp = DynArr) & (x.scale = 0) THEN
  670. Load(y, hint, stop + {mem, stk, con, short})
  671. ELSE y.form := Int32
  672. END;
  673. IF inxchk & ~x.typ.untagged THEN
  674. DevCPL486.GenComp(y, len); DevCPL486.GenAssert(ccA, inxTrap)
  675. END;
  676. IF (y.mode = Con) & (btyp.comp # DynArr) THEN
  677. INC(x.offset, y.offset * elsize)
  678. ELSIF x.scale = 0 THEN
  679. WHILE btyp.comp = DynArr DO btyp := btyp.BaseTyp END;
  680. x.index := y.reg; x.scale := btyp.size
  681. ELSE
  682. DevCPL486.GenAdd(y, idx, FALSE); Free(y)
  683. END
  684. END;
  685. IF x.tmode = VarPar THEN Free(len) END; (* ??? *)
  686. IF x.typ.BaseTyp.comp # DynArr THEN x.tmode := Con END
  687. END
  688. END Index;
  689. PROCEDURE TypTest* (VAR x: DevCPL486.Item; testtyp: DevCPT.Struct; guard, equal: BOOLEAN);
  690. VAR tag, tdes, r: DevCPL486.Item; typ: DevCPT.Struct;
  691. BEGIN
  692. typ := x.typ;
  693. IF typ.form = Pointer THEN testtyp := testtyp.BaseTyp; typ := typ.BaseTyp END;
  694. IF ~guard & typ.untagged THEN DevCPM.err(139)
  695. ELSIF ~guard OR typchk & ~typ.untagged THEN
  696. IF testtyp.untagged THEN DevCPM.err(139)
  697. ELSE
  698. IF (x.typ.form = Pointer) & (x.mode # Reg) THEN
  699. GetReg(r, Pointer, {}, {}); DevCPL486.GenMove(x, r); Free(r); r.typ := x.typ; Tag(r, tag)
  700. ELSE Tag(x, tag)
  701. END;
  702. IF ~guard THEN Free(x) END;
  703. IF ~equal THEN
  704. GetReg(r, Pointer, {}, {}); DevCPL486.GenMove(tag, r); Free(r);
  705. tag.mode := Ind; tag.reg := r.reg; tag.scale := 0; tag.offset := Tag0Offset + 4 * testtyp.extlev
  706. END;
  707. DevCPL486.MakeConst(tdes, 0, Pointer); tdes.obj := DevCPE.TypeObj(testtyp);
  708. DevCPL486.GenComp(tdes, tag);
  709. IF guard THEN
  710. IF equal THEN DevCPL486.GenAssert(ccE, recTrap) ELSE DevCPL486.GenAssert(ccE, typTrap) END
  711. ELSE setCC(x, eql, FALSE, FALSE)
  712. END
  713. END
  714. END
  715. END TypTest;
  716. PROCEDURE ShortTypTest* (VAR x: DevCPL486.Item; testtyp: DevCPT.Struct);
  717. VAR tag, tdes: DevCPL486.Item;
  718. BEGIN
  719. (* tag must be in AX ! *)
  720. IF testtyp.form = Pointer THEN testtyp := testtyp.BaseTyp END;
  721. IF testtyp.untagged THEN DevCPM.err(139)
  722. ELSE
  723. tag.mode := Ind; tag.reg := AX; tag.scale := 0; tag.offset := Tag0Offset + 4 * testtyp.extlev; tag.form := Pointer;
  724. DevCPL486.MakeConst(tdes, 0, Pointer); tdes.obj := DevCPE.TypeObj(testtyp);
  725. DevCPL486.GenComp(tdes, tag);
  726. setCC(x, eql, FALSE, FALSE)
  727. END
  728. END ShortTypTest;
  729. PROCEDURE Check (VAR x: DevCPL486.Item; min, max: INTEGER);
  730. VAR c: DevCPL486.Item;
  731. BEGIN
  732. ASSERT((x.mode # Reg) OR (max > 255) OR (max = 31) OR (x.reg < 4));
  733. IF ranchk & (x.mode # Con) THEN
  734. DevCPL486.MakeConst(c, max, x.form); DevCPL486.GenComp(c, x);
  735. IF min # 0 THEN
  736. DevCPL486.GenAssert(ccLE, ranTrap);
  737. c.offset := min; DevCPL486.GenComp(c, x);
  738. DevCPL486.GenAssert(ccGE, ranTrap)
  739. ELSIF max # 0 THEN
  740. DevCPL486.GenAssert(ccBE, ranTrap)
  741. ELSE
  742. DevCPL486.GenAssert(ccNS, ranTrap)
  743. END
  744. END
  745. END Check;
  746. PROCEDURE Floor (VAR x: DevCPL486.Item; useSt1: BOOLEAN);
  747. VAR c: DevCPL486.Item; local: DevCPL486.Label;
  748. BEGIN
  749. IF useSt1 THEN DevCPL486.GenFMOp(5D1H); (* FST ST1 *)
  750. ELSE DevCPL486.GenFMOp(1C0H); (* FLD ST0 *)
  751. END;
  752. DevCPL486.GenFMOp(1FCH); (* FRNDINT *)
  753. DevCPL486.GenFMOp(0D1H); (* FCOM *)
  754. CheckAv(AX);
  755. DevCPL486.GenFMOp(FSTSW);
  756. DevCPL486.GenFMOp(5D9H); (* FSTP ST1 *)
  757. (* DevCPL486.GenCode(WAIT); *) DevCPL486.GenCode(SAHF);
  758. local := DevCPL486.NewLbl; DevCPL486.GenJump(ccBE, local, TRUE);
  759. DevCPL486.AllocConst(c, DevCPL486.one, Real32);
  760. DevCPL486.GenFDOp(FSUB, c);
  761. DevCPL486.SetLabel(local);
  762. END Floor;
  763. PROCEDURE Entier(VAR x: DevCPL486.Item; typ: DevCPT.Struct; hint, stop: SET);
  764. BEGIN
  765. IF typ # DevCPT.intrealtyp THEN Floor(x, FALSE) END;
  766. DevCPL486.GenFStore(x, TRUE);
  767. IF (x.mode = Stk) & (stk IN stop) THEN Pop(x, x.form, hint, stop) END
  768. END Entier;
  769. PROCEDURE ConvMove (VAR x, y: DevCPL486.Item; sysval: BOOLEAN; hint, stop: SET); (* x := y *)
  770. (* scalar values only, y.mode # Con, all kinds of conversions, x.mode = Undef => convert y only *)
  771. VAR f, m: BYTE; s: INTEGER; z: DevCPL486.Item;
  772. BEGIN
  773. f := x.form; m := x.mode; ASSERT(m IN {Undef, Reg, Abs, Ind, Stk});
  774. IF y.form IN {Real32, Real64} THEN
  775. IF f IN {Real32, Real64} THEN
  776. IF m = Undef THEN
  777. IF (y.form = Real64) & (f = Real32) THEN
  778. IF y.mode # Reg THEN LoadR(y) END;
  779. Free(y); DecStack(Real32); y.mode := Stk; y.form := Real32; DevCPL486.GenFStore(y, TRUE)
  780. END
  781. ELSE
  782. IF y.mode # Reg THEN LoadR(y) END;
  783. IF m = Stk THEN DecStack(f) END;
  784. IF m # Reg THEN Free(y); DevCPL486.GenFStore(x, TRUE) END;
  785. END
  786. ELSE (* x not real *)
  787. IF sysval THEN
  788. IF y.mode = Reg THEN Free(y);
  789. IF (m # Stk) & (m # Undef) & (m # Reg) & (f >= Int32) THEN
  790. x.form := y.form; DevCPL486.GenFStore(x, TRUE); x.form := f
  791. ELSE
  792. ASSERT(y.form # Real64);
  793. DecStack(y.form); y.mode := Stk; DevCPL486.GenFStore(y, TRUE); y.form := Int32;
  794. IF m # Stk THEN
  795. Pop(y, y.form, hint, stop);
  796. IF f < Int16 THEN ASSERT(y.reg < 4) END;
  797. y.form := f;
  798. IF m # Undef THEN Free(y); DevCPL486.GenMove(y, x) END
  799. END
  800. END
  801. ELSE (* y.mode # Reg *)
  802. y.form := f;
  803. IF m # Undef THEN LoadW(y, hint, stop); Free(y);
  804. IF m = Stk THEN DevCPL486.GenPush(y) ELSE DevCPL486.GenMove(y, x) END
  805. END
  806. END
  807. ELSE (* not sysval *)
  808. IF y.mode # Reg THEN LoadR(y) END;
  809. Free(y);
  810. IF (m # Stk) & (m # Undef) & (m # Reg) & (f >= Int16) & (f # Char16) THEN
  811. Entier(x, y.typ, hint, stop);
  812. ELSE
  813. DecStack(f); y.mode := Stk;
  814. IF (f < Int16) OR (f = Char16) THEN y.form := Int32 ELSE y.form := f END;
  815. IF m = Stk THEN Entier(y, y.typ, {}, {})
  816. ELSIF m = Undef THEN Entier(y, y.typ, hint, stop)
  817. ELSE Entier(y, y.typ, hint, stop + {stk})
  818. END;
  819. IF f = Int8 THEN Check(y, -128, 127); FreeHi(y)
  820. ELSIF f = Char8 THEN Check(y, 0, 255); FreeHi(y)
  821. ELSIF f = Char16 THEN Check(y, 0, 65536); FreeHi(y)
  822. END;
  823. y.form := f;
  824. IF (m # Undef) & (m # Stk) THEN
  825. IF f = Int64 THEN
  826. Free(y); y.form := Int32; z := x; z.form := Int32; DevCPL486.GenMove(y, z);
  827. IF z.mode = Reg THEN z.reg := z.index ELSE INC(z.offset, 4) END;
  828. y.reg := y.index; DevCPL486.GenMove(y, z);
  829. ELSE
  830. Free(y); DevCPL486.GenMove(y, x);
  831. END
  832. END
  833. END
  834. END
  835. END
  836. ELSE (* y not real *)
  837. IF sysval THEN
  838. IF (y.form < Int16) & (f >= Int16) OR (y.form IN {Int16, Char16}) & (f >= Int32) & (f < Char16) THEN LoadL(y, hint, stop) END;
  839. IF (y.form >= Int16) & (f < Int16) THEN FreeHi(y) END
  840. ELSE
  841. CASE y.form OF
  842. | Byte, Bool:
  843. IF f = Int64 THEN LoadLong(y, hint, stop)
  844. ELSIF f >= Int16 THEN LoadL(y, hint, stop)
  845. END
  846. | Char8:
  847. IF f = Int8 THEN Check(y, 0, 0)
  848. ELSIF f = Int64 THEN LoadLong(y, hint, stop)
  849. ELSIF f >= Int16 THEN LoadL(y, hint, stop)
  850. END
  851. | Char16:
  852. IF f = Char8 THEN Check(y, 0, 255); FreeHi(y)
  853. ELSIF f = Int8 THEN Check(y, -128, 127); FreeHi(y)
  854. ELSIF f = Int16 THEN Check(y, 0, 0)
  855. ELSIF f = Char16 THEN (* ok *)
  856. ELSIF f = Int64 THEN LoadLong(y, hint, stop)
  857. ELSIF f >= Int32 THEN LoadL(y, hint, stop)
  858. END
  859. | Int8:
  860. IF f = Char8 THEN Check(y, 0, 0)
  861. ELSIF f = Int64 THEN LoadLong(y, hint, stop)
  862. ELSIF f >= Int16 THEN LoadL(y, hint, stop)
  863. END
  864. | Int16:
  865. IF f = Char8 THEN Check(y, 0, 255); FreeHi(y)
  866. ELSIF f = Char16 THEN Check(y, 0, 0)
  867. ELSIF f = Int8 THEN Check(y, -128, 127); FreeHi(y)
  868. ELSIF f = Int64 THEN LoadLong(y, hint, stop)
  869. ELSIF (f = Int32) OR (f = Set) THEN LoadL(y, hint, stop)
  870. END
  871. | Int32, Set, Pointer, ProcTyp:
  872. IF f = Char8 THEN Check(y, 0, 255); FreeHi(y)
  873. ELSIF f = Char16 THEN Check(y, 0, 65536)
  874. ELSIF f = Int8 THEN Check(y, -128, 127); FreeHi(y)
  875. ELSIF f = Int16 THEN Check(y, -32768, 32767)
  876. ELSIF f = Int64 THEN LoadLong(y, hint, stop)
  877. END
  878. | Int64:
  879. IF f IN {Bool..Int32, Char16} THEN
  880. (* make range checks !!! *)
  881. FreeHi(y)
  882. END
  883. END
  884. END;
  885. IF f IN {Real32, Real64} THEN
  886. IF sysval THEN
  887. IF (m # Undef) & (m # Reg) THEN
  888. IF y.mode # Reg THEN LoadW(y, hint, stop) END;
  889. Free(y);
  890. IF m = Stk THEN DevCPL486.GenPush(y)
  891. ELSE x.form := Int32; DevCPL486.GenMove(y, x); x.form := f
  892. END
  893. ELSE
  894. IF y.mode = Reg THEN Push(y) END;
  895. y.form := f;
  896. IF m = Reg THEN LoadR(y) END
  897. END
  898. ELSE (* not sysval *) (* int -> float *)
  899. IF y.mode = Reg THEN Push(y) END;
  900. IF m = Stk THEN
  901. Free(y); DevCPL486.GenFLoad(y); s := -4;
  902. IF f = Real64 THEN DEC(s, 4) END;
  903. IF y.mode = Stk THEN
  904. IF y.form = Int64 THEN INC(s, 8) ELSE INC(s, 4) END
  905. END;
  906. IF s # 0 THEN AdjustStack(s) END;
  907. GetReg(y, Real32, {}, {});
  908. Free(y); DevCPL486.GenFStore(x, TRUE)
  909. ELSIF m = Reg THEN
  910. LoadR(y)
  911. ELSIF m # Undef THEN
  912. LoadR(y); Free(y); DevCPL486.GenFStore(x, TRUE)
  913. END
  914. END
  915. ELSE
  916. y.form := f;
  917. IF m = Stk THEN
  918. IF ((f < Int32) OR (f = Char16)) & (y.mode # Reg) THEN LoadW(y, hint, stop) END;
  919. Push(y)
  920. ELSIF m # Undef THEN
  921. IF f = Int64 THEN
  922. IF y.mode # Reg THEN LoadLong(y, hint, stop) END;
  923. Free(y); y.form := Int32; z := x; z.form := Int32; DevCPL486.GenMove(y, z);
  924. IF z.mode = Reg THEN ASSERT(z.reg # y.index); z.reg := z.index ELSE INC(z.offset, 4) END;
  925. y.reg := y.index; DevCPL486.GenMove(y, z);
  926. ELSE
  927. IF y.mode # Reg THEN LoadW(y, hint, stop) END;
  928. Free(y); DevCPL486.GenMove(y, x)
  929. END
  930. END
  931. END
  932. END
  933. END ConvMove;
  934. PROCEDURE Convert* (VAR x: DevCPL486.Item; f: BYTE; size: INTEGER; hint, stop: SET); (* size >= 0: sysval *)
  935. VAR y: DevCPL486.Item;
  936. BEGIN
  937. ASSERT(x.mode # Con);
  938. IF (size >= 0)
  939. & ((size # x.typ.size) & ((size > 4) OR (x.typ.size > 4))
  940. OR (f IN {Comp, Real64, Int64}) & (x.mode IN {Reg, Stk})) THEN DevCPM.err(220) END;
  941. (*
  942. IF sysval & ((x.form = Real64) & ~(f IN {Comp, Int64}) OR (f = Real64) & ~(x.form IN {Comp, Int64})) THEN DevCPM.err(220) END;
  943. *)
  944. y.mode := Undef; y.form := f; ConvMove(y, x, size >= 0, hint, stop)
  945. END Convert;
  946. PROCEDURE LoadCond* (VAR x, y: DevCPL486.Item; F, T: DevCPL486.Label; hint, stop: SET);
  947. VAR end, T1: DevCPL486.Label; c, r: DevCPL486.Item;
  948. BEGIN
  949. IF mem IN stop THEN GetReg(x, Bool, hint, stop) END;
  950. IF (F = DevCPL486.NewLbl) & (T = DevCPL486.NewLbl) THEN (* no label used *)
  951. DevCPL486.GenSetCC(y.offset, x)
  952. ELSE
  953. end := DevCPL486.NewLbl; T1 := DevCPL486.NewLbl;
  954. DevCPL486.GenJump(y.offset, T1, TRUE); (* T1 to enable short jump *)
  955. DevCPL486.SetLabel(F);
  956. DevCPL486.MakeConst(c, 0, Bool); DevCPL486.GenMove(c, x);
  957. DevCPL486.GenJump(ccAlways, end, TRUE);
  958. DevCPL486.SetLabel(T); DevCPL486.SetLabel(T1);
  959. DevCPL486.MakeConst(c, 1, Bool); DevCPL486.GenMove(c, x);
  960. DevCPL486.SetLabel(end)
  961. END;
  962. IF x.mode # Reg THEN Free(x) END
  963. END LoadCond;
  964. PROCEDURE IntDOp* (VAR x, y: DevCPL486.Item; subcl: BYTE; rev: BOOLEAN);
  965. VAR local: DevCPL486.Label;
  966. BEGIN
  967. ASSERT((x.mode = Reg) OR (y.mode = Reg) OR (y.mode = Con));
  968. CASE subcl OF
  969. | eql..geq:
  970. DevCPL486.GenComp(y, x); Free(x);
  971. setCC(x, subcl, rev, x.typ.form IN {Int8..Int32})
  972. | times:
  973. IF x.form = Set THEN DevCPL486.GenAnd(y, x) ELSE DevCPL486.GenMul(y, x, ovflchk) END
  974. | slash:
  975. DevCPL486.GenXor(y, x)
  976. | plus:
  977. IF x.form = Set THEN DevCPL486.GenOr(y, x) ELSE DevCPL486.GenAdd(y, x, ovflchk) END
  978. | minus, msk:
  979. IF (x.form = Set) OR (subcl = msk) THEN (* and not *)
  980. IF rev THEN DevCPL486.GenNot(x); DevCPL486.GenAnd(y, x) (* y and not x *)
  981. ELSIF y.mode = Con THEN y.offset := -1 - y.offset; DevCPL486.GenAnd(y, x) (* x and y' *)
  982. ELSIF y.mode = Reg THEN DevCPL486.GenNot(y); DevCPL486.GenAnd(y, x) (* x and not y *)
  983. ELSE DevCPL486.GenNot(x); DevCPL486.GenOr(y, x); DevCPL486.GenNot(x) (* not (not x or y) *)
  984. END
  985. ELSE (* minus *)
  986. IF rev THEN (* y - x *)
  987. IF (y.mode = Con) & (y.offset = -1) THEN DevCPL486.GenNot(x)
  988. ELSE DevCPL486.GenNeg(x, ovflchk); DevCPL486.GenAdd(y, x, ovflchk) (* ??? *)
  989. END
  990. ELSE (* x - y *)
  991. DevCPL486.GenSub(y, x, ovflchk)
  992. END
  993. END
  994. | min, max:
  995. local := DevCPL486.NewLbl;
  996. DevCPL486.GenComp(y, x);
  997. IF subcl = min THEN
  998. IF x.typ.form IN {Char8, Char16} THEN DevCPL486.GenJump(ccBE, local, TRUE)
  999. ELSE DevCPL486.GenJump(ccLE, local, TRUE)
  1000. END
  1001. ELSE
  1002. IF x.typ.form IN {Char8, Char16} THEN DevCPL486.GenJump(ccAE, local, TRUE)
  1003. ELSE DevCPL486.GenJump(ccGE, local, TRUE)
  1004. END
  1005. END;
  1006. DevCPL486.GenMove(y, x);
  1007. DevCPL486.SetLabel(local)
  1008. END;
  1009. Free(y);
  1010. IF x.mode # Reg THEN Free(x) END
  1011. END IntDOp;
  1012. PROCEDURE LargeInc* (VAR x, y: DevCPL486.Item; dec: BOOLEAN); (* INC(x, y) or DEC(x, y) *)
  1013. BEGIN
  1014. ASSERT(x.form = Int64);
  1015. IF ~(y.mode IN {Reg, Con}) THEN LoadLong(y, {}, {}) END;
  1016. Free(x); Free(y); x.form := Int32; y.form := Int32;
  1017. IF dec THEN DevCPL486.GenSubC(y, x, TRUE, FALSE) ELSE DevCPL486.GenAddC(y, x, TRUE, FALSE) END;
  1018. INC(x.offset, 4);
  1019. IF y.mode = Reg THEN y.reg := y.index ELSE y.offset := y.scale END;
  1020. IF dec THEN DevCPL486.GenSubC(y, x, FALSE, ovflchk) ELSE DevCPL486.GenAddC(y, x, FALSE, ovflchk) END;
  1021. END LargeInc;
  1022. PROCEDURE FloatDOp* (VAR x, y: DevCPL486.Item; subcl: BYTE; rev: BOOLEAN);
  1023. VAR local: DevCPL486.Label; a, b: DevCPL486.Item;
  1024. BEGIN
  1025. ASSERT(x.mode = Reg);
  1026. IF y.form = Int64 THEN LoadR(y) END;
  1027. IF y.mode = Reg THEN rev := ~rev END;
  1028. CASE subcl OF
  1029. | eql..geq: DevCPL486.GenFDOp(FCOMP, y)
  1030. | times: DevCPL486.GenFDOp(FMUL, y)
  1031. | slash: IF rev THEN DevCPL486.GenFDOp(FDIVR, y) ELSE DevCPL486.GenFDOp(FDIV, y) END
  1032. | plus: DevCPL486.GenFDOp(FADD, y)
  1033. | minus: IF rev THEN DevCPL486.GenFDOp(FSUBR, y) ELSE DevCPL486.GenFDOp(FSUB, y) END
  1034. | min, max:
  1035. IF y.mode = Reg THEN
  1036. DevCPL486.GenFMOp(0D1H); (* FCOM ST1 *)
  1037. CheckAv(AX); DevCPL486.GenFMOp(FSTSW); (* DevCPL486.GenCode(WAIT); *) DevCPL486.GenCode(SAHF);
  1038. local := DevCPL486.NewLbl;
  1039. IF subcl = min THEN DevCPL486.GenJump(ccAE, local, TRUE) ELSE DevCPL486.GenJump(ccBE, local, TRUE) END;
  1040. DevCPL486.GenFMOp(5D1H); (* FST ST1 *)
  1041. DevCPL486.SetLabel(local);
  1042. DevCPL486.GenFMOp(5D8H) (* FSTP ST0 *)
  1043. ELSE
  1044. DevCPL486.GenFDOp(FCOM, y);
  1045. CheckAv(AX); DevCPL486.GenFMOp(FSTSW); (* DevCPL486.GenCode(WAIT); *) DevCPL486.GenCode(SAHF);
  1046. local := DevCPL486.NewLbl;
  1047. IF subcl = min THEN DevCPL486.GenJump(ccBE, local, TRUE) ELSE DevCPL486.GenJump(ccAE, local, TRUE) END;
  1048. DevCPL486.GenFMOp(5D8H); (* FSTP ST0 *)
  1049. DevCPL486.GenFLoad(y);
  1050. DevCPL486.SetLabel(local)
  1051. END
  1052. (* largeint support *)
  1053. | div:
  1054. IF rev THEN DevCPL486.GenFDOp(FDIVR, y) ELSE DevCPL486.GenFDOp(FDIV, y) END;
  1055. Floor(y, FALSE)
  1056. | mod:
  1057. IF y.mode # Reg THEN LoadR(y); rev := ~rev END;
  1058. IF rev THEN DevCPL486.GenFMOp(1C9H); (* FXCH ST1 *) END;
  1059. DevCPL486.GenFMOp(1F8H); (* FPREM *)
  1060. DevCPL486.GenFMOp(1E4H); (* FTST *)
  1061. CheckAv(AX);
  1062. DevCPL486.GenFMOp(FSTSW);
  1063. DevCPL486.MakeReg(a, AX, Int32); GetReg(b, Int32, {}, {AX});
  1064. DevCPL486.GenMove(a, b);
  1065. DevCPL486.GenFMOp(0D1H); (* FCOM *)
  1066. DevCPL486.GenFMOp(FSTSW);
  1067. DevCPL486.GenXor(b, a); Free(b);
  1068. (* DevCPL486.GenCode(WAIT); *) DevCPL486.GenCode(SAHF);
  1069. local := DevCPL486.NewLbl; DevCPL486.GenJump(ccBE, local, TRUE);
  1070. DevCPL486.GenFMOp(0C1H); (* FADD ST1 *)
  1071. DevCPL486.SetLabel(local);
  1072. DevCPL486.GenFMOp(5D9H); (* FSTP ST1 *)
  1073. | ash:
  1074. IF y.mode # Reg THEN LoadR(y); rev := ~rev END;
  1075. IF rev THEN DevCPL486.GenFMOp(1C9H); (* FXCH ST1 *) END;
  1076. DevCPL486.GenFMOp(1FDH); (* FSCALE *)
  1077. Floor(y, TRUE)
  1078. END;
  1079. IF y.mode = Stk THEN IncStack(y.form) END;
  1080. Free(y);
  1081. IF (subcl >= eql) & (subcl <= geq) THEN
  1082. Free(x); CheckAv(AX);
  1083. DevCPL486.GenFMOp(FSTSW);
  1084. (* DevCPL486.GenCode(WAIT); *) DevCPL486.GenCode(SAHF);
  1085. setCC(x, subcl, rev, FALSE)
  1086. END
  1087. END FloatDOp;
  1088. PROCEDURE IntMOp* (VAR x: DevCPL486.Item; subcl: BYTE);
  1089. VAR L: DevCPL486.Label; c: DevCPL486.Item;
  1090. BEGIN
  1091. CASE subcl OF
  1092. | minus:
  1093. IF x.form = Set THEN DevCPL486.GenNot(x) ELSE DevCPL486.GenNeg(x, ovflchk) END
  1094. | abs:
  1095. L := DevCPL486.NewLbl; DevCPL486.MakeConst(c, 0, x.form);
  1096. DevCPL486.GenComp(c, x);
  1097. DevCPL486.GenJump(ccNS, L, TRUE);
  1098. DevCPL486.GenNeg(x, ovflchk);
  1099. DevCPL486.SetLabel(L)
  1100. | cap:
  1101. DevCPL486.MakeConst(c, -1 - 20H, x.form);
  1102. DevCPL486.GenAnd(c, x)
  1103. | not:
  1104. DevCPL486.MakeConst(c, 1, x.form);
  1105. DevCPL486.GenXor(c, x)
  1106. END;
  1107. IF x.mode # Reg THEN Free(x) END
  1108. END IntMOp;
  1109. PROCEDURE FloatMOp* (VAR x: DevCPL486.Item; subcl: BYTE);
  1110. BEGIN
  1111. ASSERT(x.mode = Reg);
  1112. IF subcl = minus THEN DevCPL486.GenFMOp(FCHS)
  1113. ELSE ASSERT(subcl = abs); DevCPL486.GenFMOp(FABS)
  1114. END
  1115. END FloatMOp;
  1116. PROCEDURE MakeSet* (VAR x: DevCPL486.Item; range, neg: BOOLEAN; hint, stop: SET);
  1117. (* range neg result
  1118. F F {x}
  1119. F T -{x}
  1120. T F {x..31}
  1121. T T -{0..x} *)
  1122. VAR c, r: DevCPL486.Item; val: INTEGER;
  1123. BEGIN
  1124. IF x.mode = Con THEN
  1125. IF range THEN
  1126. IF neg THEN val := -2 ELSE val := -1 END;
  1127. x.offset := SYSTEM.LSH(val, x.offset)
  1128. ELSE
  1129. val := 1; x.offset := SYSTEM.LSH(val, x.offset);
  1130. IF neg THEN x.offset := -1 - x.offset END
  1131. END
  1132. ELSE
  1133. Check(x, 0, 31);
  1134. IF neg THEN val := -2
  1135. ELSIF range THEN val := -1
  1136. ELSE val := 1
  1137. END;
  1138. DevCPL486.MakeConst(c, val, Set); GetReg(r, Set, hint, stop); DevCPL486.GenMove(c, r);
  1139. IF range THEN DevCPL486.GenShiftOp(SHL, x, r) ELSE DevCPL486.GenShiftOp(ROL, x, r) END;
  1140. Free(x); x.reg := r.reg
  1141. END;
  1142. x.typ := DevCPT.settyp; x.form := Set
  1143. END MakeSet;
  1144. PROCEDURE MakeCond* (VAR x: DevCPL486.Item);
  1145. VAR c: DevCPL486.Item;
  1146. BEGIN
  1147. IF x.mode = Con THEN
  1148. setCC(x, SHORT(SHORT(x.offset)), FALSE, FALSE)
  1149. ELSE
  1150. DevCPL486.MakeConst(c, 0, x.form);
  1151. DevCPL486.GenComp(c, x); Free(x);
  1152. setCC(x, neq, FALSE, FALSE)
  1153. END
  1154. END MakeCond;
  1155. PROCEDURE Not* (VAR x: DevCPL486.Item);
  1156. VAR a: INTEGER;
  1157. BEGIN
  1158. x.offset := Inverted(x.offset); (* invert cc *)
  1159. END Not;
  1160. PROCEDURE Odd* (VAR x: DevCPL486.Item);
  1161. VAR c: DevCPL486.Item;
  1162. BEGIN
  1163. IF x.mode = Stk THEN Pop(x, x.form, {}, {}) END;
  1164. Free(x); DevCPL486.MakeConst(c, 1, x.form);
  1165. IF x.mode = Reg THEN
  1166. IF x.form IN {Int16, Int64} THEN x.form := Int32; c.form := Int32 END;
  1167. DevCPL486.GenAnd(c, x)
  1168. ELSE
  1169. c.form := Int8; x.form := Int8; DevCPL486.GenTest(c, x)
  1170. END;
  1171. setCC(x, neq, FALSE, FALSE)
  1172. END Odd;
  1173. PROCEDURE In* (VAR x, y: DevCPL486.Item);
  1174. BEGIN
  1175. IF y.form = Set THEN Check(x, 0, 31) END;
  1176. DevCPL486.GenBitOp(BT, x, y); Free(x); Free(y);
  1177. setCC(x, lss, FALSE, FALSE); (* carry set *)
  1178. END In;
  1179. PROCEDURE Shift* (VAR x, y: DevCPL486.Item; subcl: BYTE); (* ASH, LSH, ROT *)
  1180. VAR L1, L2: DevCPL486.Label; c: DevCPL486.Item; opl, opr: INTEGER;
  1181. BEGIN
  1182. IF subcl = ash THEN opl := SHL; opr := SAR
  1183. ELSIF subcl = lsh THEN opl := SHL; opr := SHR
  1184. ELSE opl := ROL; opr := ROR
  1185. END;
  1186. IF y.mode = Con THEN
  1187. IF y.offset > 0 THEN
  1188. DevCPL486.GenShiftOp(opl, y, x)
  1189. ELSIF y.offset < 0 THEN
  1190. y.offset := -y.offset;
  1191. DevCPL486.GenShiftOp(opr, y, x)
  1192. END
  1193. ELSE
  1194. ASSERT(y.mode = Reg);
  1195. Check(y, -31, 31);
  1196. L1 := DevCPL486.NewLbl; L2 := DevCPL486.NewLbl;
  1197. DevCPL486.MakeConst(c, 0, y.form); DevCPL486.GenComp(c, y);
  1198. DevCPL486.GenJump(ccNS, L1, TRUE);
  1199. DevCPL486.GenNeg(y, FALSE);
  1200. DevCPL486.GenShiftOp(opr, y, x);
  1201. DevCPL486.GenJump(ccAlways, L2, TRUE);
  1202. DevCPL486.SetLabel(L1);
  1203. DevCPL486.GenShiftOp(opl, y, x);
  1204. DevCPL486.SetLabel(L2);
  1205. Free(y)
  1206. END;
  1207. IF x.mode # Reg THEN Free(x) END
  1208. END Shift;
  1209. PROCEDURE DivMod* (VAR x, y: DevCPL486.Item; mod: BOOLEAN);
  1210. VAR s: SET; r: DevCPL486.Item; pos: BOOLEAN;
  1211. BEGIN
  1212. ASSERT((x.mode = Reg) & (x.reg = AX)); pos := FALSE;
  1213. IF y.mode = Con THEN pos := (y.offset > 0) & (y.obj = NIL); Load(y, {}, {AX, DX, con}) END;
  1214. DevCPL486.GenDiv(y, mod, pos); Free(y);
  1215. IF mod THEN
  1216. r := x; GetReg(x, x.form, {}, wreg - {AX, DX}); Free(r) (* ax -> dx; al -> ah *) (* ??? *)
  1217. END
  1218. END DivMod;
  1219. PROCEDURE Mem* (VAR x: DevCPL486.Item; offset: INTEGER; typ: DevCPT.Struct); (* x := Mem[x+offset] *)
  1220. BEGIN
  1221. IF x.mode = Con THEN x.mode := Abs; x.obj := NIL; INC(x.offset, offset)
  1222. ELSE ASSERT(x.mode = Reg); x.mode := Ind; x.offset := offset
  1223. END;
  1224. x.scale := 0; x.typ := typ; x.form := typ.form
  1225. END Mem;
  1226. PROCEDURE SysMove* (VAR len: DevCPL486.Item); (* implementation of SYSTEM.MOVE *)
  1227. BEGIN
  1228. IF len.mode = Con THEN
  1229. IF len.offset > 0 THEN DevCPL486.GenBlockMove(1, len.offset) END
  1230. ELSE
  1231. Load(len, {}, wreg - {CX} + {short, mem, stk}); DevCPL486.GenBlockMove(1, 0); Free(len)
  1232. END;
  1233. FreeWReg(SI); FreeWReg(DI)
  1234. END SysMove;
  1235. PROCEDURE Len* (VAR x, y: DevCPL486.Item);
  1236. VAR typ: DevCPT.Struct; dim: INTEGER;
  1237. BEGIN
  1238. dim := y.offset; typ := x.typ;
  1239. IF typ.untagged THEN DevCPM.err(136) END;
  1240. WHILE dim > 0 DO typ := typ.BaseTyp; DEC(dim) END;
  1241. LenDesc(x, x, typ);
  1242. END Len;
  1243. PROCEDURE StringWSize (VAR x: DevCPL486.Item): INTEGER;
  1244. BEGIN
  1245. CASE x.form OF
  1246. | String8, VString8: RETURN 1
  1247. | String16, VString16: RETURN 2
  1248. | VString16to8: RETURN 0
  1249. | Comp: RETURN x.typ.BaseTyp.size
  1250. END
  1251. END StringWSize;
  1252. PROCEDURE CmpString* (VAR x, y: DevCPL486.Item; rel: BYTE; rev: BOOLEAN);
  1253. VAR sw, dw: INTEGER;
  1254. BEGIN
  1255. CheckAv(CX);
  1256. IF (x.typ = DevCPT.guidtyp) OR (y.typ = DevCPT.guidtyp) THEN
  1257. DevCPL486.GenBlockComp(4, 4)
  1258. ELSIF x.form = String8 THEN DevCPL486.GenBlockComp(1, x.index)
  1259. ELSIF y.form = String8 THEN DevCPL486.GenBlockComp(1, y.index)
  1260. ELSIF x.form = String16 THEN DevCPL486.GenBlockComp(2, x.index)
  1261. ELSIF y.form = String16 THEN DevCPL486.GenBlockComp(2, y.index)
  1262. ELSE DevCPL486.GenStringComp(StringWSize(y), StringWSize(x))
  1263. END;
  1264. FreeWReg(SI); FreeWReg(DI); setCC(x, rel, ~rev, FALSE);
  1265. END CmpString;
  1266. PROCEDURE VarParDynArr (ftyp: DevCPT.Struct; VAR y: DevCPL486.Item);
  1267. VAR len, z: DevCPL486.Item; atyp: DevCPT.Struct;
  1268. BEGIN
  1269. atyp := y.typ;
  1270. WHILE ftyp.comp = DynArr DO
  1271. IF ftyp.BaseTyp = DevCPT.bytetyp THEN
  1272. IF atyp.comp = DynArr THEN
  1273. IF atyp.untagged THEN DevCPM.err(137) END;
  1274. LenDesc(y, len, atyp);
  1275. IF y.tmode = VarPar THEN Free(len) END; (* ??? *)
  1276. GetReg(z, Int32, {}, {}); DevCPL486.GenMove(len, z);
  1277. len.mode := Reg; len.reg := z.reg; atyp := atyp.BaseTyp;
  1278. WHILE atyp.comp = DynArr DO
  1279. LenDesc(y, z, atyp); DevCPL486.GenMul(z, len, FALSE);
  1280. IF y.tmode = VarPar THEN Free(z) END; (* ??? *)
  1281. atyp := atyp.BaseTyp
  1282. END;
  1283. DevCPL486.MakeConst(z, atyp.size, Int32); DevCPL486.GenMul(z, len, FALSE);
  1284. Free(len)
  1285. ELSE
  1286. DevCPL486.MakeConst(len, atyp.size, Int32)
  1287. END
  1288. ELSE
  1289. IF atyp.comp = DynArr THEN LenDesc(y, len, atyp);
  1290. IF atyp.untagged THEN DevCPM.err(137) END;
  1291. IF y.tmode = VarPar THEN Free(len) END; (* ??? *)
  1292. ELSE DevCPL486.MakeConst(len, atyp.n, Int32)
  1293. END
  1294. END;
  1295. DevCPL486.GenPush(len);
  1296. ftyp := ftyp.BaseTyp; atyp := atyp.BaseTyp
  1297. END
  1298. END VarParDynArr;
  1299. PROCEDURE Assign* (VAR x, y: DevCPL486.Item); (* x := y *)
  1300. BEGIN
  1301. IF y.mode = Con THEN
  1302. IF y.form IN {Real32, Real64} THEN
  1303. DevCPL486.GenFLoad(y); GetReg(y, Real32, {}, {});
  1304. IF x.mode # Reg THEN Free(y); DevCPL486.GenFStore(x, TRUE) END (* ??? move const *)
  1305. ELSIF x.form = Int64 THEN
  1306. ASSERT(x.mode IN {Ind, Abs});
  1307. y.form := Int32; x.form := Int32; DevCPL486.GenMove(y, x);
  1308. y.offset := y.scale; INC(x.offset, 4); DevCPL486.GenMove(y, x);
  1309. DEC(x.offset, 4); x.form := Int64
  1310. ELSE
  1311. DevCPL486.GenMove(y, x)
  1312. END
  1313. ELSE
  1314. IF y.form IN {Comp, String8, String16, VString8, VString16} THEN (* convert to pointer *)
  1315. ASSERT(x.form = Pointer);
  1316. GetAdr(y, {}, {}); y.typ := x.typ; y.form := Pointer
  1317. END;
  1318. IF ~(x.form IN realSet) OR ~(y.form IN intSet) THEN Assert(y, {}, {stk}) END;
  1319. ConvMove(x, y, FALSE, {}, {})
  1320. END;
  1321. Free(x)
  1322. END Assign;
  1323. PROCEDURE ArrayLen* (VAR x, len: DevCPL486.Item; hint, stop: SET);
  1324. VAR c: DevCPL486.Item;
  1325. BEGIN
  1326. IF x.typ.comp = Array THEN DevCPL486.MakeConst(c, x.typ.n, Int32); GetReg(len, Int32, hint, stop); DevCPL486.GenMove(c, len)
  1327. ELSIF ~x.typ.untagged THEN LenDesc(x, c, x.typ); GetReg(len, Int32, hint, stop); DevCPL486.GenMove(c, len)
  1328. ELSE len.mode := Con
  1329. END;
  1330. len.typ := DevCPT.int32typ
  1331. END ArrayLen;
  1332. (*
  1333. (!) src dest zero
  1334. sx = sy x b y b
  1335. SHORT(lx) = sy x b+ x w y b
  1336. SHORT(lx) = SHORT(ly) x b+ x w y b+
  1337. lx = ly x w y w
  1338. LONG(sx) = ly x b y w *
  1339. LONG(SHORT(lx)) = ly x b+ x w* y w *
  1340. sx := sy y b x b
  1341. sx := SHORT(ly) y b+ y w x b
  1342. lx := ly y w x w
  1343. lx := LONG(sy) y b x w *
  1344. lx := LONG(SHORT(ly)) y b+ y w* x w *
  1345. (!)*)
  1346. PROCEDURE AddCopy* (VAR x, y: DevCPL486.Item; last: BOOLEAN); (* x := .. + y + .. *)
  1347. BEGIN
  1348. IF (x.typ.comp = DynArr) & x.typ.untagged THEN
  1349. DevCPL486.GenStringMove(~last, StringWSize(y), StringWSize(x), -1)
  1350. ELSE
  1351. DevCPL486.GenStringMove(~last, StringWSize(y), StringWSize(x), 0)
  1352. END;
  1353. FreeWReg(SI); FreeWReg(DI)
  1354. END AddCopy;
  1355. PROCEDURE Copy* (VAR x, y: DevCPL486.Item; short: BOOLEAN); (* x := y *)
  1356. VAR sx, sy, sy2, sy4: INTEGER; c, r: DevCPL486.Item;
  1357. BEGIN
  1358. sx := x.typ.size; CheckAv(CX);
  1359. IF y.form IN {String8, String16} THEN
  1360. sy := y.index * y.typ.BaseTyp.size;
  1361. IF x.typ.comp = Array THEN (* adjust size for optimal performance *)
  1362. sy2 := sy + sy MOD 2; sy4 := sy2 + sy2 MOD 4;
  1363. IF sy4 <= sx THEN sy := sy4
  1364. ELSIF sy2 <= sx THEN sy := sy2
  1365. ELSIF sy > sx THEN DevCPM.err(114); sy := 1
  1366. END
  1367. ELSIF inxchk & ~x.typ.untagged THEN (* check array length *)
  1368. Free(x); LenDesc(x, c, x.typ);
  1369. DevCPL486.MakeConst(y, y.index, Int32);
  1370. DevCPL486.GenComp(y, c); DevCPL486.GenAssert(ccAE, copyTrap);
  1371. Free(c)
  1372. END;
  1373. DevCPL486.GenBlockMove(1, sy)
  1374. ELSIF x.typ.comp = DynArr THEN
  1375. IF x.typ.untagged THEN
  1376. DevCPL486.GenStringMove(FALSE, StringWSize(y), StringWSize(x), -1)
  1377. ELSE
  1378. Free(x); LenDesc(x, c, x.typ); DevCPL486.MakeReg(r, CX, Int32); DevCPL486.GenMove(c, r); Free(c);
  1379. DevCPL486.GenStringMove(FALSE, StringWSize(y), StringWSize(x), 0)
  1380. END
  1381. ELSIF y.form IN {VString16to8, VString8, VString16} THEN
  1382. DevCPL486.GenStringMove(FALSE, StringWSize(y), StringWSize(x), x.typ.n);
  1383. ASSERT(y.mode # Stk)
  1384. ELSIF short THEN (* COPY *)
  1385. sy := y.typ.size;
  1386. IF (y.typ.comp # DynArr) & (sy < sx) THEN sx := sy END;
  1387. DevCPL486.GenStringMove(FALSE, StringWSize(y), StringWSize(x), x.typ.n);
  1388. IF y.mode = Stk THEN AdjustStack(sy) END
  1389. ELSE (* := *)
  1390. IF sx > 0 THEN DevCPL486.GenBlockMove(1, sx) END;
  1391. IF y.mode = Stk THEN AdjustStack(sy) END
  1392. END;
  1393. FreeWReg(SI); FreeWReg(DI)
  1394. END Copy;
  1395. PROCEDURE StrLen* (VAR x: DevCPL486.Item; typ: DevCPT.Struct; incl0x: BOOLEAN);
  1396. VAR c: DevCPL486.Item;
  1397. BEGIN
  1398. CheckAv(AX); CheckAv(CX);
  1399. DevCPL486.GenStringLength(typ.BaseTyp.size, -1);
  1400. Free(x); GetReg(x, Int32, {}, wreg - {CX});
  1401. DevCPL486.GenNot(x);
  1402. IF ~incl0x THEN DevCPL486.MakeConst(c, 1, Int32); DevCPL486.GenSub(c, x, FALSE) END;
  1403. FreeWReg(DI)
  1404. END StrLen;
  1405. PROCEDURE MulDim* (VAR y, z: DevCPL486.Item; VAR fact: INTEGER; dimtyp: DevCPT.Struct); (* z := z * y *)
  1406. VAR c: DevCPL486.Item;
  1407. BEGIN
  1408. IF y.mode = Con THEN fact := fact * y.offset
  1409. ELSE
  1410. IF ranchk OR inxchk THEN
  1411. DevCPL486.MakeConst(c, 0, Int32); DevCPL486.GenComp(c, y); DevCPL486.GenAssert(ccG, ranTrap)
  1412. END;
  1413. DevCPL486.GenPush(y);
  1414. IF z.mode = Con THEN z := y
  1415. ELSE DevCPL486.GenMul(y, z, ovflchk OR inxchk); Free(y)
  1416. END
  1417. END
  1418. END MulDim;
  1419. PROCEDURE SetDim* (VAR x, y: DevCPL486.Item; dimtyp: DevCPT.Struct); (* set LEN(x^, -dimtyp.n) *)
  1420. (* y const or on stack *)
  1421. VAR z: DevCPL486.Item; end: DevCPL486.Label;
  1422. BEGIN
  1423. ASSERT((x.mode = Reg) & (x.form = Pointer));
  1424. z.mode := Ind; z.reg := x.reg; z.offset := ArrDOffs + 4 + dimtyp.n * 4; z.scale := 0; z.form := Int32;
  1425. IF y.mode = Con THEN y.form := Int32
  1426. ELSE Pop(y, Int32, {}, {})
  1427. END;
  1428. end := DevCPL486.NewLbl; DevCPL486.GenJump(ccE, end, TRUE); (* flags set in New *)
  1429. DevCPL486.GenMove(y, z);
  1430. DevCPL486.SetLabel(end);
  1431. IF y.mode = Reg THEN Free(y) END
  1432. END SetDim;
  1433. PROCEDURE SysNew* (VAR x: DevCPL486.Item);
  1434. BEGIN
  1435. DevCPM.err(141)
  1436. END SysNew;
  1437. PROCEDURE New* (VAR x, nofel: DevCPL486.Item; fact: INTEGER);
  1438. (* x.typ.BaseTyp.comp IN {Record, Array, DynArr} *)
  1439. VAR p, tag, c: DevCPL486.Item; nofdim, dlen, n: INTEGER; typ, eltyp: DevCPT.Struct; lbl: DevCPL486.Label;
  1440. BEGIN
  1441. typ := x.typ.BaseTyp;
  1442. IF typ.untagged THEN DevCPM.err(138) END;
  1443. IF typ.comp = Record THEN (* call to Kernel.NewRec(tag: Tag): ADDRESS *)
  1444. DevCPL486.MakeConst(tag, 0, Pointer); tag.obj := DevCPE.TypeObj(typ);
  1445. IF ContainsIPtrs(typ) THEN INC(tag.offset) END;
  1446. DevCPL486.GenPush(tag);
  1447. p.mode := XProc; p.obj := DevCPE.KNewRec;
  1448. ELSE eltyp := typ.BaseTyp;
  1449. IF typ.comp = Array THEN
  1450. nofdim := 0; nofel.mode := Con; nofel.form := Int32; fact := typ.n
  1451. ELSE (* DynArr *)
  1452. nofdim := typ.n+1;
  1453. WHILE eltyp.comp = DynArr DO eltyp := eltyp.BaseTyp END
  1454. END ;
  1455. WHILE eltyp.comp = Array DO fact := fact * eltyp.n; eltyp := eltyp.BaseTyp END;
  1456. IF eltyp.comp = Record THEN
  1457. IF eltyp.untagged THEN DevCPM.err(138) END;
  1458. DevCPL486.MakeConst(tag, 0, Pointer); tag.obj := DevCPE.TypeObj(eltyp);
  1459. IF ContainsIPtrs(eltyp) THEN INC(tag.offset) END;
  1460. ELSIF eltyp.form = Pointer THEN
  1461. IF ~eltyp.untagged THEN
  1462. DevCPL486.MakeConst(tag, 0, Pointer) (* special TDesc in Kernel for ARRAY OF pointer *)
  1463. ELSIF eltyp.sysflag = interface THEN
  1464. DevCPL486.MakeConst(tag, -1, Pointer) (* special TDesc in Kernel for ARRAY OF interface pointer *)
  1465. ELSE
  1466. DevCPL486.MakeConst(tag, 12, Pointer)
  1467. END
  1468. ELSE (* eltyp is pointerless basic type *)
  1469. CASE eltyp.form OF
  1470. | Undef, Byte, Char8: n := 1;
  1471. | Int16: n := 2;
  1472. | Int8: n := 3;
  1473. | Int32: n := 4;
  1474. | Bool: n := 5;
  1475. | Set: n := 6;
  1476. | Real32: n := 7;
  1477. | Real64: n := 8;
  1478. | Char16: n := 9;
  1479. | Int64: n := 10;
  1480. | ProcTyp: n := 11;
  1481. END;
  1482. DevCPL486.MakeConst(tag, n, Pointer)
  1483. (*
  1484. DevCPL486.MakeConst(tag, eltyp.size, Pointer)
  1485. *)
  1486. END;
  1487. IF nofel.mode = Con THEN nofel.offset := fact; nofel.obj := NIL
  1488. ELSE DevCPL486.MakeConst(p, fact, Int32); DevCPL486.GenMul(p, nofel, ovflchk OR inxchk)
  1489. END;
  1490. DevCPL486.MakeConst(p, nofdim, Int32); DevCPL486.GenPush(p);
  1491. DevCPL486.GenPush(nofel); Free(nofel); DevCPL486.GenPush(tag);
  1492. p.mode := XProc; p.obj := DevCPE.KNewArr;
  1493. END;
  1494. DevCPL486.GenCall(p); GetReg(x, Pointer, {}, wreg - {AX});
  1495. IF typ.comp = DynArr THEN (* set flags for nil test *)
  1496. DevCPL486.MakeConst(c, 0, Pointer); DevCPL486.GenComp(c, x)
  1497. ELSIF typ.comp = Record THEN
  1498. n := NumOfIntProc(typ);
  1499. IF n > 0 THEN (* interface method table pointer setup *)
  1500. DevCPL486.MakeConst(c, 0, Pointer); DevCPL486.GenComp(c, x);
  1501. lbl := DevCPL486.NewLbl; DevCPL486.GenJump(ccE, lbl, TRUE);
  1502. tag.offset := - 4 * (n + numPreIntProc);
  1503. p.mode := Ind; p.reg := AX; p.offset := 0; p.scale := 0; p.form := Pointer;
  1504. DevCPL486.GenMove(tag, p);
  1505. IF nofel.mode # Con THEN (* unk pointer setup *)
  1506. p.offset := 8;
  1507. DevCPL486.GenMove(nofel, p);
  1508. Free(nofel)
  1509. END;
  1510. DevCPL486.SetLabel(lbl);
  1511. END
  1512. END
  1513. END New;
  1514. PROCEDURE Param* (fp: DevCPT.Object; rec, niltest: BOOLEAN; VAR ap, tag: DevCPL486.Item); (* returns tag if rec *)
  1515. VAR f: BYTE; s, ss: INTEGER; par, a, c: DevCPL486.Item; recTyp: DevCPT.Struct;
  1516. BEGIN
  1517. par.mode := Stk; par.typ := fp.typ; par.form := par.typ.form;
  1518. IF ODD(fp.sysflag DIV nilBit) THEN niltest := FALSE END;
  1519. IF ap.typ = DevCPT.niltyp THEN
  1520. IF ((par.typ.comp = Record) OR (par.typ.comp = DynArr)) & ~par.typ.untagged THEN
  1521. DevCPM.err(142)
  1522. END;
  1523. DevCPL486.GenPush(ap)
  1524. ELSIF par.typ.comp = DynArr THEN
  1525. IF ap.form IN {String8, String16} THEN
  1526. IF ~par.typ.untagged THEN
  1527. DevCPL486.MakeConst(c, ap.index (* * ap.typ.BaseTyp.size *), Int32); DevCPL486.GenPush(c)
  1528. END;
  1529. ap.mode := Con; DevCPL486.GenPush(ap);
  1530. ELSIF ap.form IN {VString8, VString16} THEN
  1531. DevCPL486.MakeReg(a, DX, Pointer); DevCPL486.GenLoadAdr(ap, a);
  1532. IF ~par.typ.untagged THEN
  1533. DevCPL486.MakeReg(c, DI, Pointer); DevCPL486.GenMove(a, c);
  1534. Free(ap); StrLen(c, ap.typ, TRUE);
  1535. DevCPL486.GenPush(c); Free(c)
  1536. END;
  1537. DevCPL486.GenPush(a)
  1538. ELSE
  1539. IF ~par.typ.untagged THEN
  1540. IF ap.typ.comp = DynArr THEN niltest := FALSE END; (* ap dereferenced for length descriptor *)
  1541. VarParDynArr(par.typ, ap)
  1542. END;
  1543. PushAdr(ap, niltest)
  1544. END
  1545. ELSIF fp.mode = VarPar THEN
  1546. recTyp := ap.typ;
  1547. IF recTyp.form = Pointer THEN recTyp := recTyp.BaseTyp END;
  1548. IF (par.typ.comp = Record) & (~fp.typ.untagged) THEN
  1549. Tag(ap, tag);
  1550. IF rec & (tag.mode # Con) THEN
  1551. GetReg(c, Pointer, {}, {}); DevCPL486.GenMove(tag, c); tag := c
  1552. END;
  1553. DevCPL486.GenPush(tag);
  1554. IF tag.mode # Con THEN niltest := FALSE END;
  1555. PushAdr(ap, niltest);
  1556. IF rec THEN Free(tag) END
  1557. ELSE PushAdr(ap, niltest)
  1558. END;
  1559. tag.typ := recTyp
  1560. ELSIF par.form = Comp THEN
  1561. s := par.typ.size;
  1562. IF initializeStr & (ap.form IN {String8, String16, VString8, VString16, VString16to8}) THEN
  1563. s := (s + 3) DIV 4 * 4; AdjustStack(-s);
  1564. IF ap.form IN {String8, String16} THEN
  1565. IF ap.index > 1 THEN (* nonempty string *)
  1566. ss := (ap.index * ap.typ.BaseTyp.size + 3) DIV 4 * 4;
  1567. DevCPL486.MakeReg(c, SI, Pointer); DevCPL486.GenLoadAdr(ap, c); Free(ap);
  1568. DevCPL486.MakeReg(c, DI, Pointer); DevCPL486.GenLoadAdr(par, c);
  1569. DevCPL486.GenBlockMove(1, ss);
  1570. ELSE
  1571. ss := 0;
  1572. DevCPL486.MakeReg(c, DI, Pointer); DevCPL486.GenLoadAdr(par, c)
  1573. END;
  1574. IF s > ss THEN
  1575. DevCPL486.MakeReg(a, AX, Int32); DevCPL486.MakeConst(c, 0, Int32); DevCPL486.GenMove(c, a);
  1576. DevCPL486.GenBlockStore(1, s - ss)
  1577. END;
  1578. ELSE
  1579. DevCPL486.MakeReg(c, SI, Pointer); DevCPL486.GenLoadAdr(ap, c); Free(ap);
  1580. DevCPL486.MakeReg(c, DI, Pointer); DevCPL486.GenLoadAdr(par, c);
  1581. DevCPL486.GenStringMove(TRUE, StringWSize(ap), StringWSize(par), par.typ.n);
  1582. DevCPL486.MakeReg(a, AX, Int32); DevCPL486.MakeConst(c, 0, Int32); DevCPL486.GenMove(c, a);
  1583. DevCPL486.GenBlockStore(StringWSize(par), 0)
  1584. END
  1585. ELSE
  1586. IF (ap.form IN {String8, String16}) & (ap.index = 1) THEN (* empty string *)
  1587. AdjustStack((4 - s) DIV 4 * 4);
  1588. DevCPL486.MakeConst(c, 0, Int32); DevCPL486.GenPush(c)
  1589. ELSE
  1590. AdjustStack((-s) DIV 4 * 4);
  1591. DevCPL486.MakeReg(c, SI, Pointer); DevCPL486.GenLoadAdr(ap, c); Free(ap);
  1592. DevCPL486.MakeReg(c, DI, Pointer); DevCPL486.GenLoadAdr(par, c);
  1593. IF ap.form IN {String8, String16} THEN
  1594. DevCPL486.GenBlockMove(1, (ap.index * ap.typ.BaseTyp.size + 3) DIV 4 * 4)
  1595. ELSIF ap.form IN {VString8, VString16, VString16to8} THEN
  1596. DevCPL486.GenStringMove(FALSE, StringWSize(ap), StringWSize(par), par.typ.n)
  1597. ELSE
  1598. DevCPL486.GenBlockMove(1, (s + 3) DIV 4 * 4)
  1599. END
  1600. END
  1601. END
  1602. ELSIF ap.mode = Con THEN
  1603. IF ap.form IN {Real32, Real64} THEN (* ??? push const *)
  1604. DevCPL486.GenFLoad(ap); DecStack(par.typ.form); DevCPL486.GenFStore(par, TRUE)
  1605. ELSE
  1606. ap.form := Int32;
  1607. IF par.form = Int64 THEN DevCPL486.MakeConst(c, ap.scale, Int32); DevCPL486.GenPush(c) END;
  1608. DevCPL486.GenPush(ap)
  1609. END
  1610. ELSIF ap.typ.form = Pointer THEN
  1611. recTyp := ap.typ.BaseTyp;
  1612. IF rec THEN
  1613. Load(ap, {}, {}); Tag(ap, tag);
  1614. IF tag.mode = Con THEN (* explicit nil test needed *)
  1615. DevCPL486.MakeReg(a, AX, Int32);
  1616. c.mode := Ind; c.form := Int32; c.offset := 0; c.scale := 0; c.reg := ap.reg;
  1617. DevCPL486.GenTest(a, c)
  1618. END
  1619. END;
  1620. DevCPL486.GenPush(ap); Free(ap);
  1621. tag.typ := recTyp
  1622. ELSIF ap.form IN {Comp, String8, String16, VString8, VString16} THEN (* convert to pointer *)
  1623. ASSERT(par.form = Pointer);
  1624. PushAdr(ap, FALSE)
  1625. ELSE
  1626. ConvMove(par, ap, FALSE, {}, {high});
  1627. END
  1628. END Param;
  1629. PROCEDURE Result* (proc: DevCPT.Object; VAR res: DevCPL486.Item);
  1630. VAR r: DevCPL486.Item;
  1631. BEGIN
  1632. DevCPL486.MakeReg(r, AX, proc.typ.form); (* don't allocate AX ! *)
  1633. IF res.mode = Con THEN
  1634. IF r.form IN {Real32, Real64} THEN DevCPL486.GenFLoad(res);
  1635. ELSIF r.form = Int64 THEN
  1636. r.form := Int32; res.form := Int32; DevCPL486.GenMove(res, r);
  1637. r.reg := DX; res.offset := res.scale; DevCPL486.GenMove(res, r)
  1638. ELSE DevCPL486.GenMove(res, r);
  1639. END
  1640. ELSIF res.form IN {Comp, String8, String16, VString8, VString16} THEN (* convert to pointer *)
  1641. ASSERT(r.form = Pointer);
  1642. GetAdr(res, {}, wreg - {AX})
  1643. ELSE
  1644. r.index := DX; (* for int64 *)
  1645. ConvMove(r, res, FALSE, wreg - {AX} + {high}, {});
  1646. END;
  1647. Free(res)
  1648. END Result;
  1649. PROCEDURE InitFpu;
  1650. VAR x: DevCPL486.Item;
  1651. BEGIN
  1652. DevCPL486.MakeConst(x, FpuControlRegister, Int32); DevCPL486.GenPush(x);
  1653. DevCPL486.GenFMOp(12CH); DevCPL486.GenCode(24H); (* FLDCW 0(SP) *)
  1654. DevCPL486.MakeReg(x, CX, Int32); DevCPL486.GenPop(x); (* reset stack *)
  1655. END InitFpu;
  1656. PROCEDURE PrepCall* (proc: DevCPT.Object);
  1657. VAR lev: BYTE; r: DevCPL486.Item;
  1658. BEGIN
  1659. lev := proc.mnolev;
  1660. IF (slNeeded IN proc.conval.setval) & (imLevel[lev] > 0) & (imLevel[DevCPL486.level] > imLevel[lev]) THEN
  1661. DevCPL486.MakeReg(r, BX, Pointer); DevCPL486.GenPush(r)
  1662. END
  1663. END PrepCall;
  1664. PROCEDURE Call* (VAR x, tag: DevCPL486.Item); (* TProc: tag.typ = actual receiver type *)
  1665. VAR i, n: INTEGER; r, y: DevCPL486.Item; typ: DevCPT.Struct; lev: BYTE; saved: BOOLEAN; p: DevCPT.Object;
  1666. BEGIN
  1667. IF x.mode IN {LProc, XProc, IProc} THEN
  1668. lev := x.obj.mnolev; saved := FALSE;
  1669. IF (slNeeded IN x.obj.conval.setval) & (imLevel[lev] > 0) THEN (* pass static link *)
  1670. n := imLevel[DevCPL486.level] - imLevel[lev];
  1671. IF n > 0 THEN
  1672. saved := TRUE;
  1673. y.mode := Ind; y.scale := 0; y.form := Pointer; y.reg := BX; y.offset := -4;
  1674. DevCPL486.MakeReg(r, BX, Pointer);
  1675. WHILE n > 0 DO DevCPL486.GenMove(y, r); DEC(n) END
  1676. END
  1677. END;
  1678. DevCPL486.GenCall(x);
  1679. IF x.obj.sysflag = ccall THEN (* remove parameters *)
  1680. p := x.obj.link; n := 0;
  1681. WHILE p # NIL DO
  1682. IF p.mode = VarPar THEN INC(n, 4)
  1683. ELSE INC(n, (p.typ.size + 3) DIV 4 * 4)
  1684. END;
  1685. p := p.link
  1686. END;
  1687. AdjustStack(n)
  1688. END;
  1689. IF saved THEN DevCPL486.GenPop(r) END;
  1690. ELSIF x.mode = TProc THEN
  1691. IF x.scale = 1 THEN (* super *)
  1692. DevCPL486.MakeConst(tag, 0, Pointer); tag.obj := DevCPE.TypeObj(tag.typ.BaseTyp)
  1693. ELSIF x.scale = 2 THEN (* static call *)
  1694. DevCPL486.MakeConst(tag, 0, Pointer); typ := x.obj.link.typ;
  1695. IF typ.form = Pointer THEN typ := typ.BaseTyp END;
  1696. tag.obj := DevCPE.TypeObj(typ)
  1697. ELSIF x.scale = 3 THEN (* interface method call *)
  1698. DevCPM.err(200)
  1699. END;
  1700. IF tag.mode = Con THEN
  1701. y.mode := Abs; y.offset := tag.offset; y.obj := tag.obj; y.scale := 0
  1702. ELSIF (x.obj.conval.setval * {absAttr, empAttr, extAttr} = {}) & ~(DevCPM.oberon IN DevCPM.options) THEN (* final method *)
  1703. y.mode := Abs; y.offset := 0; y.obj := DevCPE.TypeObj(tag.typ); y.scale := 0;
  1704. IF tag.mode = Ind THEN (* nil test *)
  1705. DevCPL486.MakeReg(r, AX, Int32); tag.offset := 0; DevCPL486.GenTest(r, tag)
  1706. END
  1707. ELSE
  1708. IF tag.mode = Reg THEN y.reg := tag.reg
  1709. ELSE GetReg(y, Pointer, {}, {}); DevCPL486.GenMove(tag, y)
  1710. END;
  1711. y.mode := Ind; y.offset := 0; y.scale := 0
  1712. END;
  1713. IF (tag.typ.sysflag = interface) & (y.mode = Ind) THEN y.offset := 4 * x.offset
  1714. ELSIF tag.typ.untagged THEN DevCPM.err(140)
  1715. ELSE
  1716. IF x.obj.link.typ.sysflag = interface THEN (* correct method number *)
  1717. x.offset := numPreIntProc + NumOfIntProc(tag.typ) - 1 - x.offset
  1718. END;
  1719. INC(y.offset, Mth0Offset - 4 * x.offset)
  1720. END;
  1721. DevCPL486.GenCall(y); Free(y)
  1722. ELSIF x.mode = CProc THEN
  1723. IF x.obj.link # NIL THEN (* tag = first param *)
  1724. IF x.obj.link.mode = VarPar THEN
  1725. GetAdr(tag, {}, wreg - {AX} + {stk, mem, con}); Free(tag)
  1726. ELSE
  1727. (* Load(tag, {}, wreg - {AX} + {con}); Free(tag) *)
  1728. Result(x.obj.link, tag) (* use result load for first parameter *)
  1729. END
  1730. END;
  1731. i := 1; n := ORD(x.obj.conval.ext^[0]);
  1732. WHILE i <= n DO DevCPL486.GenCode(ORD(x.obj.conval.ext^[i])); INC(i) END
  1733. ELSE (* proc var *)
  1734. DevCPL486.GenCall(x); Free(x);
  1735. IF x.typ.sysflag = ccall THEN (* remove parameters *)
  1736. p := x.typ.link; n := 0;
  1737. WHILE p # NIL DO
  1738. IF p.mode = VarPar THEN INC(n, 4)
  1739. ELSE INC(n, (p.typ.size + 3) DIV 4 * 4)
  1740. END;
  1741. p := p.link
  1742. END;
  1743. AdjustStack(n)
  1744. END;
  1745. x.typ := x.typ.BaseTyp
  1746. END;
  1747. IF procedureUsesFpu & (x.mode = XProc) & (x.obj.mnolev < 0) & (x.obj.mnolev > -128)
  1748. & ((x.obj.library # NIL) OR (DevCPT.GlbMod[-x.obj.mnolev].library # NIL)) THEN (* restore fpu *)
  1749. InitFpu
  1750. END;
  1751. CheckReg;
  1752. IF x.typ.form = Int64 THEN
  1753. GetReg(x, Int32, {}, wreg - {AX}); GetReg(y, Int32, {}, wreg - {DX});
  1754. x.index := y.reg; x.form := Int64
  1755. ELSIF x.typ.form # NoTyp THEN GetReg(x, x.typ.form, {}, wreg - {AX} + {high})
  1756. END
  1757. END Call;
  1758. PROCEDURE CopyDynArray* (adr: INTEGER; typ: DevCPT.Struct); (* needs CX, SI, DI *)
  1759. VAR len, ptr, c, sp, src, dst: DevCPL486.Item; bt: DevCPT.Struct;
  1760. BEGIN
  1761. IF typ.untagged THEN DevCPM.err(-137) END;
  1762. ptr.mode := Ind; ptr.reg := BP; ptr.offset := adr+4; ptr.scale := 0; ptr.form := Pointer;
  1763. DevCPL486.MakeReg(len, CX, Int32); DevCPL486.MakeReg(sp, SP, Int32);
  1764. DevCPL486.MakeReg(src, SI, Int32); DevCPL486.MakeReg(dst, DI, Int32);
  1765. DevCPL486.GenMove(ptr, len); bt := typ.BaseTyp;
  1766. WHILE bt.comp = DynArr DO
  1767. INC(ptr.offset, 4); DevCPL486.GenMul(ptr, len, FALSE); bt := bt.BaseTyp
  1768. END;
  1769. ptr.offset := adr; DevCPL486.GenMove(ptr, src);
  1770. DevCPL486.MakeConst(c, bt.size, Int32); DevCPL486.GenMul(c, len, FALSE);
  1771. (* CX = length in bytes *)
  1772. StackAlloc;
  1773. (* CX = length in 32bit words *)
  1774. DevCPL486.GenMove(sp, dst); DevCPL486.GenMove(dst, ptr);
  1775. DevCPL486.GenBlockMove(4, 0) (* 32bit moves *)
  1776. END CopyDynArray;
  1777. PROCEDURE Sort (VAR tab: ARRAY OF INTEGER; VAR n: INTEGER);
  1778. VAR i, j, x: INTEGER;
  1779. BEGIN
  1780. (* align *)
  1781. i := 1;
  1782. WHILE i < n DO
  1783. x := tab[i]; j := i-1;
  1784. WHILE (j >= 0) & (tab[j] < x) DO tab[j+1] := tab[j]; DEC(j) END;
  1785. tab[j+1] := x; INC(i)
  1786. END;
  1787. (* eliminate equals *)
  1788. i := 1; j := 1;
  1789. WHILE i < n DO
  1790. IF tab[i] # tab[i-1] THEN tab[j] := tab[i]; INC(j) END;
  1791. INC(i)
  1792. END;
  1793. n := j
  1794. END Sort;
  1795. PROCEDURE FindPtrs (typ: DevCPT.Struct; adr: INTEGER; VAR num: INTEGER);
  1796. VAR fld: DevCPT.Object; btyp: DevCPT.Struct; i, n: INTEGER;
  1797. BEGIN
  1798. IF typ.form IN {Pointer, ProcTyp} THEN
  1799. IF num < MaxPtrs THEN ptrTab[num] := adr DIV 4 * 4 END;
  1800. INC(num);
  1801. IF adr MOD 4 # 0 THEN
  1802. IF num < MaxPtrs THEN ptrTab[num] := adr DIV 4 * 4 + 4 END;
  1803. INC(num)
  1804. END
  1805. ELSIF typ.comp = Record THEN
  1806. btyp := typ.BaseTyp;
  1807. IF btyp # NIL THEN FindPtrs(btyp, adr, num) END ;
  1808. fld := typ.link;
  1809. WHILE (fld # NIL) & (fld.mode = Fld) DO
  1810. IF (fld.name^ = DevCPM.HdPtrName) OR
  1811. (fld.name^ = DevCPM.HdUtPtrName) OR
  1812. (fld.name^ = DevCPM.HdProcName) THEN
  1813. FindPtrs(DevCPT.sysptrtyp, fld.adr + adr, num)
  1814. ELSE FindPtrs(fld.typ, fld.adr + adr, num)
  1815. END;
  1816. fld := fld.link
  1817. END
  1818. ELSIF typ.comp = Array THEN
  1819. btyp := typ.BaseTyp; n := typ.n;
  1820. WHILE btyp.comp = Array DO n := btyp.n * n; btyp := btyp.BaseTyp END ;
  1821. IF (btyp.form = Pointer) OR (btyp.comp = Record) THEN
  1822. i := num; FindPtrs(btyp, adr, num);
  1823. IF num # i THEN i := 1;
  1824. WHILE (i < n) & (num <= MaxPtrs) DO
  1825. INC(adr, btyp.size); FindPtrs(btyp, adr, num); INC(i)
  1826. END
  1827. END
  1828. END
  1829. END
  1830. END FindPtrs;
  1831. PROCEDURE InitOutPar (par: DevCPT.Object; VAR zreg: DevCPL486.Item);
  1832. VAR x, y, c, len: DevCPL486.Item; lbl: DevCPL486.Label; size, s: INTEGER; bt: DevCPT.Struct;
  1833. BEGIN
  1834. x.mode := Ind; x.reg := BP; x.scale := 0; x.form := Pointer; x.offset := par.adr;
  1835. DevCPL486.MakeReg(y, DI, Int32);
  1836. IF par.typ.comp # DynArr THEN
  1837. DevCPL486.GenMove(x, y);
  1838. lbl := DevCPL486.NewLbl;
  1839. IF ODD(par.sysflag DIV nilBit) THEN
  1840. DevCPL486.GenComp(zreg, y);
  1841. DevCPL486.GenJump(ccE, lbl, TRUE)
  1842. END;
  1843. size := par.typ.size;
  1844. IF size <= 16 THEN
  1845. x.mode := Ind; x.reg := DI; x.form := Int32; x.offset := 0;
  1846. WHILE size > 0 DO
  1847. IF size = 1 THEN x.form := Int8; s := 1
  1848. ELSIF size = 2 THEN x.form := Int16; s := 2
  1849. ELSE x.form := Int32; s := 4
  1850. END;
  1851. zreg.form := x.form; DevCPL486.GenMove(zreg, x); INC(x.offset, s); DEC(size, s)
  1852. END;
  1853. zreg.form := Int32
  1854. ELSE
  1855. DevCPL486.GenBlockStore(1, size)
  1856. END;
  1857. DevCPL486.SetLabel(lbl)
  1858. ELSIF initializeDyn & ~par.typ.untagged THEN (* untagged open arrays not initialized !!! *)
  1859. DevCPL486.GenMove(x, y);
  1860. DevCPL486.MakeReg(len, CX, Int32);
  1861. INC(x.offset, 4); DevCPL486.GenMove(x, len); (* first len *)
  1862. bt := par.typ.BaseTyp;
  1863. WHILE bt.comp = DynArr DO
  1864. INC(x.offset, 4); DevCPL486.GenMul(x, len, FALSE); bt := bt.BaseTyp
  1865. END;
  1866. size := bt.size;
  1867. IF size MOD 4 = 0 THEN size := size DIV 4; s := 4
  1868. ELSIF size MOD 2 = 0 THEN size := size DIV 2; s := 2
  1869. ELSE s := 1
  1870. END;
  1871. DevCPL486.MakeConst(c, size, Int32); DevCPL486.GenMul(c, len, FALSE);
  1872. DevCPL486.GenBlockStore(s, 0)
  1873. END
  1874. END InitOutPar;
  1875. PROCEDURE AllocAndInitAll (proc: DevCPT.Object; adr, size: INTEGER; VAR nofptrs: INTEGER);
  1876. VAR x, y, z, zero: DevCPL486.Item; par: DevCPT.Object; op: INTEGER;
  1877. BEGIN
  1878. op := 0; par := proc.link;
  1879. WHILE par # NIL DO (* count out parameters [with COM pointers] *)
  1880. IF (par.mode = VarPar) & (par.vis = outPar) & (initializeOut OR ContainsIPtrs(par.typ)) THEN INC(op) END;
  1881. par := par.link
  1882. END;
  1883. DevCPL486.MakeConst(zero, 0, Int32);
  1884. IF (op = 0) & (size <= 8) THEN (* use PUSH 0 *)
  1885. WHILE size > 0 DO DevCPL486.GenPush(zero); DEC(size, 4) END
  1886. ELSE
  1887. DevCPL486.MakeReg(z, AX, Int32); DevCPL486.GenMove(zero, z);
  1888. IF size <= 32 THEN (* use PUSH reg *)
  1889. WHILE size > 0 DO DevCPL486.GenPush(z); DEC(size, 4) END
  1890. ELSE (* use string store *)
  1891. AdjustStack(-size);
  1892. DevCPL486.MakeReg(x, SP, Int32); DevCPL486.MakeReg(y, DI, Int32); DevCPL486.GenMove(x, y);
  1893. DevCPL486.GenBlockStore(1, size)
  1894. END;
  1895. IF op > 0 THEN
  1896. par := proc.link;
  1897. WHILE par # NIL DO (* init out parameters [with COM pointers] *)
  1898. IF (par.mode = VarPar) & (par.vis = outPar) & (initializeOut OR ContainsIPtrs(par.typ)) THEN InitOutPar(par, z) END;
  1899. par := par.link
  1900. END
  1901. END
  1902. END
  1903. END AllocAndInitAll;
  1904. PROCEDURE AllocAndInitPtrs1 (proc: DevCPT.Object; adr, size: INTEGER; VAR nofptrs: INTEGER); (* needs AX *)
  1905. VAR i, base, a, gaps: INTEGER; x, z: DevCPL486.Item; obj: DevCPT.Object;
  1906. BEGIN
  1907. IF ptrinit & (proc.scope # NIL) THEN
  1908. nofptrs := 0; obj := proc.scope.scope; (* local variables *)
  1909. WHILE (obj # NIL) & (nofptrs <= MaxPtrs) DO
  1910. FindPtrs(obj.typ, obj.adr, nofptrs);
  1911. obj := obj.link
  1912. END;
  1913. IF (nofptrs > 0) & (nofptrs <= MaxPtrs) THEN
  1914. base := proc.conval.intval2;
  1915. Sort(ptrTab, nofptrs); i := 0; a := size + base; gaps := 0;
  1916. WHILE i < nofptrs DO
  1917. DEC(a, 4);
  1918. IF a # ptrTab[i] THEN a := ptrTab[i]; INC(gaps) END;
  1919. INC(i)
  1920. END;
  1921. IF a # base THEN INC(gaps) END;
  1922. IF (gaps <= (nofptrs + 1) DIV 2) & (size < stackAllocLimit) THEN
  1923. DevCPL486.MakeConst(z, 0, Pointer);
  1924. IF (nofptrs > 4) THEN x := z; DevCPL486.MakeReg(z, AX, Int32); DevCPL486.GenMove(x, z) END;
  1925. i := 0; a := size + base;
  1926. WHILE i < nofptrs DO
  1927. DEC(a, 4);
  1928. IF a # ptrTab[i] THEN AdjustStack(ptrTab[i] - a); a := ptrTab[i] END;
  1929. DevCPL486.GenPush(z); INC(i)
  1930. END;
  1931. IF a # base THEN AdjustStack(base - a) END
  1932. ELSE
  1933. AdjustStack(-size);
  1934. DevCPL486.MakeConst(x, 0, Pointer); DevCPL486.MakeReg(z, AX, Int32); DevCPL486.GenMove(x, z);
  1935. x.mode := Ind; x.reg := BP; x.scale := 0; x.form := Pointer; i := 0;
  1936. WHILE i < nofptrs DO
  1937. x.offset := ptrTab[i]; DevCPL486.GenMove(z, x); INC(i)
  1938. END
  1939. END
  1940. ELSE
  1941. AdjustStack(-size)
  1942. END
  1943. ELSE
  1944. nofptrs := 0;
  1945. AdjustStack(-size)
  1946. END
  1947. END AllocAndInitPtrs1;
  1948. PROCEDURE InitPtrs2 (proc: DevCPT.Object; adr, size, nofptrs: INTEGER); (* needs AX, CX, DI *)
  1949. VAR x, y, z, zero: DevCPL486.Item; obj: DevCPT.Object; zeroed: BOOLEAN; i: INTEGER; lbl: DevCPL486.Label;
  1950. BEGIN
  1951. IF ptrinit THEN
  1952. zeroed := FALSE; DevCPL486.MakeConst(zero, 0, Pointer);
  1953. IF nofptrs > MaxPtrs THEN
  1954. DevCPL486.MakeReg(z, AX, Int32); DevCPL486.GenMove(zero, z); zeroed := TRUE;
  1955. x.mode := Ind; x.reg := BP; x.scale := 0; x.form := Pointer; x.offset := adr;
  1956. DevCPL486.MakeReg(y, DI, Int32); DevCPL486.GenLoadAdr(x, y);
  1957. DevCPL486.GenStrStore(size)
  1958. END;
  1959. obj := proc.link; (* parameters *)
  1960. WHILE obj # NIL DO
  1961. IF (obj.mode = VarPar) & (obj.vis = outPar) THEN
  1962. nofptrs := 0;
  1963. IF obj.typ.comp = DynArr THEN (* currently not initialized *)
  1964. ELSE FindPtrs(obj.typ, 0, nofptrs)
  1965. END;
  1966. IF nofptrs > 0 THEN
  1967. IF ~zeroed THEN
  1968. DevCPL486.MakeReg(z, AX, Int32); DevCPL486.GenMove(zero, z); zeroed := TRUE
  1969. END;
  1970. x.mode := Ind; x.reg := BP; x.scale := 0; x.form := Pointer; x.offset := obj.adr;
  1971. DevCPL486.MakeReg(y, DI, Int32); DevCPL486.GenMove(x, y);
  1972. IF ODD(obj.sysflag DIV nilBit) THEN
  1973. DevCPL486.GenComp(zero, y);
  1974. lbl := DevCPL486.NewLbl; DevCPL486.GenJump(ccE, lbl, TRUE)
  1975. END;
  1976. IF nofptrs > MaxPtrs THEN
  1977. DevCPL486.GenStrStore(obj.typ.size)
  1978. ELSE
  1979. Sort(ptrTab, nofptrs);
  1980. x.reg := DI; i := 0;
  1981. WHILE i < nofptrs DO
  1982. x.offset := ptrTab[i]; DevCPL486.GenMove(z, x); INC(i)
  1983. END
  1984. END;
  1985. IF ODD(obj.sysflag DIV nilBit) THEN DevCPL486.SetLabel(lbl) END
  1986. END
  1987. END;
  1988. obj := obj.link
  1989. END
  1990. END
  1991. END InitPtrs2;
  1992. PROCEDURE NeedOutPtrInit (proc: DevCPT.Object): BOOLEAN;
  1993. VAR obj: DevCPT.Object; nofptrs: INTEGER;
  1994. BEGIN
  1995. IF ptrinit THEN
  1996. obj := proc.link;
  1997. WHILE obj # NIL DO
  1998. IF (obj.mode = VarPar) & (obj.vis = outPar) THEN
  1999. nofptrs := 0;
  2000. IF obj.typ.comp = DynArr THEN (* currently not initialized *)
  2001. ELSE FindPtrs(obj.typ, 0, nofptrs)
  2002. END;
  2003. IF nofptrs > 0 THEN RETURN TRUE END
  2004. END;
  2005. obj := obj.link
  2006. END
  2007. END;
  2008. RETURN FALSE
  2009. END NeedOutPtrInit;
  2010. PROCEDURE Enter* (proc: DevCPT.Object; empty, useFpu: BOOLEAN);
  2011. VAR sp, fp, r, r1: DevCPL486.Item; par: DevCPT.Object; adr, size, np: INTEGER;
  2012. BEGIN
  2013. procedureUsesFpu := useFpu;
  2014. SetReg({AX, CX, DX, SI, DI});
  2015. DevCPL486.MakeReg(fp, BP, Pointer); DevCPL486.MakeReg(sp, SP, Pointer);
  2016. IF proc # NIL THEN (* enter proc *)
  2017. DevCPL486.SetLabel(proc.adr);
  2018. IF (~empty OR NeedOutPtrInit(proc)) & (proc.sysflag # noframe) THEN
  2019. DevCPL486.GenPush(fp);
  2020. DevCPL486.GenMove(sp, fp);
  2021. adr := proc.conval.intval2; size := -adr;
  2022. IF isGuarded IN proc.conval.setval THEN
  2023. DevCPL486.MakeReg(r, BX, Pointer); DevCPL486.GenPush(r);
  2024. DevCPL486.MakeReg(r, DI, Pointer); DevCPL486.GenPush(r);
  2025. DevCPL486.MakeReg(r, SI, Pointer); DevCPL486.GenPush(r);
  2026. r1.mode := Con; r1.form := Int32; r1.offset := proc.conval.intval - 8; r1.obj := NIL;
  2027. DevCPL486.GenPush(r1);
  2028. intHandler.used := TRUE;
  2029. r1.mode := Con; r1.form := Int32; r1.offset := 0; r1.obj := intHandler;
  2030. DevCPL486.GenPush(r1);
  2031. r1.mode := Abs; r1.form := Int32; r1.offset := 0; r1.scale := 0; r1.obj := NIL;
  2032. DevCPL486.GenCode(64H); DevCPL486.GenPush(r1);
  2033. DevCPL486.GenCode(64H); DevCPL486.GenMove(sp, r1);
  2034. DEC(size, 24)
  2035. ELSE
  2036. IF imVar IN proc.conval.setval THEN (* set down pointer *)
  2037. DevCPL486.MakeReg(r, BX, Pointer); DevCPL486.GenPush(r); DEC(size, 4)
  2038. END;
  2039. IF isCallback IN proc.conval.setval THEN
  2040. DevCPL486.MakeReg(r, DI, Pointer); DevCPL486.GenPush(r);
  2041. DevCPL486.MakeReg(r, SI, Pointer); DevCPL486.GenPush(r); DEC(size, 8)
  2042. END
  2043. END;
  2044. ASSERT(size >= 0);
  2045. IF initializeAll THEN
  2046. AllocAndInitAll(proc, adr, size, np)
  2047. ELSE
  2048. AllocAndInitPtrs1(proc, adr, size, np); (* needs AX *)
  2049. InitPtrs2(proc, adr, size, np); (* needs AX, CX, DI *)
  2050. END;
  2051. par := proc.link; (* parameters *)
  2052. WHILE par # NIL DO
  2053. IF (par.mode = Var) & (par.typ.comp = DynArr) THEN
  2054. CopyDynArray(par.adr, par.typ)
  2055. END;
  2056. par := par.link
  2057. END;
  2058. IF imVar IN proc.conval.setval THEN
  2059. DevCPL486.MakeReg(r, BX, Pointer); DevCPL486.GenMove(fp, r)
  2060. END
  2061. END
  2062. ELSIF ~empty THEN (* enter module *)
  2063. DevCPL486.GenPush(fp);
  2064. DevCPL486.GenMove(sp, fp);
  2065. DevCPL486.MakeReg(r, DI, Int32); DevCPL486.GenPush(r);
  2066. DevCPL486.MakeReg(r, SI, Int32); DevCPL486.GenPush(r)
  2067. END;
  2068. IF useFpu THEN InitFpu END
  2069. END Enter;
  2070. PROCEDURE Exit* (proc: DevCPT.Object; empty: BOOLEAN);
  2071. VAR sp, fp, r, x: DevCPL486.Item; mode: SHORTINT; size: INTEGER;
  2072. BEGIN
  2073. DevCPL486.MakeReg(sp, SP, Pointer); DevCPL486.MakeReg(fp, BP, Pointer);
  2074. IF proc # NIL THEN (* exit proc *)
  2075. IF proc.sysflag # noframe THEN
  2076. IF ~empty OR NeedOutPtrInit(proc) THEN
  2077. IF isGuarded IN proc.conval.setval THEN (* remove exception frame *)
  2078. x.mode := Ind; x.reg := BP; x.offset := -24; x.scale := 0; x.form := Int32;
  2079. DevCPL486.MakeReg(r, CX, Int32); DevCPL486.GenMove(x, r);
  2080. x.mode := Abs; x.offset := 0; x.scale := 0; x.form := Int32; x.obj := NIL;
  2081. DevCPL486.GenCode(64H); DevCPL486.GenMove(r, x);
  2082. size := 12
  2083. ELSE
  2084. size := 0;
  2085. IF imVar IN proc.conval.setval THEN INC(size, 4) END;
  2086. IF isCallback IN proc.conval.setval THEN INC(size, 8) END
  2087. END;
  2088. IF size > 0 THEN
  2089. x.mode := Ind; x.reg := BP; x.offset := -size; x.scale := 0; x.form := Int32;
  2090. DevCPL486.GenLoadAdr(x, sp);
  2091. IF size > 4 THEN
  2092. DevCPL486.MakeReg(r, SI, Int32); DevCPL486.GenPop(r);
  2093. DevCPL486.MakeReg(r, DI, Int32); DevCPL486.GenPop(r)
  2094. END;
  2095. IF size # 8 THEN
  2096. DevCPL486.MakeReg(r, BX, Int32); DevCPL486.GenPop(r)
  2097. END
  2098. ELSE
  2099. DevCPL486.GenMove(fp, sp)
  2100. END;
  2101. DevCPL486.GenPop(fp)
  2102. END;
  2103. IF proc.sysflag = ccall THEN DevCPL486.GenReturn(0)
  2104. ELSE DevCPL486.GenReturn(proc.conval.intval - 8)
  2105. END
  2106. END
  2107. ELSE (* exit module *)
  2108. IF ~empty THEN
  2109. DevCPL486.MakeReg(r, SI, Int32); DevCPL486.GenPop(r);
  2110. DevCPL486.MakeReg(r, DI, Int32); DevCPL486.GenPop(r);
  2111. DevCPL486.GenMove(fp, sp); DevCPL486.GenPop(fp)
  2112. END;
  2113. DevCPL486.GenReturn(0)
  2114. END
  2115. END Exit;
  2116. PROCEDURE InstallStackAlloc*;
  2117. VAR name: ARRAY 32 OF SHORTCHAR; ax, cx, sp, c, x: DevCPL486.Item; l1, l2: DevCPL486.Label;
  2118. BEGIN
  2119. IF stkAllocLbl # DevCPL486.NewLbl THEN
  2120. DevCPL486.SetLabel(stkAllocLbl);
  2121. DevCPL486.MakeReg(ax, AX, Int32);
  2122. DevCPL486.MakeReg(cx, CX, Int32);
  2123. DevCPL486.MakeReg(sp, SP, Int32);
  2124. DevCPL486.GenPush(ax);
  2125. DevCPL486.MakeConst(c, -5, Int32); DevCPL486.GenAdd(c, cx, FALSE);
  2126. l1 := DevCPL486.NewLbl; DevCPL486.GenJump(ccNS, l1, TRUE);
  2127. DevCPL486.MakeConst(c, 0, Int32); DevCPL486.GenMove(c, cx);
  2128. DevCPL486.SetLabel(l1);
  2129. DevCPL486.MakeConst(c, -4, Int32); DevCPL486.GenAnd(c, cx);
  2130. DevCPL486.GenMove(cx, ax);
  2131. DevCPL486.MakeConst(c, 4095, Int32); DevCPL486.GenAnd(c, ax);
  2132. DevCPL486.GenSub(ax, sp, FALSE);
  2133. DevCPL486.GenMove(cx, ax);
  2134. DevCPL486.MakeConst(c, 12, Int32); DevCPL486.GenShiftOp(SHR, c, ax);
  2135. l2 := DevCPL486.NewLbl; DevCPL486.GenJump(ccE, l2, TRUE);
  2136. l1 := DevCPL486.NewLbl; DevCPL486.SetLabel(l1);
  2137. DevCPL486.MakeConst(c, 0, Int32); DevCPL486.GenPush(c);
  2138. DevCPL486.MakeConst(c, 4092, Int32); DevCPL486.GenSub(c, sp, FALSE);
  2139. DevCPL486.MakeConst(c, -1, Int32); DevCPL486.GenAdd(c, ax, FALSE);
  2140. DevCPL486.GenJump(ccNE, l1, TRUE);
  2141. DevCPL486.SetLabel(l2);
  2142. DevCPL486.MakeConst(c, 8, Int32); DevCPL486.GenAdd(c, cx, FALSE);
  2143. x.mode := Ind; x.form := Int32; x.offset := -4; x.index := CX; x.reg := SP; x.scale := 1;
  2144. DevCPL486.GenMove(x, ax);
  2145. DevCPL486.GenPush(ax);
  2146. DevCPL486.GenMove(x, ax);
  2147. DevCPL486.MakeConst(c, 2, Int32); DevCPL486.GenShiftOp(SHR, c, cx);
  2148. DevCPL486.GenReturn(0);
  2149. name := "$StackAlloc"; DevCPE.OutRefName(name);
  2150. END
  2151. END InstallStackAlloc;
  2152. PROCEDURE Trap* (n: INTEGER);
  2153. BEGIN
  2154. DevCPL486.GenAssert(ccNever, n)
  2155. END Trap;
  2156. PROCEDURE Jump* (VAR L: DevCPL486.Label);
  2157. BEGIN
  2158. DevCPL486.GenJump(ccAlways, L, FALSE)
  2159. END Jump;
  2160. PROCEDURE JumpT* (VAR x: DevCPL486.Item; VAR L: DevCPL486.Label);
  2161. BEGIN
  2162. DevCPL486.GenJump(x.offset, L, FALSE);
  2163. END JumpT;
  2164. PROCEDURE JumpF* (VAR x: DevCPL486.Item; VAR L: DevCPL486.Label);
  2165. BEGIN
  2166. DevCPL486.GenJump(Inverted(x.offset), L, FALSE);
  2167. END JumpF;
  2168. PROCEDURE CaseTableJump* (VAR x: DevCPL486.Item; low, high: INTEGER; VAR else: DevCPL486.Label);
  2169. VAR c: DevCPL486.Item; n: INTEGER;
  2170. BEGIN
  2171. n := high - low + 1;
  2172. DevCPL486.MakeConst(c, low, Int32); DevCPL486.GenSub(c, x, FALSE);
  2173. DevCPL486.MakeConst(c, n, Int32); DevCPL486.GenComp(c, x);
  2174. DevCPL486.GenJump(ccAE, else, FALSE);
  2175. DevCPL486.GenCaseJump(x)
  2176. END CaseTableJump;
  2177. PROCEDURE CaseJump* (VAR x: DevCPL486.Item; low, high: INTEGER; VAR this, else: DevCPL486.Label; tree, first: BOOLEAN);
  2178. VAR c: DevCPL486.Item;
  2179. BEGIN
  2180. IF high = low THEN
  2181. DevCPL486.MakeConst(c, low, Int32); DevCPL486.GenComp(c, x);
  2182. IF tree THEN DevCPL486.GenJump(ccG, else, FALSE) END;
  2183. DevCPL486.GenJump(ccE, this, FALSE)
  2184. ELSIF first THEN
  2185. DevCPL486.MakeConst(c, low, Int32); DevCPL486.GenComp(c, x);
  2186. DevCPL486.GenJump(ccL, else, FALSE);
  2187. DevCPL486.MakeConst(c, high, Int32); DevCPL486.GenComp(c, x);
  2188. DevCPL486.GenJump(ccLE, this, FALSE);
  2189. ELSE
  2190. DevCPL486.MakeConst(c, high, Int32); DevCPL486.GenComp(c, x);
  2191. DevCPL486.GenJump(ccG, else, FALSE);
  2192. DevCPL486.MakeConst(c, low, Int32); DevCPL486.GenComp(c, x);
  2193. DevCPL486.GenJump(ccGE, this, FALSE);
  2194. END
  2195. END CaseJump;
  2196. BEGIN
  2197. imLevel[0] := 0
  2198. END LindevCPC486.