FoxBinaryCode.Mod 20 KB

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