O7ARMv6MLinker.Mod 38 KB

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