CPC486.txt 80 KB

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