O7ARMv7MLinker.Mod 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. MODULE O7ARMv7MLinker;
  2. (* Link and load on RISC; NW 20.10.2013 / 8.1.2019 *)
  3. (* ARMv7-M: Alexander Shiryaev, 2014.10, 2015.02, 2016.06, 2017.01, 2019.11, 2021.08 *)
  4. (*
  5. TODO:
  6. procedure addresses (progbase-relative...)
  7. add support of version-0 files
  8. resource files (simple copy to flashOrg before all)
  9. NOTES:
  10. we do not fill global data by zeros
  11. do not call GC.Collect before all global pointers initialization!
  12. pointer references for GC only
  13. MTab stored in RAM for fast access
  14. modules ptrs table stored in RAM for fast GC work
  15. *)
  16. IMPORT SYSTEM, Files (*:= O7Files*), Texts (*:= O7Texts*), Oberon (*:= O7Oberon*), ARMv6M := O7ARMv6M, ARMv7M := O7ARMv7M;
  17. TYPE
  18. LONGINT = INTEGER;
  19. BYTE = CHAR;
  20. CONST versionkey = 1X; MT = 6; SB = 3;
  21. trace = FALSE;
  22. (* fixup tags *)
  23. tagFixup = 00FFFFFFH; (* Add/Ldr/LdrB/Str/StrB *)
  24. tagVLDR = 00FFFFFCH;
  25. tagBL = 00FFFFE0H;
  26. tagLdrSB = 00FFFFD0H;
  27. TYPE Module = POINTER TO ModDesc;
  28. ModuleName = ARRAY 32 OF CHAR;
  29. ModDesc = RECORD
  30. name: ModuleName;
  31. next: Module;
  32. key, num: INTEGER;
  33. data: INTEGER; (* address, relative to mem, bytes *)
  34. strs: INTEGER; (* address, relative to data, bytes *)
  35. code: INTEGER; (* address, relative to flash start, halfwords *)
  36. entries: POINTER TO ARRAY OF INTEGER;
  37. entriesLen: INTEGER;
  38. imports: ARRAY 255 OF Module;
  39. body: INTEGER;
  40. typeds: POINTER TO ARRAY OF INTEGER;
  41. typedsLen: INTEGER;
  42. strings: POINTER TO ARRAY OF INTEGER;
  43. stringsLen: INTEGER;
  44. fixorgT: INTEGER;
  45. nPtrs: INTEGER; (* number of pointer references *)
  46. ptr: INTEGER (* address, relative to flash start, halfwords *)
  47. END;
  48. TargetName = ARRAY 32 OF CHAR;
  49. Target = POINTER TO RECORD
  50. next: Target;
  51. name: TargetName;
  52. isNXP: BOOLEAN;
  53. flashStart, flashSize: INTEGER;
  54. maxExtInts, flashOrg: INTEGER;
  55. SRAMStart, SRAMSize: INTEGER
  56. END;
  57. VAR
  58. root: Module;
  59. modules: ARRAY 100H OF Module;
  60. flash: ARRAY 200000H DIV 2 OF INTEGER; flashW: INTEGER;
  61. memW: INTEGER; (* bytes *)
  62. nPtrs: INTEGER;
  63. res*: INTEGER;
  64. importing, imported: ModuleName;
  65. W: Texts.Writer;
  66. target: Target;
  67. targets: Target;
  68. PROCEDURE BITS (x: INTEGER): SET;
  69. BEGIN
  70. RETURN SYSTEM.VAL(SET, x)
  71. END BITS;
  72. PROCEDURE ORDSET (x: SET): INTEGER;
  73. BEGIN
  74. RETURN SYSTEM.VAL(INTEGER, x)
  75. END ORDSET;
  76. PROCEDURE StrLen (VAR x: ARRAY OF CHAR): INTEGER;
  77. VAR i: INTEGER;
  78. BEGIN
  79. i := 0;
  80. WHILE (i < LEN(x)) & (x[i] # 0X) DO INC(i) END;
  81. RETURN i
  82. END StrLen;
  83. PROCEDURE CmpStr (VAR a, b: ARRAY OF CHAR): BOOLEAN;
  84. VAR i: INTEGER;
  85. res: BOOLEAN;
  86. BEGIN
  87. i := 0;
  88. WHILE (i < LEN(a)) & (i < LEN(b)) & (a[i] # 0X) & (b[i] # 0X) & (a[i] = b[i]) DO INC(i) END;
  89. res := (i = LEN(a)) OR (i = LEN(b)) OR ((a[i] = 0X) & (b[i] = 0X));
  90. RETURN res
  91. END CmpStr;
  92. PROCEDURE ReadInt (VAR R: Files.Rider; VAR x: INTEGER);
  93. VAR y: SYSTEM.INT64;
  94. BEGIN
  95. Files.ReadLInt(R, y);
  96. IF R.eof THEN x := -1
  97. ELSE x := SHORT(y)
  98. END
  99. END ReadInt;
  100. PROCEDURE ThisFile ((*IN*) VAR name: ARRAY OF CHAR): Files.File;
  101. VAR i: INTEGER;
  102. filename: ModuleName;
  103. BEGIN i := 0;
  104. WHILE name[i] # 0X DO filename[i] := name[i]; INC(i) END ;
  105. filename[i] := "."; filename[i+1] := "a"; filename[i+2] := "7";
  106. filename[i+3] := "m"; filename[i+4] := 0X;
  107. RETURN Files.Old(filename)
  108. END ThisFile;
  109. PROCEDURE NewHexFile ((*IN*) VAR name: ARRAY OF CHAR): Files.File;
  110. VAR i: INTEGER;
  111. filename: ModuleName;
  112. BEGIN i := 0;
  113. WHILE name[i] # 0X DO filename[i] := name[i]; INC(i) END ;
  114. filename[i] := "."; filename[i+1] := "h"; filename[i+2] := "e";
  115. filename[i+3] := "x"; filename[i+4] := 0X;
  116. RETURN Files.New(filename)
  117. END NewHexFile;
  118. PROCEDURE NewBinFile ((*IN*) VAR name: ARRAY OF CHAR): Files.File;
  119. VAR i: INTEGER;
  120. filename: ModuleName;
  121. BEGIN i := 0;
  122. WHILE name[i] # 0X DO filename[i] := name[i]; INC(i) END ;
  123. filename[i] := "."; filename[i+1] := "b"; filename[i+2] := "i";
  124. filename[i+3] := "n"; filename[i+4] := 0X;
  125. RETURN Files.New(filename)
  126. END NewBinFile;
  127. PROCEDURE error (n: INTEGER; (*IN*) VAR name: ARRAY OF CHAR);
  128. BEGIN res := n; COPY(name, importing)
  129. END error;
  130. PROCEDURE Check ((*IN*) VAR s: ARRAY OF CHAR);
  131. VAR i: INTEGER; ch: CHAR;
  132. BEGIN ch := s[0]; res := 1; i := 1;
  133. IF (ch >= "A") & (ch <= "Z") OR (ch >= "a") & (ch <= "z") THEN
  134. REPEAT ch := s[i]; INC(i)
  135. UNTIL ~((ch >= "0") & (ch <= "9") OR (ch >= "A") & (ch <= "Z")
  136. OR (ch >= "a") & (ch <= "z") OR (ch = ".")) OR (i = 32);
  137. IF (i < 32) & (ch = 0X) THEN res := 0 END
  138. END
  139. END Check;
  140. (* emit 2 instructions *)
  141. PROCEDURE EmitADDSIm0 (VAR code: ARRAY OF INTEGER; VAR pc: INTEGER; a, b, im: INTEGER);
  142. CONST S = 1;
  143. VAR i, imm3, imm8: INTEGER; isMI: BOOLEAN;
  144. BEGIN
  145. ARMv7M.EncodeMI12(im, i, imm3, imm8, isMI);
  146. IF isMI THEN
  147. ASSERT(b # 15, 100);
  148. ASSERT((b = 13) OR (a # 13), 101);
  149. (* A7.7.3: ADD (immediate); encoding T3 ARMv7-M *)
  150. (* A7.7.5: ADD (SP plus immediate); encoding T3 ARMv7-M *)
  151. ARMv7M.EmitDPMI(code, pc, i, 16 + S, b, imm3, a, imm8)
  152. ELSIF im <= 255 + 7 THEN
  153. ARMv6M.EmitADDSIm(code, pc, a, b, 7);
  154. ARMv6M.EmitADDSIm(code, pc, a, a, im - 7)
  155. ELSE HALT(1)
  156. (* fixup failed: offset is too big
  157. (implementation limit) *)
  158. END
  159. END EmitADDSIm0;
  160. (* search module in list; if not found, load module *)
  161. PROCEDURE Load ((*IN*) VAR name: ARRAY OF CHAR; VAR newmod: Module);
  162. VAR mod, impmod: Module;
  163. i, n, key, impkey, mno, nofimps, size: INTEGER;
  164. u, v, w: INTEGER; (*addresses*)
  165. ch: CHAR;
  166. fixorgP, fixorgD: INTEGER;
  167. disp, adr, inst, pno, vno, dest, offset: INTEGER;
  168. name1, impname: ModuleName;
  169. F: Files.File; R: Files.Rider;
  170. import: ARRAY 255 OF Module;
  171. a, b: INTEGER;
  172. op: INTEGER; (* 0: LW, 1: LB, 2: ADDS, 3: SW, 4: SB, 5: VLDR *)
  173. nxt: INTEGER;
  174. ok: BOOLEAN;
  175. BEGIN
  176. mod := root; error(0, name); nofimps := 0;
  177. WHILE (mod # NIL) & ~CmpStr(name, mod.name) DO mod := mod.next END;
  178. IF mod = NIL THEN (*load*)
  179. Check(name);
  180. IF res = 0 THEN F := ThisFile(name) ELSE F := NIL END;
  181. IF F # NIL THEN
  182. Files.Set(R, F, 0); Files.ReadString(R, name1);
  183. ReadInt(R, key); Files.Read(R, ch);
  184. ReadInt(R, size); importing := name1;
  185. IF ch = versionkey THEN
  186. Files.ReadString(R, impname); (*imports*)
  187. WHILE (impname[0] # 0X) & (res = 0) DO
  188. ReadInt(R, impkey);
  189. Load(impname, impmod);
  190. import[nofimps] := impmod; importing := name1;
  191. IF res = 0 THEN
  192. IF impmod.key = impkey THEN INC(nofimps)
  193. ELSE error(3, name1); imported := impname
  194. END
  195. END;
  196. Files.ReadString(R, impname)
  197. END
  198. ELSE error(2, name1)
  199. END
  200. ELSE error(1, name(*$*))
  201. END;
  202. IF res = 0 THEN NEW(mod); mod.next := root;
  203. IF root = NIL THEN mod.num := 0
  204. ELSE mod.num := root.num + 1
  205. END;
  206. root := mod
  207. END;
  208. IF res = 0 THEN (*read file*)
  209. COPY(name, mod.name); mod.key := key;
  210. mod.data := memW;
  211. modules[mod.num] := mod;
  212. (* type descriptors *)
  213. ReadInt(R, n); ASSERT(n MOD 4 = 0, 100);
  214. INC(memW, n);
  215. n := n DIV 4;
  216. IF n > 0 THEN NEW(mod.typeds, n) END;
  217. mod.typedsLen := n;
  218. i := 0;
  219. WHILE n > 0 DO ReadInt(R, w);
  220. mod.typeds[i] := w; INC(i);
  221. DEC(n)
  222. END;
  223. (* variable space *)
  224. ReadInt(R, n); INC(memW, n);
  225. (* strings *)
  226. mod.strs := memW - mod.data;
  227. ReadInt(R, n); ASSERT(n MOD 4 = 0, 101);
  228. INC(memW, n);
  229. n := n DIV 4;
  230. IF n > 0 THEN NEW(mod.strings, n) END;
  231. mod.stringsLen := n;
  232. i := 0;
  233. WHILE n > 0 DO ReadInt(R, w);
  234. mod.strings[i] := w; INC(i);
  235. DEC(n)
  236. END;
  237. (* program *)
  238. IF ODD(flashW) THEN
  239. (* align, required for modules with
  240. "LDR r, [pc, offset]" instructions, pc must be multiple of 4;
  241. used for constants loading *)
  242. ARMv6M.EmitNOP(flash, flashW)
  243. END;
  244. mod.code := flashW;
  245. (* program code *)
  246. ReadInt(R, n);
  247. WHILE n > 0 DO ReadInt(R, w);
  248. flash[flashW] := w; INC(flashW);
  249. DEC(n)
  250. END;
  251. (* copy imports *)
  252. i := 0;
  253. WHILE i < nofimps DO
  254. mod.imports[i] := import[i];
  255. INC(i)
  256. END;
  257. (* skip commands *)
  258. Files.Read(R, ch);
  259. WHILE ch # 0X DO
  260. REPEAT Files.Read(R, ch) UNTIL ch = 0X; ReadInt(R, n);
  261. Files.Read(R, ch)
  262. END;
  263. (* entries *)
  264. ReadInt(R, n);
  265. NEW(mod.entries, n); mod.entriesLen := n; i := 0;
  266. WHILE n > 0 DO ReadInt(R, w);
  267. mod.entries[i] := w; INC(i);
  268. DEC(n)
  269. END;
  270. (* pointer references *)
  271. mod.nPtrs := 0;
  272. ReadInt(R, w);
  273. IF (w >= 0) & ODD(flashW) THEN (* align *)
  274. flash[flashW] := 0; INC(flashW)
  275. END;
  276. mod.ptr := flashW;
  277. WHILE w >= 0 DO
  278. ASSERT(w < mod.strs, 100);
  279. flash[flashW] := mod.data + w; (* will be fixed up in Link1 *)
  280. INC(flashW, 2); INC(mod.nPtrs);
  281. ReadInt(R, w)
  282. END;
  283. IF mod.nPtrs # 0 THEN
  284. flash[flashW] := 0; INC(flashW);
  285. flash[flashW] := 0; INC(flashW);
  286. INC(nPtrs)
  287. END;
  288. ReadInt(R, fixorgP);
  289. ReadInt(R, fixorgD);
  290. ReadInt(R, mod.fixorgT);
  291. (* entry point *)
  292. ReadInt(R, w); ASSERT(w MOD 4 = 0, 100);
  293. mod.body := mod.code + w DIV 4;
  294. Files.Read(R, ch);
  295. IF ch # "O" THEN (* corrupted file *) mod := NIL; error(4, name(*$*)) END
  296. END;
  297. IF res = 0 THEN
  298. (* fixup of BL *)
  299. adr := mod.code + fixorgP;
  300. WHILE adr # mod.code DO
  301. inst := flash[adr];
  302. ASSERT(inst DIV 10H * 10H = tagBL);
  303. a := inst MOD 10H;
  304. DEC(adr);
  305. inst := flash[adr];
  306. ASSERT(inst DIV 1000000H MOD 100H = 0F7H, 101); (* BL *)
  307. mno := inst DIV 100000H MOD 10H + a * 10H;
  308. pno := inst DIV 1000H MOD 100H;
  309. disp := inst MOD 1000H;
  310. impmod := mod.imports[mno-1];
  311. dest := impmod.entries[pno];
  312. ASSERT(dest MOD 4 = 0, 102); dest := dest DIV 4;
  313. dest := dest + impmod.code;
  314. offset := dest - adr - 1;
  315. i := adr; ARMv6M.EmitBL(flash, i, offset - 1);
  316. adr := adr - disp
  317. END;
  318. (* fixup of LDR/STR/ADD *)
  319. adr := (mod.code + fixorgD) * 4;
  320. WHILE adr DIV 4 # mod.code DO
  321. inst := flash[adr DIV 4];
  322. mno := inst DIV 100000H MOD 10H;
  323. disp := inst MOD 1000H;
  324. a := inst DIV 1000000H MOD 10H;
  325. ASSERT(a = SB, 103);
  326. ASSERT(inst DIV 10000000H MOD 10H = 8, 103); (* Ldr *)
  327. ASSERT(flash[adr DIV 4 + 1] DIV 10H * 10H = tagLdrSB);
  328. mno := mno + flash[adr DIV 4 + 1] MOD 10H * 10H;
  329. IF mno = 0 THEN (* global *)
  330. i := adr DIV 4;
  331. ARMv7M.EmitLWImW(flash, i, a, MT, mod.num * 4)
  332. ELSE (* import *)
  333. impmod := mod.imports[mno-1]; v := impmod.num;
  334. i := adr DIV 4; ARMv7M.EmitLWImW(flash, i, a, MT, v * 4);
  335. inst := flash[adr DIV 4 + 2];
  336. vno := inst MOD 100H;
  337. a := inst DIV 1000000H MOD 10H;
  338. b := inst DIV 100000H MOD 10H; ASSERT(b = SB, 100);
  339. nxt := flash[adr DIV 4 + 3];
  340. CASE inst DIV 10000000H MOD 10H OF 4:
  341. ASSERT(nxt = tagFixup);
  342. IF inst DIV 10000H MOD 10H = 8 (* Add *) THEN op := 2
  343. ELSE HALT(1)
  344. END
  345. | 8: (* Ldr *)
  346. IF nxt = tagFixup THEN op := 0
  347. ELSIF nxt = tagVLDR THEN op := 5
  348. ELSE HALT(2)
  349. END
  350. | 9: (* LdrB *)
  351. ASSERT(nxt = tagFixup);
  352. op := 1
  353. | 10: (* Str *)
  354. ASSERT(nxt = tagFixup);
  355. op := 3
  356. | 11: (* StrB *)
  357. ASSERT(nxt = tagFixup);
  358. op := 4
  359. END;
  360. offset := impmod.entries[vno];
  361. IF ODD(inst DIV 100H) THEN
  362. ASSERT(offset MOD 4 = 0);
  363. offset := offset DIV 2; (* now offset in bytes *)
  364. offset := offset + impmod.code * 2;
  365. HALT(126);
  366. offset := offset - impmod.data
  367. END;
  368. i := adr DIV 4 + 2;
  369. CASE op OF 0: ASSERT(offset MOD 4 = 0, 100);
  370. ARMv7M.EmitLWImW(flash, i, a, b, offset)
  371. | 1: ARMv7M.EmitLBImW(flash, i, a, b, offset)
  372. | 2: ASSERT(a # b, 102);
  373. EmitADDSIm0(flash, i, a, b, offset)
  374. | 3: ASSERT(offset MOD 4 = 0, 126);
  375. ARMv7M.EmitSWImW(flash, i, a, b, offset)
  376. | 4: ARMv7M.EmitSBImW(flash, i, a, b, offset)
  377. | 5: ASSERT(offset MOD 4 = 0);
  378. ARMv7M.EmitVLDR(flash, i, a, b, 1, offset DIV 4)
  379. END
  380. END;
  381. adr := adr - disp * 4
  382. END
  383. (* fixup of type descriptors will be made in Link1 *)
  384. ELSIF res >= 3 THEN COPY(name, importing);
  385. WHILE nofimps > 0 DO DEC(nofimps) END
  386. END
  387. END;
  388. newmod := mod
  389. END Load;
  390. PROCEDURE WriteIHEX32 ((*IN*) VAR name: ARRAY OF CHAR; (*IN*) VAR code: ARRAY OF INTEGER; codeLen: INTEGER; startAdr: INTEGER; SLA: INTEGER; (*OUT*) VAR ok: BOOLEAN);
  391. CONST maxRecLen = 16; (* <= 255 *)
  392. (*
  393. FlashMagic 7.50.3174 incorrectly handles hex files
  394. with maxRecLen = 255 (actually 252)
  395. Astrobe produces hex files with maxRecLen = 16
  396. *)
  397. VAR F: Files.File; R: Files.Rider;
  398. a: ARRAY 1 + 2 + 1 + maxRecLen + 1 OF INTEGER;
  399. r, offset, i: INTEGER;
  400. PROCEDURE WriteRec;
  401. VAR cs: INTEGER;
  402. PROCEDURE WriteH (x: INTEGER);
  403. PROCEDURE H (x: INTEGER);
  404. BEGIN
  405. IF x < 10 THEN Files.Write(R, CHR(x + ORD('0')))
  406. ELSE Files.Write(R, CHR(x - 10 + ORD('A')))
  407. END
  408. END H;
  409. BEGIN
  410. ASSERT(x >= 0, 20);
  411. ASSERT(x < 100H, 21);
  412. H(x DIV 10H); H(x MOD 10H)
  413. END WriteH;
  414. BEGIN
  415. Files.Write(R, ':');
  416. cs := 0;
  417. i := 0;
  418. WHILE i < 1 + 2 + 1 + a[0] DO
  419. WriteH(a[i]); cs := cs + a[i];
  420. INC(i)
  421. END;
  422. WriteH((-cs) MOD 100H);
  423. Files.Write(R, 0DX); Files.Write(R, 0AX)
  424. END WriteRec;
  425. PROCEDURE WriteELA (adr: INTEGER);
  426. BEGIN
  427. ASSERT(adr >= 0, 20);
  428. ASSERT(adr < 10000H, 21);
  429. a[0] := 2; (* len *)
  430. a[1] := 0; a[2] := 0; (* offset *)
  431. a[3] := 4; (* type: extended linear address *)
  432. a[4] := adr DIV 100H;
  433. a[5] := adr MOD 100H;
  434. WriteRec
  435. END WriteELA;
  436. BEGIN
  437. ASSERT(codeLen >= 0, 20);
  438. ASSERT(startAdr MOD 4 = 0, 21);
  439. F := NewHexFile(name);
  440. IF F # NIL THEN
  441. Files.Set(R, F, 0);
  442. r := 0;
  443. IF codeLen > 0 THEN
  444. offset := startAdr MOD 10000H;
  445. startAdr := startAdr DIV 10000H MOD 10000H;
  446. WriteELA(startAdr);
  447. REPEAT
  448. a[0] := 0;
  449. a[1] := offset DIV 100H; a[2] := offset MOD 100H;
  450. a[3] := 0; (* type: data *)
  451. i := 0;
  452. WHILE (i <= maxRecLen - 2) & (offset <= 10000H - 2) & (codeLen > 0) DO
  453. a[4+i] := code[r] MOD 100H;
  454. a[5+i] := code[r] DIV 100H MOD 100H;
  455. ASSERT(code[r] DIV 10000H = 0, 100); (* all fixups done *)
  456. INC(a[0], 2);
  457. INC(r); DEC(codeLen);
  458. INC(i, 2);
  459. INC(offset, 2)
  460. END;
  461. WriteRec;
  462. IF (codeLen > 0) & (offset = 10000H) THEN
  463. INC(startAdr);
  464. WriteELA(startAdr);
  465. offset := 0
  466. END
  467. UNTIL codeLen = 0
  468. END;
  469. a[0] := 4; (* len *)
  470. a[1] := 0; a[2] := 0; (* offset *)
  471. a[3] := 5; (* type: start linear address *)
  472. a[4] := SLA DIV 1000000H MOD 100H;
  473. a[5] := SLA DIV 10000H MOD 100H;
  474. a[6] := SLA DIV 100H MOD 100H;
  475. a[7] := SLA MOD 100H;
  476. WriteRec;
  477. a[0] := 0; a[1] := 0; a[2] := 0; a[3] := 1 (* type: EOF *); WriteRec;
  478. Files.Register(F);
  479. ok := TRUE
  480. ELSE ok := FALSE
  481. END
  482. END WriteIHEX32;
  483. PROCEDURE WriteBin ((*IN*) VAR name: ARRAY OF CHAR; (*IN*) VAR code: ARRAY OF INTEGER; codeLen: INTEGER; (*OUT*) VAR ok: BOOLEAN);
  484. VAR F: Files.File; R: Files.Rider;
  485. r: INTEGER;
  486. BEGIN
  487. ASSERT(codeLen >= 0, 20);
  488. F := NewBinFile(name);
  489. IF F # NIL THEN
  490. Files.Set(R, F, 0); r := 0;
  491. WHILE codeLen > 0 DO
  492. ASSERT(code[r] DIV 10000H = 0, 100); (* all fixups done *)
  493. Files.Write(*Byte*)(R, CHR(code[r] MOD 100H));
  494. Files.Write(*Byte*)(R, CHR(code[r] DIV 100H));
  495. INC(r); DEC(codeLen)
  496. END;
  497. Files.Register(F); ok := TRUE
  498. ELSE ok := FALSE
  499. END
  500. END WriteBin;
  501. PROCEDURE opcode (VAR d: INTEGER; w: LONGINT);
  502. VAR s: ARRAY 64 OF CHAR;
  503. BEGIN
  504. ARMv6M.OpcodeRepr(d, w, s);
  505. IF s[0] # 0X THEN Texts.WriteString(W, s) END
  506. END opcode;
  507. (* R.a := im *)
  508. (* see ARMv7MG.MovIm *)
  509. PROCEDURE MovIm0 (VAR code: ARRAY OF INTEGER; VAR pc: INTEGER; a: INTEGER; im: INTEGER);
  510. CONST S = 0;
  511. VAR shift: INTEGER;
  512. isLR: BOOLEAN;
  513. imInv: INTEGER; isMI: BOOLEAN; i, imm3, imm8, imm4: INTEGER;
  514. BEGIN
  515. ASSERT(a IN {0..14}, 21);
  516. isLR := a DIV 8 = 0;
  517. IF isLR & (im DIV 100H = 0) THEN
  518. ARMv6M.EmitMOVSIm(code, pc, a, im)
  519. ELSE
  520. ARMv7M.EncodeMI12(im, i, imm3, imm8, isMI);
  521. IF isMI THEN
  522. (* A7.7.75: MOV (immediate); encoding T2 ARMv7-M *)
  523. ARMv7M.EmitDPMI(code, pc, i, 4 + S, 0FH, imm3, a, imm8)
  524. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  525. ELSE
  526. imInv := ORDSET(BITS(im) / {0..31});
  527. ARMv7M.EncodeMI12(imInv, i, imm3, imm8, isMI);
  528. IF isMI THEN
  529. (* A7.7.84: MVN (immediate); encoding T1 ARMv7-M *)
  530. ARMv7M.EmitDPMI(code, pc, i, 6 + S, 0FH, imm3, a, imm8)
  531. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  532. ELSIF isLR & (im > 255) & (im <= 255 + 255) THEN
  533. ARMv6M.EmitMOVSIm(code, pc, a, 255);
  534. ARMv6M.EmitADDSIm(code, pc, a, a, im - 255)
  535. ELSE
  536. shift := 8;
  537. WHILE (shift < 32) & (SYSTEM.ROT(im DIV 100H * 100H, -shift) DIV 100H # 0) DO INC(shift) END;
  538. IF isLR & (shift < 32) THEN
  539. ASSERT(im =
  540. SYSTEM.LSH(SYSTEM.ROT(im DIV 100H * 100H, -shift), shift)
  541. + im MOD 100H);
  542. ARMv6M.EmitMOVSIm(code, pc, a, SYSTEM.ROT(im DIV 100H * 100H, -shift));
  543. ARMv6M.EmitLSLSIm(code, pc, a, a, shift);
  544. ARMv6M.EmitADDSIm(code, pc, a, a, im MOD 100H)
  545. ELSE
  546. (* TODO: 3 ops: mov; (add, lsl), (lsl, sub), (lsl, sub) | MI12; add, lsl, sub *)
  547. IF isLR & (im MOD 10000H DIV 100H = 0) THEN
  548. ARMv6M.EmitMOVSIm(code, pc, a, im MOD 10000H)
  549. ELSE
  550. (* A7.7.75: MOV (immediate); encoding T3 ARMv7-M *)
  551. imm4 := im DIV 1000H MOD 10H;
  552. i := im DIV 800H MOD 2;
  553. imm3 := im DIV 100H MOD 8;
  554. imm8 := im MOD 100H;
  555. ARMv7M.EmitDPPBI(code, pc, i, 4, imm4, imm3 * 1000H + a * 100H + imm8)
  556. END;
  557. im := im DIV 10000H;
  558. IF im # 0 THEN
  559. (* A7.7.78: MOVT; encoding T1 ARMv7 *)
  560. imm4 := im DIV 1000H MOD 10H;
  561. i := im DIV 800H MOD 2;
  562. imm3 := im DIV 100H MOD 8;
  563. imm8 := im MOD 100H;
  564. ARMv7M.EmitDPPBI(code, pc, i, 12, imm4, imm3 * 1000H + a * 100H + imm8)
  565. END
  566. END
  567. END
  568. END
  569. END
  570. END MovIm0;
  571. PROCEDURE SubIm0 (VAR code: ARRAY OF INTEGER; VAR pc: INTEGER; d, n, im: INTEGER);
  572. BEGIN
  573. IF im DIV 8 = 0 THEN
  574. ARMv6M.EmitSUBSIm(code, pc, d, n, im)
  575. ELSE
  576. IF d # n THEN
  577. ARMv6M.EmitMOVSR(code, pc, d, n);
  578. END;
  579. ARMv6M.EmitSUBSIm(code, pc, d, d, im)
  580. END
  581. END SubIm0;
  582. PROCEDURE StrIm0 (VAR code: ARRAY OF INTEGER; VAR pc: INTEGER; t, n, im: INTEGER);
  583. BEGIN
  584. IF im DIV 32 = 0 THEN ARMv6M.EmitSTRIm(code, pc, t, n, im)
  585. ELSE ARMv7M.EmitSWImW(code, pc, t, n, im * 4)
  586. END
  587. END StrIm0;
  588. PROCEDURE Link1 ((*IN*) VAR name: ARRAY OF CHAR);
  589. VAR MTOrg, StkOrg, i, j: INTEGER;
  590. ok: BOOLEAN;
  591. mod, impmod: Module;
  592. adr, inst, mno, vno, disp, offset: INTEGER;
  593. r0, r1: INTEGER; r0a, r1a: BOOLEAN;
  594. BEGIN
  595. ASSERT(memW MOD 4 = 0, 100); (* should be aligned *)
  596. (* memW := (memW + 3) DIV 4 * 4; *) (* align *)
  597. MTOrg := target.SRAMStart + target.SRAMSize
  598. - (root.num + 1) * 4; (* MTab *)
  599. (* initial SP *)
  600. StkOrg := MTOrg - (nPtrs + 1) * 4 - memW;
  601. flash[0] := StkOrg MOD 10000H;
  602. flash[1] := StkOrg DIV 10000H MOD 10000H;
  603. (* reset vector *)
  604. inst := target.flashStart + flashW * 2 + 1;
  605. flash[2] := inst MOD 10000H;
  606. flash[3] := inst DIV 10000H MOD 10000H;
  607. (* CPU exceptions (NMI..SysTick) *)
  608. i := 4; WHILE i < 40H DIV 2 DO
  609. flash[i] := 1; INC(i);
  610. flash[i] := 0; INC(i)
  611. END;
  612. WHILE i < 40H DIV 2 + target.maxExtInts * 2 DO
  613. flash[i] := 1; INC(i);
  614. flash[i] := 0; INC(i)
  615. END;
  616. WHILE i < target.flashOrg DIV 2 DO
  617. flash[i] := 0; INC(i);
  618. flash[i] := 0; INC(i)
  619. END;
  620. IF target.isNXP THEN
  621. (* code read protection (CRP) *)
  622. flash[2FCH DIV 2] := 0; flash[2FCH DIV 2 + 1] := 0;
  623. (* NXP checksum *)
  624. j := 0; i := 0; WHILE i < 7 DO
  625. j := j + flash[2 * i] + 10000H * flash[2 * i + 1];
  626. INC(i)
  627. END;
  628. flash[2 * i] := (-j) MOD 10000H;
  629. flash[2 * i + 1] := (-j) DIV 10000H MOD 10000H
  630. END;
  631. IF memW > 0 THEN
  632. (* R[MT] := MTOrg *)
  633. MovIm0(flash, flashW, MT, MTOrg);
  634. (* modules ptrs table *)
  635. (* R[0] := MT - (nPtrs + 1) * 4 *)
  636. SubIm0(flash, flashW, 0, MT, (nPtrs + 1) * 4);
  637. i := 0; mod := root;
  638. WHILE mod # NIL DO
  639. IF mod.nPtrs # 0 THEN
  640. (* R[1] := flashStart + mod.ptr * 2 *)
  641. MovIm0(flash, flashW, 1,
  642. target.flashStart + mod.ptr * 2);
  643. (* Mem[R[0] + i * 4] := R[1] *)
  644. StrIm0(flash, flashW, 1, 0, i);
  645. INC(i)
  646. END;
  647. mod := mod.next
  648. END;
  649. ASSERT(i = nPtrs, 101);
  650. (* R[1] := i *)
  651. MovIm0(flash, flashW, 1, i);
  652. (* Mem[R[0] + i * 4] := R[1] *)
  653. StrIm0(flash, flashW, 1, 0, i);
  654. (* MT, type descriptors and strings *)
  655. j := 0;
  656. r0a := FALSE; r1a := FALSE;
  657. WHILE j <= root.num DO mod := modules[j];
  658. IF ~r0a OR (r0 # StkOrg + mod.data) THEN
  659. (* R[0] := StkOrg + mod.data *)
  660. MovIm0(flash, flashW, 0, StkOrg + mod.data);
  661. r0 := StkOrg + mod.data; r0a := TRUE
  662. END;
  663. (* MTab *)
  664. (* Mem[R[MT] + mod.num * 4] := R[0] *)
  665. StrIm0(flash, flashW, 0, MT, mod.num);
  666. (* fixup of type descriptors *)
  667. adr := mod.fixorgT * 4;
  668. WHILE adr DIV 4 # 0 DO
  669. inst := mod.typeds[adr DIV 4];
  670. IF trace THEN Texts.WriteLn(W);
  671. Texts.WriteString(W, "td fixup: ");
  672. Texts.WriteInt(W, adr DIV 4, 0);
  673. Texts.WriteHex(W, inst);
  674. Texts.WriteString(W, " -> ")
  675. END;
  676. mno := inst DIV 1000000H MOD 100H;
  677. vno := inst DIV 1000H MOD 1000H;
  678. disp := inst MOD 1000H;
  679. IF mno = 0 THEN (*global*) inst := StkOrg + mod.data + vno
  680. ELSE (*import*)
  681. impmod := mod.imports[mno-1];
  682. offset := impmod.entries[vno];
  683. inst := StkOrg + impmod.data + offset
  684. END;
  685. IF trace THEN Texts.WriteHex(W, inst) END;
  686. mod.typeds[adr DIV 4] := inst;
  687. adr := adr - disp * 4
  688. END;
  689. IF mod.typeds # NIL THEN (* type descriptors *)
  690. i := 0;
  691. WHILE i < mod.typedsLen DO
  692. IF ~r1a OR (r1 # mod.typeds[i]) THEN
  693. (* R[1] := mod.typeds[i] *)
  694. MovIm0(flash, flashW, 1, mod.typeds[i]);
  695. r1 := mod.typeds[i]; r1a := TRUE
  696. END;
  697. (* Mem[R[0] + i * 4] := R[1] *)
  698. StrIm0(flash, flashW, 1, 0, i);
  699. INC(i)
  700. END
  701. END;
  702. IF mod.strings # NIL THEN (* strings *)
  703. i := 0;
  704. WHILE i < mod.stringsLen DO
  705. IF ~r1a OR (r1 # mod.strings[i]) THEN
  706. (* R[1] := mod.strings[i] *)
  707. MovIm0(flash, flashW, 1, mod.strings[i]);
  708. r1 := mod.strings[i]; r1a := TRUE
  709. END;
  710. (* Mem[R[0] + mod.strs + i * 4] := R[1] *)
  711. ASSERT(mod.strs MOD 4 = 0);
  712. StrIm0(flash, flashW, 1, 0, mod.strs DIV 4 + i);
  713. INC(i)
  714. END
  715. END;
  716. (* fixup of pointer references *)
  717. i := 0;
  718. WHILE i < mod.nPtrs DO
  719. inst := StkOrg + flash[mod.ptr + i * 2];
  720. flash[mod.ptr + i * 2] := inst MOD 10000H;
  721. flash[mod.ptr + i * 2 + 1] := inst DIV 10000H MOD 10000H;
  722. INC(i)
  723. END;
  724. INC(j)
  725. END
  726. END;
  727. (* body calls *)
  728. i := 0;
  729. WHILE i <= root.num DO
  730. ARMv6M.EmitBL(flash, flashW, modules[i].body - flashW - 1 - 1);
  731. INC(i)
  732. END;
  733. (* stop *)
  734. ARMv6M.EmitB(flash, flashW, -1 - 1);
  735. IF ODD(flashW) THEN (* align *)
  736. ARMv6M.EmitNOP(flash, flashW)
  737. END;
  738. IF flashW * 2 <= target.flashSize THEN
  739. WriteIHEX32(name, flash, flashW,
  740. target.flashStart, target.flashStart + 1, ok);
  741. IF ~ok THEN res := 9 END;
  742. WriteBin(name, flash, flashW, ok);
  743. IF ~ok & (res = 0) THEN res := 10 END
  744. ELSE
  745. res := 8
  746. END
  747. END Link1;
  748. PROCEDURE Link*;
  749. VAR i: INTEGER;
  750. S: Texts.Scanner;
  751. mod: Module;
  752. d: INTEGER;
  753. BEGIN res := 0;
  754. Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  755. IF (S.class = Texts.Name) OR (S.class = Texts.String) THEN
  756. target := targets;
  757. WHILE (target # NIL) & ~CmpStr(target.name, S.s) DO
  758. target := target.next
  759. END;
  760. IF target # NIL THEN
  761. Texts.Scan(S);
  762. IF S.class = Texts.Name THEN
  763. Texts.WriteString(W, "linking "); Texts.WriteString(W, S.s); Texts.WriteString(W, " ");
  764. root := NIL;
  765. flashW := target.flashOrg DIV 2;
  766. memW := 0;
  767. nPtrs := 0;
  768. Load(S.s, mod);
  769. IF res = 0 THEN Link1(S.s) END;
  770. CASE res OF 0:
  771. IF trace THEN Texts.WriteLn(W) END;
  772. Texts.WriteString(W, "Ok"); Texts.WriteLn(W);
  773. i := 0;
  774. WHILE i <= root.num DO mod := modules[i];
  775. Texts.Write(W, 9X);
  776. Texts.WriteString(W, mod.name);
  777. Texts.Write(W, 9X);
  778. Texts.WriteInt(W, mod.code, 0); Texts.WriteLn(W);
  779. INC(i)
  780. END;
  781. Texts.WriteString(W, "ROM: ");
  782. Texts.WriteInt(W, flashW * 2 (* - target.flashOrg *), 0);
  783. Texts.WriteString(W, " B; RAM: ");
  784. Texts.WriteInt(W,
  785. memW + (nPtrs + 1) * 4 + (root.num + 1) * 4, 0);
  786. Texts.WriteString(W, " B");
  787. IF trace THEN Texts.WriteLn(W);
  788. mod := root;
  789. WHILE mod # NIL DO
  790. Texts.WriteString(W, mod.name); Texts.WriteString(W, ":"); Texts.WriteLn(W);
  791. Texts.WriteString(W, " num: ");
  792. Texts.WriteInt(W, mod.num, 0); Texts.WriteLn(W);
  793. Texts.WriteString(W, " data: ");
  794. Texts.WriteInt(W, mod.data, 0); Texts.WriteLn(W);
  795. Texts.WriteString(W, " strs: ");
  796. Texts.WriteInt(W, mod.strs, 0); Texts.WriteLn(W);
  797. Texts.WriteString(W, " code: ");
  798. Texts.WriteInt(W, mod.code, 0); Texts.WriteLn(W);
  799. Texts.WriteString(W, " entries:");
  800. i := 0;
  801. WHILE i < mod.entriesLen DO
  802. Texts.Write(W, ' ');
  803. Texts.WriteInt(W, mod.entries[i], 0);
  804. INC(i)
  805. END;
  806. Texts.WriteLn(W);
  807. Texts.WriteString(W, " body: ");
  808. Texts.WriteInt(W, mod.body, 0); Texts.WriteLn(W);
  809. mod := mod.next
  810. END;
  811. i := 0; d := 0;
  812. WHILE i < flashW DO
  813. Texts.WriteInt(W, i, 4); Texts.Write(W, 9X);
  814. Texts.WriteHex(W, flash[i]); Texts.Write(W, 9X); opcode(d, flash[i]);
  815. Texts.WriteLn(W);
  816. INC(i)
  817. END;
  818. IF d # 0 THEN
  819. Texts.WriteString(W, "invalid decoder state");
  820. Texts.WriteLn(W)
  821. END
  822. END
  823. | 1: Texts.WriteString(W, "file not available: "); Texts.WriteString(W, importing)
  824. | 2: Texts.WriteString(W, "invalid version: "); Texts.WriteString(W, importing)
  825. | 3: Texts.WriteString(W, "key conflict: "); Texts.WriteString(W, importing); Texts.WriteString(W, ": "); Texts.WriteString(W, imported)
  826. | 4: Texts.WriteString(W, "corrupted file: "); Texts.WriteString(W, importing)
  827. | 7: Texts.WriteString(W, "no space: "); Texts.WriteString(W, importing)
  828. | 8: Texts.WriteString(W, "end of flash")
  829. | 9: Texts.WriteString(W, "write HEX failed")
  830. | 10: Texts.WriteString(W, "write BIN failed")
  831. END;
  832. Texts.WriteLn(W)
  833. END
  834. ELSE Texts.WriteString(W, "invalid target"); Texts.WriteLn(W);
  835. target := targets;
  836. WHILE target # NIL DO
  837. Texts.WriteString(W, target.name); Texts.WriteLn(W);
  838. target := target.next
  839. END
  840. END;
  841. Texts.Append(Oberon.Log, W.buf)
  842. END;
  843. (*Oberon.Collect(0)*)
  844. END Link;
  845. PROCEDURE EnterNXP ((*IN*) name: TargetName; maxExtInts, flashSize, SRAMSize, IAPReserve: INTEGER);
  846. VAR target: Target;
  847. BEGIN
  848. ASSERT(maxExtInts > 0, 20);
  849. ASSERT(maxExtInts <= 240 (* Cortex-M4 *), 21);
  850. ASSERT(flashSize MOD 4 = 0, 22);
  851. ASSERT(SRAMSize MOD 4 = 0, 23);
  852. NEW(target); target.next := targets; targets := target;
  853. target.name := name;
  854. target.isNXP := TRUE;
  855. target.flashStart := 0;
  856. target.maxExtInts := maxExtInts;
  857. target.flashOrg := (16 + maxExtInts) * 4;
  858. IF target.flashOrg <= 2FCH (* CRP *) THEN
  859. target.flashOrg := 2FCH (* CRP *) + 4
  860. END;
  861. target.flashSize := flashSize;
  862. target.SRAMStart := 10000000H;
  863. target.SRAMSize := SRAMSize - IAPReserve
  864. END EnterNXP;
  865. PROCEDURE EnterSTM ((*IN*) name0, fpo0, fpo1, suffix: ARRAY OF CHAR; maxExtInts, flashOrg, SRAMSize: INTEGER);
  866. VAR target: Target; i, j, k, l: INTEGER;
  867. BEGIN
  868. ASSERT(maxExtInts > 0, 20);
  869. ASSERT(maxExtInts <= 240 (* Cortex-M4 *), 21);
  870. ASSERT(flashOrg MOD 4 = 0, 22);
  871. ASSERT(flashOrg >= (16 + maxExtInts) * 4, 23);
  872. ASSERT(SRAMSize MOD 4 = 0, 24);
  873. i := 0;
  874. WHILE i < StrLen(fpo0) DO
  875. j := 0;
  876. WHILE j < StrLen(fpo1) DO
  877. NEW(target); target.next := targets; targets := target;
  878. target.name := name0(*$*); k := StrLen(target.name);
  879. target.name[k] := fpo0[i]; INC(k);
  880. target.name[k] := fpo1[j]; INC(k);
  881. l := 0;
  882. WHILE l < StrLen(suffix) DO
  883. target.name[k] := suffix[l]; INC(l); INC(k)
  884. END;
  885. target.name[k] := 0X;
  886. target.isNXP := FALSE;
  887. target.flashStart := 08000000H;
  888. target.maxExtInts := maxExtInts;
  889. target.flashOrg := flashOrg;
  890. IF fpo1[j] = '4' THEN target.flashSize := 4000H (* 16 KiB *)
  891. ELSIF fpo1[j] = '6' THEN target.flashSize := 8000H (* 32 KiB *)
  892. ELSIF fpo1[j] = '8' THEN target.flashSize := 10000H (* 64 KiB *)
  893. ELSIF fpo1[j] = 'B' THEN target.flashSize := 20000H (* 128 KiB *)
  894. ELSIF fpo1[j] = 'C' THEN target.flashSize := 40000H (* 256 KiB *)
  895. ELSIF fpo1[j] = 'D' THEN target.flashSize := 60000H (* 384 KiB *)
  896. ELSIF fpo1[j] = 'E' THEN target.flashSize := 80000H (* 512 KiB *)
  897. ELSIF fpo1[j] = 'F' THEN target.flashSize := 0C0000H (* 768 KiB *)
  898. ELSIF fpo1[j] = 'G' THEN target.flashSize := 100000H (* 1 MiB *)
  899. ELSIF fpo1[j] = 'I' THEN target.flashSize := 200000H (* 2 MiB *)
  900. ELSE HALT(100) (* invalid fpo1[j] *)
  901. END;
  902. target.SRAMStart := 20000000H;
  903. target.SRAMSize := SRAMSize;
  904. INC(j)
  905. END;
  906. INC(i)
  907. END
  908. END EnterSTM;
  909. (* Cortex-M3 *)
  910. PROCEDURE EnterCC1310 ((*IN*) name: TargetName; flashSize, SRAMSize: INTEGER);
  911. CONST
  912. maxExtInts = 34;
  913. CCFGSize = 88;
  914. BEGIN
  915. ASSERT(flashSize MOD 4 = 0, 20);
  916. ASSERT(SRAMSize MOD 4 = 0, 21);
  917. NEW(target); target.next := targets; targets := target;
  918. target.name := name;
  919. target.isNXP := FALSE;
  920. target.flashStart := 0;
  921. target.maxExtInts := maxExtInts;
  922. target.flashOrg := (16 + maxExtInts) * 4;
  923. target.flashSize := flashSize - CCFGSize;
  924. target.SRAMStart := 20000000H;
  925. target.SRAMSize := SRAMSize
  926. END EnterCC1310;
  927. (* Cortex-M3 *)
  928. PROCEDURE EnterLM3S ((*IN*) name: TargetName; flashSize, SRAMSize: INTEGER; maxExtInts: INTEGER);
  929. BEGIN
  930. ASSERT(flashSize MOD 4 = 0, 20);
  931. ASSERT(SRAMSize MOD 4 = 0, 21);
  932. ASSERT(maxExtInts > 0, 22);
  933. ASSERT(maxExtInts <= 240 (* Cortex-M4 *), 23);
  934. NEW(target); target.next := targets; targets := target;
  935. target.name := name;
  936. target.isNXP := FALSE;
  937. target.flashStart := 0;
  938. target.maxExtInts := maxExtInts;
  939. target.flashOrg := (16 + maxExtInts) * 4;
  940. target.flashSize := flashSize;
  941. target.SRAMStart := 20000000H;
  942. target.SRAMSize := SRAMSize
  943. END EnterLM3S;
  944. PROCEDURE EnterSAM ((*IN*) name0, fpo0: ARRAY OF CHAR; maxExtInts, flashOrg, flashSize, SRAMSize: INTEGER);
  945. CONST
  946. flashStart = 400000H;
  947. internalROMStart = 800000H;
  948. SRAMStart = 20000000H;
  949. VAR i, k: INTEGER;
  950. BEGIN
  951. ASSERT(maxExtInts > 0, 20);
  952. ASSERT(maxExtInts <= 240 (* Cortex-M4 *), 21);
  953. ASSERT(flashOrg MOD 80H = 0, 22);
  954. ASSERT(flashOrg >= (16 + maxExtInts) * 4, 23);
  955. ASSERT(flashSize MOD 4 = 0, 24);
  956. ASSERT(flashStart + flashSize <= internalROMStart, 25);
  957. ASSERT(SRAMSize MOD 4 = 0, 26);
  958. i := 0;
  959. WHILE i < StrLen(fpo0) DO
  960. NEW(target); target.next := targets; targets := target;
  961. target.name := name0(*$*); k := StrLen(target.name);
  962. target.name[k] := fpo0[i]; INC(k);
  963. target.name[k] := 0X;
  964. target.isNXP := FALSE;
  965. target.flashStart := flashStart;
  966. target.maxExtInts := maxExtInts;
  967. target.flashOrg := flashOrg;
  968. target.flashSize := flashSize;
  969. target.SRAMStart := SRAMStart;
  970. target.SRAMSize := SRAMSize;
  971. INC(i)
  972. END
  973. END EnterSAM;
  974. BEGIN Texts.OpenWriter(W); Texts.WriteString(W, "OARMv7MLinker 27.12.2021");
  975. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
  976. targets := NIL;
  977. EnterNXP("LPC1311", 58, 2000H (* 8 KiB *), 1000H (* 4 KiB *), 32);
  978. EnterNXP("LPC1313", 58, 8000H (* 32 KiB *), 2000H (* 8 KiB *), 32);
  979. EnterNXP("LPC1342", 58, 4000H (* 16 KiB *), 1000H (* 4 KiB *), 32);
  980. EnterNXP("LPC1343", 58, 8000H (* 32 KiB *), 2000H (* 8 KiB *), 32);
  981. EnterNXP("LPC1751", 35, 8000H (* 32 KiB *), 2000H (* 8 KiB *), 32);
  982. EnterNXP("LPC1752", 35, 10000H (* 64 KiB *), 4000H (* 16 KiB *), 32);
  983. EnterNXP("LPC1754", 35, 20000H (* 128 KiB *), 8000H (* 32 KiB *), 32);
  984. EnterNXP("LPC1756", 35, 40000H (* 256 KiB *), 8000H (* 32 KiB *), 32);
  985. EnterNXP("LPC1758", 35, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  986. EnterNXP("LPC1759", 35, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  987. EnterNXP("LPC1763", 35, 40000H (* 256 KiB *), 10000H (* 64 KiB *), 32);
  988. EnterNXP("LPC1764", 35, 20000H (* 128 KiB *), 8000H (* 32 KiB *), 32);
  989. EnterNXP("LPC1765", 35, 40000H (* 256 KiB *), 10000H (* 64 KiB *), 32);
  990. EnterNXP("LPC1766", 35, 40000H (* 256 KiB *), 10000H (* 64 KiB *), 32);
  991. EnterNXP("LPC1767", 35, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  992. EnterNXP("LPC1768", 35, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  993. EnterNXP("LPC1769", 35, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  994. EnterNXP("LPC1773", 41, 20000H (* 128 KiB *), 8000H (* 32 KiB *), 32);
  995. EnterNXP("LPC1774", 41, 20000H (* 128 KiB *), 8000H (* 32 KiB *), 32);
  996. EnterNXP("LPC1776", 41, 40000H (* 256 KiB *), 10000H (* 64 KiB *), 32);
  997. EnterNXP("LPC1777", 41, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  998. EnterNXP("LPC1778", 41, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  999. EnterNXP("LPC1785", 41, 40000H (* 256 KiB *), 10000H (* 64 KiB *), 32);
  1000. EnterNXP("LPC1786", 41, 40000H (* 256 KiB *), 10000H (* 64 KiB *), 32);
  1001. EnterNXP("LPC1787", 41, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  1002. EnterNXP("LPC1788", 41, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  1003. (* no FPU *)
  1004. EnterNXP("LPC4072", 41, 10000H (* 64 KiB *), 4000H (* 16 KiB *), 32);
  1005. EnterNXP("LPC4074", 41, 20000H (* 128 KiB *), 8000H (* 32 KiB *), 32);
  1006. EnterNXP("LPC4076", 41, 40000H (* 256 KiB *), 10000H (* 64 KiB *), 32);
  1007. EnterNXP("LPC4078", 41, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  1008. EnterNXP("LPC4088", 41, 80000H (* 512 KiB *), 10000H (* 64 KiB *), 32);
  1009. (* 4 KiB of SRAM *)
  1010. EnterSTM("STM32F100", "CR", "46", "", 61, 200H, 1000H);
  1011. EnterSTM("STM32F101", "RT", "4", "", 60, 200H, 1000H);
  1012. EnterSTM("STM32F102", "CR", "4", "", 60, 200H, 1000H);
  1013. (* 6 KiB of SRAM *)
  1014. EnterSTM("STM32F101", "CRT", "6", "", 60, 200H, 1800H);
  1015. EnterSTM("STM32F102", "CR", "6", "", 60, 200H, 1800H);
  1016. EnterSTM("STM32F103", "CRT", "4", "", 60, 200H, 1800H);
  1017. (* 8 KiB of SRAM *)
  1018. EnterSTM("STM32F100", "CRV", "8B", "", 61, 200H, 2000H);
  1019. (* 10 KiB of SRAM *)
  1020. EnterSTM("STM32F101", "CRTV", "8", "", 60, 200H, 2800H);
  1021. EnterSTM("STM32F102", "CR", "8", "", 60, 200H, 2800H);
  1022. EnterSTM("STM32F103", "CRT", "6", "", 60, 200H, 2800H);
  1023. (* 16 KiB of SRAM *)
  1024. EnterSTM("STM32F101", "CRTV", "B", "", 60, 200H, 4000H);
  1025. EnterSTM("STM32F102", "CR", "B", "", 60, 200H, 4000H);
  1026. EnterSTM("STM32F301", "CKR", "68", "", 82, 200H, 4000H);
  1027. EnterSTM("STM32F302", "CKR", "68", "", 82, 200H, 4000H);
  1028. EnterSTM("STM32F303", "CKR", "68", "", 82, 200H, 4000H);
  1029. EnterSTM("STM32L151", "CR", "6", "-A", 45, 200H, 4000H);
  1030. (* 20 KiB of SRAM *)
  1031. EnterSTM("STM32F103", "CRTV", "8B", "", 60, 200H, 5000H);
  1032. (* 24 KiB of SRAM *)
  1033. EnterSTM("STM32F100", "RVZ", "C", "", 61, 200H, 6000H);
  1034. (* 32 KiB of SRAM *)
  1035. EnterSTM("STM32F100", "RVZ", "DE", "", 61, 200H, 8000H);
  1036. EnterSTM("STM32F101", "RVZ", "C", "", 60, 200H, 8000H);
  1037. EnterSTM("STM32F302", "CRV", "B", "", 85, 200H, 8000H);
  1038. EnterSTM("STM32L151", "CRV", "8B", "-A", 45, 200H, 8000H);
  1039. (* 40 KiB of SRAM *)
  1040. EnterSTM("STM32F302", "CRV", "C", "", 85, 200H, 0A000H);
  1041. EnterSTM("STM32F303", "CRV", "B", "", 85, 200H, 0A000H);
  1042. (* 48 KiB of SRAM *)
  1043. EnterSTM("STM32F101", "RVZ", "DE", "", 60, 200H, 0C000H);
  1044. EnterSTM("STM32F103", "RVZ", "C", "", 60, 200H, 0C000H);
  1045. EnterSTM("STM32F303", "CRV", "C", "", 85, 200H, 0C000H);
  1046. (* 64 KiB of SRAM *)
  1047. EnterSTM("STM32F103", "RVZ", "DE", "", 60, 200H, 10000H);
  1048. EnterSTM("STM32F105", "RV", "8BC", "", 68, 200H, 10000H);
  1049. EnterSTM("STM32F107", "RV", "BC", "", 68, 200H, 10000H);
  1050. EnterSTM("STM32F302", "RVZ", "DE", "", 85, 200H, 10000H);
  1051. EnterSTM("STM32F401", "CRV", "BC", "", 85, 200H, 10000H);
  1052. (* memory hole?
  1053. (* 48+16 KiB of SRAM *)
  1054. EnterSTM("STM32F205", "RV", "B", "", 81, 200H, 10000H);
  1055. *)
  1056. (* 80 KiB of SRAM *)
  1057. EnterSTM("STM32F101", "RVZ", "FG", "", 60, 200H, 14000H);
  1058. EnterSTM("STM32F303", "RVZ", "DE", "", 85, 200H, 14000H);
  1059. (* 96 KiB of SRAM *)
  1060. EnterSTM("STM32F103", "RVZ", "FG", "", 60, 200H, 18000H);
  1061. EnterSTM("STM32F401", "CRV", "DE", "", 85, 200H, 18000H);
  1062. (* memory hole?
  1063. (* 80+16 KiB of SRAM *)
  1064. EnterSTM("STM32F205", "RVZ", "C", "", 81, 200H, 18000H);
  1065. *)
  1066. (* 128 KiB of SRAM *)
  1067. EnterSTM("STM32F411", "CRV", "CE", "", 86, 200H, 20000H);
  1068. (* 112+16 KiB of SRAM *)
  1069. EnterSTM("STM32F205", "RVZ", "EFG", "", 81, 200H, 20000H);
  1070. EnterSTM("STM32F207", "IVZ", "CEFG", "", 81, 200H, 20000H);
  1071. EnterSTM("STM32F215", "RVZ", "EG", "", 81, 200H, 20000H);
  1072. EnterSTM("STM32F217", "IVZ", "EG", "", 81, 200H, 20000H);
  1073. EnterSTM("STM32F405", "O", "E", "", 82, 200H, 20000H);
  1074. EnterSTM("STM32F405", "ORVZ", "G", "", 82, 200H, 20000H);
  1075. EnterSTM("STM32F407", "IVZ", "EG", "", 82, 200H, 20000H);
  1076. EnterSTM("STM32F415", "ORVZ", "G", "", 82, 200H, 20000H);
  1077. EnterSTM("STM32F417", "IVZ", "EG", "", 82, 200H, 20000H);
  1078. EnterSTM("STM32F446", "MRVZ", "CE", "", 97, 200H, 20000H);
  1079. (* 112+16+64 KiB of SRAM *)
  1080. EnterSTM("STM32F427", "IVZ", "GI", "", 91, 200H, 30000H);
  1081. EnterSTM("STM32F429", "BINVZ", "EGI", "", 91, 200H, 30000H);
  1082. EnterSTM("STM32F437", "IVZ", "GI", "", 91, 200H, 30000H);
  1083. EnterSTM("STM32F439", "BINVZ", "GI", "", 91, 200H, 30000H);
  1084. (* 64 KiB (DTCM) + 240 KiB (SRAM1) + 16 KiB (SRAM2) *)
  1085. EnterSTM("STM32F756", "BINVZ", "EG", "",
  1086. 98, (16 + 240) * 4 (* FIXME *), 50000H);
  1087. (* 128 KiB (DTCM) *)
  1088. EnterSTM("STM32H723", "VZ", "EG", "",
  1089. 163, (16 + 240) * 4, 20000H);
  1090. EnterSTM("STM32H725", "AIRVZ", "EG", "",
  1091. 163, (16 + 240) * 4, 20000H);
  1092. EnterSTM("STM32H730", "AIVZ", "B", "",
  1093. 163, (16 + 240) * 4, 20000H);
  1094. EnterSTM("STM32H733", "VZ", "G", "",
  1095. 163, (16 + 240) * 4, 20000H);
  1096. EnterSTM("STM32H735", "AIRVZ", "G", "",
  1097. 163, (16 + 240) * 4, 20000H);
  1098. EnterSTM("STM32H742", "ABIVXZ", "GI", "",
  1099. 150, (16 + 240) * 4, 20000H);
  1100. EnterSTM("STM32H743", "ABIVXZ", "GI", "",
  1101. 150, (16 + 240) * 4, 20000H);
  1102. (*
  1103. EnterSTM("STM32H745", "BIXZ", "GI", "",
  1104. 150, (16 + 240) * 4, 20000H);
  1105. EnterSTM("STM32H747", "ABIX", "GI", "",
  1106. 150, (16 + 240) * 4, 20000H);
  1107. EnterSTM("STM32H747", "Z", "I", "",
  1108. 150, (16 + 240) * 4, 20000H);
  1109. *)
  1110. EnterSTM("STM32H750", "IVXZ", "B", "",
  1111. 150, (16 + 240) * 4, 20000H);
  1112. EnterSTM("STM32H753", "ABIVXZ", "I", "",
  1113. 150, (16 + 240) * 4, 20000H);
  1114. (*
  1115. EnterSTM("STM32H755", "BIXZ", "I", "",
  1116. 150, (16 + 240) * 4, 20000H);
  1117. EnterSTM("STM32H757", "ABIXZ", "I", "",
  1118. 150, (16 + 240) * 4, 20000H);
  1119. *)
  1120. EnterSTM("STM32H7A3", "AILNRVZ", "IG", "",
  1121. 155, (16 + 240) * 4, 20000H);
  1122. EnterSTM("STM32H7B3", "AILNRVZ", "I", "",
  1123. 155, (16 + 240) * 4, 20000H);
  1124. EnterSTM("STM32H7B0", "AIRVZ", "B", "",
  1125. 155, (16 + 240) * 4, 20000H);
  1126. EnterCC1310("CC1310F32", 8000H (* 32 KiB *), 4000H (* 16 KiB *));
  1127. EnterCC1310("CC1310F64", 10000H (* 64 KiB *), 4000H (* 16 KiB *));
  1128. EnterCC1310("CC1310F128", 20000H (* 128 KiB *), 5000H (* 20 KiB *));
  1129. EnterLM3S("LM3S811", 10000H (* 64 KiB *), 2000H (* 8 KiB *), 26);
  1130. EnterLM3S("LM3S6965", 40000H (* 256 KiB *), 10000H (* 64 KiB *), 38);
  1131. EnterSAM("SAM3S1", "ABC", 35, 200H,
  1132. 10000H (* 64 KiB *), 4000H (* 16 KiB *));
  1133. EnterSAM("SAM3S2", "ABC", 35, 200H,
  1134. 20000H (* 128 KiB *), 8000H (* 32 KiB *));
  1135. EnterSAM("SAM3S4", "ABC", 35, 200H,
  1136. 40000H (* 256 KiB *), 0C000H (* 48 KiB *))
  1137. END O7ARMv7MLinker.