ORG.Mod.txt 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. MODULE ORG; (* NW 18.4.2016 / 4.4.2017 code generator in Oberon-07 for RISC*)
  2. IMPORT SYSTEM, Files, ORS, ORB;
  3. (*Code generator for Oberon compiler for RISC processor.
  4. Procedural interface to Parser OSAP; result in array "code".
  5. Procedure Close writes code-files*)
  6. CONST WordSize* = 4;
  7. StkOrg0 = -64; VarOrg0 = 0; (*for RISC-0 only*)
  8. MT = 12; SB = 13; SP = 14; LNK = 15; (*dedicated registers*)
  9. maxCode = 8000; maxStrx = 2400; maxTD = 120; C24 = 1000000H;
  10. Reg = 10; RegI = 11; Cond = 12; (*internal item modes*)
  11. (*frequently used opcodes*) U = 2000H; V = 1000H;
  12. Mov = 0; Lsl = 1; Asr = 2; Ror= 3; And = 4; Ann = 5; Ior = 6; Xor = 7;
  13. Add = 8; Sub = 9; Cmp = 9; Mul = 10; Div = 11;
  14. Fad = 12; Fsb = 13; Fml = 14; Fdv = 15;
  15. Ldr = 8; Str = 10;
  16. BR = 0; BLR = 1; BC = 2; BL = 3;
  17. MI = 0; PL = 8; EQ = 1; NE = 9; LT = 5; GE = 13; LE = 6; GT = 14;
  18. TYPE Item* = RECORD
  19. mode*: INTEGER;
  20. type*: ORB.Type;
  21. a*, b*, r: LONGINT;
  22. rdo*: BOOLEAN (*read only*)
  23. END ;
  24. (* Item forms and meaning of fields:
  25. mode r a b
  26. --------------------------------
  27. Const - value (proc adr) (immediate value)
  28. Var base off - (direct adr)
  29. Par - off0 off1 (indirect adr)
  30. Reg regno
  31. RegI regno off -
  32. Cond cond Fchain Tchain *)
  33. VAR pc*, varsize: LONGINT; (*program counter, data index*)
  34. tdx, strx: LONGINT;
  35. entry: LONGINT; (*main entry point*)
  36. RH: LONGINT; (*available registers R[0] ... R[H-1]*)
  37. curSB: LONGINT; (*current static base in SB*)
  38. frame: LONGINT; (*frame offset changed in SaveRegs and RestoreRegs*)
  39. fixorgP, fixorgD, fixorgT: LONGINT; (*origins of lists of locations to be fixed up by loader*)
  40. check: BOOLEAN; (*emit run-time checks*)
  41. version: INTEGER; (* 0 = RISC-0, 1 = RISC-5 *)
  42. relmap: ARRAY 6 OF INTEGER; (*condition codes for relations*)
  43. code: ARRAY maxCode OF LONGINT;
  44. data: ARRAY maxTD OF LONGINT; (*type descriptors*)
  45. str: ARRAY maxStrx OF CHAR;
  46. (*instruction assemblers according to formats*)
  47. PROCEDURE Put0(op, a, b, c: LONGINT);
  48. BEGIN (*emit format-0 instruction*)
  49. code[pc] := ((a*10H + b) * 10H + op) * 10000H + c; INC(pc)
  50. END Put0;
  51. PROCEDURE Put1(op, a, b, im: LONGINT);
  52. BEGIN (*emit format-1 instruction, -10000H <= im < 10000H*)
  53. IF im < 0 THEN INC(op, V) END ;
  54. code[pc] := (((a+40H) * 10H + b) * 10H + op) * 10000H + (im MOD 10000H); INC(pc)
  55. END Put1;
  56. PROCEDURE Put1a(op, a, b, im: LONGINT);
  57. BEGIN (*same as Put1, but with range test -10000H <= im < 10000H*)
  58. IF (im >= -10000H) & (im <= 0FFFFH) THEN Put1(op, a, b, im)
  59. ELSE Put1(Mov+U, RH, 0, im DIV 10000H);
  60. IF im MOD 10000H # 0 THEN Put1(Ior, RH, RH, im MOD 10000H) END ;
  61. Put0(op, a, b, RH)
  62. END
  63. END Put1a;
  64. PROCEDURE Put2(op, a, b, off: LONGINT);
  65. BEGIN (*emit load/store instruction*)
  66. code[pc] := ((op * 10H + a) * 10H + b) * 100000H + (off MOD 100000H); INC(pc)
  67. END Put2;
  68. PROCEDURE Put3(op, cond, off: LONGINT);
  69. BEGIN (*emit branch instruction*)
  70. code[pc] := ((op+12) * 10H + cond) * 1000000H + (off MOD 1000000H); INC(pc)
  71. END Put3;
  72. PROCEDURE incR;
  73. BEGIN
  74. IF RH < MT-1 THEN INC(RH) ELSE ORS.Mark("register stack overflow") END
  75. END incR;
  76. PROCEDURE CheckRegs*;
  77. BEGIN
  78. IF RH # 0 THEN ORS.Mark("Reg Stack"); RH := 0 END ;
  79. IF pc >= maxCode - 40 THEN ORS.Mark("program too long") END
  80. END CheckRegs;
  81. PROCEDURE SetCC(VAR x: Item; n: LONGINT);
  82. BEGIN x.mode := Cond; x.a := 0; x.b := 0; x.r := n
  83. END SetCC;
  84. PROCEDURE Trap(cond, num: LONGINT);
  85. BEGIN Put3(BLR, cond, ORS.Pos()*100H + num*10H + MT)
  86. END Trap;
  87. (*handling of forward reference, fixups of branch addresses and constant tables*)
  88. PROCEDURE negated(cond: LONGINT): LONGINT;
  89. BEGIN
  90. IF cond < 8 THEN cond := cond+8 ELSE cond := cond-8 END ;
  91. RETURN cond
  92. END negated;
  93. PROCEDURE invalSB;
  94. BEGIN curSB := 1
  95. END invalSB;
  96. PROCEDURE fix(at, with: LONGINT);
  97. BEGIN code[at] := code[at] DIV C24 * C24 + (with MOD C24)
  98. END fix;
  99. PROCEDURE FixLink*(L: LONGINT);
  100. VAR L1: LONGINT;
  101. BEGIN invalSB;
  102. WHILE L # 0 DO L1 := code[L] MOD 40000H; fix(L, pc-L-1); L := L1 END
  103. END FixLink;
  104. PROCEDURE FixLinkWith(L0, dst: LONGINT);
  105. VAR L1: LONGINT;
  106. BEGIN
  107. WHILE L0 # 0 DO
  108. L1 := code[L0] MOD C24;
  109. code[L0] := code[L0] DIV C24 * C24 + ((dst - L0 - 1) MOD C24); L0 := L1
  110. END
  111. END FixLinkWith;
  112. PROCEDURE merged(L0, L1: LONGINT): LONGINT;
  113. VAR L2, L3: LONGINT;
  114. BEGIN
  115. IF L0 # 0 THEN L3 := L0;
  116. REPEAT L2 := L3; L3 := code[L2] MOD 40000H UNTIL L3 = 0;
  117. code[L2] := code[L2] + L1; L1 := L0
  118. END ;
  119. RETURN L1
  120. END merged;
  121. (* loading of operands and addresses into registers *)
  122. PROCEDURE GetSB(base: LONGINT);
  123. BEGIN
  124. IF (version # 0) & ((base # curSB) OR (base # 0)) THEN
  125. Put2(Ldr, SB, -base, pc-fixorgD); fixorgD := pc-1; curSB := base
  126. END
  127. END GetSB;
  128. PROCEDURE NilCheck;
  129. BEGIN IF check THEN Trap(EQ, 4) END
  130. END NilCheck;
  131. PROCEDURE load(VAR x: Item);
  132. VAR op: LONGINT;
  133. BEGIN
  134. IF x.type.size = 1 THEN op := Ldr+1 ELSE op := Ldr END ;
  135. IF x.mode # Reg THEN
  136. IF x.mode = ORB.Const THEN
  137. IF x.type.form = ORB.Proc THEN
  138. IF x.r > 0 THEN ORS.Mark("not allowed")
  139. ELSIF x.r = 0 THEN Put3(BL, 7, 0); Put1a(Sub, RH, LNK, pc*4 - x.a)
  140. ELSE GetSB(x.r); Put1(Add, RH, SB, x.a + 100H) (*mark as progbase-relative*)
  141. END
  142. ELSIF (x.a <= 0FFFFH) & (x.a >= -10000H) THEN Put1(Mov, RH, 0, x.a)
  143. ELSE Put1(Mov+U, RH, 0, x.a DIV 10000H MOD 10000H);
  144. IF x.a MOD 10000H # 0 THEN Put1(Ior, RH, RH, x.a MOD 10000H) END
  145. END ;
  146. x.r := RH; incR
  147. ELSIF x.mode = ORB.Var THEN
  148. IF x.r > 0 THEN (*local*) Put2(op, RH, SP, x.a + frame)
  149. ELSE GetSB(x.r); Put2(op, RH, SB, x.a)
  150. END ;
  151. x.r := RH; incR
  152. ELSIF x.mode = ORB.Par THEN Put2(Ldr, RH, SP, x.a + frame); Put2(op, RH, RH, x.b); x.r := RH; incR
  153. ELSIF x.mode = RegI THEN Put2(op, x.r, x.r, x.a)
  154. ELSIF x.mode = Cond THEN
  155. Put3(BC, negated(x.r), 2);
  156. FixLink(x.b); Put1(Mov, RH, 0, 1); Put3(BC, 7, 1);
  157. FixLink(x.a); Put1(Mov, RH, 0, 0); x.r := RH; incR
  158. END ;
  159. x.mode := Reg
  160. END
  161. END load;
  162. PROCEDURE loadAdr(VAR x: Item);
  163. BEGIN
  164. IF x.mode = ORB.Var THEN
  165. IF x.r > 0 THEN (*local*) Put1a(Add, RH, SP, x.a + frame)
  166. ELSE GetSB(x.r); Put1a(Add, RH, SB, x.a)
  167. END ;
  168. x.r := RH; incR
  169. ELSIF x.mode = ORB.Par THEN Put2(Ldr, RH, SP, x.a + frame);
  170. IF x.b # 0 THEN Put1a(Add, RH, RH, x.b) END ;
  171. x.r := RH; incR
  172. ELSIF x.mode = RegI THEN
  173. IF x.a # 0 THEN Put1a(Add, x.r, x.r, x.a) END
  174. ELSE ORS.Mark("address error")
  175. END ;
  176. x.mode := Reg
  177. END loadAdr;
  178. PROCEDURE loadCond(VAR x: Item);
  179. BEGIN
  180. IF x.type.form = ORB.Bool THEN
  181. IF x.mode = ORB.Const THEN x.r := 15 - x.a*8
  182. ELSE load(x);
  183. IF code[pc-1] DIV 40000000H # -2 THEN Put1(Cmp, x.r, x.r, 0) END ;
  184. x.r := NE; DEC(RH)
  185. END ;
  186. x.mode := Cond; x.a := 0; x.b := 0
  187. ELSE ORS.Mark("not Boolean?")
  188. END
  189. END loadCond;
  190. PROCEDURE loadTypTagAdr(T: ORB.Type);
  191. VAR x: Item;
  192. BEGIN x.mode := ORB.Var; x.a := T.len; x.r := -T.mno; loadAdr(x)
  193. END loadTypTagAdr;
  194. PROCEDURE loadStringAdr(VAR x: Item);
  195. BEGIN GetSB(0); Put1a(Add, RH, SB, varsize+x.a); x.mode := Reg; x.r := RH; incR
  196. END loadStringAdr;
  197. (* Items: Conversion from constants or from Objects on the Heap to Items on the Stack*)
  198. PROCEDURE MakeConstItem*(VAR x: Item; typ: ORB.Type; val: LONGINT);
  199. BEGIN x.mode := ORB.Const; x.type := typ; x.a := val
  200. END MakeConstItem;
  201. PROCEDURE MakeRealItem*(VAR x: Item; val: REAL);
  202. BEGIN x.mode := ORB.Const; x.type := ORB.realType; x.a := SYSTEM.VAL(LONGINT, val)
  203. END MakeRealItem;
  204. PROCEDURE MakeStringItem*(VAR x: Item; len: LONGINT); (*copies string from ORS-buffer to ORG-string array*)
  205. VAR i: LONGINT;
  206. BEGIN x.mode := ORB.Const; x.type := ORB.strType; x.a := strx; x.b := len; i := 0;
  207. IF strx + len + 4 < maxStrx THEN
  208. WHILE len > 0 DO str[strx] := ORS.str[i]; INC(strx); INC(i); DEC(len) END ;
  209. WHILE strx MOD 4 # 0 DO str[strx] := 0X; INC(strx) END
  210. ELSE ORS.Mark("too many strings")
  211. END
  212. END MakeStringItem;
  213. PROCEDURE MakeItem*(VAR x: Item; y: ORB.Object; curlev: LONGINT);
  214. BEGIN x.mode := y.class; x.type := y.type; x.a := y.val; x.rdo := y.rdo;
  215. IF y.class = ORB.Par THEN x.b := 0
  216. ELSIF y.class = ORB.Typ THEN x.a := y.type.len; x.r := -y.lev
  217. ELSIF (y.class = ORB.Const) & (y.type.form = ORB.String) THEN x.b := y.lev (*len*)
  218. ELSE x.r := y.lev
  219. END ;
  220. IF (y.lev > 0) & (y.lev # curlev) & (y.class # ORB.Const) THEN ORS.Mark("level error, not accessible") END
  221. END MakeItem;
  222. (* Code generation for Selectors, Variables, Constants *)
  223. PROCEDURE Field*(VAR x: Item; y: ORB.Object); (* x := x.y *)
  224. BEGIN;
  225. IF x.mode = ORB.Var THEN
  226. IF x.r >= 0 THEN x.a := x.a + y.val
  227. ELSE loadAdr(x); x.mode := RegI; x.a := y.val
  228. END
  229. ELSIF x.mode = RegI THEN x.a := x.a + y.val
  230. ELSIF x.mode = ORB.Par THEN x.b := x.b + y.val
  231. END
  232. END Field;
  233. PROCEDURE Index*(VAR x, y: Item); (* x := x[y] *)
  234. VAR s, lim: LONGINT;
  235. BEGIN s := x.type.base.size; lim := x.type.len;
  236. IF (y.mode = ORB.Const) & (lim >= 0) THEN
  237. IF (y.a < 0) OR (y.a >= lim) THEN ORS.Mark("bad index") END ;
  238. IF x.mode IN {ORB.Var, RegI} THEN x.a := y.a * s + x.a
  239. ELSIF x.mode = ORB.Par THEN x.b := y.a * s + x.b
  240. END
  241. ELSE load(y);
  242. IF check THEN (*check array bounds*)
  243. IF lim >= 0 THEN Put1a(Cmp, RH, y.r, lim)
  244. ELSE (*open array*)
  245. IF x.mode IN {ORB.Var, ORB.Par} THEN Put2(Ldr, RH, SP, x.a+4+frame); Put0(Cmp, RH, y.r, RH)
  246. ELSE ORS.Mark("error in Index")
  247. END
  248. END ;
  249. Trap(10, 1) (*BCC*)
  250. END ;
  251. IF s = 4 THEN Put1(Lsl, y.r, y.r, 2) ELSIF s > 1 THEN Put1a(Mul, y.r, y.r, s) END ;
  252. IF x.mode = ORB.Var THEN
  253. IF x.r > 0 THEN Put0(Add, y.r, SP, y.r); INC(x.a, frame)
  254. ELSE GetSB(x.r);
  255. IF x.r = 0 THEN Put0(Add, y.r, SB, y.r)
  256. ELSE Put1a(Add, RH, SB, x.a); Put0(Add, y.r, RH, y.r); x.a := 0
  257. END
  258. END ;
  259. x.r := y.r; x.mode := RegI
  260. ELSIF x.mode = ORB.Par THEN
  261. Put2(Ldr, RH, SP, x.a + frame);
  262. Put0(Add, y.r, RH, y.r); x.mode := RegI; x.r := y.r; x.a := x.b
  263. ELSIF x.mode = RegI THEN Put0(Add, x.r, x.r, y.r); DEC(RH)
  264. END
  265. END
  266. END Index;
  267. PROCEDURE DeRef*(VAR x: Item);
  268. BEGIN
  269. IF x.mode = ORB.Var THEN
  270. IF x.r > 0 THEN (*local*) Put2(Ldr, RH, SP, x.a + frame) ELSE GetSB(x.r); Put2(Ldr, RH, SB, x.a) END ;
  271. NilCheck; x.r := RH; incR
  272. ELSIF x.mode = ORB.Par THEN
  273. Put2(Ldr, RH, SP, x.a + frame); Put2(Ldr, RH, RH, x.b); NilCheck; x.r := RH; incR
  274. ELSIF x.mode = RegI THEN Put2(Ldr, x.r, x.r, x.a); NilCheck
  275. ELSIF x.mode # Reg THEN ORS.Mark("bad mode in DeRef")
  276. END ;
  277. x.mode := RegI; x.a := 0; x.b := 0
  278. END DeRef;
  279. PROCEDURE Q(T: ORB.Type; VAR dcw: LONGINT);
  280. BEGIN (*one entry of type descriptor extension table*)
  281. IF T.base # NIL THEN
  282. Q(T.base, dcw); data[dcw] := (T.mno*1000H + T.len) * 1000H + dcw - fixorgT;
  283. fixorgT := dcw; INC(dcw)
  284. END
  285. END Q;
  286. PROCEDURE FindPtrFlds(typ: ORB.Type; off: LONGINT; VAR dcw: LONGINT);
  287. VAR fld: ORB.Object; i, s: LONGINT;
  288. BEGIN
  289. IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN data[dcw] := off; INC(dcw)
  290. ELSIF typ.form = ORB.Record THEN
  291. fld := typ.dsc;
  292. WHILE fld # NIL DO FindPtrFlds(fld.type, fld.val + off, dcw); fld := fld.next END
  293. ELSIF typ.form = ORB.Array THEN
  294. s := typ.base.size;
  295. FOR i := 0 TO typ.len-1 DO FindPtrFlds(typ.base, i*s + off, dcw) END
  296. END
  297. END FindPtrFlds;
  298. PROCEDURE BuildTD*(T: ORB.Type; VAR dc: LONGINT);
  299. VAR dcw, k, s: LONGINT; (*dcw = word address*)
  300. BEGIN dcw := dc DIV 4; s := T.size; (*convert size for heap allocation*)
  301. IF s <= 24 THEN s := 32 ELSIF s <= 56 THEN s := 64 ELSIF s <= 120 THEN s := 128
  302. ELSE s := (s+263) DIV 256 * 256
  303. END ;
  304. T.len := dc; data[dcw] := s; INC(dcw); (*len used as address*)
  305. k := T.nofpar; (*extension level!*)
  306. IF k > 3 THEN ORS.Mark("ext level too large")
  307. ELSE Q(T, dcw);
  308. WHILE k < 3 DO data[dcw] := -1; INC(dcw); INC(k) END
  309. END ;
  310. FindPtrFlds(T, 0, dcw); data[dcw] := -1; INC(dcw); tdx := dcw; dc := dcw*4;
  311. IF tdx >= maxTD THEN ORS.Mark("too many record types"); tdx := 0 END
  312. END BuildTD;
  313. PROCEDURE TypeTest*(VAR x: Item; T: ORB.Type; varpar, isguard: BOOLEAN);
  314. VAR pc0: LONGINT;
  315. BEGIN (*fetch tag into RH*)
  316. IF varpar THEN Put2(Ldr, RH, SP, x.a+4+frame)
  317. ELSE load(x);
  318. pc0 := pc; Put3(BC, EQ, 0); (*NIL belongs to every pointer type*)
  319. Put2(Ldr, RH, x.r, -8)
  320. END ;
  321. Put2(Ldr, RH, RH, T.nofpar*4); incR;
  322. loadTypTagAdr(T); (*tag of T*)
  323. Put0(Cmp, RH-1, RH-1, RH-2); DEC(RH, 2);
  324. IF ~varpar THEN fix(pc0, pc - pc0 - 1) END ;
  325. IF isguard THEN
  326. IF check THEN Trap(NE, 2) END
  327. ELSE SetCC(x, EQ);
  328. IF ~varpar THEN DEC(RH) END
  329. END
  330. END TypeTest;
  331. (* Code generation for Boolean operators *)
  332. PROCEDURE Not*(VAR x: Item); (* x := ~x *)
  333. VAR t: LONGINT;
  334. BEGIN
  335. IF x.mode # Cond THEN loadCond(x) END ;
  336. x.r := negated(x.r); t := x.a; x.a := x.b; x.b := t
  337. END Not;
  338. PROCEDURE And1*(VAR x: Item); (* x := x & *)
  339. BEGIN
  340. IF x.mode # Cond THEN loadCond(x) END ;
  341. Put3(BC, negated(x.r), x.a); x.a := pc-1; FixLink(x.b); x.b := 0
  342. END And1;
  343. PROCEDURE And2*(VAR x, y: Item);
  344. BEGIN
  345. IF y.mode # Cond THEN loadCond(y) END ;
  346. x.a := merged(y.a, x.a); x.b := y.b; x.r := y.r
  347. END And2;
  348. PROCEDURE Or1*(VAR x: Item); (* x := x OR *)
  349. BEGIN
  350. IF x.mode # Cond THEN loadCond(x) END ;
  351. Put3(BC, x.r, x.b); x.b := pc-1; FixLink(x.a); x.a := 0
  352. END Or1;
  353. PROCEDURE Or2*(VAR x, y: Item);
  354. BEGIN
  355. IF y.mode # Cond THEN loadCond(y) END ;
  356. x.a := y.a; x.b := merged(y.b, x.b); x.r := y.r
  357. END Or2;
  358. (* Code generation for arithmetic operators *)
  359. PROCEDURE Neg*(VAR x: Item); (* x := -x *)
  360. BEGIN
  361. IF x.type.form = ORB.Int THEN
  362. IF x.mode = ORB.Const THEN x.a := -x.a
  363. ELSE load(x); Put1(Mov, RH, 0, 0); Put0(Sub, x.r, RH, x.r)
  364. END
  365. ELSIF x.type.form = ORB.Real THEN
  366. IF x.mode = ORB.Const THEN x.a := x.a + 7FFFFFFFH + 1
  367. ELSE load(x); Put1(Mov, RH, 0, 0); Put0(Fsb, x.r, RH, x.r)
  368. END
  369. ELSE (*form = Set*)
  370. IF x.mode = ORB.Const THEN x.a := -x.a-1
  371. ELSE load(x); Put1(Xor, x.r, x.r, -1)
  372. END
  373. END
  374. END Neg;
  375. PROCEDURE AddOp*(op: LONGINT; VAR x, y: Item); (* x := x +- y *)
  376. BEGIN
  377. IF op = ORS.plus THEN
  378. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN x.a := x.a + y.a
  379. ELSIF y.mode = ORB.Const THEN load(x);
  380. IF y.a # 0 THEN Put1a(Add, x.r, x.r, y.a) END
  381. ELSE load(x); load(y); Put0(Add, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  382. END
  383. ELSE (*op = ORS.minus*)
  384. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN x.a := x.a - y.a
  385. ELSIF y.mode = ORB.Const THEN load(x);
  386. IF y.a # 0 THEN Put1a(Sub, x.r, x.r, y.a) END
  387. ELSE load(x); load(y); Put0(Sub, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  388. END
  389. END
  390. END AddOp;
  391. PROCEDURE log2(m: LONGINT; VAR e: LONGINT): LONGINT;
  392. BEGIN e := 0;
  393. WHILE ~ODD(m) DO m := m DIV 2; INC(e) END ;
  394. RETURN m
  395. END log2;
  396. PROCEDURE MulOp*(VAR x, y: Item); (* x := x * y *)
  397. VAR e: LONGINT;
  398. BEGIN
  399. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN x.a := x.a * y.a
  400. ELSIF (y.mode = ORB.Const) & (y.a >= 2) & (log2(y.a, e) = 1) THEN load(x); Put1(Lsl, x.r, x.r, e)
  401. ELSIF y.mode = ORB.Const THEN load(x); Put1a(Mul, x.r, x.r, y.a)
  402. ELSIF (x.mode = ORB.Const) & (x.a >= 2) & (log2(x.a, e) = 1) THEN load(y); Put1(Lsl, y.r, y.r, e); x.mode := Reg; x.r := y.r
  403. ELSIF x.mode = ORB.Const THEN load(y); Put1a(Mul, y.r, y.r, x.a); x.mode := Reg; x.r := y.r
  404. ELSE load(x); load(y); Put0(Mul, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  405. END
  406. END MulOp;
  407. PROCEDURE DivOp*(op: LONGINT; VAR x, y: Item); (* x := x op y *)
  408. VAR e: LONGINT;
  409. BEGIN
  410. IF op = ORS.div THEN
  411. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
  412. IF y.a > 0 THEN x.a := x.a DIV y.a ELSE ORS.Mark("bad divisor") END
  413. ELSIF (y.mode = ORB.Const) & (y.a >= 2) & (log2(y.a, e) = 1) THEN load(x); Put1(Asr, x.r, x.r, e)
  414. ELSIF y.mode = ORB.Const THEN
  415. IF y.a > 0 THEN load(x); Put1a(Div, x.r, x.r, y.a) ELSE ORS.Mark("bad divisor") END
  416. ELSE load(y);
  417. IF check THEN Trap(LE, 6) END ;
  418. load(x); Put0(Div, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  419. END
  420. ELSE (*op = ORS.mod*)
  421. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
  422. IF y.a > 0 THEN x.a := x.a MOD y.a ELSE ORS.Mark("bad modulus") END
  423. ELSIF (y.mode = ORB.Const) & (y.a >= 2) & (log2(y.a, e) = 1) THEN load(x);
  424. IF e <= 16 THEN Put1(And, x.r, x.r, y.a-1) ELSE Put1(Lsl, x.r, x.r, 32-e); Put1(Ror, x.r, x.r, 32-e) END
  425. ELSIF y.mode = ORB.Const THEN
  426. IF y.a > 0 THEN load(x); Put1a(Div, x.r, x.r, y.a); Put0(Mov+U, x.r, 0, 0) ELSE ORS.Mark("bad modulus") END
  427. ELSE load(y);
  428. IF check THEN Trap(LE, 6) END ;
  429. load(x); Put0(Div, RH-2, x.r, y.r); Put0(Mov+U, RH-2, 0, 0); DEC(RH); x.r := RH-1
  430. END
  431. END
  432. END DivOp;
  433. (* Code generation for REAL operators *)
  434. PROCEDURE RealOp*(op: INTEGER; VAR x, y: Item); (* x := x op y *)
  435. BEGIN load(x); load(y);
  436. IF op = ORS.plus THEN Put0(Fad, RH-2, x.r, y.r)
  437. ELSIF op = ORS.minus THEN Put0(Fsb, RH-2, x.r, y.r)
  438. ELSIF op = ORS.times THEN Put0(Fml, RH-2, x.r, y.r)
  439. ELSIF op = ORS.rdiv THEN Put0(Fdv, RH-2, x.r, y.r)
  440. END ;
  441. DEC(RH); x.r := RH-1
  442. END RealOp;
  443. (* Code generation for set operators *)
  444. PROCEDURE Singleton*(VAR x: Item); (* x := {x} *)
  445. BEGIN
  446. IF x.mode = ORB.Const THEN x.a := LSL(1, x.a)
  447. ELSE load(x); Put1(Mov, RH, 0, 1); Put0(Lsl, x.r, RH, x.r)
  448. END
  449. END Singleton;
  450. PROCEDURE Set*(VAR x, y: Item); (* x := {x .. y} *)
  451. BEGIN
  452. IF (x.mode = ORB.Const) & ( y.mode = ORB.Const) THEN
  453. IF x.a <= y.a THEN x.a := LSL(2, y.a) - LSL(1, x.a) ELSE x.a := 0 END
  454. ELSE
  455. IF (x.mode = ORB.Const) & (x.a <= 16) THEN x.a := LSL(-1, x.a)
  456. ELSE load(x); Put1(Mov, RH, 0, -1); Put0(Lsl, x.r, RH, x.r)
  457. END ;
  458. IF (y.mode = ORB.Const) & (y.a < 16) THEN Put1(Mov, RH, 0, LSL(-2, y.a)); y.mode := Reg; y.r := RH; incR
  459. ELSE load(y); Put1(Mov, RH, 0, -2); Put0(Lsl, y.r, RH, y.r)
  460. END ;
  461. IF x.mode = ORB.Const THEN
  462. IF x.a # 0 THEN Put1(Xor, y.r, y.r, -1); Put1a(And, RH-1, y.r, x.a) END ;
  463. x.mode := Reg; x.r := RH-1
  464. ELSE DEC(RH); Put0(Ann, RH-1, x.r, y.r)
  465. END
  466. END
  467. END Set;
  468. PROCEDURE In*(VAR x, y: Item); (* x := x IN y *)
  469. BEGIN load(y);
  470. IF x.mode = ORB.Const THEN Put1(Ror, y.r, y.r, (x.a + 1) MOD 20H); DEC(RH)
  471. ELSE load(x); Put1(Add, x.r, x.r, 1); Put0(Ror, y.r, y.r, x.r); DEC(RH, 2)
  472. END ;
  473. SetCC(x, MI)
  474. END In;
  475. PROCEDURE SetOp*(op: LONGINT; VAR x, y: Item); (* x := x op y *)
  476. VAR xset, yset: SET; (*x.type.form = Set*)
  477. BEGIN
  478. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
  479. xset := SYSTEM.VAL(SET, x.a); yset := SYSTEM.VAL(SET, y.a);
  480. IF op = ORS.plus THEN xset := xset + yset
  481. ELSIF op = ORS.minus THEN xset := xset - yset
  482. ELSIF op = ORS.times THEN xset := xset * yset
  483. ELSIF op = ORS.rdiv THEN xset := xset / yset
  484. END ;
  485. x.a := SYSTEM.VAL(LONGINT, xset)
  486. ELSIF y.mode = ORB.Const THEN
  487. load(x);
  488. IF op = ORS.plus THEN Put1a(Ior, x.r, x.r, y.a)
  489. ELSIF op = ORS.minus THEN Put1a(Ann, x.r, x.r, y.a)
  490. ELSIF op = ORS.times THEN Put1a(And, x.r, x.r, y.a)
  491. ELSIF op = ORS.rdiv THEN Put1a(Xor, x.r, x.r, y.a)
  492. END ;
  493. ELSE load(x); load(y);
  494. IF op = ORS.plus THEN Put0(Ior, RH-2, x.r, y.r)
  495. ELSIF op = ORS.minus THEN Put0(Ann, RH-2, x.r, y.r)
  496. ELSIF op = ORS.times THEN Put0(And, RH-2, x.r, y.r)
  497. ELSIF op = ORS.rdiv THEN Put0(Xor, RH-2, x.r, y.r)
  498. END ;
  499. DEC(RH); x.r := RH-1
  500. END
  501. END SetOp;
  502. (* Code generation for relations *)
  503. PROCEDURE IntRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  504. BEGIN
  505. IF (y.mode = ORB.Const) & (y.type.form # ORB.Proc) THEN
  506. load(x);
  507. IF (y.a # 0) OR ~(op IN {ORS.eql, ORS.neq}) OR (code[pc-1] DIV 40000000H # -2) THEN Put1a(Cmp, x.r, x.r, y.a) END ;
  508. DEC(RH)
  509. ELSE
  510. IF (x.mode = Cond) OR (y.mode = Cond) THEN ORS.Mark("not implemented") END ;
  511. load(x); load(y); Put0(Cmp, x.r, x.r, y.r); DEC(RH, 2)
  512. END ;
  513. SetCC(x, relmap[op - ORS.eql])
  514. END IntRelation;
  515. PROCEDURE RealRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  516. BEGIN load(x);
  517. IF (y.mode = ORB.Const) & (y.a = 0) THEN DEC(RH)
  518. ELSE load(y); Put0(Fsb, x.r, x.r, y.r); DEC(RH, 2)
  519. END ;
  520. SetCC(x, relmap[op - ORS.eql])
  521. END RealRelation;
  522. PROCEDURE StringRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  523. (*x, y are char arrays or strings*)
  524. BEGIN
  525. IF x.type.form = ORB.String THEN loadStringAdr(x) ELSE loadAdr(x) END ;
  526. IF y.type.form = ORB.String THEN loadStringAdr(y) ELSE loadAdr(y) END ;
  527. Put2(Ldr+1, RH, x.r, 0); Put1(Add, x.r, x.r, 1);
  528. Put2(Ldr+1, RH+1, y.r, 0); Put1(Add, y.r, y.r, 1);
  529. Put0(Cmp, RH+2, RH, RH+1); Put3(BC, NE, 2);
  530. Put1(Cmp, RH+2, RH, 0); Put3(BC, NE, -8);
  531. DEC(RH, 2); SetCC(x, relmap[op - ORS.eql])
  532. END StringRelation;
  533. (* Code generation of Assignments *)
  534. PROCEDURE StrToChar*(VAR x: Item);
  535. BEGIN x.type := ORB.charType; DEC(strx, 4); x.a := ORD(str[x.a])
  536. END StrToChar;
  537. PROCEDURE Store*(VAR x, y: Item); (* x := y *)
  538. VAR op: LONGINT;
  539. BEGIN load(y);
  540. IF x.type.size = 1 THEN op := Str+1 ELSE op := Str END ;
  541. IF x.mode = ORB.Var THEN
  542. IF x.r > 0 THEN (*local*) Put2(op, y.r, SP, x.a + frame)
  543. ELSE GetSB(x.r); Put2(op, y.r, SB, x.a)
  544. END
  545. ELSIF x.mode = ORB.Par THEN Put2(Ldr, RH, SP, x.a + frame); Put2(op, y.r, RH, x.b);
  546. ELSIF x.mode = RegI THEN Put2(op, y.r, x.r, x.a); DEC(RH);
  547. ELSE ORS.Mark("bad mode in Store")
  548. END ;
  549. DEC(RH)
  550. END Store;
  551. PROCEDURE StoreStruct*(VAR x, y: Item); (* x := y, frame = 0 *)
  552. VAR s, pc0: LONGINT;
  553. BEGIN
  554. IF y.type.size # 0 THEN
  555. loadAdr(x); loadAdr(y);
  556. IF (x.type.form = ORB.Array) & (x.type.len > 0) THEN
  557. IF y.type.len >= 0 THEN
  558. IF x.type.size = y.type.size THEN Put1a(Mov, RH, 0, (y.type.size+3) DIV 4)
  559. ELSE ORS.Mark("different length/size, not implemented")
  560. END
  561. ELSE (*y open array*) Put2(Ldr, RH, SP, y.a+4); s := y.type.base.size; (*element size*)
  562. pc0 := pc; Put3(BC, EQ, 0);
  563. IF s = 1 THEN Put1(Add, RH, RH, 3); Put1(Asr, RH, RH, 2)
  564. ELSIF s # 4 THEN Put1a(Mul, RH, RH, s DIV 4)
  565. END ;
  566. IF check THEN
  567. Put1a(Mov, RH+1, 0, (x.type.size+3) DIV 4); Put0(Cmp, RH+1, RH, RH+1); Trap(GT, 3)
  568. END ;
  569. fix(pc0, pc + 5 - pc0)
  570. END
  571. ELSIF x.type.form = ORB.Record THEN Put1a(Mov, RH, 0, x.type.size DIV 4)
  572. ELSE ORS.Mark("inadmissible assignment")
  573. END ;
  574. Put2(Ldr, RH+1, y.r, 0); Put1(Add, y.r, y.r, 4);
  575. Put2(Str, RH+1, x.r, 0); Put1(Add, x.r, x.r, 4);
  576. Put1(Sub, RH, RH, 1); Put3(BC, NE, -6)
  577. END ;
  578. RH := 0
  579. END StoreStruct;
  580. PROCEDURE CopyString*(VAR x, y: Item); (* x := y *)
  581. VAR len: LONGINT;
  582. BEGIN loadAdr(x); len := x.type.len;
  583. IF len >= 0 THEN
  584. IF len < y.b THEN ORS.Mark("string too long") END
  585. ELSIF check THEN Put2(Ldr, RH, SP, x.a+4); (*open array len, frame = 0*)
  586. Put1(Cmp,RH, RH, y.b); Trap(LT, 3)
  587. END ;
  588. loadStringAdr(y);
  589. Put2(Ldr, RH, y.r, 0); Put1(Add, y.r, y.r, 4);
  590. Put2(Str, RH, x.r, 0); Put1(Add, x.r, x.r, 4);
  591. Put1(Asr, RH, RH, 24); Put3(BC, NE, -6); RH := 0
  592. END CopyString;
  593. (* Code generation for parameters *)
  594. PROCEDURE OpenArrayParam*(VAR x: Item);
  595. BEGIN loadAdr(x);
  596. IF x.type.len >= 0 THEN Put1a(Mov, RH, 0, x.type.len) ELSE Put2(Ldr, RH, SP, x.a+4+frame) END ;
  597. incR
  598. END OpenArrayParam;
  599. PROCEDURE VarParam*(VAR x: Item; ftype: ORB.Type);
  600. VAR xmd: INTEGER;
  601. BEGIN xmd := x.mode; loadAdr(x);
  602. IF (ftype.form = ORB.Array) & (ftype.len < 0) THEN (*open array*)
  603. IF x.type.len >= 0 THEN Put1a(Mov, RH, 0, x.type.len) ELSE Put2(Ldr, RH, SP, x.a+4+frame) END ;
  604. incR
  605. ELSIF ftype.form = ORB.Record THEN
  606. IF xmd = ORB.Par THEN Put2(Ldr, RH, SP, x.a+4+frame); incR ELSE loadTypTagAdr(x.type) END
  607. END
  608. END VarParam;
  609. PROCEDURE ValueParam*(VAR x: Item);
  610. BEGIN load(x)
  611. END ValueParam;
  612. PROCEDURE StringParam*(VAR x: Item);
  613. BEGIN loadStringAdr(x); Put1(Mov, RH, 0, x.b); incR (*len*)
  614. END StringParam;
  615. (*For Statements*)
  616. PROCEDURE For0*(VAR x, y: Item);
  617. BEGIN load(y)
  618. END For0;
  619. PROCEDURE For1*(VAR x, y, z, w: Item; VAR L: LONGINT);
  620. BEGIN
  621. IF z.mode = ORB.Const THEN Put1a(Cmp, RH, y.r, z.a)
  622. ELSE load(z); Put0(Cmp, RH-1, y.r, z.r); DEC(RH)
  623. END ;
  624. L := pc;
  625. IF w.a > 0 THEN Put3(BC, GT, 0)
  626. ELSIF w.a < 0 THEN Put3(BC, LT, 0)
  627. ELSE ORS.Mark("zero increment"); Put3(BC, MI, 0)
  628. END ;
  629. Store(x, y)
  630. END For1;
  631. PROCEDURE For2*(VAR x, y, w: Item);
  632. BEGIN load(x); DEC(RH); Put1a(Add, x.r, x.r, w.a)
  633. END For2;
  634. (* Branches, procedure calls, procedure prolog and epilog *)
  635. PROCEDURE Here*(): LONGINT;
  636. BEGIN invalSB; RETURN pc
  637. END Here;
  638. PROCEDURE FJump*(VAR L: LONGINT);
  639. BEGIN Put3(BC, 7, L); L := pc-1
  640. END FJump;
  641. PROCEDURE CFJump*(VAR x: Item);
  642. BEGIN
  643. IF x.mode # Cond THEN loadCond(x) END ;
  644. Put3(BC, negated(x.r), x.a); FixLink(x.b); x.a := pc-1
  645. END CFJump;
  646. PROCEDURE BJump*(L: LONGINT);
  647. BEGIN Put3(BC, 7, L-pc-1)
  648. END BJump;
  649. PROCEDURE CBJump*(VAR x: Item; L: LONGINT);
  650. BEGIN
  651. IF x.mode # Cond THEN loadCond(x) END ;
  652. Put3(BC, negated(x.r), L-pc-1); FixLink(x.b); FixLinkWith(x.a, L)
  653. END CBJump;
  654. PROCEDURE Fixup*(VAR x: Item);
  655. BEGIN FixLink(x.a)
  656. END Fixup;
  657. PROCEDURE SaveRegs(r: LONGINT); (* R[0 .. r-1]*)
  658. VAR r0: LONGINT;
  659. BEGIN (*r > 0*) r0 := 0;
  660. Put1(Sub, SP, SP, r*4); INC(frame, 4*r);
  661. REPEAT Put2(Str, r0, SP, (r-r0-1)*4); INC(r0) UNTIL r0 = r
  662. END SaveRegs;
  663. PROCEDURE RestoreRegs(r: LONGINT); (*R[0 .. r-1]*)
  664. VAR r0: LONGINT;
  665. BEGIN (*r > 0*) r0 := r;
  666. REPEAT DEC(r0); Put2(Ldr, r0, SP, (r-r0-1)*4) UNTIL r0 = 0;
  667. Put1(Add, SP, SP, r*4); DEC(frame, 4*r)
  668. END RestoreRegs;
  669. PROCEDURE PrepCall*(VAR x: Item; VAR r: LONGINT);
  670. BEGIN (*x.type.form = ORB.Proc*)
  671. IF x.mode > ORB.Par THEN load(x) END ;
  672. r := RH;
  673. IF RH > 0 THEN SaveRegs(RH); RH := 0 END
  674. END PrepCall;
  675. PROCEDURE Call*(VAR x: Item; r: LONGINT);
  676. BEGIN (*x.type.form = ORB.Proc*)
  677. IF x.mode = ORB.Const THEN
  678. IF x.r >= 0 THEN Put3(BL, 7, (x.a DIV 4)-pc-1)
  679. ELSE (*imported*)
  680. IF pc - fixorgP < 1000H THEN
  681. Put3(BL, 7, ((-x.r) * 100H + x.a) * 1000H + pc-fixorgP); fixorgP := pc-1
  682. ELSE ORS.Mark("fixup impossible")
  683. END
  684. END
  685. ELSE
  686. IF x.mode <= ORB.Par THEN load(x); DEC(RH)
  687. ELSE Put2(Ldr, RH, SP, 0); Put1(Add, SP, SP, 4); DEC(r); DEC(frame, 4)
  688. END ;
  689. IF check THEN Trap(EQ, 5) END ;
  690. Put3(BLR, 7, RH)
  691. END ;
  692. IF x.type.base.form = ORB.NoTyp THEN (*procedure*) RH := 0
  693. ELSE (*function*)
  694. IF r > 0 THEN Put0(Mov, r, 0, 0); RestoreRegs(r) END ;
  695. x.mode := Reg; x.r := r; RH := r+1
  696. END ;
  697. invalSB
  698. END Call;
  699. PROCEDURE Enter*(parblksize, locblksize: LONGINT; int: BOOLEAN);
  700. VAR a, r: LONGINT;
  701. BEGIN invalSB; frame := 0;
  702. IF ~int THEN (*procedure prolog*)
  703. IF locblksize >= 10000H THEN ORS.Mark("too many locals") END ;
  704. a := 4; r := 0;
  705. Put1(Sub, SP, SP, locblksize); Put2(Str, LNK, SP, 0);
  706. WHILE a < parblksize DO Put2(Str, r, SP, a); INC(r); INC(a, 4) END
  707. ELSE (*interrupt procedure*)
  708. IF locblksize > 0H THEN ORS.Mark("locals not allowed") END ;
  709. Put1(Sub, SP, SP, 12); Put2(Str, 0, SP, 0); Put2(Str, 1, SP, 4); Put2(Str, SB, SP, 8)
  710. (*R0, R1, SB saved on stack*)
  711. END
  712. END Enter;
  713. PROCEDURE Return*(form: INTEGER; VAR x: Item; size: LONGINT; int: BOOLEAN);
  714. BEGIN
  715. IF form # ORB.NoTyp THEN load(x) END ;
  716. IF ~int THEN (*procedure epilog*)
  717. Put2(Ldr, LNK, SP, 0); Put1(Add, SP, SP, size); Put3(BR, 7, LNK)
  718. ELSE (*interrupt return, restore SB, R1, R0*)
  719. Put2(Ldr, SB, SP, 8); Put2(Ldr, 1, SP, 4); Put2(Ldr, 0, SP, 0); Put1(Add, SP, SP, 12); Put3(BR, 7, 10H)
  720. END ;
  721. RH := 0
  722. END Return;
  723. (* In-line code procedures*)
  724. PROCEDURE Increment*(upordown: LONGINT; VAR x, y: Item);
  725. VAR op, zr, v: LONGINT;
  726. BEGIN (*frame = 0*)
  727. IF upordown = 0 THEN op := Add ELSE op := Sub END ;
  728. IF x.type = ORB.byteType THEN v := 1 ELSE v := 0 END ;
  729. IF y.type.form = ORB.NoTyp THEN y.mode := ORB.Const; y.a := 1 END ;
  730. IF (x.mode = ORB.Var) & (x.r > 0) THEN
  731. zr := RH; Put2(Ldr+v, zr, SP, x.a); incR;
  732. IF y.mode = ORB.Const THEN Put1a(op, zr, zr, y.a) ELSE load(y); Put0(op, zr, zr, y.r); DEC(RH) END ;
  733. Put2(Str+v, zr, SP, x.a); DEC(RH)
  734. ELSE loadAdr(x); zr := RH; Put2(Ldr+v, RH, x.r, 0); incR;
  735. IF y.mode = ORB.Const THEN Put1a(op, zr, zr, y.a) ELSE load(y); Put0(op, zr, zr, y.r); DEC(RH) END ;
  736. Put2(Str+v, zr, x.r, 0); DEC(RH, 2)
  737. END
  738. END Increment;
  739. PROCEDURE Include*(inorex: LONGINT; VAR x, y: Item);
  740. VAR op, zr: LONGINT;
  741. BEGIN loadAdr(x); zr := RH; Put2(Ldr, RH, x.r, 0); incR;
  742. IF inorex = 0 THEN op := Ior ELSE op := Ann END ;
  743. IF y.mode = ORB.Const THEN Put1a(op, zr, zr, LSL(1, y.a))
  744. ELSE load(y); Put1(Mov, RH, 0, 1); Put0(Lsl, y.r, RH, y.r); Put0(op, zr, zr, y.r); DEC(RH)
  745. END ;
  746. Put2(Str, zr, x.r, 0); DEC(RH, 2)
  747. END Include;
  748. PROCEDURE Assert*(VAR x: Item);
  749. VAR cond: LONGINT;
  750. BEGIN
  751. IF x.mode # Cond THEN loadCond(x) END ;
  752. IF x.a = 0 THEN cond := negated(x.r)
  753. ELSE Put3(BC, x.r, x.b); FixLink(x.a); x.b := pc-1; cond := 7
  754. END ;
  755. Trap(cond, 7); FixLink(x.b)
  756. END Assert;
  757. PROCEDURE New*(VAR x: Item);
  758. BEGIN loadAdr(x); loadTypTagAdr(x.type.base); Trap(7, 0); RH := 0; invalSB
  759. END New;
  760. PROCEDURE Pack*(VAR x, y: Item);
  761. VAR z: Item;
  762. BEGIN z := x; load(x); load(y);
  763. Put1(Lsl, y.r, y.r, 23); Put0(Add, x.r, x.r, y.r); DEC(RH); Store(z, x)
  764. END Pack;
  765. PROCEDURE Unpk*(VAR x, y: Item);
  766. VAR z, e0: Item;
  767. BEGIN z := x; load(x); e0.mode := Reg; e0.r := RH; e0.type := ORB.intType;
  768. Put1(Asr, RH, x.r, 23); Put1(Sub, RH, RH, 127); Store(y, e0); incR;
  769. Put1(Lsl, RH, RH, 23); Put0(Sub, x.r, x.r, RH); Store(z, x)
  770. END Unpk;
  771. PROCEDURE Led*(VAR x: Item);
  772. BEGIN load(x); Put1(Mov, RH, 0, -60); Put2(Str, x.r, RH, 0); DEC(RH)
  773. END Led;
  774. PROCEDURE Get*(VAR x, y: Item);
  775. BEGIN load(x); x.type := y.type; x.mode := RegI; x.a := 0; Store(y, x)
  776. END Get;
  777. PROCEDURE Put*(VAR x, y: Item);
  778. BEGIN load(x); x.type := y.type; x.mode := RegI; x.a := 0; Store(x, y)
  779. END Put;
  780. PROCEDURE Copy*(VAR x, y, z: Item);
  781. BEGIN load(x); load(y);
  782. IF z.mode = ORB.Const THEN
  783. IF z.a > 0 THEN load(z) ELSE ORS.Mark("bad count") END
  784. ELSE load(z);
  785. IF check THEN Trap(LT, 3) END ;
  786. Put3(BC, EQ, 6)
  787. END ;
  788. Put2(Ldr, RH, x.r, 0); Put1(Add, x.r, x.r, 4);
  789. Put2(Str, RH, y.r, 0); Put1(Add, y.r, y.r, 4);
  790. Put1(Sub, z.r, z.r, 1); Put3(BC, NE, -6); DEC(RH, 3)
  791. END Copy;
  792. PROCEDURE LDPSR*(VAR x: Item);
  793. BEGIN (*x.mode = Const*) Put3(0, 15, x.a + 20H)
  794. END LDPSR;
  795. PROCEDURE LDREG*(VAR x, y: Item);
  796. BEGIN
  797. IF y.mode = ORB.Const THEN Put1a(Mov, x.a, 0, y.a)
  798. ELSE load(y); Put0(Mov, x.a, 0, y.r); DEC(RH)
  799. END
  800. END LDREG;
  801. (*In-line code functions*)
  802. PROCEDURE Abs*(VAR x: Item);
  803. BEGIN
  804. IF x.mode = ORB.Const THEN x.a := ABS(x.a)
  805. ELSE load(x);
  806. IF x.type.form = ORB.Real THEN Put1(Lsl, x.r, x.r, 1); Put1(Ror, x.r, x.r, 1)
  807. ELSE Put1(Cmp, x.r, x.r, 0); Put3(BC, GE, 2); Put1(Mov, RH, 0, 0); Put0(Sub, x.r, RH, x.r)
  808. END
  809. END
  810. END Abs;
  811. PROCEDURE Odd*(VAR x: Item);
  812. BEGIN load(x); Put1(And, x.r, x.r, 1); SetCC(x, NE); DEC(RH)
  813. END Odd;
  814. PROCEDURE Floor*(VAR x: Item);
  815. BEGIN load(x); Put1(Mov+U, RH, 0, 4B00H); Put0(Fad+V, x.r, x.r, RH)
  816. END Floor;
  817. PROCEDURE Float*(VAR x: Item);
  818. BEGIN load(x); Put1(Mov+U, RH, 0, 4B00H); Put0(Fad+U, x.r, x.r, RH)
  819. END Float;
  820. PROCEDURE Ord*(VAR x: Item);
  821. BEGIN
  822. IF x.mode IN {ORB.Var, ORB.Par, RegI, Cond} THEN load(x) END
  823. END Ord;
  824. PROCEDURE Len*(VAR x: Item);
  825. BEGIN
  826. IF x.type.len >= 0 THEN
  827. IF x.mode = RegI THEN DEC(RH) END ;
  828. x.mode := ORB.Const; x.a := x.type.len
  829. ELSE (*open array*) Put2(Ldr, RH, SP, x.a + 4 + frame); x.mode := Reg; x.r := RH; incR
  830. END
  831. END Len;
  832. PROCEDURE Shift*(fct: LONGINT; VAR x, y: Item);
  833. VAR op: LONGINT;
  834. BEGIN load(x);
  835. IF fct = 0 THEN op := Lsl ELSIF fct = 1 THEN op := Asr ELSE op := Ror END ;
  836. IF y.mode = ORB.Const THEN Put1(op, x.r, x.r, y.a MOD 20H)
  837. ELSE load(y); Put0(op, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  838. END
  839. END Shift;
  840. PROCEDURE ADC*(VAR x, y: Item);
  841. BEGIN load(x); load(y); Put0(Add+2000H, x.r, x.r, y.r); DEC(RH)
  842. END ADC;
  843. PROCEDURE SBC*(VAR x, y: Item);
  844. BEGIN load(x); load(y); Put0(Sub+2000H, x.r, x.r, y.r); DEC(RH)
  845. END SBC;
  846. PROCEDURE UML*(VAR x, y: Item);
  847. BEGIN load(x); load(y); Put0(Mul+2000H, x.r, x.r, y.r); DEC(RH)
  848. END UML;
  849. PROCEDURE Bit*(VAR x, y: Item);
  850. BEGIN load(x); Put2(Ldr, x.r, x.r, 0);
  851. IF y.mode = ORB.Const THEN Put1(Ror, x.r, x.r, y.a+1); DEC(RH)
  852. ELSE load(y); Put1(Add, y.r, y.r, 1); Put0(Ror, x.r, x.r, y.r); DEC(RH, 2)
  853. END ;
  854. SetCC(x, MI)
  855. END Bit;
  856. PROCEDURE Register*(VAR x: Item);
  857. BEGIN (*x.mode = Const*)
  858. Put0(Mov, RH, 0, x.a MOD 10H); x.mode := Reg; x.r := RH; incR
  859. END Register;
  860. PROCEDURE H*(VAR x: Item);
  861. BEGIN (*x.mode = Const*)
  862. Put0(Mov + U + x.a MOD 2 * V, RH, 0, 0); x.mode := Reg; x.r := RH; incR
  863. END H;
  864. PROCEDURE Adr*(VAR x: Item);
  865. BEGIN
  866. IF x.mode IN {ORB.Var, ORB.Par, RegI} THEN loadAdr(x)
  867. ELSIF (x.mode = ORB.Const) & (x.type.form = ORB.Proc) THEN load(x)
  868. ELSIF (x.mode = ORB.Const) & (x.type.form = ORB.String) THEN loadStringAdr(x)
  869. ELSE ORS.Mark("not addressable")
  870. END
  871. END Adr;
  872. PROCEDURE Condition*(VAR x: Item);
  873. BEGIN (*x.mode = Const*) SetCC(x, x.a)
  874. END Condition;
  875. PROCEDURE Open*(v: INTEGER);
  876. BEGIN pc := 0; tdx := 0; strx := 0; RH := 0; fixorgP := 0; fixorgD := 0; fixorgT := 0; check := v # 0; version := v;
  877. IF v = 0 THEN pc := 1;
  878. REPEAT code[pc] := 0; INC(pc) UNTIL pc = 8
  879. END
  880. END Open;
  881. PROCEDURE SetDataSize*(dc: LONGINT);
  882. BEGIN varsize := dc
  883. END SetDataSize;
  884. PROCEDURE Header*;
  885. BEGIN entry := pc*4;
  886. IF version = 0 THEN code[0] := 0E7000000H-1 + pc; Put1a(Mov, SB, 0, VarOrg0); Put1a(Mov, SP, 0, StkOrg0) (*RISC-0*)
  887. ELSE Put1(Sub, SP, SP, 4); Put2(Str, LNK, SP, 0); invalSB
  888. END
  889. END Header;
  890. PROCEDURE NofPtrs(typ: ORB.Type): LONGINT;
  891. VAR fld: ORB.Object; n: LONGINT;
  892. BEGIN
  893. IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN n := 1
  894. ELSIF typ.form = ORB.Record THEN
  895. fld := typ.dsc; n := 0;
  896. WHILE fld # NIL DO n := NofPtrs(fld.type) + n; fld := fld.next END
  897. ELSIF typ.form = ORB.Array THEN n := NofPtrs(typ.base) * typ.len
  898. ELSE n := 0
  899. END ;
  900. RETURN n
  901. END NofPtrs;
  902. PROCEDURE FindPtrs(VAR R: Files.Rider; typ: ORB.Type; adr: LONGINT);
  903. VAR fld: ORB.Object; i, s: LONGINT;
  904. BEGIN
  905. IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN Files.WriteInt(R, adr)
  906. ELSIF typ.form = ORB.Record THEN
  907. fld := typ.dsc;
  908. WHILE fld # NIL DO FindPtrs(R, fld.type, fld.val + adr); fld := fld.next END
  909. ELSIF typ.form = ORB.Array THEN
  910. s := typ.base.size;
  911. FOR i := 0 TO typ.len-1 DO FindPtrs(R, typ.base, i*s + adr) END
  912. END
  913. END FindPtrs;
  914. PROCEDURE Close*(VAR modid: ORS.Ident; key, nofent: LONGINT);
  915. VAR obj: ORB.Object;
  916. i, comsize, nofimps, nofptrs, size: LONGINT;
  917. name: ORS.Ident;
  918. F: Files.File; R: Files.Rider;
  919. BEGIN (*exit code*)
  920. IF version = 0 THEN Put1(Mov, 0, 0, 0); Put3(BR, 7, 0) (*RISC-0*)
  921. ELSE Put2(Ldr, LNK, SP, 0); Put1(Add, SP, SP, 4); Put3(BR, 7, LNK)
  922. END ;
  923. obj := ORB.topScope.next; nofimps := 0; comsize := 4; nofptrs := 0;
  924. WHILE obj # NIL DO
  925. IF (obj.class = ORB.Mod) & (obj.dsc # ORB.system) THEN INC(nofimps) (*count imports*)
  926. ELSIF (obj.exno # 0) & (obj.class = ORB.Const) & (obj.type.form = ORB.Proc)
  927. & (obj.type.nofpar = 0) & (obj.type.base = ORB.noType) THEN i := 0; (*count commands*)
  928. WHILE obj.name[i] # 0X DO INC(i) END ;
  929. i := (i+4) DIV 4 * 4; INC(comsize, i+4)
  930. ELSIF obj.class = ORB.Var THEN INC(nofptrs, NofPtrs(obj.type)) (*count pointers*)
  931. END ;
  932. obj := obj.next
  933. END ;
  934. size := varsize + strx + comsize + (pc + nofimps + nofent + nofptrs + 1)*4; (*varsize includes type descriptors*)
  935. ORB.MakeFileName(name, modid, ".rsc"); (*write code file*)
  936. F := Files.New(name); Files.Set(R, F, 0); Files.WriteString(R, modid); Files.WriteInt(R, key); Files.WriteByte(R, version);
  937. Files.WriteInt(R, size);
  938. obj := ORB.topScope.next;
  939. WHILE (obj # NIL) & (obj.class = ORB.Mod) DO (*imports*)
  940. IF obj.dsc # ORB.system THEN Files.WriteString(R, obj(ORB.Module).orgname); Files.WriteInt(R, obj.val) END ;
  941. obj := obj.next
  942. END ;
  943. Files.Write(R, 0X);
  944. Files.WriteInt(R, tdx*4);
  945. i := 0;
  946. WHILE i < tdx DO Files.WriteInt(R, data[i]); INC(i) END ; (*type descriptors*)
  947. Files.WriteInt(R, varsize - tdx*4); (*data*)
  948. Files.WriteInt(R, strx);
  949. FOR i := 0 TO strx-1 DO Files.Write(R, str[i]) END ; (*strings*)
  950. Files.WriteInt(R, pc); (*code len*)
  951. FOR i := 0 TO pc-1 DO Files.WriteInt(R, code[i]) END ; (*program*)
  952. obj := ORB.topScope.next;
  953. WHILE obj # NIL DO (*commands*)
  954. IF (obj.exno # 0) & (obj.class = ORB.Const) & (obj.type.form = ORB.Proc) &
  955. (obj.type.nofpar = 0) & (obj.type.base = ORB.noType) THEN
  956. Files.WriteString(R, obj.name); Files.WriteInt(R, obj.val)
  957. END ;
  958. obj := obj.next
  959. END ;
  960. Files.Write(R, 0X);
  961. Files.WriteInt(R, nofent); Files.WriteInt(R, entry);
  962. obj := ORB.topScope.next;
  963. WHILE obj # NIL DO (*entries*)
  964. IF obj.exno # 0 THEN
  965. IF (obj.class = ORB.Const) & (obj.type.form = ORB.Proc) OR (obj.class = ORB.Var) THEN
  966. Files.WriteInt(R, obj.val)
  967. ELSIF obj.class = ORB.Typ THEN
  968. IF obj.type.form = ORB.Record THEN Files.WriteInt(R, obj.type.len MOD 10000H)
  969. ELSIF (obj.type.form = ORB.Pointer) & ((obj.type.base.typobj = NIL) OR (obj.type.base.typobj.exno = 0)) THEN
  970. Files.WriteInt(R, obj.type.base.len MOD 10000H)
  971. END
  972. END
  973. END ;
  974. obj := obj.next
  975. END ;
  976. obj := ORB.topScope.next;
  977. WHILE obj # NIL DO (*pointer variables*)
  978. IF obj.class = ORB.Var THEN FindPtrs(R, obj.type, obj.val) END ;
  979. obj := obj.next
  980. END ;
  981. Files.WriteInt(R, -1);
  982. Files.WriteInt(R, fixorgP); Files.WriteInt(R, fixorgD); Files.WriteInt(R, fixorgT); Files.WriteInt(R, entry);
  983. Files.Write(R, "O"); Files.Register(F)
  984. END Close;
  985. BEGIN
  986. relmap[0] := 1; relmap[1] := 9; relmap[2] := 5; relmap[3] := 6; relmap[4] := 14; relmap[5] := 13
  987. END ORG.