FoxBinaryCode.Mod 21 KB

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