CPC486.txt 80 KB

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