FoxBinaryCode.Mod 20 KB

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