FoxBinaryCode.Mod 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. MODULE FoxBinaryCode; (** AUTHOR ""; PURPOSE ""; *)
  2. IMPORT Basic := FoxBasic, Sections := FoxSections, Streams, ObjectFile, BitSets;
  3. CONST
  4. Absolute*=ObjectFile.Absolute;
  5. Relative*=ObjectFile.Relative;
  6. Byte=8;
  7. TYPE
  8. Code* = BitSets.BitSet;
  9. Unit*= ObjectFile.Unit;
  10. Bits*=ObjectFile.Bits;
  11. FixupPatterns*=ObjectFile.FixupPatterns;
  12. Alias*=OBJECT
  13. VAR
  14. nextAlias-: Alias;
  15. identifier-: ObjectFile.Identifier;
  16. offset-: LONGINT;
  17. PROCEDURE & InitAlias*(identifier: ObjectFile.Identifier; offset: LONGINT);
  18. BEGIN
  19. nextAlias := NIL;
  20. SELF.identifier := identifier;
  21. SELF.offset := offset;
  22. END InitAlias;
  23. PROCEDURE Dump*(w: Streams.Writer);
  24. BEGIN
  25. Basic.WriteSegmentedName(w, identifier.name);
  26. IF identifier.fingerprint # 0 THEN w.String("["); w.Hex(identifier.fingerprint,-8); w.String("]") END;
  27. w.String(" "); w.Int(offset,1);
  28. END Dump;
  29. END Alias;
  30. AliasList*=OBJECT
  31. VAR
  32. firstAlias-, lastAlias-: Alias; aliases-: LONGINT;
  33. PROCEDURE &InitAliasList*;
  34. BEGIN
  35. firstAlias := NIL; lastAlias := NIL;
  36. aliases := 0;
  37. END InitAliasList;
  38. PROCEDURE AddAlias*(alias: Alias);
  39. BEGIN
  40. IF firstAlias = NIL THEN
  41. firstAlias := alias;
  42. ELSE
  43. lastAlias.nextAlias := alias;
  44. END;
  45. lastAlias := alias; alias.nextAlias := NIL;
  46. INC(aliases);
  47. END AddAlias;
  48. PROCEDURE Dump*(w: Streams.Writer);
  49. VAR alias: Alias;
  50. BEGIN
  51. alias := firstAlias;
  52. WHILE alias # NIL DO
  53. w.String("alias "); w.Int(alias.offset,1); w.String(" <-- ");
  54. alias.Dump(w);
  55. w.Ln;
  56. alias := alias.nextAlias;
  57. END;
  58. END Dump;
  59. END AliasList;
  60. Fixup*=OBJECT
  61. VAR
  62. nextFixup-: Fixup;
  63. mode-: INTEGER; (* fixup mode: relative or absolute *)
  64. displacement-: Unit; (* displacement of the fixup ('source') *)
  65. scale-: ObjectFile.Bits; (* exponent of scale factor (factor=2^scale) *)
  66. patterns-: LONGINT;
  67. pattern-: FixupPatterns; (* patterns describing the fixup format, cf. above *)
  68. offset-: Unit;
  69. symbol-: ObjectFile.Identifier; (* reference to the fixup's destination section *)
  70. symbolOffset-: LONGINT; (* offset in intermediate section, must be patched (resolved and added to displacement) to destination section displacement *)
  71. resolved*: Sections.Section; (* cache ! *)
  72. PROCEDURE & InitFixup*(mode: INTEGER; fixupOffset: Unit; symbol: ObjectFile.Identifier; symbolOffset: LONGINT; displacement: Unit; scale: LONGINT; fixupPattern: ObjectFile.FixupPatterns);
  73. BEGIN
  74. ASSERT((mode = Relative) OR (mode = Absolute));
  75. ASSERT(symbol.name # "");
  76. ASSERT(symbol.name[0] # 0);
  77. nextFixup := NIL;
  78. SELF.mode := mode;
  79. SELF.displacement := displacement;
  80. SELF.scale := scale;
  81. SELF.offset := fixupOffset;
  82. SELF.pattern := fixupPattern;
  83. IF fixupPattern # NIL THEN
  84. SELF.patterns := LEN(fixupPattern);
  85. ELSE
  86. SELF.patterns := 0
  87. END;
  88. SELF.symbol := symbol;
  89. SELF.symbolOffset := symbolOffset;
  90. END InitFixup;
  91. PROCEDURE SetFixupOffset*(offset: Unit);
  92. BEGIN
  93. SELF.offset := offset;
  94. END SetFixupOffset;
  95. PROCEDURE SetSymbol*(symbol: Sections.SectionName; fp: ObjectFile.Fingerprint; symbolOffset: LONGINT; displacement: Unit);
  96. BEGIN
  97. SELF.symbol.name := symbol;
  98. SELF.symbol.fingerprint := fp;
  99. SELF.symbolOffset := symbolOffset;
  100. SELF.displacement := displacement;
  101. END SetSymbol;
  102. PROCEDURE Dump*(w: Streams.Writer);
  103. VAR i: LONGINT;
  104. BEGIN
  105. Basic.WriteSegmentedName(w, symbol.name);
  106. IF symbol.fingerprint # 0 THEN w.String("["); w.Hex(symbol.fingerprint,-8); w.String("]") END;
  107. IF symbolOffset # 0 THEN w.String(":"); w.Int(symbolOffset, 0) END;
  108. w.String(" (displ="); w.Int(displacement, 0); w.String(")");
  109. IF scale # 0 THEN w.String(" *"); w.Int(scale,1); END;
  110. w.String(" [");
  111. IF pattern # NIL THEN
  112. FOR i := 0 TO LEN(pattern)-1 DO
  113. w.Int(pattern[i].offset,1);
  114. IF pattern[i].bits >=0 THEN w.String("+"); w.Int(pattern[i].bits,1);
  115. ELSE w.String("-"); w.Int(-pattern[i].bits,1);
  116. END;
  117. IF i < LEN(pattern)-1 THEN w.String(", ") ELSE w.String(" ") END;
  118. END;
  119. END;
  120. IF mode = Absolute THEN w.String("abs") ELSIF mode = Relative THEN w.String("rel") ELSE w.String("?"); END;
  121. w.String("]");
  122. END Dump;
  123. END Fixup;
  124. FixupList*=OBJECT
  125. VAR
  126. firstFixup-, lastFixup-: Fixup; fixups-: LONGINT;
  127. PROCEDURE &InitFixupList*;
  128. BEGIN
  129. firstFixup := NIL; lastFixup := NIL;
  130. fixups := 0;
  131. END InitFixupList;
  132. PROCEDURE AddFixup*(fixup: Fixup);
  133. BEGIN
  134. IF firstFixup = NIL THEN
  135. firstFixup := fixup;
  136. ELSE
  137. lastFixup.nextFixup := fixup;
  138. END;
  139. lastFixup := fixup; fixup.nextFixup := NIL;
  140. INC(fixups);
  141. END AddFixup;
  142. PROCEDURE Dump*(w: Streams.Writer);
  143. VAR fixup: Fixup;
  144. BEGIN
  145. fixup := firstFixup;
  146. WHILE fixup # NIL DO
  147. w.String("fixup "); w.Int(fixup.offset,1); w.String(" <-- ");
  148. fixup.Dump(w);
  149. w.Ln;
  150. fixup := fixup.nextFixup;
  151. END;
  152. END Dump;
  153. END FixupList;
  154. LabelList*= POINTER TO RECORD
  155. offset-: LONGINT; position-: Basic.Position;
  156. prev-: LabelList;
  157. END;
  158. Section* = OBJECT
  159. VAR
  160. os*: ObjectFile.Section;
  161. labels-: LabelList; (* labels for tracking the PC / debugging *)
  162. fixupList-: FixupList;
  163. aliasList-: AliasList;
  164. finally-: Unit; (* position of finally section in bitstream -1 if none *)
  165. comments-: Sections.CommentWriter; (* writer to write comment text between instructions *)
  166. bigEndian-: BOOLEAN; (* endianess of bits (not bytes) *)
  167. pc-: Unit; (* current position, in units *)
  168. PROCEDURE GetPC(): LONGINT;
  169. BEGIN
  170. RETURN pc
  171. END GetPC;
  172. PROCEDURE & InitBinarySection*(type: SHORTINT; unit: LONGINT; CONST name:Basic.SegmentedName; dump: BOOLEAN; bigEndian: BOOLEAN);
  173. BEGIN
  174. ASSERT(unit > 0);
  175. ASSERT(unit <= 32); (* implementation restriction *)
  176. SELF.os.type := type;
  177. os.identifier.name := name;
  178. (*
  179. ObjectFile.ToSegmentedName(name, SELF.identifier.name);
  180. *)
  181. (*COPY(name,SELF.identifier.name);*)
  182. NEW(os.bits,0);
  183. SELF.os.unit := unit;
  184. IF dump THEN
  185. comments := Sections.NewCommentWriter(GetPC);
  186. ELSE
  187. comments := NIL
  188. END;
  189. os.alignment := 0;
  190. finally := -1;
  191. labels := NIL;
  192. SELF.bigEndian := bigEndian;
  193. NEW(fixupList);
  194. NEW(aliasList);
  195. pc := 0;
  196. os.fixed := FALSE;
  197. END InitBinarySection;
  198. PROCEDURE Reset*;
  199. BEGIN
  200. NEW(os.bits,0);
  201. NEW(fixupList);
  202. IF comments # NIL THEN comments.Reset END;
  203. pc := 0;
  204. END Reset;
  205. PROCEDURE AddLabel*(position: Basic.Position);
  206. VAR new: LabelList;
  207. BEGIN
  208. NEW(new);
  209. IF labels = NIL THEN
  210. labels := new
  211. ELSE
  212. new.prev := labels; labels := new;
  213. END;
  214. new.position := position;
  215. new.offset := pc;
  216. END AddLabel;
  217. PROCEDURE SetPC*(pc: Unit);
  218. BEGIN
  219. SELF.pc := pc;
  220. CheckSize(0); (* adjust size *)
  221. END SetPC;
  222. PROCEDURE Align*(alignment: Unit);
  223. BEGIN
  224. SetPC(pc + (-pc) MOD alignment)
  225. END Align;
  226. PROCEDURE SetFinally*(atPC: Unit);
  227. BEGIN finally := atPC
  228. END SetFinally;
  229. PROCEDURE SetAlignment*(fixed: BOOLEAN; alignat: LONGINT);
  230. BEGIN os.alignment := alignat; SELF.os.fixed := fixed;
  231. END SetAlignment;
  232. PROCEDURE CheckSize(size: LONGINT);
  233. BEGIN
  234. IF os.bits.GetSize() < size + pc*os.unit THEN os.bits.Resize(size + pc*os.unit) END;
  235. ASSERT(os.bits.GetSize() MOD os.unit = 0);
  236. END CheckSize;
  237. PROCEDURE CopyBits*(src: BitSets.BitSet; srcPos, len: Bits);
  238. BEGIN
  239. ASSERT(len MOD os.unit = 0);
  240. CheckSize(src.GetSize());
  241. BitSets.CopyBits(src,srcPos,os.bits,pc*os.unit,len);
  242. INC(pc,len DIV os.unit);
  243. END CopyBits;
  244. PROCEDURE PutBits*(d: HUGEINT; size: Bits);
  245. BEGIN
  246. (*ASSERT(size MOD unit = 0);*)
  247. CheckSize(size);
  248. os.bits.SetBits(pc*os.unit,size,d);
  249. INC(pc,size DIV os.unit);
  250. END PutBits;
  251. PROCEDURE PutBitsAt*(at: Unit; d: HUGEINT; size: Bits);
  252. VAR oldpc: LONGINT;
  253. BEGIN
  254. oldpc := pc;
  255. pc := at;
  256. PutBits(d,size);
  257. pc := oldpc;
  258. END PutBitsAt;
  259. PROCEDURE PutByte* (b: LONGINT);
  260. BEGIN
  261. PutBits(b,Byte);
  262. END PutByte;
  263. PROCEDURE PutWord*(w: LONGINT);
  264. VAR c1,c2: LONGINT;
  265. BEGIN
  266. ASSERT((2*Byte) MOD os.unit = 0);
  267. CheckSize(2*Byte);
  268. c1 := w;
  269. c2 := w DIV 100H;
  270. IF bigEndian THEN
  271. os.bits.SetBits(pc*os.unit,Byte,c2);
  272. os.bits.SetBits(pc*os.unit+Byte,Byte,c1);
  273. ELSE
  274. os.bits.SetBits(pc*os.unit,Byte,c1);
  275. os.bits.SetBits(pc*os.unit+Byte,Byte,c2);
  276. END;
  277. INC(pc,(2*Byte) DIV os.unit);
  278. END PutWord;
  279. PROCEDURE PutDWord*(d: LONGINT);
  280. VAR c1,c2,c3,c4: LONGINT;
  281. BEGIN
  282. ASSERT((4*Byte) MOD os.unit = 0);
  283. CheckSize(4*Byte);
  284. c1 := d;
  285. c2 := d DIV 100H;
  286. c3 := d DIV 10000H;
  287. c4 := d DIV 1000000H;
  288. IF bigEndian THEN
  289. os.bits.SetBits(pc*os.unit+0*Byte,Byte,c4);
  290. os.bits.SetBits(pc*os.unit+1*Byte,Byte,c3);
  291. os.bits.SetBits(pc*os.unit+2*Byte,Byte,c2);
  292. os.bits.SetBits(pc*os.unit+3*Byte,Byte,c1);
  293. ELSE
  294. os.bits.SetBits(pc*os.unit+0*Byte,Byte,c1);
  295. os.bits.SetBits(pc*os.unit+1*Byte,Byte,c2);
  296. os.bits.SetBits(pc*os.unit+2*Byte,Byte,c3);
  297. os.bits.SetBits(pc*os.unit+3*Byte,Byte,c4);
  298. END;
  299. INC(pc,(4*Byte) DIV os.unit);
  300. END PutDWord;
  301. PROCEDURE PutQWord* (q: HUGEINT);
  302. VAR c: ARRAY 8 OF LONGINT; i: LONGINT;
  303. BEGIN
  304. ASSERT((8*Byte) MOD os.unit = 0);
  305. CheckSize(8*Byte);
  306. FOR i := 0 TO 7 DO
  307. c[i] := SHORT(q MOD 100H);
  308. q := q DIV 100H;
  309. END;
  310. IF bigEndian THEN
  311. FOR i := 0 TO 7 DO
  312. os.bits.SetBits(pc*os.unit+i*Byte,Byte,c[7-i]);
  313. END;
  314. ELSE
  315. FOR i := 0 TO 7 DO
  316. os.bits.SetBits(pc*os.unit+i*Byte,Byte,c[i]);
  317. END;
  318. END;
  319. INC(pc,(8*Byte) DIV os.unit);
  320. END PutQWord;
  321. PROCEDURE PutReal*(f: REAL);
  322. VAR x: LONGINT;
  323. BEGIN
  324. x := ConvertReal(f);
  325. PutDWord(x)
  326. END PutReal;
  327. PROCEDURE PutLongreal*(f: LONGREAL);
  328. VAR x: HUGEINT;
  329. BEGIN
  330. x := ConvertLongreal(f);
  331. PutQWord(x)
  332. END PutLongreal;
  333. PROCEDURE PutByteAt*(at: Unit; d: LONGINT);
  334. VAR oldpc: LONGINT;
  335. BEGIN
  336. oldpc := pc;
  337. pc := at;
  338. PutByte(d);
  339. pc := oldpc;
  340. END PutByteAt;
  341. PROCEDURE PutWordAt*(at: Unit; d: LONGINT);
  342. VAR oldpc: LONGINT;
  343. BEGIN
  344. oldpc := pc;
  345. pc := at;
  346. PutWord(d);
  347. pc := oldpc;
  348. END PutWordAt;
  349. PROCEDURE PutDWordAt*(at: Unit; d: LONGINT);
  350. VAR oldpc: LONGINT;
  351. BEGIN
  352. oldpc := pc;
  353. pc := at;
  354. PutDWord(d);
  355. pc := oldpc;
  356. END PutDWordAt;
  357. PROCEDURE PutQWordAt*(at: Unit; d: HUGEINT);
  358. VAR oldpc: LONGINT;
  359. BEGIN
  360. oldpc := pc;
  361. pc := at;
  362. PutQWord(d);
  363. pc := oldpc;
  364. END PutQWordAt;
  365. PROCEDURE PutBytes* (data: HUGEINT; bytes: SHORTINT);
  366. BEGIN
  367. CASE bytes OF
  368. 1: PutByte (SHORT(data));
  369. | 2: PutWord (SHORT(data));
  370. | 4: PutDWord (SHORT(data));
  371. | 8: PutQWord(data);
  372. END
  373. END PutBytes;
  374. PROCEDURE GetByte* (pc: Unit): CHAR;
  375. BEGIN
  376. RETURN CHR(os.bits.GetBits(pc*os.unit,8));
  377. END GetByte;
  378. PROCEDURE GetWord*(pc: Unit): LONGINT;
  379. VAR c1,c2: WORD;
  380. BEGIN
  381. c1 := os.bits.GetBits(pc*os.unit,8);
  382. c2 := os.bits.GetBits(pc*os.unit+8,8);
  383. IF bigEndian THEN
  384. RETURN c1*100H + c2;
  385. ELSE
  386. RETURN c1 + c2*100H;
  387. END
  388. END GetWord;
  389. PROCEDURE GetDWord*(pc: Unit): LONGINT;
  390. VAR c1,c2,c3,c4: WORD;
  391. BEGIN
  392. c1 := os.bits.GetBits(pc*os.unit+0*Byte,Byte);
  393. c2 := os.bits.GetBits(pc*os.unit+1*Byte,Byte);
  394. c3 := os.bits.GetBits(pc*os.unit+2*Byte,Byte);
  395. c4 := os.bits.GetBits(pc*os.unit+3*Byte,Byte);
  396. IF bigEndian THEN
  397. RETURN c4 + 100H * (c3 + 100H * (c2 + c1*100H));
  398. ELSE
  399. RETURN c1 + 100H * (c2 + 100H * (c3 + c4*100H));
  400. END
  401. END GetDWord;
  402. PROCEDURE GetQWord*(pc: Unit): HUGEINT;
  403. VAR i: LONGINT; h: HUGEINT;
  404. BEGIN
  405. h := 0;
  406. IF bigEndian THEN
  407. FOR i := 0 TO 7 DO
  408. h := 100H*h;
  409. h := h + os.bits.GetBits(pc*os.unit+i*Byte,Byte);
  410. END;
  411. ELSE
  412. FOR i := 7 TO 0 BY -1 DO
  413. h := 100H*h;
  414. h := h + os.bits.GetBits(pc*os.unit+i*Byte,Byte);
  415. END;
  416. END;
  417. RETURN h
  418. END GetQWord;
  419. PROCEDURE GetReal*(pc: Unit): REAL;
  420. VAR x: LONGINT;
  421. BEGIN
  422. x := GetDWord(pc);
  423. RETURN ConvertToReal(x)
  424. END GetReal;
  425. PROCEDURE GetLongreal*(pc: Unit): LONGREAL;
  426. VAR x: HUGEINT;
  427. BEGIN
  428. x := GetDWord(pc);
  429. RETURN ConvertToLongreal(x)
  430. END GetLongreal;
  431. PROCEDURE GetBits*(pc: Unit; size: Bits): WORD;
  432. BEGIN
  433. RETURN os.bits.GetBits(pc*os.unit,size)
  434. END GetBits;
  435. PROCEDURE ApplyFixup*(fixup: Fixup): BOOLEAN;
  436. VAR address,i: LONGINT;
  437. PROCEDURE PatchPattern (CONST pattern: ObjectFile.FixupPattern);
  438. BEGIN
  439. IF pattern.offset # MIN(SHORTINT) THEN
  440. os.bits.SetBits(fixup.offset*os.unit+pattern.offset,pattern.bits,address);
  441. END;
  442. address := ASH (address, -pattern.bits);
  443. END PatchPattern;
  444. PROCEDURE CheckBits(): BOOLEAN;
  445. VAR nobits,remainder,i: LONGINT;
  446. BEGIN
  447. nobits := 0;
  448. FOR i := 0 TO fixup.patterns-1 DO
  449. INC(nobits,fixup.pattern[i].bits);
  450. END;
  451. IF fixup.mode = Relative THEN DEC(nobits) END;
  452. remainder := ASH(address,-nobits);
  453. RETURN (nobits >31) OR (remainder = 0) OR (remainder = -1)
  454. END CheckBits;
  455. BEGIN
  456. address := fixup.displacement;
  457. IF fixup.mode = Relative THEN
  458. address := address - fixup.offset
  459. ELSE
  460. ASSERT(fixup.mode = Absolute)
  461. END;
  462. address := ASH(address,fixup.scale);
  463. IF CheckBits() THEN
  464. FOR i := 0 TO fixup.patterns-1 DO
  465. PatchPattern(fixup.pattern[i]);
  466. END;
  467. RETURN TRUE
  468. ELSE
  469. RETURN FALSE
  470. END;
  471. END ApplyFixup;
  472. PROCEDURE DumpCode*(w: Streams.Writer; from,to: Unit);
  473. VAR i: LONGINT; c: Sections.Comment; nextpos: LONGINT;
  474. PROCEDURE Hex(i: LONGINT): CHAR;
  475. BEGIN
  476. ASSERT(i>=0);
  477. ASSERT(i<16);
  478. IF i<10 THEN
  479. RETURN CHR(ORD("0")+i)
  480. ELSE
  481. RETURN CHR(ORD("A")+i-10);
  482. END;
  483. END Hex;
  484. PROCEDURE DumpUnit(at: LONGINT);
  485. VAR val: WORD; a: ARRAY 9 OF CHAR; bits: LONGINT;
  486. BEGIN
  487. val := GetBits(at,os.unit);
  488. bits := os.unit;
  489. a[(bits-1) DIV 4 +1] := 0X;
  490. WHILE (bits > 0) DO
  491. a[(bits-1) DIV 4] := Hex(val MOD 16);
  492. val := LSH(val,-4);
  493. DEC(bits,4);
  494. END;
  495. w.String(a);
  496. END DumpUnit;
  497. PROCEDURE DumpBlock(from,to: LONGINT);
  498. VAR i: LONGINT; nr: LONGINT;
  499. BEGIN
  500. i := from; nr := 0;
  501. IF to >= pc THEN to := pc-1 END;
  502. WHILE i <= to DO
  503. w.String("["); w.Hex(i,3); w.String("] ");
  504. nr := 0;
  505. WHILE (i<=to) & (nr<16) DO
  506. IF i = 8 THEN w.String(" ") END;
  507. DumpUnit(i);
  508. w.String(" ");
  509. INC(i); INC(nr);
  510. END;
  511. IF i <= to THEN
  512. w.Ln;
  513. END;
  514. END;
  515. END DumpBlock;
  516. BEGIN
  517. IF comments # NIL THEN
  518. c := comments.firstComment;
  519. WHILE(c # NIL) & (c.pos <from) DO
  520. c := c.nextComment;
  521. END;
  522. i := from;
  523. WHILE(i<=to) DO
  524. WHILE (c # NIL) & (c.pos = i) DO
  525. c.Dump(w); w.Ln;
  526. c := c.nextComment;
  527. END;
  528. IF (c # NIL) & (c.pos <= to) THEN nextpos := c.pos-1 ELSE nextpos := to END;
  529. DumpBlock(i,nextpos);w.Ln;
  530. i := nextpos+1;
  531. END;
  532. WHILE (c#NIL) & (c.pos = to+1) DO
  533. c.Dump(w); w.Ln; c := c.nextComment;
  534. END;
  535. ELSE
  536. DumpBlock(0,SELF.pc-1)
  537. END
  538. END DumpCode;
  539. PROCEDURE Dump*(w: Streams.Writer);
  540. VAR ww: Basic.Writer;
  541. BEGIN
  542. IF comments # NIL THEN comments.Update END;
  543. ww := Basic.GetWriter(w);
  544. ww.String(" unit="); ww.Int(os.unit,1);
  545. IF os.fixed THEN w.String(" fixed") ELSE w.String(" relocatable") END;
  546. w.String(" align="); w.Int(os.alignment,1);
  547. ww.String(" size="); ww.Int(SELF.pc,1);
  548. ww.String(" fixups="); ww.Int(SELF.os.fixups,1);
  549. ww.Ln;
  550. ww.IncIndent;
  551. fixupList.Dump(ww);
  552. DumpCode(ww,0,SELF.pc-1);
  553. ww.DecIndent;
  554. END Dump;
  555. END Section;
  556. PROCEDURE ConvertReal* (value: REAL): LONGINT;
  557. CONST Exponent = 8; Significant = 23;
  558. VAR result: LONGINT; VAR exponent, i: INTEGER;
  559. BEGIN
  560. (*! NaN code missing, we need an extra - machine specific - functionality for that / cf. Streams.NaNCode *)
  561. IF value = 0 THEN RETURN 0 END;
  562. result := 0; exponent := 0;
  563. IF value < 0 THEN value := -value; result := ASH (1, Exponent) END;
  564. WHILE value < 1 DO value := value * 2; DEC (exponent) END;
  565. WHILE value >= 2 DO value := value / 2; INC (exponent) END;
  566. value := value - 1; INC (result, ASH (1, Exponent - 1) - 1 + exponent);
  567. FOR i := 0 TO Significant - 1 DO
  568. value := value * 2; INC (result, result);
  569. IF value >= 1 THEN value := value - 1; INC (result) END;
  570. END;
  571. RETURN result;
  572. END ConvertReal;
  573. PROCEDURE ConvertLongreal*(value: LONGREAL): HUGEINT;
  574. CONST Exponent = 11; Significant = 52;
  575. VAR result: HUGEINT; VAR exponent, i: INTEGER;
  576. BEGIN
  577. (*! NaN code missing, we need an extra - machine specific - functionality for that / cf. Streams.NaNCode *)
  578. IF value = 0 THEN RETURN 0 END;
  579. result := 0; exponent := 0;
  580. IF value < 0 THEN value := -value; result := ASH (1, Exponent) END;
  581. WHILE value < 1 DO value := value * 2; DEC (exponent) END;
  582. WHILE value >= 2 DO value := value / 2; INC (exponent) END;
  583. value := value - 1; INC (result, ASH (1, Exponent - 1) - 1 + exponent);
  584. FOR i := 0 TO Significant - 1 DO
  585. value := value * 2; INC (result, result);
  586. IF value >= 1 THEN value := value - 1; INC (result) END;
  587. END;
  588. RETURN result;
  589. END ConvertLongreal;
  590. PROCEDURE ConvertToReal*(x: LONGINT): REAL;
  591. VAR result: REAL; e,i: LONGINT;
  592. PROCEDURE Bit(bit: LONGINT): BOOLEAN;
  593. BEGIN
  594. RETURN ODD(ASH(x,-bit))
  595. END Bit;
  596. BEGIN
  597. result := 0; e := 0;
  598. FOR i := 0 TO 22 DO
  599. IF Bit(i) THEN result := result + 1 END; result := result / 2;
  600. END;
  601. FOR i := 30 TO 23 BY -1 DO
  602. e := e*2; IF Bit(i) THEN e := e+1 END;
  603. END;
  604. IF e = 0FFH THEN (* NaN or Inf *)
  605. HALT(200);
  606. (*! NaN code missing, we need an extra - machine specific - functionality for that / cf. Streams.NaNCode *)
  607. ELSIF (result # 0) OR (e#0) THEN
  608. result := result + 1;
  609. DEC(e,127);
  610. WHILE e > 0 DO result := result *2; DEC(e) END;
  611. WHILE e < 0 DO result := result / 2; INC(e) END;
  612. IF Bit(31) THEN result := -result END;
  613. END;
  614. RETURN result
  615. END ConvertToReal;
  616. PROCEDURE ConvertToLongreal*(x: HUGEINT): LONGREAL;
  617. VAR result: LONGREAL; e,i: LONGINT;
  618. PROCEDURE Bit(bit: LONGINT): BOOLEAN;
  619. BEGIN
  620. RETURN ODD(ASH(x,-bit))
  621. END Bit;
  622. BEGIN
  623. result := 0; e:= 0;
  624. FOR i := 0 TO 51 DO
  625. IF Bit(i) THEN result := result + 1 END; result := result / 2;
  626. END;
  627. result := result + 1;
  628. FOR i := 62 TO 52 BY -1 DO
  629. e := e*2; IF Bit(i) THEN e := e+1 END;
  630. END;
  631. IF e = 7FFH THEN (* NaN or Inf *)
  632. HALT(200)
  633. (*! NaN code missing, we need an extra - machine specific - functionality for that / cf. Streams.NaNCode *)
  634. ELSIF (result # 0) OR (e#0) THEN
  635. DEC(e,1023);
  636. WHILE e > 0 DO result := result *2; DEC(e) END;
  637. WHILE e < 0 DO result := result / 2; INC(e) END;
  638. IF Bit(63) THEN result := -result END;
  639. END;
  640. RETURN result
  641. END ConvertToLongreal;
  642. PROCEDURE NewFixup*(mode: INTEGER; fixupOffset: LONGINT; symbol: ObjectFile.Identifier; symbolOffset,displacement: LONGINT; scale: LONGINT; fixupPattern: ObjectFile.FixupPatterns): Fixup;
  643. VAR fixup: Fixup;
  644. BEGIN
  645. NEW(fixup,mode,fixupOffset,symbol,symbolOffset,displacement,scale,fixupPattern); RETURN fixup
  646. END NewFixup;
  647. PROCEDURE NewBinarySection*(type: SHORTINT; unit: LONGINT; CONST name: Basic.SegmentedName; dump: BOOLEAN; bigEndian: BOOLEAN): Section;
  648. VAR binarySection: Section;
  649. BEGIN
  650. NEW(binarySection,type,unit,name,dump,bigEndian); RETURN binarySection
  651. END NewBinarySection;
  652. END FoxBinaryCode.
  653. FoxBinaryCode.TestFixup
  654. (*
  655. PROCEDURE TestFixup*;
  656. VAR data1,data2: Section; i: LONGINT; fixup: Fixup; fixupFormat: FixupFormat;
  657. PROCEDURE DumpBits(ch: CHAR);
  658. VAR v: LONGINT; s: ARRAY 9 OF CHAR; i: LONGINT;
  659. BEGIN
  660. v := ORD(ch);
  661. FOR i := 7 TO 0 BY -1 DO
  662. IF ODD(v) THEN s[i]:='1' ELSE s[i] := '0' END;
  663. v := ASH(v,-1);
  664. END;
  665. s[8] := 0X;
  666. D.String(s);
  667. END DumpBits;
  668. BEGIN
  669. NEW(data1,Sections.CodeSection,8,"test",NIL,FALSE,TRUE);
  670. NEW(data2,Sections.CodeSection,8,"test",NIL,FALSE,TRUE);
  671. FOR i := 0 TO 100 DO
  672. data1.PutByte(170);
  673. data2.PutByte(85);
  674. END;
  675. FOR i := 15 TO 20 DO DumpBits(data1.data[i]); END; D.Ln;
  676. FOR i := 15 TO 20 DO DumpBits(data2.data[i]); END;D.Ln;
  677. NEW(fixupFormat,3);
  678. fixupFormat[0].offset := 0;
  679. fixupFormat[0].bits := 12;
  680. fixupFormat[1].offset := MIN(SHORTINT);
  681. fixupFormat[1].bits := 8;
  682. fixupFormat[2].offset := 20;
  683. fixupFormat[2].bits := 12;
  684. NEW(fixup,Absolute,16,NIL,0,0,0,fixupFormat);
  685. data1.ApplyFixup(fixup,3F7DEEDH);
  686. data2.ApplyFixup(fixup,3F7DEEDH);
  687. FOR i := 15 TO 20 DO DumpBits(data1.data[i]); END; D.Ln;
  688. FOR i := 15 TO 20 DO DumpBits(data2.data[i]); END;D.Ln; D.Ln;
  689. D.Update;
  690. data1.Dump(D.Log); D.Ln;
  691. data2.Dump(D.Log); D.Ln;
  692. END TestFixup;
  693. *)