O7ARMv7MTool.Mod 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. MODULE O7ARMv7MTool; (*NW 18.2.2013*)
  2. (*
  3. Alexander Shiryaev:
  4. 2014.09:
  5. Modified for ARMv6-M and ARMv7-M
  6. DecBin and DecHex added
  7. *)
  8. IMPORT SYSTEM, Files (*:= O7Files*), Texts (*:= O7Texts*), Oberon (*:= O7Oberon*), ORB := O7B, ARMv7M := O7ARMv7M;
  9. TYPE
  10. LONGINT = INTEGER;
  11. BYTE = CHAR;
  12. VAR W: Texts.Writer;
  13. Form: INTEGER; (*result of ReadType*)
  14. PROCEDURE Read (VAR R: Files.Rider; VAR n: INTEGER);
  15. VAR b: BYTE;
  16. BEGIN Files.Read(*Byte*)(R, b);
  17. IF ORD(b) < 80H THEN n := ORD(b) ELSE n := ORD(b) - 100H END
  18. END Read;
  19. PROCEDURE ReadInt (VAR R: Files.Rider; VAR x: INTEGER);
  20. VAR y: SYSTEM.INT64;
  21. BEGIN
  22. Files.ReadLInt(R, y);
  23. IF R.eof THEN x := -1
  24. ELSE x := SHORT(y)
  25. END
  26. END ReadInt;
  27. PROCEDURE ReadType (VAR R: Files.Rider);
  28. VAR key, len, lev, size, off: INTEGER;
  29. ref, mno, class, form, readonly: INTEGER;
  30. name, modname: ARRAY 32 OF CHAR;
  31. BEGIN Read(R, ref); Texts.Write(W, " "); Texts.Write(W, "[");
  32. IF ref < 0 THEN Texts.Write(W, "^"); Texts.WriteInt(W, -ref, 1)
  33. ELSE Texts.WriteInt(W, ref, 1);
  34. Read(R, form); Texts.WriteString(W, " form = "); Texts.WriteInt(W, form, 1);
  35. IF form = ORB.Pointer THEN ReadType(R)
  36. ELSIF form = ORB.Array THEN
  37. ReadType(R); Files.ReadNum(R, len); Files.ReadNum(R, size);
  38. Texts.WriteString(W, " len = "); Texts.WriteInt(W, len, 1);
  39. Texts.WriteString(W, " size = "); Texts.WriteInt(W, size, 1)
  40. ELSIF form = ORB.Record THEN
  41. ReadType(R); (*base type*)
  42. Files.ReadNum(R, off); Texts.WriteString(W, " exno = "); Texts.WriteInt(W, off, 1);
  43. Files.ReadNum(R, off); Texts.WriteString(W, " extlev = "); Texts.WriteInt(W, off, 1);
  44. Files.ReadNum(R, size); Texts.WriteString(W, " size = "); Texts.WriteInt(W, size, 1);
  45. Texts.Write(W, " "); Texts.Write(W, "{"); Read(R, class);
  46. WHILE class # 0 DO (*fields*)
  47. Files.ReadString(R, name);
  48. IF name[0] # 0X THEN Texts.Write(W, " "); Texts.WriteString(W, name); ReadType(R)
  49. ELSE Texts.WriteString(W, " --")
  50. END ;
  51. Files.ReadNum(R, off); Texts.WriteInt(W, off, 4); Read(R, class)
  52. END ;
  53. Texts.Write(W, "}")
  54. ELSIF form = ORB.Proc THEN
  55. ReadType(R); Texts.Write(W, "("); Read(R, class);
  56. WHILE class # 0 DO
  57. Texts.WriteString(W, " class = "); Texts.WriteInt(W, class, 1); Read(R, readonly);
  58. IF readonly = 1 THEN Texts.Write(W, "#") END ;
  59. ReadType(R); Read(R, class)
  60. END ;
  61. Texts.Write(W, ")")
  62. END ;
  63. Files.ReadString(R, modname);
  64. IF modname[0] # 0X THEN
  65. ReadInt(R, key); Files.ReadString(R, name);
  66. Texts.Write(W, " "); Texts.WriteString(W, modname); Texts.Write(W, "."); Texts.WriteString(W, name);
  67. Texts.WriteHex(W, key)
  68. END
  69. END ;
  70. Form := form; Texts.Write(W, "]")
  71. END ReadType;
  72. PROCEDURE DecSym*; (*decode symbol file*)
  73. VAR class, typno, k: INTEGER;
  74. name: ARRAY 32 OF CHAR;
  75. F: Files.File; R: Files.Rider;
  76. S: Texts.Scanner;
  77. BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  78. IF S.class = Texts.Name THEN
  79. Texts.WriteString(W, "OR-decode "); Texts.WriteString(W, S.s);
  80. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
  81. F := Files.Old(S.s);
  82. IF F # NIL THEN
  83. Files.Set(R, F, 0); ReadInt(R, k); ReadInt(R, k);
  84. Files.ReadString(R, name); Texts.WriteString(W, name); Texts.WriteHex(W, k);
  85. Read(R, class); Texts.WriteInt(W, class, 3); (*sym file version*)
  86. IF class = ORB.versionkey THEN
  87. Texts.WriteLn(W); Read(R, class);
  88. WHILE class # 0 DO
  89. Texts.WriteInt(W, class, 4); Files.ReadString(R, name); Texts.Write(W, " "); Texts.WriteString(W, name);
  90. ReadType(R);
  91. IF class = ORB.Typ THEN
  92. Texts.Write(W, "("); Read(R, class);
  93. WHILE class # 0 DO (*pointer base fixup*)
  94. Texts.WriteString(W, " ->"); Texts.WriteInt(W, class, 4); Read(R, class)
  95. END ;
  96. Texts.Write(W, ")")
  97. ELSIF (class = ORB.Const) OR (class = ORB.Var) THEN
  98. Files.ReadNum(R, k); Texts.WriteInt(W, k, 5); (*Reals, Strings!*)
  99. END ;
  100. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
  101. Read(R, class)
  102. END
  103. ELSE Texts.WriteString(W, " bad symfile version")
  104. END
  105. ELSE Texts.WriteString(W, " not found")
  106. END ;
  107. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
  108. END;
  109. (*Oberon.Collect(0)*)
  110. END DecSym;
  111. (* ---------------------------------------------------*)
  112. PROCEDURE opcode (VAR d: INTEGER; w: LONGINT);
  113. VAR s: ARRAY 64 OF CHAR;
  114. BEGIN
  115. IF w DIV 10000H = 0 THEN
  116. ARMv7M.OpcodeRepr(d, w, s);
  117. IF s # "" THEN Texts.WriteString(W, s) END
  118. END
  119. END opcode;
  120. PROCEDURE Sync (VAR R: Files.Rider);
  121. VAR ch: CHAR;
  122. BEGIN Files.Read(R, ch); Texts.WriteString(W, "Sync "); Texts.Write(W, ch); Texts.WriteLn(W)
  123. END Sync;
  124. PROCEDURE Write (VAR R: Files.Rider; x: INTEGER);
  125. BEGIN Files.Write(*Byte*)(R, CHR(x)) (* -128 <= x < 128 *)
  126. END Write;
  127. PROCEDURE DecObj*; (*decode object file*)
  128. VAR class, i, n, key, size, fix, adr, data, len: INTEGER;
  129. ch: CHAR;
  130. name: ARRAY 32 OF CHAR;
  131. F: Files.File; R: Files.Rider;
  132. S: Texts.Scanner;
  133. d: INTEGER; (* ARMv7-M decoder state *)
  134. BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  135. IF S.class = Texts.Name THEN
  136. Texts.WriteString(W, "decode "); Texts.WriteString(W, S.s); F := Files.Old(S.s);
  137. IF F # NIL THEN
  138. Files.Set(R, F, 0); Files.ReadString(R, name); Texts.WriteLn(W); Texts.WriteString(W, name);
  139. ReadInt(R, key); Texts.WriteHex(W, key); Read(R, class); Texts.WriteInt(W, class, 4); (*version*)
  140. ReadInt(R, size); Texts.WriteInt(W, size, 6); Texts.WriteLn(W);
  141. Texts.WriteString(W, "imports:"); Texts.WriteLn(W); Files.ReadString(R, name);
  142. WHILE name[0] # 0X DO
  143. Texts.Write(W, 9X); Texts.WriteString(W, name);
  144. ReadInt(R, key); Texts.WriteHex(W, key); Texts.WriteLn(W);
  145. Files.ReadString(R, name)
  146. END ;
  147. (* Sync(R); *)
  148. Texts.WriteString(W, "type descriptors"); Texts.WriteLn(W);
  149. ReadInt(R, n); n := n DIV 4; i := 0;
  150. WHILE i < n DO ReadInt(R, data); Texts.WriteHex(W, data); INC(i) END ;
  151. Texts.WriteLn(W);
  152. Texts.WriteString(W, "data"); ReadInt(R, data); Texts.WriteInt(W, data, 6); Texts.WriteLn(W);
  153. Texts.WriteString(W, "strings"); Texts.WriteLn(W);
  154. ReadInt(R, n); i := 0;
  155. WHILE i < n DO Files.Read(R, ch); Texts.Write(W, ch); INC(i) END ;
  156. Texts.WriteLn(W);
  157. Texts.WriteString(W, "code"); Texts.WriteLn(W);
  158. ReadInt(R, n); i := 0; d := 0;
  159. WHILE i < n DO
  160. ReadInt(R, data); Texts.WriteInt(W, i, 4); Texts.Write(W, 9X); Texts.WriteHex(W, data);
  161. Texts.Write(W, 9X); opcode(d, data); Texts.WriteLn(W); INC(i)
  162. END;
  163. ASSERT(d = 0, 100);
  164. (* Sync(R); *)
  165. Texts.WriteString(W, "commands:"); Texts.WriteLn(W);
  166. Files.ReadString(R, name);
  167. WHILE name[0] # 0X DO
  168. Texts.Write(W, 9X); Texts.WriteString(W, name);
  169. ReadInt(R, adr); Texts.WriteInt(W, adr, 5); Texts.WriteLn(W);
  170. Files.ReadString(R, name)
  171. END ;
  172. (* Sync(R); *)
  173. Texts.WriteString(W, "entries"); Texts.WriteLn(W);
  174. ReadInt(R, n); i := 0;
  175. WHILE i < n DO
  176. ReadInt(R, adr); Texts.WriteInt(W, adr, 6); INC(i)
  177. END ;
  178. Texts.WriteLn(W);
  179. (* Sync(R); *)
  180. Texts.WriteString(W, "pointer refs"); Texts.WriteLn(W); ReadInt(R, adr);
  181. WHILE adr # -1 DO Texts.WriteInt(W, adr, 6); ReadInt(R, adr) END ;
  182. Texts.WriteLn(W);
  183. (* Sync(R); *)
  184. ReadInt(R, data); Texts.WriteString(W, "fixP = "); Texts.WriteInt(W, data, 8); Texts.WriteLn(W);
  185. ReadInt(R, data); Texts.WriteString(W, "fixD = "); Texts.WriteInt(W, data, 8); Texts.WriteLn(W);
  186. ReadInt(R, data); Texts.WriteString(W, "fixT = "); Texts.WriteInt(W, data, 8); Texts.WriteLn(W);
  187. ReadInt(R, data); Texts.WriteString(W, "entry = "); Texts.WriteInt(W, data, 8); Texts.WriteLn(W);
  188. Files.Read(R, ch);
  189. IF ch # "O" THEN Texts.WriteString(W, "format eror"); Texts.WriteLn(W) END
  190. (* Sync(R); *)
  191. ELSE Texts.WriteString(W, " not found"); Texts.WriteLn(W)
  192. END ;
  193. Texts.Append(Oberon.Log, W.buf)
  194. END;
  195. (*Oberon.Collect(0)*)
  196. END DecObj;
  197. PROCEDURE DecBin*; (* decode binary image file *)
  198. VAR i, data: INTEGER;
  199. F: Files.File; R: Files.Rider;
  200. S: Texts.Scanner;
  201. d: INTEGER; (* ARMv7-M decoder state *)
  202. PROCEDURE Read (VAR x: INTEGER);
  203. VAR c0, c1: CHAR;
  204. BEGIN
  205. Files.Read(R, c0); Files.Read(R, c1);
  206. x := ORD(c0) + 100H * ORD(c1);
  207. ASSERT(x DIV 10000H = 0, 100)
  208. END Read;
  209. BEGIN
  210. Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  211. IF S.class = Texts.Name THEN
  212. Texts.WriteString(W, "decode "); Texts.WriteString(W, S.s); Texts.WriteLn(W); F := Files.Old(S.s);
  213. IF F # NIL THEN
  214. Files.Set(R, F, 0); Read(data); i := 0; d := 0;
  215. WHILE ~R.eof DO
  216. Texts.WriteInt(W, i, 4); Texts.Write(W, 9X); Texts.WriteHex(W, data); Texts.Write(W, 9X); opcode(d, data); Texts.WriteLn(W); INC(i);
  217. Read(data)
  218. END;
  219. IF d # 0 THEN Texts.WriteString(W, "invalid decoder state");
  220. Texts.WriteLn(W) END
  221. ELSE Texts.WriteString(W, " not found"); Texts.WriteLn(W)
  222. END;
  223. Texts.Append(Oberon.Log, W.buf)
  224. END;
  225. (*Oberon.Collect(0)*)
  226. END DecBin;
  227. PROCEDURE DecHex*; (* decode Intel HEX file *)
  228. VAR ch: CHAR; err, eof: BOOLEAN;
  229. pos, cs, offH: INTEGER;
  230. F: Files.File; R: Files.Rider;
  231. S: Texts.Scanner;
  232. d: INTEGER; (* ARMv7-M decoder state *)
  233. PROCEDURE Get;
  234. BEGIN Files.Read(R, ch); IF R.eof THEN ch := 0X ELSE INC(pos) END
  235. END Get;
  236. PROCEDURE Err ((*IN*) msg: ARRAY OF CHAR);
  237. BEGIN
  238. IF ~err THEN Texts.WriteString(W, "pos = ");
  239. Texts.WriteInt(W, pos, 0); Texts.WriteString(W, ": ");
  240. Texts.WriteString(W, msg); Texts.WriteLn(W)
  241. END; err := TRUE
  242. END Err;
  243. PROCEDURE CheckD;
  244. BEGIN IF d # 0 THEN Err("invalid decoder state") END; d := 0
  245. END CheckD;
  246. PROCEDURE B ((*OUT*) VAR x: INTEGER);
  247. PROCEDURE H;
  248. BEGIN
  249. IF (ch >= '0') & (ch <= '9') THEN x := x * 10H + ORD(ch) - ORD('0')
  250. ELSIF (ch >= 'A') & (ch <= 'F') THEN x := x * 10H + ORD(ch) - ORD('A') + 10
  251. ELSE Err("invalid HEX")
  252. END; Get
  253. END H;
  254. BEGIN x := 0; H; H; cs := cs + x
  255. END B;
  256. PROCEDURE Line;
  257. VAR len, offL, type, cs, i, x: INTEGER;
  258. a: ARRAY 255 OF INTEGER;
  259. BEGIN
  260. IF eof THEN Err("EOF already reached") END;
  261. IF ch # ':' THEN Err("':' expected") END; Get; cs := 0;
  262. B(len); B(i); B(offL); offL := i * 100H + offL; B(type);
  263. i := 0; WHILE i < len DO B(a[i]); INC(i) END;
  264. B(i); IF cs MOD 100H # 0 THEN Err("checksum error") END;
  265. WHILE (ch = 0AX) OR (ch = 0DX) DO Get END;
  266. IF ~err THEN
  267. CASE type OF 0: (* data *)
  268. IF len # 0 THEN
  269. IF (offL MOD 2 = 0) & (len MOD 2 = 0) THEN
  270. i := 0;
  271. WHILE i < len DIV 2 DO
  272. Texts.WriteInt(W, offL DIV 2 + i, 4); Texts.Write(W, 9X);
  273. x := a[i * 2] + 100H * a[i * 2 + 1];
  274. Texts.WriteHex(W, x); Texts.Write(W, 9X); opcode(d, x); Texts.WriteLn(W); INC(i)
  275. END
  276. ELSE Err("unaligned data support not implemented")
  277. END
  278. ELSE Err("data length is zero")
  279. END
  280. | 1: (* EOF *)
  281. IF (len = 0) & (offL = 0) THEN eof := TRUE
  282. ELSE Err("invalid EOF")
  283. END
  284. | 2: (* extended segment address *)
  285. IF (len = 2) & (offL = 0) THEN
  286. Err("I16HEX support not implemented")
  287. ELSE Err("invalid extended segment address")
  288. END
  289. | 3: (* start segment address *)
  290. IF (len = 4) & (offL = 0) THEN
  291. Err("I16HEX support not implemented")
  292. ELSE Err("invalid start segment address")
  293. END
  294. | 4: (* extended linear address *)
  295. IF (len = 2) & (offL = 0) THEN CheckD;
  296. offH := (a[0] * 100H + a[1]) * 10000H;
  297. Texts.WriteHex(W, offH); Texts.WriteString(W, "H:");
  298. Texts.WriteLn(W)
  299. ELSE Err("invalid extended linear address")
  300. END
  301. | 5: (* start linear address *)
  302. IF (len = 4) & (offL = 0) THEN
  303. Texts.WriteString(W, "start linear address: ");
  304. x := a[0] * 1000000H + a[1] * 10000H + a[2] * 100H + a[3];
  305. Texts.WriteHex(W, x); Texts.Write(W, 'H'); Texts.WriteLn(W)
  306. ELSE Err("invalid start linear address")
  307. END
  308. ELSE Err("unexpected record type")
  309. END
  310. END
  311. END Line;
  312. BEGIN
  313. Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  314. IF S.class = Texts.Name THEN
  315. Texts.WriteString(W, "decode "); Texts.WriteString(W, S.s); Texts.WriteLn(W); F := Files.Old(S.s);
  316. IF F # NIL THEN
  317. Files.Set(R, F, 0); err := FALSE; eof := FALSE; pos := 0; Get;
  318. offH := 0; d := 0; REPEAT Line UNTIL err OR (ch = 0X);
  319. IF ~eof THEN Err("EOF expected") END; CheckD
  320. ELSE Texts.WriteString(W, " not found"); Texts.WriteLn(W)
  321. END;
  322. Texts.Append(Oberon.Log, W.buf)
  323. END;
  324. (*Oberon.Collect(0)*)
  325. END DecHex;
  326. BEGIN Texts.OpenWriter(W); Texts.WriteString(W, "O7ARMv7MTool 19.9.2014");
  327. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
  328. END O7ARMv7MTool.