FoxBinaryCode.Mod 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  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-: Unit;
  17. PROCEDURE & InitAlias*(identifier: ObjectFile.Identifier; offset: Unit);
  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,0); 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-: SIZE;
  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,0); 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-: Unit; 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(): Unit;
  169. BEGIN
  170. RETURN pc
  171. END GetPC;
  172. PROCEDURE & InitBinarySection*(type: SHORTINT; unit: Bits; 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: Unit;
  253. BEGIN
  254. oldpc := pc;
  255. pc := at;
  256. PutBits(d,size);
  257. pc := oldpc;
  258. END PutBitsAt;
  259. PROCEDURE PutByte* (b: WORD);
  260. BEGIN
  261. PutBits(b,Byte);
  262. END PutByte;
  263. PROCEDURE PutWord*(w: WORD);
  264. VAR c1,c2: WORD;
  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: WORD);
  280. VAR c1,c2,c3,c4: WORD;
  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 WORD; i: WORD;
  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. BEGIN
  323. PutDWord(ConvertReal(f))
  324. END PutReal;
  325. PROCEDURE PutLongreal*(f: LONGREAL);
  326. BEGIN
  327. PutQWord(ConvertLongreal(f))
  328. END PutLongreal;
  329. PROCEDURE PutByteAt*(at: Unit; d: WORD);
  330. VAR oldpc: Unit;
  331. BEGIN
  332. oldpc := pc;
  333. pc := at;
  334. PutByte(d);
  335. pc := oldpc;
  336. END PutByteAt;
  337. PROCEDURE PutWordAt*(at: Unit; d: WORD);
  338. VAR oldpc: Unit;
  339. BEGIN
  340. oldpc := pc;
  341. pc := at;
  342. PutWord(d);
  343. pc := oldpc;
  344. END PutWordAt;
  345. PROCEDURE PutDWordAt*(at: Unit; d: WORD);
  346. VAR oldpc: Unit;
  347. BEGIN
  348. oldpc := pc;
  349. pc := at;
  350. PutDWord(d);
  351. pc := oldpc;
  352. END PutDWordAt;
  353. PROCEDURE PutQWordAt*(at: Unit; d: HUGEINT);
  354. VAR oldpc: Unit;
  355. BEGIN
  356. oldpc := pc;
  357. pc := at;
  358. PutQWord(d);
  359. pc := oldpc;
  360. END PutQWordAt;
  361. PROCEDURE PutBytes* (data: HUGEINT; bytes: SHORTINT);
  362. BEGIN
  363. CASE bytes OF
  364. 1: PutByte (SHORT(data));
  365. | 2: PutWord (SHORT(data));
  366. | 4: PutDWord (SHORT(data));
  367. | 8: PutQWord(data);
  368. END
  369. END PutBytes;
  370. PROCEDURE GetByte* (pc: Unit): CHAR;
  371. BEGIN
  372. RETURN CHR(os.bits.GetBits(pc*os.unit,8));
  373. END GetByte;
  374. PROCEDURE GetWord*(pc: Unit): WORD;
  375. VAR c1,c2: WORD;
  376. BEGIN
  377. c1 := os.bits.GetBits(pc*os.unit,8);
  378. c2 := os.bits.GetBits(pc*os.unit+8,8);
  379. IF bigEndian THEN
  380. RETURN c1*100H + c2;
  381. ELSE
  382. RETURN c1 + c2*100H;
  383. END
  384. END GetWord;
  385. PROCEDURE GetDWord*(pc: Unit): WORD;
  386. VAR c1,c2,c3,c4: WORD;
  387. BEGIN
  388. c1 := os.bits.GetBits(pc*os.unit+0*Byte,Byte);
  389. c2 := os.bits.GetBits(pc*os.unit+1*Byte,Byte);
  390. c3 := os.bits.GetBits(pc*os.unit+2*Byte,Byte);
  391. c4 := os.bits.GetBits(pc*os.unit+3*Byte,Byte);
  392. IF bigEndian THEN
  393. RETURN c4 + 100H * (c3 + 100H * (c2 + c1*100H));
  394. ELSE
  395. RETURN c1 + 100H * (c2 + 100H * (c3 + c4*100H));
  396. END
  397. END GetDWord;
  398. PROCEDURE GetQWord*(pc: Unit): HUGEINT;
  399. VAR i: WORD; h: HUGEINT;
  400. BEGIN
  401. h := 0;
  402. IF bigEndian THEN
  403. FOR i := 0 TO 7 DO
  404. h := 100H*h;
  405. h := h + os.bits.GetBits(pc*os.unit+i*Byte,Byte);
  406. END;
  407. ELSE
  408. FOR i := 7 TO 0 BY -1 DO
  409. h := 100H*h;
  410. h := h + os.bits.GetBits(pc*os.unit+i*Byte,Byte);
  411. END;
  412. END;
  413. RETURN h
  414. END GetQWord;
  415. PROCEDURE GetReal*(pc: Unit): REAL;
  416. BEGIN
  417. RETURN ConvertToReal(GetDWord(pc))
  418. END GetReal;
  419. PROCEDURE GetLongreal*(pc: Unit): LONGREAL;
  420. BEGIN
  421. RETURN ConvertToLongreal(GetDWord(pc))
  422. END GetLongreal;
  423. PROCEDURE GetBits*(pc: Unit; size: Bits): WORD;
  424. BEGIN
  425. RETURN os.bits.GetBits(pc*os.unit,size)
  426. END GetBits;
  427. PROCEDURE ApplyFixup*(fixup: Fixup): BOOLEAN;
  428. VAR address: Unit; i: SIZE;
  429. PROCEDURE PatchPattern (CONST pattern: ObjectFile.FixupPattern);
  430. BEGIN
  431. IF pattern.offset # MIN(SHORTINT) THEN
  432. os.bits.SetBits(fixup.offset*os.unit+pattern.offset,pattern.bits,address);
  433. END;
  434. address := ASH (address, -pattern.bits);
  435. END PatchPattern;
  436. PROCEDURE CheckBits(): BOOLEAN;
  437. VAR nobits, remainder: Bits; i: SIZE;
  438. BEGIN
  439. nobits := 0;
  440. FOR i := 0 TO fixup.patterns-1 DO
  441. INC(nobits,fixup.pattern[i].bits);
  442. END;
  443. IF fixup.mode = Relative THEN DEC(nobits) END;
  444. remainder := ASH(address,-nobits);
  445. RETURN (nobits >31) OR (remainder = 0) OR (remainder = -1)
  446. END CheckBits;
  447. BEGIN
  448. address := fixup.displacement;
  449. IF fixup.mode = Relative THEN
  450. address := address - fixup.offset
  451. ELSE
  452. ASSERT(fixup.mode = Absolute)
  453. END;
  454. address := ASH(address,fixup.scale);
  455. IF CheckBits() THEN
  456. FOR i := 0 TO fixup.patterns-1 DO
  457. PatchPattern(fixup.pattern[i]);
  458. END;
  459. RETURN TRUE
  460. ELSE
  461. RETURN FALSE
  462. END;
  463. END ApplyFixup;
  464. PROCEDURE DumpCode*(w: Streams.Writer; from,to: Unit);
  465. VAR i: Unit; c: Sections.Comment; nextpos: Unit;
  466. PROCEDURE Hex(i: LONGINT): CHAR;
  467. BEGIN
  468. ASSERT(i>=0);
  469. ASSERT(i<16);
  470. IF i<10 THEN
  471. RETURN CHR(ORD("0")+i)
  472. ELSE
  473. RETURN CHR(ORD("A")+i-10);
  474. END;
  475. END Hex;
  476. PROCEDURE DumpUnit(at: Unit);
  477. VAR val: WORD; a: ARRAY 9 OF CHAR; bits: Bits;
  478. BEGIN
  479. val := GetBits(at,os.unit);
  480. bits := os.unit;
  481. a[(bits-1) DIV 4 +1] := 0X;
  482. WHILE (bits > 0) DO
  483. a[(bits-1) DIV 4] := Hex(val MOD 16);
  484. val := LSH(val,-4);
  485. DEC(bits,4);
  486. END;
  487. w.String(a);
  488. END DumpUnit;
  489. PROCEDURE DumpBlock(from,to: Unit);
  490. VAR i: Unit; nr: WORD;
  491. BEGIN
  492. i := from; nr := 0;
  493. IF to >= pc THEN to := pc-1 END;
  494. WHILE i <= to DO
  495. w.String("[");
  496. IF comments = NIL THEN w.Hex(i,3) ELSE w.Int(i,4) END;
  497. w.String("] ");
  498. nr := 0;
  499. WHILE (i<=to) & (nr<16) DO
  500. IF i = 8 THEN w.String(" ") END;
  501. DumpUnit(i);
  502. w.String(" ");
  503. INC(i); INC(nr);
  504. END;
  505. IF i <= to THEN
  506. w.Ln;
  507. END;
  508. END;
  509. END DumpBlock;
  510. BEGIN
  511. IF comments # NIL THEN
  512. c := comments.firstComment;
  513. WHILE(c # NIL) & (c.pos <from) DO
  514. c := c.nextComment;
  515. END;
  516. i := from;
  517. WHILE(i<=to) DO
  518. WHILE (c # NIL) & (c.pos = i) DO
  519. c.Dump(w); w.Ln;
  520. c := c.nextComment;
  521. END;
  522. IF (c # NIL) & (c.pos <= to) THEN nextpos := c.pos-1 ELSE nextpos := to END;
  523. DumpBlock(i,nextpos);w.Ln;
  524. i := nextpos+1;
  525. END;
  526. WHILE (c#NIL) & (c.pos = to+1) DO
  527. c.Dump(w); w.Ln; c := c.nextComment;
  528. END;
  529. ELSE
  530. DumpBlock(0,SELF.pc-1)
  531. END
  532. END DumpCode;
  533. PROCEDURE Dump*(w: Streams.Writer);
  534. VAR ww: Basic.Writer;
  535. BEGIN
  536. IF comments # NIL THEN comments.Update END;
  537. ww := Basic.GetWriter(w);
  538. ww.String(" unit="); ww.Int(os.unit,1);
  539. IF os.fixed THEN w.String(" fixed") ELSE w.String(" relocatable") END;
  540. w.String(" align="); w.Int(os.alignment,1);
  541. ww.String(" size="); ww.Int(SELF.pc,1);
  542. ww.String(" fixups="); ww.Int(SELF.os.fixups,1);
  543. ww.Ln;
  544. ww.IncIndent;
  545. fixupList.Dump(ww);
  546. DumpCode(ww,0,SELF.pc-1);
  547. ww.DecIndent;
  548. END Dump;
  549. END Section;
  550. PROCEDURE ConvertReal* (value: REAL): LONGINT;
  551. CONST Exponent = 8; Significant = 23;
  552. VAR result: LONGINT; VAR exponent, i: INTEGER;
  553. BEGIN
  554. (*! NaN code missing, we need an extra - machine specific - functionality for that / cf. Streams.NaNCode *)
  555. IF value = 0 THEN RETURN 0 END;
  556. result := 0; exponent := 0;
  557. IF value < 0 THEN value := -value; result := ASH (1, Exponent) END;
  558. WHILE value < 1 DO value := value * 2; DEC (exponent) END;
  559. WHILE value >= 2 DO value := value / 2; INC (exponent) END;
  560. value := value - 1; INC (result, ASH (1, Exponent - 1) - 1 + exponent);
  561. FOR i := 0 TO Significant - 1 DO
  562. value := value * 2; INC (result, result);
  563. IF value >= 1 THEN value := value - 1; INC (result) END;
  564. END;
  565. RETURN result;
  566. END ConvertReal;
  567. PROCEDURE ConvertLongreal*(value: LONGREAL): HUGEINT;
  568. CONST Exponent = 11; Significant = 52;
  569. VAR result: HUGEINT; VAR exponent, i: INTEGER;
  570. BEGIN
  571. (*! NaN code missing, we need an extra - machine specific - functionality for that / cf. Streams.NaNCode *)
  572. IF value = 0 THEN RETURN 0 END;
  573. result := 0; exponent := 0;
  574. IF value < 0 THEN value := -value; result := ASH (1, Exponent) END;
  575. WHILE value < 1 DO value := value * 2; DEC (exponent) END;
  576. WHILE value >= 2 DO value := value / 2; INC (exponent) END;
  577. value := value - 1; INC (result, ASH (1, Exponent - 1) - 1 + exponent);
  578. FOR i := 0 TO Significant - 1 DO
  579. value := value * 2; INC (result, result);
  580. IF value >= 1 THEN value := value - 1; INC (result) END;
  581. END;
  582. RETURN result;
  583. END ConvertLongreal;
  584. PROCEDURE ConvertToReal*(x: LONGINT): REAL;
  585. VAR result: REAL; e,i: LONGINT;
  586. PROCEDURE Bit(bit: LONGINT): BOOLEAN;
  587. BEGIN
  588. RETURN ODD(ASH(x,-bit))
  589. END Bit;
  590. BEGIN
  591. result := 0; e := 0;
  592. FOR i := 0 TO 22 DO
  593. IF Bit(i) THEN result := result + 1 END; result := result / 2;
  594. END;
  595. FOR i := 30 TO 23 BY -1 DO
  596. e := e*2; IF Bit(i) THEN e := e+1 END;
  597. END;
  598. IF e = 0FFH THEN (* NaN or Inf *)
  599. HALT(200);
  600. (*! NaN code missing, we need an extra - machine specific - functionality for that / cf. Streams.NaNCode *)
  601. ELSIF (result # 0) OR (e#0) THEN
  602. result := result + 1;
  603. DEC(e,127);
  604. WHILE e > 0 DO result := result *2; DEC(e) END;
  605. WHILE e < 0 DO result := result / 2; INC(e) END;
  606. IF Bit(31) THEN result := -result END;
  607. END;
  608. RETURN result
  609. END ConvertToReal;
  610. PROCEDURE ConvertToLongreal*(x: HUGEINT): LONGREAL;
  611. VAR result: LONGREAL; e,i: LONGINT;
  612. PROCEDURE Bit(bit: LONGINT): BOOLEAN;
  613. BEGIN
  614. RETURN ODD(ASH(x,-bit))
  615. END Bit;
  616. BEGIN
  617. result := 0; e:= 0;
  618. FOR i := 0 TO 51 DO
  619. IF Bit(i) THEN result := result + 1 END; result := result / 2;
  620. END;
  621. result := result + 1;
  622. FOR i := 62 TO 52 BY -1 DO
  623. e := e*2; IF Bit(i) THEN e := e+1 END;
  624. END;
  625. IF e = 7FFH THEN (* NaN or Inf *)
  626. HALT(200)
  627. (*! NaN code missing, we need an extra - machine specific - functionality for that / cf. Streams.NaNCode *)
  628. ELSIF (result # 0) OR (e#0) THEN
  629. DEC(e,1023);
  630. WHILE e > 0 DO result := result *2; DEC(e) END;
  631. WHILE e < 0 DO result := result / 2; INC(e) END;
  632. IF Bit(63) THEN result := -result END;
  633. END;
  634. RETURN result
  635. END ConvertToLongreal;
  636. PROCEDURE NewFixup*(mode: INTEGER; fixupOffset: LONGINT; symbol: ObjectFile.Identifier; symbolOffset,displacement: LONGINT; scale: LONGINT; fixupPattern: ObjectFile.FixupPatterns): Fixup;
  637. VAR fixup: Fixup;
  638. BEGIN
  639. NEW(fixup,mode,fixupOffset,symbol,symbolOffset,displacement,scale,fixupPattern); RETURN fixup
  640. END NewFixup;
  641. PROCEDURE NewBinarySection*(type: SHORTINT; unit: LONGINT; CONST name: Basic.SegmentedName; dump: BOOLEAN; bigEndian: BOOLEAN): Section;
  642. VAR binarySection: Section;
  643. BEGIN
  644. NEW(binarySection,type,unit,name,dump,bigEndian); RETURN binarySection
  645. END NewBinarySection;
  646. END FoxBinaryCode.
  647. FoxBinaryCode.TestFixup
  648. (*
  649. PROCEDURE TestFixup*;
  650. VAR data1,data2: Section; i: LONGINT; fixup: Fixup; fixupFormat: FixupFormat;
  651. PROCEDURE DumpBits(ch: CHAR);
  652. VAR v: LONGINT; s: ARRAY 9 OF CHAR; i: LONGINT;
  653. BEGIN
  654. v := ORD(ch);
  655. FOR i := 7 TO 0 BY -1 DO
  656. IF ODD(v) THEN s[i]:='1' ELSE s[i] := '0' END;
  657. v := ASH(v,-1);
  658. END;
  659. s[8] := 0X;
  660. D.String(s);
  661. END DumpBits;
  662. BEGIN
  663. NEW(data1,Sections.CodeSection,8,"test",NIL,FALSE,TRUE);
  664. NEW(data2,Sections.CodeSection,8,"test",NIL,FALSE,TRUE);
  665. FOR i := 0 TO 100 DO
  666. data1.PutByte(170);
  667. data2.PutByte(85);
  668. END;
  669. FOR i := 15 TO 20 DO DumpBits(data1.data[i]); END; D.Ln;
  670. FOR i := 15 TO 20 DO DumpBits(data2.data[i]); END;D.Ln;
  671. NEW(fixupFormat,3);
  672. fixupFormat[0].offset := 0;
  673. fixupFormat[0].bits := 12;
  674. fixupFormat[1].offset := MIN(SHORTINT);
  675. fixupFormat[1].bits := 8;
  676. fixupFormat[2].offset := 20;
  677. fixupFormat[2].bits := 12;
  678. NEW(fixup,Absolute,16,NIL,0,0,0,fixupFormat);
  679. data1.ApplyFixup(fixup,3F7DEEDH);
  680. data2.ApplyFixup(fixup,3F7DEEDH);
  681. FOR i := 15 TO 20 DO DumpBits(data1.data[i]); END; D.Ln;
  682. FOR i := 15 TO 20 DO DumpBits(data2.data[i]); END;D.Ln; D.Ln;
  683. D.Update;
  684. data1.Dump(D.Log); D.Ln;
  685. data2.Dump(D.Log); D.Ln;
  686. END TestFixup;
  687. *)