O7ARMv6MG.Mod 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268
  1. MODULE O7ARMv6MG; (* NW 18.4.2016 / 31.5.2019 code generator in Oberon-07 for RISC*)
  2. (* Modified for ARMv6-M by A. V. Shiryaev, 2016.05.07, 2019.10.21, 2023.06.21 *)
  3. (*
  4. http://www.inf.ethz.ch/personal/wirth/FPGA-relatedWork/RISC-Arch.pdf
  5. ARMv6-M Architecture Reference Manual
  6. http://ecee.colorado.edu/ecen3000/labs/lab3/files/DDI0419C_arm_architecture_v6m_reference_manual.pdf
  7. *)
  8. (*
  9. TODO:
  10. LEN(record.arrayOfChar):
  11. Reg Stack
  12. invalid code generated when no Reg Stack compile-time error
  13. implement "special feautures" (see RISC-Arch.pdf, section 4):
  14. implement MOV+U F0, c = 1 feature? save flags to register
  15. when it's required?
  16. MRS instruction
  17. check loadCond (IsFlagsUp0 related)
  18. implement LDPSR
  19. see PO.Applications.pdf, p. 47
  20. shifts...
  21. implementation limits:
  22. long B branches: use BX
  23. optimizations:
  24. optimize MovIm (3-4 instr-s)
  25. arrays assignment (see PO.Applications.pdf, 45):
  26. use special command instead of loop
  27. bits:
  28. SYSTEM.BIT(adr, bit)
  29. ...
  30. register procedures https://github.com/aixp/ProjectOberon2013/commit/873fe7ef74a2c41592f9904ad7c3893e4a368d58
  31. *)
  32. IMPORT SYSTEM, Files, ORS := O7S, ORB := O7B, ARMv6M := O7ARMv6M;
  33. (*Code generator for Oberon compiler for RISC processor.
  34. Procedural interface to Parser OSAP; result in array "code".
  35. Procedure Close writes code-files*)
  36. TYPE
  37. LONGINT = INTEGER;
  38. BYTE = CHAR;
  39. CONST WordSize* = 4;
  40. parblksize0Proc* = 0; parblksize0Int* = 0;
  41. (* MT = 12; SB = 13; SP = 14; LNK = 15; (*dedicated registers*) *)
  42. MT = 6; SB = 7; SP = ARMv6M.SP; LNK = ARMv6M.LR;
  43. maxCode = 8000; maxStrx = 2400; maxTD = 160; C24 = 1000000H;
  44. Reg = 10; RegI = 11; Cond = 12; (*internal item modes*)
  45. (*frequently used opcodes*) U = 2000H; V = 1000H;
  46. Mov = 0; Lsl = 1; Asr = 2; Ror= 3; And = 4; Ann = 5; Ior = 6; Xor = 7;
  47. Add = 8; Sub = 9; Cmp = 9; Mul = 10; Div = 11;
  48. Fad = 12; Fsb = 13; Fml = 14; Fdv = 15;
  49. Ldr = 8; Str = 10;
  50. BR = 0; BLR = 1; BC = 2; BL = 3;
  51. MI = 0; PL = 8; EQ = 1; NE = 9; LT = 5; GE = 13; LE = 6; GT = 14;
  52. TYPE Item* = RECORD
  53. mode*: INTEGER;
  54. type*: ORB.Type;
  55. a-, b-, r: LONGINT;
  56. rdo-: BOOLEAN (*read only*)
  57. END ;
  58. (* Item forms and meaning of fields:
  59. mode r a b
  60. --------------------------------
  61. Const - value (proc adr) (immediate value)
  62. Var base off - (direct adr)
  63. Par - off0 off1 (indirect adr)
  64. Reg regno
  65. RegI regno off -
  66. Cond cond Fchain Tchain *)
  67. VAR pc-, varsize: LONGINT; (*program counter, data index*)
  68. tdx, strx: LONGINT;
  69. entry: LONGINT; (*main entry point*)
  70. RH: LONGINT; (*available registers R[0] ... R[H-1]*)
  71. curSB: LONGINT; (*current static base in SB*)
  72. frame: LONGINT; (*frame offset changed in SaveRegs and RestoreRegs*)
  73. fixorgP, fixorgD, fixorgT: LONGINT; (*origins of lists of locations to be fixed up by loader*)
  74. check: BOOLEAN; (*emit run-time checks*)
  75. version: INTEGER; (* 0 = RISC-0, 1 = RISC-5 *)
  76. relmap: ARRAY 6 OF INTEGER; (*condition codes for relations*)
  77. armcode: ARRAY maxCode OF LONGINT;
  78. data: ARRAY maxTD OF LONGINT; (*type descriptors*)
  79. str: ARRAY maxStrx OF CHAR;
  80. RM: SET; (* registers modified *)
  81. enterPushFixup: INTEGER;
  82. PROCEDURE BITS (x: INTEGER): SET;
  83. BEGIN
  84. RETURN SYSTEM.VAL(SET, x)
  85. END BITS;
  86. PROCEDURE ORDSET (x: SET): INTEGER;
  87. BEGIN
  88. RETURN SYSTEM.VAL(INTEGER, x)
  89. END ORDSET;
  90. PROCEDURE LSL (x, n: INTEGER): INTEGER;
  91. BEGIN RETURN SYSTEM.LSH(x, n)
  92. END LSL;
  93. (*instruction assemblers according to formats*)
  94. (* encode register *)
  95. PROCEDURE ER (a: INTEGER): INTEGER;
  96. BEGIN
  97. IF a = SB THEN RETURN 3
  98. ELSIF a = 3 THEN RETURN SB
  99. ELSE RETURN a
  100. END
  101. END ER;
  102. PROCEDURE ERs (s: SET): SET;
  103. VAR r: SET; i: INTEGER;
  104. BEGIN
  105. r := {}; i := 0;
  106. WHILE i < 10H DO
  107. IF i IN s THEN INCL(r, ER(i)) END;
  108. INC(i)
  109. END;
  110. RETURN r
  111. END ERs;
  112. (* decode register *)
  113. PROCEDURE DR (a: INTEGER): INTEGER;
  114. BEGIN
  115. IF a = SB THEN RETURN 3
  116. ELSIF a = 3 THEN RETURN SB
  117. ELSE RETURN a
  118. END
  119. END DR;
  120. PROCEDURE UpdateFlags (a: INTEGER);
  121. BEGIN
  122. ARMv6M.EmitCMPIm(armcode, pc, ER(a), 0)
  123. END UpdateFlags;
  124. (* emit RSBS a, a, #0 *)
  125. PROCEDURE RSBS0 (a: INTEGER);
  126. BEGIN
  127. INCL(RM, a);
  128. a := ER(a);
  129. ARMv6M.EmitRSBS0(armcode, pc, a, a)
  130. END RSBS0;
  131. (* A6.7.17 *)
  132. PROCEDURE IsCMPIm (c: INTEGER): BOOLEAN;
  133. BEGIN
  134. RETURN c DIV 800H = 5
  135. END IsCMPIm;
  136. PROCEDURE RemoveRedundantCmp;
  137. BEGIN
  138. IF (pc >= 2) & ~ARMv6M.IsLThumb32(armcode[pc - 2]) & IsCMPIm(armcode[pc - 1]) THEN DEC(pc) END
  139. END RemoveRedundantCmp;
  140. (* op # Mov: R.a := R.b op R.c; op = Mov: R.a := R.c *)
  141. (* S=1: change NZCV according R.a after *)
  142. PROCEDURE Put00 (S: INTEGER; op, a, b, c: LONGINT);
  143. VAR u, v: BOOLEAN;
  144. r: INTEGER;
  145. BEGIN (*emit format-0 instruction
  146. code[pc] := ((a*10H + b) * 10H + op) * 10000H + c; *)
  147. ASSERT(S IN {0,1}, 20);
  148. IF ORS.errcnt = 0 THEN
  149. u := 13 IN BITS(op);
  150. IF u THEN DEC(op, U) END;
  151. v := 12 IN BITS(op);
  152. IF v THEN DEC(op, V) END;
  153. ASSERT(op DIV 10H = 0, 21);
  154. ASSERT(a DIV 10H = 0, 22);
  155. ASSERT(b DIV 10H = 0, 23);
  156. ASSERT(c DIV 10H = 0, 24);
  157. INCL(RM, a);
  158. IF ~((op IN {Add,Sub}) & u) THEN RemoveRedundantCmp END;
  159. CASE op MOD 10H OF Mov: (* R.a := R.c *)
  160. ASSERT(~v, 100);
  161. IF ~u THEN
  162. IF c = SP THEN
  163. ARMv6M.EmitADDSPIm(armcode, pc, ER(a), 0);
  164. IF S = 1 THEN UpdateFlags(a) END
  165. ELSIF c = LNK THEN
  166. ARMv6M.EmitPUSH(armcode, pc, {LNK});
  167. ARMv6M.EmitPOP(armcode, pc, {ER(a)});
  168. IF S = 1 THEN UpdateFlags(a) END
  169. ELSE
  170. ARMv6M.EmitMOVSR(armcode, pc, ER(a), ER(c))
  171. END
  172. ELSE
  173. ASSERT(b = 0, 101);
  174. ASSERT(c IN {0,1}, 102);
  175. IF c = 0 THEN
  176. HALT(103)
  177. ELSE (* c = 1 *)
  178. HALT(126) (* TODO *)
  179. END
  180. END
  181. | Lsl: (* R.a := R.b <- R.c *)
  182. ASSERT(~u, 104);
  183. ASSERT(~v, 105);
  184. IF a = b THEN
  185. ARMv6M.EmitLSLSR(armcode, pc, ER(a), ER(c))
  186. ELSIF a # c THEN
  187. Put00(0, Mov, a, 0, b);
  188. ARMv6M.EmitLSLSR(armcode, pc, ER(a), ER(c))
  189. ELSE (* R.a := R.b <- R.a *)
  190. r := RH;
  191. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  192. IF (b < MT) & (r <= b) THEN r := b + 1 END;
  193. ASSERT(r < MT, 100);
  194. Put00(0, Mov, r, 0, a);
  195. Put00(0, Mov, a, 0, b);
  196. ARMv6M.EmitLSLSR(armcode, pc, ER(a), ER(r))
  197. END
  198. | Asr: (* R.a := R.b -> R.c *)
  199. ASSERT(~u, 109);
  200. ASSERT(~v, 110);
  201. IF a = b THEN
  202. ARMv6M.EmitASRSR(armcode, pc, ER(a), ER(c))
  203. ELSIF a # c THEN
  204. Put00(0, Mov, a, 0, b);
  205. ARMv6M.EmitASRSR(armcode, pc, ER(a), ER(c))
  206. ELSE (* R.a := R.b -> R.a *)
  207. r := RH;
  208. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  209. IF (b < MT) & (r <= b) THEN r := b + 1 END;
  210. ASSERT(r < MT, 100);
  211. Put00(0, Mov, r, 0, a);
  212. Put00(0, Mov, a, 0, b);
  213. ARMv6M.EmitASRSR(armcode, pc, ER(a), ER(r))
  214. END
  215. | Ror: (* R.a := R.b rot R.c *)
  216. ASSERT(~u, 114);
  217. ASSERT(~v, 115);
  218. IF a = b THEN
  219. ARMv6M.EmitRORSR(armcode, pc, ER(a), ER(c))
  220. ELSIF a # c THEN
  221. Put00(0, Mov, a, 0, b);
  222. ARMv6M.EmitRORSR(armcode, pc, ER(a), ER(c))
  223. ELSE (* R.a := R.b rot R.a *)
  224. r := RH;
  225. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  226. IF (b < MT) & (r <= b) THEN r := b + 1 END;
  227. ASSERT(r < MT, 100);
  228. Put00(0, Mov, r, 0, a);
  229. Put00(0, Mov, a, 0, b);
  230. ARMv6M.EmitRORSR(armcode, pc, ER(a), ER(r))
  231. END
  232. | And: (* R.a := R.b & R.c *)
  233. ASSERT(~u, 119);
  234. ASSERT(~v, 120);
  235. IF a = b THEN
  236. ARMv6M.EmitANDSR(armcode, pc, ER(a), ER(c))
  237. ELSIF a = c THEN
  238. ARMv6M.EmitANDSR(armcode, pc, ER(a), ER(b))
  239. ELSIF b = c THEN HALT(1) (* R.a := R.b *)
  240. ELSE
  241. Put00(0, Mov, a, 0, b);
  242. ARMv6M.EmitANDSR(armcode, pc, ER(a), ER(c))
  243. END
  244. | Ann: (* R.a := R.b & ~R.c *)
  245. ASSERT(~u, 124);
  246. ASSERT(~v, 125);
  247. ASSERT(b # c, 100); (* in this case, emit R.a := 0 *)
  248. IF a = b THEN (* R.a := R.a & ~R.c *)
  249. ARMv6M.EmitBICSR(armcode, pc, ER(a), ER(c))
  250. ELSIF a # c THEN
  251. Put00(0, Mov, a, 0, b);
  252. ARMv6M.EmitBICSR(armcode, pc, ER(a), ER(c))
  253. ELSE (* R.a := R.b & ~R.a *)
  254. r := RH;
  255. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  256. IF (b < MT) & (r <= b) THEN r := b + 1 END;
  257. ASSERT(r < MT, 100);
  258. Put00(0, Mov, r, 0, a);
  259. Put00(0, Mov, a, 0, b);
  260. ARMv6M.EmitBICSR(armcode, pc, ER(a), ER(r))
  261. END
  262. | Ior: (* R.a := R.b or R.c *)
  263. ASSERT(~u, 104);
  264. ASSERT(~v, 105);
  265. IF a = b THEN
  266. ARMv6M.EmitORRSR(armcode, pc, ER(a), ER(c))
  267. ELSIF a = c THEN
  268. ARMv6M.EmitORRSR(armcode, pc, ER(a), ER(b))
  269. ELSIF b = c THEN HALT(1) (* R.a := R.b *)
  270. ELSE
  271. Put00(0, Mov, a, 0, b);
  272. ARMv6M.EmitORRSR(armcode, pc, ER(a), ER(c))
  273. END
  274. | Xor: (* R.a := R.b xor R.c *)
  275. ASSERT(~u, 109);
  276. ASSERT(~v, 110);
  277. IF a = b THEN
  278. ARMv6M.EmitEORSR(armcode, pc, ER(a), ER(c))
  279. ELSIF a = c THEN
  280. ARMv6M.EmitEORSR(armcode, pc, ER(a), ER(b))
  281. ELSIF b = c THEN HALT(1)
  282. ELSE
  283. Put00(0, Mov, a, 0, b);
  284. ARMv6M.EmitEORSR(armcode, pc, ER(a), ER(c))
  285. END
  286. | Add: (* R.a := R.b + R.c *)
  287. ASSERT(~v, 114);
  288. IF ~u THEN
  289. IF b = SP THEN
  290. ARMv6M.EmitADDSPR(armcode, pc, ER(a), ER(c));
  291. IF S = 1 THEN UpdateFlags(a) END
  292. ELSIF c = SP THEN
  293. ARMv6M.EmitADDSPR(armcode, pc, ER(a), ER(b));
  294. IF S = 1 THEN UpdateFlags(a) END
  295. ELSIF (ER(a) IN {0..7}) & (ER(b) IN {0..7}) & (ER(c) IN {0..7}) THEN
  296. ARMv6M.EmitADDSR(armcode, pc, ER(a), ER(b), ER(c))
  297. ELSIF a = b THEN
  298. ARMv6M.EmitADDR(armcode, pc, ER(a), ER(c));
  299. IF S = 1 THEN UpdateFlags(a) END
  300. ELSIF a = c THEN
  301. ARMv6M.EmitADDR(armcode, pc, ER(a), ER(b));
  302. IF S = 1 THEN UpdateFlags(a) END
  303. ELSE HALT(126)
  304. END
  305. ELSE (* with carry *)
  306. IF a = b THEN
  307. ARMv6M.EmitADCSR(armcode, pc, ER(a), ER(c))
  308. ELSIF a = c THEN
  309. ARMv6M.EmitADCSR(armcode, pc, ER(a), ER(b))
  310. ELSE HALT(126)
  311. END
  312. END
  313. | Sub: (* R.a := R.b - R.c *)
  314. ASSERT(~v, 119);
  315. IF ~u THEN
  316. ARMv6M.EmitSUBSR(armcode, pc, ER(a), ER(b), ER(c))
  317. ELSE (* with carry *)
  318. ASSERT(a = b, 120);
  319. ARMv6M.EmitSBCSR(armcode, pc, ER(a), ER(c))
  320. END
  321. | Mul: (* R.a := R.b * R.c *)
  322. ASSERT(~v, 124);
  323. IF ~u THEN
  324. IF (a # b) & (a = c) THEN r := b; b := c; c := r END;
  325. ASSERT(a = b, 126);
  326. ARMv6M.EmitMULSR(armcode, pc, ER(a), ER(c))
  327. ELSE
  328. HALT(126)
  329. END
  330. | Div: (* R.a := R.b div R.c *)
  331. ASSERT(~u, 103);
  332. ASSERT(~v, 104);
  333. ORS.Mark("not implemented")
  334. | Fad,Fsb,Fml,Fdv:
  335. ASSERT(~u, 108);
  336. ASSERT(~v, 109);
  337. ORS.Mark("not implemented")
  338. END
  339. END
  340. END Put00;
  341. PROCEDURE Put0 (op, a, b, c: INTEGER);
  342. BEGIN
  343. Put00(1, op, a, b, c)
  344. END Put0;
  345. (* R.a := im *)
  346. (* NOTE: ARMv6MLinker.MovIm0 *)
  347. PROCEDURE MovIm (S: INTEGER; a: INTEGER; im: INTEGER);
  348. VAR shift: INTEGER;
  349. BEGIN
  350. ASSERT(S IN {0,1}, 20);
  351. ASSERT(a IN {0..14}, 21);
  352. INCL(RM, a);
  353. IF a # SP THEN
  354. shift := 0;
  355. WHILE (shift < 32) & ~(
  356. (SYSTEM.LSH(im, -shift) DIV 100H = 0)
  357. & (im = SYSTEM.LSH(SYSTEM.LSH(im, -shift), shift))
  358. ) DO INC(shift)
  359. END;
  360. IF shift < 32 THEN
  361. ARMv6M.EmitMOVSIm(armcode, pc, ER(a), SYSTEM.LSH(im, -shift));
  362. IF shift # 0 THEN
  363. ARMv6M.EmitLSLSIm(armcode, pc, ER(a), ER(a), shift)
  364. END
  365. ELSIF (im > 255) & (im <= 255 + 255) THEN
  366. ARMv6M.EmitMOVSIm(armcode, pc, ER(a), 255);
  367. ARMv6M.EmitADDSIm(armcode, pc, ER(a), ER(a), im - 255)
  368. ELSIF (im >= -255) & (im < 0) THEN
  369. ARMv6M.EmitMOVSIm(armcode, pc, ER(a), 0);
  370. ARMv6M.EmitSUBSIm(armcode, pc, ER(a), ER(a), -im)
  371. ELSE
  372. shift := 8;
  373. WHILE (shift < 32) & (SYSTEM.ROT(im DIV 100H * 100H, -shift) DIV 100H # 0) DO INC(shift) END;
  374. IF shift < 32 THEN
  375. ASSERT(im =
  376. SYSTEM.LSH(SYSTEM.ROT(im DIV 100H * 100H, -shift), shift)
  377. + im MOD 100H);
  378. ARMv6M.EmitMOVSIm(armcode, pc, ER(a), SYSTEM.ROT(im DIV 100H * 100H, -shift));
  379. ARMv6M.EmitLSLSIm(armcode, pc, ER(a), ER(a), shift);
  380. ARMv6M.EmitADDSIm(armcode, pc, ER(a), ER(a), im MOD 100H)
  381. ELSE
  382. (* TODO: 3 ops: mov; (add, lsl), (lsl, sub), (lsl, sub) *)
  383. ARMv6M.EmitMOVSIm(armcode, pc, ER(a),
  384. im DIV 1000000H MOD 100H);
  385. IF im DIV 1000000H MOD 100H # 0 THEN
  386. ARMv6M.EmitLSLSIm(armcode, pc, ER(a), ER(a), 8)
  387. END;
  388. IF im DIV 10000H MOD 100H # 0 THEN
  389. ARMv6M.EmitADDSIm(armcode, pc, ER(a), ER(a),
  390. im DIV 10000H MOD 100H)
  391. END;
  392. ARMv6M.EmitLSLSIm(armcode, pc, ER(a), ER(a), 8);
  393. IF im DIV 100H MOD 100H # 0 THEN
  394. ARMv6M.EmitADDSIm(armcode, pc, ER(a), ER(a),
  395. im DIV 100H MOD 100H)
  396. END;
  397. ARMv6M.EmitLSLSIm(armcode, pc, ER(a), ER(a), 8);
  398. IF im MOD 100H # 0 THEN
  399. ARMv6M.EmitADDSIm(armcode, pc, ER(a), ER(a), im MOD 100H)
  400. END
  401. END
  402. END
  403. ELSE (* a = SP *)
  404. ASSERT(RH < MT, 100);
  405. ASSERT(RH # SP, 101);
  406. MovIm(S, RH, im);
  407. Put00(S, Mov, SP, 0, RH)
  408. END
  409. END MovIm;
  410. (* op # Mov: R.a := R.b op im; op = Mov: R.a := im *)
  411. (* change NZCV according R.a after *)
  412. PROCEDURE Put10 (S: INTEGER; op, a, b, im: LONGINT);
  413. VAR u, v: BOOLEAN;
  414. r: INTEGER;
  415. BEGIN (*emit format-1 instruction, -10000H <= im < 10000H
  416. IF im < 0 THEN INC(op, V) END ;
  417. code[pc] := (((a+40H) * 10H + b) * 10H + op) * 10000H + (im MOD 10000H); INC(pc) *)
  418. ASSERT(S IN {0,1}, 20);
  419. IF ORS.errcnt = 0 THEN
  420. v := 12 IN BITS(op);
  421. IF v THEN DEC(op, V) END;
  422. ASSERT(~v, 100);
  423. u := 13 IN BITS(op);
  424. IF u THEN
  425. ASSERT(im DIV 10000H = 0, 21);
  426. DEC(op, U);
  427. ASSERT(op = Mov, 100);
  428. im := im * 10000H
  429. END;
  430. IF op MOD 10H = Ann THEN
  431. op := (op DIV 10H) * 10H + And;
  432. im := ORDSET(BITS(im) / {0..31}) (* im := ~im *)
  433. END;
  434. (* im: any const *)
  435. ASSERT(op DIV 10H = 0, 22);
  436. ASSERT(a DIV 10H = 0, 23);
  437. ASSERT(b DIV 10H = 0, 24);
  438. IF ~((op = Cmp) & (a = b) & (im = 0)) THEN (* ~Cmp *)
  439. INCL(RM, a)
  440. END;
  441. RemoveRedundantCmp;
  442. op := op MOD 10H;
  443. IF op IN {Lsl,Asr,Ror} THEN
  444. IF im = 0 THEN
  445. Put00(S, Mov, a, 0, b)
  446. ELSIF (im = 32) & (op = Ror) & (S = 1) THEN
  447. IF a = b THEN
  448. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  449. ASSERT(r < MT, 100);
  450. MovIm(0, r, im);
  451. Put00(S, op, a, b, r)
  452. ELSE
  453. MovIm(0, a, im);
  454. Put00(S, op, a, b, a)
  455. END
  456. ELSE
  457. CASE op OF Lsl: (* R.a := R.b <- im *)
  458. ARMv6M.EmitLSLSIm(armcode, pc, ER(a), ER(b), im)
  459. | Asr: (* R.a := R.b -> im *)
  460. ARMv6M.EmitASRSIm(armcode, pc, ER(a), ER(b), im)
  461. | Ror: (* R.a := R.b rot im *)
  462. IF a = b THEN
  463. r := RH;
  464. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  465. ASSERT(r < MT, 101);
  466. MovIm(0, r, im);
  467. Put00(S, op, a, b, r)
  468. ELSE
  469. MovIm(0, a, im);
  470. Put00(S, op, a, b, a)
  471. END
  472. END
  473. END
  474. ELSIF op = Mov THEN
  475. MovIm(S, a, im)
  476. ELSE
  477. CASE op OF And: (* R.a := R.b & im *)
  478. IF a = b THEN
  479. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  480. ASSERT(r < MT, 102);
  481. MovIm(0, r, im);
  482. Put00(S, op, a, b, r)
  483. ELSE
  484. MovIm(0, a, im);
  485. Put00(S, op, a, b, a)
  486. END
  487. | Ior: (* R.a := R.b or im *)
  488. IF a = b THEN
  489. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  490. ASSERT(r < MT, 102);
  491. MovIm(0, r, im);
  492. Put00(S, op, a, b, r)
  493. ELSE
  494. MovIm(0, a, im);
  495. Put00(S, op, a, b, a)
  496. END
  497. | Xor: (* R.a := R.b xor im *)
  498. IF a = b THEN
  499. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  500. ASSERT(r < MT, 102);
  501. MovIm(0, r, im);
  502. Put00(S, op, a, b, r)
  503. ELSE
  504. MovIm(0, a, im);
  505. Put00(S, op, a, b, a)
  506. END
  507. | Add: (* R.a := R.b + im *)
  508. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & ((im DIV 8 = 0) OR (im DIV 100H = 0) & (a = b)) THEN
  509. ARMv6M.EmitADDSIm(armcode, pc, ER(a), ER(b), im)
  510. ELSIF (b = SP) & (im MOD 4 = 0) THEN
  511. ARMv6M.EmitADDSPIm(armcode, pc, ER(a), im DIV 4);
  512. IF S = 1 THEN UpdateFlags(a) END
  513. ELSIF a = b THEN
  514. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  515. ASSERT(r < MT, 108);
  516. MovIm(0, r, im);
  517. Put00(S, op, a, b, r)
  518. ELSE
  519. MovIm(0, a, im);
  520. Put00(S, op, a, b, a)
  521. END
  522. | Sub: (* R.a := R.b - im *)
  523. IF (a = b) & (im = 0) THEN (* Cmp *)
  524. ASSERT(S = 1, 100);
  525. UpdateFlags(a)
  526. ELSIF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & ((im DIV 8 = 0) OR (im DIV 100H = 0) & (a = b)) THEN
  527. ARMv6M.EmitSUBSIm(armcode, pc, ER(a), ER(b), im)
  528. ELSIF (a = SP) & (b = SP) & (im MOD 4 = 0) THEN
  529. ARMv6M.EmitSUBSPIm(armcode, pc, im DIV 4);
  530. IF S = 1 THEN UpdateFlags(a) END
  531. ELSIF (b = LNK) & (a # b) THEN
  532. Put00(0, Mov, a, 0, b);
  533. Put10(S, Sub, a, a, im)
  534. ELSIF a = b THEN
  535. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  536. ASSERT(r < MT, 111);
  537. MovIm(0, r, im);
  538. Put00(S, op, a, b, r)
  539. ELSE
  540. MovIm(0, a, im);
  541. Put00(S, op, a, b, a)
  542. END
  543. | Mul: (* R.a := R.b * im *)
  544. IF a = b THEN
  545. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  546. ASSERT(r < MT, 112);
  547. MovIm(0, r, im);
  548. Put00(S, op, a, b, r)
  549. ELSE
  550. MovIm(0, a, im);
  551. Put00(S, op, a, b, a)
  552. END
  553. | Div: (* R.a := R.b div im *)
  554. IF a = b THEN
  555. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  556. ASSERT(r < MT, 113);
  557. MovIm(0, r, im);
  558. Put00(S, op, a, b, r)
  559. ELSE
  560. MovIm(0, a, im);
  561. Put00(S, op, a, b, a)
  562. END
  563. | Fad,Fsb,Fml,Fdv:
  564. IF a = b THEN
  565. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  566. ASSERT(r < MT, 114);
  567. MovIm(0, r, im); (* TODO: optimize: move to coprocessor register... *)
  568. Put00(S, op, a, b, r)
  569. ELSE
  570. MovIm(0, a, im);
  571. Put00(S, op, a, b, a)
  572. END
  573. END
  574. END
  575. END
  576. END Put10;
  577. PROCEDURE Put1 (op, a, b, im: INTEGER);
  578. BEGIN
  579. Put10(1, op, a, b, im)
  580. END Put1;
  581. PROCEDURE Put1a (op, a, b, im: LONGINT);
  582. BEGIN (*same as Put1, but with range test -10000H <= im < 10000H
  583. IF (im >= -10000H) & (im <= 0FFFFH) THEN Put1(op, a, b, im)
  584. ELSE Put1(Mov+U, RH, 0, im DIV 10000H);
  585. IF im MOD 10000H # 0 THEN Put1(Ior, RH, RH, im MOD 10000H) END ;
  586. Put0(op, a, b, RH)
  587. END *)
  588. ASSERT(op DIV 10H = 0, 20);
  589. Put1(op, a, b, im)
  590. END Put1a;
  591. PROCEDURE Put20 (S: INTEGER; op, a, b, off: LONGINT);
  592. VAR v: BOOLEAN;
  593. r: INTEGER;
  594. BEGIN (*emit load/store instruction
  595. code[pc] := ((op * 10H + a) * 10H + b) * 100000H + (off MOD 100000H); INC(pc) *)
  596. ASSERT(S IN {0,1}, 20);
  597. IF ORS.errcnt = 0 THEN
  598. ASSERT(a DIV 10H = 0, 21);
  599. ASSERT(b DIV 10H = 0, 22);
  600. ASSERT(off >= 0, 23);
  601. ASSERT(off < 100000H, 24);
  602. v := ODD(op); IF v THEN DEC(op) END;
  603. RemoveRedundantCmp;
  604. IF op = Ldr THEN (* R.a := Mem[R.b + off] *)
  605. INCL(RM, a);
  606. IF ~v THEN (* load word *)
  607. ASSERT(off MOD 4 = 0, 100);
  608. IF (b = SP) OR (off DIV 4 DIV 32 = 0) THEN
  609. ARMv6M.EmitLDRIm(armcode, pc, ER(a), ER(b), off DIV 4)
  610. ELSIF a # b THEN
  611. MovIm(0, a, off);
  612. ARMv6M.EmitLDRR(armcode, pc, ER(a), ER(b), ER(a))
  613. ELSE
  614. r := RH;
  615. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  616. ASSERT(r < MT, 101);
  617. MovIm(0, r, off);
  618. ARMv6M.EmitLDRR(armcode, pc, ER(a), ER(b), ER(r))
  619. END
  620. ELSE (* load byte *)
  621. IF b # SP THEN
  622. IF off DIV 32 = 0 THEN
  623. ARMv6M.EmitLDRBIm(armcode, pc, ER(a), ER(b), off)
  624. ELSIF a # b THEN
  625. MovIm(0, a, off);
  626. ARMv6M.EmitLDRBR(armcode, pc, ER(a), ER(b), ER(a))
  627. ELSE
  628. r := RH;
  629. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  630. ASSERT(r < MT, 101);
  631. MovIm(0, r, off);
  632. ARMv6M.EmitLDRBR(armcode, pc, ER(a), ER(b), ER(r))
  633. END
  634. ELSE
  635. r := RH;
  636. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  637. ASSERT(r < MT, 101);
  638. Put00(0, Mov, r, 0, b);
  639. ARMv6M.EmitLDRBIm(armcode, pc, ER(a), ER(r), off)
  640. END
  641. END;
  642. IF S = 1 THEN UpdateFlags(a) END
  643. ELSIF op = Str THEN (* Mem[R.b + off] := R.a *)
  644. IF ~v THEN (* store word *)
  645. ASSERT(off MOD 4 = 0, 102);
  646. IF (b = SP) OR (off DIV 4 DIV 32 = 0) THEN
  647. ARMv6M.EmitSTRIm(armcode, pc, ER(a), ER(b), off DIV 4)
  648. ELSE
  649. r := RH;
  650. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  651. IF (b < MT) & (r <= b) THEN r := b + 1 END;
  652. ASSERT(r < MT, 101);
  653. MovIm(0, r, off);
  654. ARMv6M.EmitSTRR(armcode, pc, ER(a), ER(b), ER(r))
  655. END
  656. ELSE (* store byte *)
  657. IF b # SP THEN
  658. IF off DIV 32 = 0 THEN
  659. ARMv6M.EmitSTRBIm(armcode, pc, ER(a), ER(b), off)
  660. ELSE
  661. r := RH;
  662. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  663. IF (b < MT) & (r <= b) THEN r := b + 1 END;
  664. ASSERT(r < MT, 101);
  665. MovIm(0, r, off);
  666. ARMv6M.EmitSTRBR(armcode, pc, ER(a), ER(b), ER(r))
  667. END
  668. ELSE
  669. r := RH;
  670. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  671. ASSERT(r < MT, 103);
  672. Put00(0, Mov, r, 0, b);
  673. ARMv6M.EmitSTRBIm(armcode, pc, ER(a), ER(r), off)
  674. END
  675. END
  676. ELSE HALT(1) (* invalid operation *)
  677. END
  678. END
  679. END Put20;
  680. PROCEDURE Put2 (op, a, b, off: INTEGER);
  681. BEGIN
  682. Put20(1, op, a, b, off)
  683. END Put2;
  684. PROCEDURE CondRISCToARM (cond: INTEGER): INTEGER;
  685. BEGIN
  686. CASE cond OF MI: RETURN ARMv6M.MI
  687. | EQ: RETURN ARMv6M.EQ
  688. | 2: RETURN ARMv6M.CC
  689. | LT: RETURN ARMv6M.LT
  690. | LE: RETURN ARMv6M.LE
  691. | 7: RETURN ARMv6M.AL
  692. | PL: RETURN ARMv6M.PL
  693. | NE: RETURN ARMv6M.NE
  694. | 10: RETURN ARMv6M.CS
  695. | GE: RETURN ARMv6M.GE
  696. | GT: RETURN ARMv6M.GT
  697. (* | 15: RETURN 15 *)
  698. END
  699. END CondRISCToARM;
  700. (*
  701. PROCEDURE CondARMToRISC (armcond: INTEGER): INTEGER;
  702. BEGIN
  703. CASE armcond OF ARMv6M.EQ: RETURN EQ
  704. | ARMv6M.NE: RETURN NE
  705. | ARMv6M.CS: RETURN 10
  706. | ARMv6M.CC: RETURN 2
  707. | ARMv6M.MI: RETURN MI
  708. | ARMv6M.PL: RETURN PL
  709. | ARMv6M.GE: RETURN GE
  710. | ARMv6M.LT: RETURN LT
  711. | ARMv6M.GT: RETURN GT
  712. | ARMv6M.LE: RETURN LE
  713. | ARMv6M.AL: RETURN 7
  714. (* | 15: RETURN 15 *)
  715. END
  716. END CondARMToRISC;
  717. *)
  718. PROCEDURE ^ negated(cond: LONGINT): LONGINT;
  719. PROCEDURE Put3 (op, cond, off: LONGINT);
  720. VAR S, imm10, J1, J2, imm11, imm6: INTEGER;
  721. pc0, pc1: INTEGER;
  722. BEGIN (*emit branch instruction
  723. code[pc] := ((op+12) * 10H + cond) * 1000000H + (off MOD 1000000H); INC(pc) *)
  724. IF ORS.errcnt = 0 THEN
  725. ASSERT(op DIV 4 = 0, 20);
  726. ASSERT(cond DIV 10H = 0, 21);
  727. CASE op OF BR: (* if cond, then PC := R.c *)
  728. IF off IN {0..15} THEN
  729. ASSERT(cond = 7, 102);
  730. ARMv6M.EmitBX(armcode, pc, ER(off))
  731. ELSIF off = 10H THEN
  732. (* return from interrupt *)
  733. HALT(126)
  734. ELSE HALT(1)
  735. END
  736. | BLR:
  737. IF off MOD 10H = MT THEN (* Trap or New *)
  738. off := off DIV 10H MOD 10000000H;
  739. (* see Kernel.Trap, System.Trap *)
  740. IF off MOD 10H = 0 THEN (* New *)
  741. ASSERT(cond = 7, 100);
  742. (* NOTE: New() arguments in R0, R1 *)
  743. ARMv6M.EmitSVC(armcode, pc, off MOD 10H)
  744. ELSIF cond = 7 THEN
  745. MovIm(0, 1, off DIV 10H); (* R1 := ORS.Pos *)
  746. ARMv6M.EmitSVC(armcode, pc, off MOD 10H)
  747. ELSE
  748. pc0 := pc; Put3(BC, 0, 0);
  749. MovIm(0, 1, off DIV 10H); (* R1 := ORS.Pos *)
  750. ARMv6M.EmitSVC(armcode, pc, off MOD 10H);
  751. pc1 := pc;
  752. pc := pc0;
  753. Put3(BC, negated(cond), pc1 - pc0 - 1);
  754. pc := pc1
  755. END
  756. ELSE (* if cond, then LNK := PC+1; PC := R.c *)
  757. ASSERT(off DIV 10H = 0, 101);
  758. ASSERT(cond = 7, 102);
  759. ASSERT(off # 15, 103);
  760. INCL(RM, LNK);
  761. ARMv6M.EmitBLX(armcode, pc, ER(off))
  762. END
  763. | BC: (* if cond, then PC := PC+1+offset *)
  764. ASSERT(off >= -800000H, 102);
  765. ASSERT(off < 800000H, 103);
  766. DEC(off);
  767. IF cond = 7 THEN
  768. IF (off >= -1024) & (off <= 1023) THEN
  769. ARMv6M.EmitB(armcode, pc, off)
  770. ELSE
  771. ORS.Mark("unconditional branch is too long")
  772. END
  773. ELSIF cond = 15 THEN
  774. ARMv6M.EmitNOP(armcode, pc)
  775. ELSE
  776. IF (off >= -128) & (off <= 127) THEN
  777. ARMv6M.EmitBC(armcode, pc, CondRISCToARM(cond), off)
  778. ELSE
  779. ORS.Mark("conditional branch is too long")
  780. END
  781. END
  782. | BL: (* if cond, then LNK := PC+1; PC := PC+1+offset *)
  783. ASSERT(off >= -800000H, 104);
  784. ASSERT(off < 800000H, 105);
  785. INCL(RM, LNK);
  786. IF cond # 7 THEN
  787. HALT(126)
  788. ELSE
  789. IF off # 0 THEN DEC(off) END;
  790. ARMv6M.EmitBL(armcode, pc, off)
  791. END
  792. END
  793. END
  794. END Put3;
  795. PROCEDURE incR;
  796. BEGIN
  797. IF RH < MT-1 THEN INC(RH) ELSE ORS.Mark("register stack overflow") END
  798. END incR;
  799. PROCEDURE CheckRegs*;
  800. BEGIN
  801. IF RH # 0 THEN ORS.Mark("Reg Stack"); RH := 0 END ;
  802. IF pc >= maxCode - 40 THEN ORS.Mark("program too long") END;
  803. IF frame # 0 THEN ORS.Mark("frame error"); frame := 0 END
  804. END CheckRegs;
  805. PROCEDURE SetCC(VAR x: Item; n: LONGINT);
  806. BEGIN x.mode := Cond; x.a := 0; x.b := 0; x.r := n
  807. END SetCC;
  808. PROCEDURE Trap(cond, num: LONGINT);
  809. BEGIN Put3(BLR, cond, ORS.Pos()*100H + num*10H + MT)
  810. END Trap;
  811. (*handling of forward reference, fixups of branch addresses and constant tables*)
  812. PROCEDURE negated(cond: LONGINT): LONGINT;
  813. BEGIN
  814. IF cond < 8 THEN cond := cond+8 ELSE cond := cond-8 END ;
  815. RETURN cond
  816. END negated;
  817. PROCEDURE invalSB;
  818. BEGIN curSB := 1
  819. END invalSB;
  820. PROCEDURE fix (at, with: LONGINT);
  821. BEGIN
  822. IF ORS.errcnt = 0 THEN
  823. ASSERT(armcode[at] DIV 10000000H MOD 10H = 0EH, 100) (* BC *)
  824. END;
  825. armcode[at] := armcode[at] DIV C24 * C24 + (with MOD C24)
  826. END fix;
  827. PROCEDURE FixOne*(at: LONGINT);
  828. BEGIN fix(at, pc-at-1)
  829. END FixOne;
  830. PROCEDURE FixLink*(L: LONGINT);
  831. VAR L1: LONGINT;
  832. BEGIN invalSB;
  833. WHILE L # 0 DO L1 := armcode[L] MOD 40000H; fix(L, pc-L-1); L := L1 END
  834. END FixLink;
  835. PROCEDURE FixLinkWith (L0, dst: LONGINT);
  836. VAR L1: LONGINT;
  837. BEGIN
  838. WHILE L0 # 0 DO
  839. L1 := armcode[L0] MOD C24;
  840. armcode[L0] := armcode[L0] DIV C24 * C24 + ((dst - L0 - 1) MOD C24); L0 := L1
  841. END
  842. END FixLinkWith;
  843. PROCEDURE merged (L0, L1: LONGINT): LONGINT;
  844. VAR L2, L3: LONGINT;
  845. BEGIN
  846. IF L0 # 0 THEN L3 := L0;
  847. REPEAT L2 := L3; L3 := armcode[L2] MOD 40000H UNTIL L3 = 0;
  848. armcode[L2] := armcode[L2] + L1; L1 := L0
  849. END;
  850. RETURN L1
  851. END merged;
  852. (* loading of operands and addresses into registers *)
  853. (* for fixups only *)
  854. PROCEDURE Put1orig (op, a, b, im: LONGINT);
  855. BEGIN (*emit format-1 instruction, -10000H <= im < 10000H*)
  856. IF im < 0 THEN INC(op, V) END;
  857. armcode[pc] := (((a+40H) * 10H + b) * 10H + op) * 10000H + (im MOD 10000H); INC(pc)
  858. END Put1orig;
  859. PROCEDURE Put2orig (op, a, b, off: LONGINT);
  860. BEGIN (*emit load/store instruction*)
  861. armcode[pc] := ((op * 10H + a) * 10H + b) * 100000H + (off MOD 100000H); INC(pc)
  862. END Put2orig;
  863. PROCEDURE Put3orig (op, cond, off: LONGINT);
  864. BEGIN (*emit branch instruction*)
  865. armcode[pc] := ((op+12) * 10H + cond) * 1000000H + (off MOD 1000000H); INC(pc)
  866. END Put3orig;
  867. PROCEDURE GetSB (base: LONGINT);
  868. BEGIN
  869. IF (version # 0) & ((base # curSB) OR (base # 0)) THEN
  870. (* will be fixed up by linker/loader *)
  871. INCL(RM, SB);
  872. Put2orig(Ldr, ER(SB), -base, pc-fixorgD); fixorgD := pc-1; curSB := base
  873. END
  874. END GetSB;
  875. PROCEDURE NilCheck;
  876. BEGIN IF check THEN Trap(EQ, 4) END
  877. END NilCheck;
  878. PROCEDURE load0 (S: INTEGER; VAR x: Item);
  879. VAR op, pc0, pc1: LONGINT;
  880. BEGIN
  881. ASSERT(S IN {0,1}, 20);
  882. IF x.type.size = 1 THEN op := Ldr+1 ELSE op := Ldr END ;
  883. IF x.mode # Reg THEN
  884. IF x.mode = ORB.Const THEN
  885. IF x.type.form = ORB.Proc THEN
  886. IF x.r > 0 THEN ORS.Mark("not allowed")
  887. ELSIF x.r = 0 THEN Put3(BL, 7, 0);
  888. ASSERT(x.a MOD 2 = 0, 100);
  889. Put10(S, Sub, RH, LNK, (pc*4 - x.a) DIV 2)
  890. ELSE GetSB(x.r);
  891. INCL(RM, RH);
  892. Put1orig(Add, ER(RH), ER(SB), x.a + 100H); (*mark as progbase-relative*)
  893. armcode[pc] := 00FFFFFFH; INC(pc)
  894. END
  895. (*
  896. ELSIF (x.a <= 0FFFFH) & (x.a >= -10000H) THEN Put1(Mov, RH, 0, x.a)
  897. ELSE Put1(Mov+U, RH, 0, x.a DIV 10000H MOD 10000H);
  898. IF x.a MOD 10000H # 0 THEN Put1(Ior, RH, RH, x.a MOD 10000H) END
  899. *)
  900. ELSE Put10(S, Mov, RH, 0, x.a)
  901. END;
  902. x.r := RH; incR
  903. ELSIF x.mode = ORB.Var THEN
  904. IF x.r > 0 THEN (*local*) Put20(S, op, RH, SP, x.a + frame)
  905. ELSE GetSB(x.r);
  906. IF x.r # 0 THEN
  907. INCL(RM, RH);
  908. Put2orig(op, ER(RH), ER(SB), x.a);
  909. IF S = 1 THEN UpdateFlags(RH) END
  910. ELSE Put20(S, op, RH, SB, x.a)
  911. END
  912. END;
  913. x.r := RH; incR
  914. ELSIF x.mode = ORB.Par THEN Put20(0, Ldr, RH, SP, x.a + frame); Put20(S, op, RH, RH, x.b); x.r := RH; incR
  915. ELSIF x.mode = RegI THEN Put20(S, op, x.r, x.r, x.a)
  916. ELSIF x.mode = Cond THEN
  917. pc0 := pc; Put3orig(BC, negated(x.r), 0);
  918. FixLink(x.b); Put10(S, Mov, RH, 0, 1);
  919. pc1 := pc; Put3orig(BC, 7, 0);
  920. fix(pc0, pc - pc0 - 1);
  921. FixLink(x.a); Put10(S, Mov, RH, 0, 0);
  922. fix(pc1, pc - pc1 - 1);
  923. x.r := RH; incR
  924. END;
  925. x.mode := Reg
  926. END
  927. END load0;
  928. PROCEDURE load (VAR x: Item);
  929. BEGIN
  930. load0(1, x)
  931. END load;
  932. PROCEDURE loadAdr0 (S: INTEGER; VAR x: Item);
  933. BEGIN
  934. IF x.mode = ORB.Var THEN
  935. IF x.r > 0 THEN (*local*) Put10(S, Add, RH, SP, x.a + frame)
  936. ELSE GetSB(x.r);
  937. IF x.r # 0 THEN
  938. INCL(RM, RH);
  939. Put1orig(Add, ER(RH), ER(SB), x.a);
  940. armcode[pc] := 00FFFFFFH; INC(pc)
  941. ELSE Put10(S, Add, RH, SB, x.a)
  942. END
  943. END;
  944. x.r := RH; incR
  945. ELSIF x.mode = ORB.Par THEN
  946. IF x.b # 0 THEN Put20(0, Ldr, RH, SP, x.a + frame);
  947. Put10(S, Add, RH, RH, x.b)
  948. ELSE Put20(S, Ldr, RH, SP, x.a + frame)
  949. END;
  950. x.r := RH; incR
  951. ELSIF x.mode = RegI THEN
  952. IF x.a # 0 THEN Put10(S, Add, x.r, x.r, x.a) END
  953. ELSE ORS.Mark("address error")
  954. END;
  955. x.mode := Reg
  956. END loadAdr0;
  957. PROCEDURE loadAdr (VAR x: Item);
  958. BEGIN
  959. loadAdr0(1, x)
  960. END loadAdr;
  961. PROCEDURE IsFlagsUp0 (r: INTEGER): BOOLEAN;
  962. VAR res: BOOLEAN;
  963. BEGIN
  964. res := ~ARMv6M.IsLThumb32(armcode[pc - 2]) & IsCMPIm(armcode[pc - 1]);
  965. ASSERT(~res OR (armcode[pc - 1] DIV 100H MOD 8 = ER(r)), 100);
  966. RETURN res
  967. END IsFlagsUp0;
  968. PROCEDURE loadCond (VAR x: Item);
  969. BEGIN
  970. IF x.type.form = ORB.Bool THEN
  971. IF x.mode = ORB.Const THEN x.r := 15 - x.a*8
  972. ELSE load(x);
  973. IF ~IsFlagsUp0(x.r) THEN
  974. Put1(Cmp, x.r, x.r, 0)
  975. (* ELSE HALT(1) *)
  976. END;
  977. x.r := NE; DEC(RH)
  978. END ;
  979. x.mode := Cond; x.a := 0; x.b := 0
  980. ELSE ORS.Mark("not Boolean?")
  981. END
  982. END loadCond;
  983. PROCEDURE loadTypTagAdr0 (S: INTEGER; T: ORB.Type);
  984. VAR x: Item;
  985. BEGIN x.mode := ORB.Var; x.a := T.len; x.r := -T.mno; loadAdr0(S, x)
  986. END loadTypTagAdr0;
  987. PROCEDURE loadTypTagAdr (T: ORB.Type);
  988. BEGIN
  989. loadTypTagAdr0(1, T)
  990. END loadTypTagAdr;
  991. PROCEDURE loadStringAdr0 (S: INTEGER; VAR x: Item);
  992. BEGIN GetSB(0); Put10(S, Add, RH, SB, varsize+x.a); x.mode := Reg; x.r := RH; incR
  993. END loadStringAdr0;
  994. PROCEDURE loadStringAdr (VAR x: Item);
  995. BEGIN
  996. loadStringAdr0(1, x)
  997. END loadStringAdr;
  998. (* Items: Conversion from constants or from Objects on the Heap to Items on the Stack*)
  999. PROCEDURE MakeConstItem*(VAR x: Item; typ: ORB.Type; val: LONGINT);
  1000. BEGIN x.mode := ORB.Const; x.type := typ; x.a := val
  1001. END MakeConstItem;
  1002. PROCEDURE MakeRealItem*(VAR x: Item; val: REAL);
  1003. BEGIN x.mode := ORB.Const; x.type := ORB.realType; x.a := SYSTEM.VAL(LONGINT, val)
  1004. END MakeRealItem;
  1005. PROCEDURE MakeStringItem*(VAR x: Item; len: LONGINT); (*copies string from ORS-buffer to ORG-string array*)
  1006. VAR i: LONGINT;
  1007. BEGIN x.mode := ORB.Const; x.type := ORB.strType; x.a := strx; x.b := len; i := 0;
  1008. IF strx + len + 4 < maxStrx THEN
  1009. WHILE len > 0 DO str[strx] := ORS.str[i]; INC(strx); INC(i); DEC(len) END ;
  1010. WHILE strx MOD 4 # 0 DO str[strx] := 0X; INC(strx) END
  1011. ELSE ORS.Mark("too many strings")
  1012. END
  1013. END MakeStringItem;
  1014. PROCEDURE MakeItem*(VAR x: Item; y: ORB.Object; curlev: LONGINT);
  1015. BEGIN x.mode := y.class; x.type := y.type; x.a := y.val; x.rdo := y.rdo;
  1016. IF y.class = ORB.Par THEN x.b := 0
  1017. (* ELSIF y.class = ORB.Typ THEN x.a := y.type.len; x.r := -y.lev *)
  1018. ELSIF (y.class = ORB.Const) & (y.type.form = ORB.String) THEN x.b := y.lev (*len*)
  1019. ELSE x.r := y.lev
  1020. END;
  1021. IF (y.lev > 0) & (y.lev # curlev) & (y.class # ORB.Const) THEN ORS.Mark("not accessible") END
  1022. END MakeItem;
  1023. (* Code generation for Selectors, Variables, Constants *)
  1024. PROCEDURE Field*(VAR x: Item; y: ORB.Object); (* x := x.y *)
  1025. BEGIN;
  1026. IF x.mode = ORB.Var THEN
  1027. IF x.r >= 0 THEN x.a := x.a + y.val
  1028. ELSE loadAdr(x); x.mode := RegI; x.a := y.val
  1029. END
  1030. ELSIF x.mode = RegI THEN x.a := x.a + y.val
  1031. ELSIF x.mode = ORB.Par THEN x.b := x.b + y.val
  1032. END
  1033. END Field;
  1034. PROCEDURE Index*(VAR x, y: Item); (* x := x[y] *)
  1035. VAR s, lim: LONGINT;
  1036. BEGIN s := x.type.base.size; lim := x.type.len;
  1037. IF (y.mode = ORB.Const) & (lim >= 0) THEN
  1038. IF (y.a < 0) OR (y.a >= lim) THEN ORS.Mark("bad index") END ;
  1039. IF x.mode IN {ORB.Var, RegI} THEN
  1040. (*
  1041. x.a := y.a * s + x.a
  1042. *)
  1043. IF x.mode = ORB.Var THEN
  1044. IF x.r >= 0 THEN x.a := y.a * s + x.a
  1045. ELSE loadAdr(x); x.mode := RegI; x.a := y.a * s
  1046. END
  1047. ELSE (* x.mode = RegI *) x.a := y.a * s + x.a
  1048. END
  1049. ELSIF x.mode = ORB.Par THEN x.b := y.a * s + x.b
  1050. END
  1051. ELSE load0(0, y);
  1052. IF check THEN (*check array bounds*)
  1053. IF lim >= 0 THEN Put1a(Cmp, RH, y.r, lim)
  1054. ELSE (*open array*)
  1055. IF x.mode IN {ORB.Var, ORB.Par} THEN Put20(0, Ldr, RH, SP, x.a+4+frame); Put0(Cmp, RH, y.r, RH)
  1056. ELSE ORS.Mark("error in Index")
  1057. END
  1058. END;
  1059. Trap(10, 1) (*BCC*)
  1060. END ;
  1061. IF s = 4 THEN Put10(0, Lsl, y.r, y.r, 2) ELSIF s > 1 THEN Put10(0, Mul, y.r, y.r, s) END ;
  1062. IF x.mode = ORB.Var THEN
  1063. IF x.r > 0 THEN Put0(Add, y.r, SP, y.r); INC(x.a, frame)
  1064. ELSE GetSB(x.r);
  1065. IF x.r = 0 THEN Put0(Add, y.r, SB, y.r)
  1066. ELSE
  1067. INCL(RM, RH); Put1orig(Add, ER(RH), ER(SB), x.a);
  1068. armcode[pc] := 00FFFFFFH; INC(pc);
  1069. Put0(Add, y.r, RH, y.r); x.a := 0
  1070. END
  1071. END;
  1072. x.r := y.r; x.mode := RegI
  1073. ELSIF x.mode = ORB.Par THEN
  1074. Put20(0, Ldr, RH, SP, x.a + frame);
  1075. Put0(Add, y.r, RH, y.r); x.mode := RegI; x.r := y.r; x.a := x.b
  1076. ELSIF x.mode = RegI THEN Put0(Add, x.r, x.r, y.r); DEC(RH)
  1077. ELSE HALT(100)
  1078. (* if reached, then restore back:
  1079. load0(0,y) -> load(y)
  1080. IF s = 4...: Put10(0 -> Put1( ; Put10(0->Put1a
  1081. *)
  1082. END
  1083. END
  1084. END Index;
  1085. PROCEDURE DeRef*(VAR x: Item);
  1086. BEGIN
  1087. IF x.mode = ORB.Var THEN
  1088. IF x.r > 0 THEN (*local*) Put2(Ldr, RH, SP, x.a + frame) ELSE GetSB(x.r);
  1089. IF x.r # 0 THEN
  1090. INCL(RM, RH);
  1091. Put2orig(Ldr, ER(RH), ER(SB), x.a); UpdateFlags(RH)
  1092. ELSE Put2(Ldr, RH, SB, x.a)
  1093. END
  1094. END;
  1095. NilCheck; x.r := RH; incR
  1096. ELSIF x.mode = ORB.Par THEN
  1097. Put20(0, Ldr, RH, SP, x.a + frame); Put2(Ldr, RH, RH, x.b); NilCheck; x.r := RH; incR
  1098. ELSIF x.mode = RegI THEN Put2(Ldr, x.r, x.r, x.a); NilCheck
  1099. ELSIF x.mode # Reg THEN ORS.Mark("bad mode in DeRef")
  1100. END ;
  1101. x.mode := RegI; x.a := 0; x.b := 0
  1102. END DeRef;
  1103. PROCEDURE Q(T: ORB.Type; VAR dcw: LONGINT);
  1104. BEGIN (*one entry of type descriptor extension table*)
  1105. IF T.base # NIL THEN
  1106. Q(T.base, dcw); data[dcw] := (T.mno*1000H + T.len) * 1000H + dcw - fixorgT;
  1107. fixorgT := dcw; INC(dcw)
  1108. END
  1109. END Q;
  1110. PROCEDURE FindPtrFlds(typ: ORB.Type; off: LONGINT; VAR dcw: LONGINT);
  1111. VAR fld: ORB.Object; i, s: LONGINT;
  1112. BEGIN
  1113. IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN data[dcw] := off; INC(dcw)
  1114. ELSIF typ.form = ORB.Record THEN
  1115. fld := typ.dsc;
  1116. WHILE fld # NIL DO FindPtrFlds(fld.type, fld.val + off, dcw); fld := fld.next END
  1117. ELSIF typ.form = ORB.Array THEN
  1118. s := typ.base.size;
  1119. FOR i := 0 TO typ.len-1 DO FindPtrFlds(typ.base, i*s + off, dcw) END
  1120. END
  1121. END FindPtrFlds;
  1122. PROCEDURE BuildTD*(T: ORB.Type; VAR dc: LONGINT);
  1123. VAR dcw, k, s: LONGINT; (*dcw = word address*)
  1124. BEGIN dcw := dc DIV 4; s := T.size; (*convert size for heap allocation*)
  1125. IF s <= 24 THEN s := 32 ELSIF s <= 56 THEN s := 64 ELSIF s <= 120 THEN s := 128
  1126. ELSE s := (s+263) DIV 256 * 256
  1127. END ;
  1128. T.len := dc; data[dcw] := s; INC(dcw); (*len used as address*)
  1129. k := T.nofpar; (*extension level!*)
  1130. IF k > 3 THEN ORS.Mark("ext level too large")
  1131. ELSE Q(T, dcw);
  1132. WHILE k < 3 DO data[dcw] := -1; INC(dcw); INC(k) END
  1133. END ;
  1134. FindPtrFlds(T, 0, dcw); data[dcw] := -1; INC(dcw); tdx := dcw; dc := dcw*4;
  1135. IF tdx >= maxTD THEN ORS.Mark("too many record types"); tdx := 0 END
  1136. END BuildTD;
  1137. PROCEDURE TypeTest* (VAR x: Item; T: ORB.Type; varpar, isguard: BOOLEAN);
  1138. VAR pc0: LONGINT;
  1139. BEGIN
  1140. IF T = NIL THEN
  1141. IF x.mode >= Reg THEN DEC(RH) END;
  1142. SetCC(x, 7)
  1143. ELSE (*fetch tag into RH*)
  1144. IF varpar THEN Put20(0, Ldr, RH, SP, x.a+4+frame)
  1145. ELSE load(x);
  1146. pc0 := pc; Put3orig(BC, EQ, 0); (*NIL belongs to every pointer type*)
  1147. Put20(0, Ldr, RH, x.r, -8)
  1148. END ;
  1149. Put20(0, Ldr, RH, RH, T.nofpar*4); incR;
  1150. loadTypTagAdr0(0, T); (*tag of T*)
  1151. Put0(Cmp, RH-1, RH-1, RH-2); DEC(RH, 2);
  1152. IF ~varpar THEN fix(pc0, pc - pc0 - 1) END;
  1153. IF isguard THEN
  1154. IF check THEN Trap(NE, 2) END
  1155. ELSE SetCC(x, EQ);
  1156. IF ~varpar THEN DEC(RH) END
  1157. END
  1158. END
  1159. END TypeTest;
  1160. (* Code generation for Boolean operators *)
  1161. PROCEDURE Not*(VAR x: Item); (* x := ~x *)
  1162. VAR t: LONGINT;
  1163. BEGIN
  1164. IF x.mode # Cond THEN loadCond(x) END ;
  1165. x.r := negated(x.r); t := x.a; x.a := x.b; x.b := t
  1166. END Not;
  1167. PROCEDURE And1*(VAR x: Item); (* x := x & *)
  1168. BEGIN
  1169. IF x.mode # Cond THEN loadCond(x) END ;
  1170. Put3orig(BC, negated(x.r), x.a); x.a := pc-1; FixLink(x.b); x.b := 0
  1171. END And1;
  1172. PROCEDURE And2*(VAR x, y: Item);
  1173. BEGIN
  1174. IF y.mode # Cond THEN loadCond(y) END ;
  1175. x.a := merged(y.a, x.a); x.b := y.b; x.r := y.r
  1176. END And2;
  1177. PROCEDURE Or1*(VAR x: Item); (* x := x OR *)
  1178. BEGIN
  1179. IF x.mode # Cond THEN loadCond(x) END ;
  1180. Put3orig(BC, x.r, x.b); x.b := pc-1; FixLink(x.a); x.a := 0
  1181. END Or1;
  1182. PROCEDURE Or2*(VAR x, y: Item);
  1183. BEGIN
  1184. IF y.mode # Cond THEN loadCond(y) END ;
  1185. x.a := y.a; x.b := merged(y.b, x.b); x.r := y.r
  1186. END Or2;
  1187. (* Code generation for arithmetic operators *)
  1188. PROCEDURE Neg*(VAR x: Item); (* x := -x *)
  1189. BEGIN
  1190. IF x.type.form = ORB.Int THEN
  1191. IF x.mode = ORB.Const THEN x.a := -x.a
  1192. ELSE load0(0, x);
  1193. (* Put10(0, Mov, RH, 0, 0); Put0(Sub, x.r, RH, x.r) *)
  1194. RSBS0(x.r)
  1195. END
  1196. ELSIF x.type.form = ORB.Real THEN
  1197. IF x.mode = ORB.Const THEN x.a := x.a + 7FFFFFFFH + 1
  1198. ELSE load0(0, x); Put10(0, Mov, RH, 0, 0); Put0(Fsb, x.r, RH, x.r)
  1199. END
  1200. ELSE (*form = Set*)
  1201. IF x.mode = ORB.Const THEN x.a := -x.a-1
  1202. ELSE load0(0, x); Put1(Xor, x.r, x.r, -1)
  1203. END
  1204. END
  1205. END Neg;
  1206. PROCEDURE AddOp*(op: LONGINT; VAR x, y: Item); (* x := x +- y *)
  1207. BEGIN
  1208. IF op = ORS.plus THEN
  1209. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN x.a := x.a + y.a
  1210. ELSIF y.mode = ORB.Const THEN
  1211. IF y.a # 0 THEN load0(0, x); Put1a(Add, x.r, x.r, y.a)
  1212. ELSE load(x)
  1213. END
  1214. ELSE load0(0, x); load0(0, y); Put0(Add, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  1215. END
  1216. ELSE (*op = ORS.minus*)
  1217. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN x.a := x.a - y.a
  1218. ELSIF y.mode = ORB.Const THEN
  1219. IF y.a # 0 THEN load0(0, x); Put1a(Sub, x.r, x.r, y.a)
  1220. ELSE load(x)
  1221. END
  1222. ELSE load0(0, x); load0(0, y); Put0(Sub, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  1223. END
  1224. END
  1225. END AddOp;
  1226. PROCEDURE log2(m: LONGINT; VAR e: LONGINT): LONGINT;
  1227. BEGIN e := 0;
  1228. WHILE ~ODD(m) DO m := m DIV 2; INC(e) END ;
  1229. RETURN m
  1230. END log2;
  1231. PROCEDURE MulOp*(VAR x, y: Item); (* x := x * y *)
  1232. VAR e: LONGINT;
  1233. BEGIN
  1234. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN x.a := x.a * y.a
  1235. ELSIF (y.mode = ORB.Const) & (y.a >= 2) & (log2(y.a, e) = 1) THEN load0(0, x); Put1(Lsl, x.r, x.r, e)
  1236. ELSIF y.mode = ORB.Const THEN load0(0, x); Put1a(Mul, x.r, x.r, y.a)
  1237. ELSIF (x.mode = ORB.Const) & (x.a >= 2) & (log2(x.a, e) = 1) THEN load0(0, y); Put1(Lsl, y.r, y.r, e); x.mode := Reg; x.r := y.r
  1238. ELSIF x.mode = ORB.Const THEN load0(0, y); Put1a(Mul, y.r, y.r, x.a); x.mode := Reg; x.r := y.r
  1239. ELSE load0(0, x); load0(0, y); Put0(Mul, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  1240. END
  1241. END MulOp;
  1242. (*
  1243. http://www.inf.ethz.ch/personal/wirth/Oberon/Oberon.ARM.Compiler.pdf
  1244. p. 14
  1245. *)
  1246. PROCEDURE Div0 (Rx, Ry, Rq, Rr: INTEGER);
  1247. VAR Ri, Rtmp, pc0, pc1: INTEGER;
  1248. BEGIN
  1249. (* q := ABS(x) *)
  1250. Put00(1, Mov, Rq, 0, Rx);
  1251. pc0 := pc; Put3orig(BC, GE, 0);
  1252. RSBS0(Rq);
  1253. fix(pc0, pc - pc0 - 1);
  1254. Put10(0, Mov, Rr, 0, 0);
  1255. incR; Ri := RH-1; Rtmp := RH;
  1256. Put10(0, Mov, Ri, 0, 32);
  1257. (* REPEAT *) pc0 := pc;
  1258. (* rq := rq * 2 *)
  1259. Put00(1, Add, Rq, Rq, Rq);
  1260. Put00(0, Add+U, Rr, Rr, Rr);
  1261. (* IF r >= y *)
  1262. Put00(1, Sub, Rtmp, Rr, Ry);
  1263. pc1 := pc; Put3orig(BC, LT, 0);
  1264. (* THEN *)
  1265. Put00(0, Mov, Rr, 0, Rtmp);
  1266. Put10(0, Add, Rq, Rq, 1);
  1267. (* END *) fix(pc1, pc - pc1 - 1);
  1268. (* DEC(i) *)
  1269. Put10(1, Sub, Ri, Ri, 1);
  1270. (* UNTIL i = 0 *)
  1271. Put3orig(BC, NE, pc0 - pc - 1);
  1272. DEC(RH);
  1273. (* IF x < 0 *)
  1274. Put1(Cmp, Rx, Rx, 0);
  1275. pc0 := pc; Put3orig(BC, GE, 0);
  1276. (* THEN *)
  1277. (* q := -q *)
  1278. RSBS0(Rq);
  1279. (* IF r # 0 *)
  1280. Put1(Cmp, Rr, Rr, 0);
  1281. pc1 := pc; Put3orig(BC, EQ, 0);
  1282. (* THEN *)
  1283. Put10(0, Sub, Rq, Rq, 1);
  1284. Put00(0, Sub, Rr, Ry, Rr);
  1285. (* END *) fix(pc1, pc - pc1 - 1);
  1286. (* END *) fix(pc0, pc - pc0 - 1);
  1287. END Div0;
  1288. PROCEDURE DivOp*(op: LONGINT; VAR x, y: Item); (* x := x op y *)
  1289. VAR e: LONGINT;
  1290. BEGIN
  1291. IF op = ORS.div THEN
  1292. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
  1293. IF y.a > 0 THEN x.a := x.a DIV y.a ELSE ORS.Mark("bad divisor") END
  1294. ELSIF (y.mode = ORB.Const) & (y.a >= 2) & (log2(y.a, e) = 1) THEN load0(0, x); Put1(Asr, x.r, x.r, e)
  1295. ELSIF y.mode = ORB.Const THEN
  1296. IF y.a > 0 THEN load0(0, x);
  1297. (*
  1298. Put1a(Div, x.r, x.r, y.a)
  1299. *)
  1300. incR; incR; incR;
  1301. Put10(0, Mov, RH-3, 0, y.a); Div0(x.r, RH-3, RH-2, RH-1);
  1302. Put0(Mov, x.r, 0, RH-2);
  1303. DEC(RH, 3)
  1304. ELSE ORS.Mark("bad divisor") END
  1305. ELSE load(y);
  1306. IF check THEN Trap(LE, 6) END ;
  1307. load0(0, x);
  1308. (*
  1309. Put0(Div, RH-2, x.r, y.r);
  1310. *)
  1311. incR; incR; Div0(x.r, y.r, RH-2, RH-1); DEC(RH, 2);
  1312. Put0(Mov, RH-2, 0, RH-2+2);
  1313. DEC(RH); x.r := RH-1
  1314. END
  1315. ELSE (*op = ORS.mod*)
  1316. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
  1317. IF y.a > 0 THEN x.a := x.a MOD y.a ELSE ORS.Mark("bad modulus") END
  1318. ELSIF (y.mode = ORB.Const) & (y.a >= 2) & (log2(y.a, e) = 1) THEN load0(0, x);
  1319. IF e <= 16 THEN Put1(And, x.r, x.r, y.a-1) ELSE Put10(0, Lsl, x.r, x.r, 32-e); Put1(Ror, x.r, x.r, 32-e) END
  1320. ELSIF y.mode = ORB.Const THEN
  1321. IF y.a > 0 THEN
  1322. load0(0, x);
  1323. (*
  1324. Put1a(Div, x.r, x.r, y.a);
  1325. Put0(Mov+U, x.r, 0, 0)
  1326. *)
  1327. incR; incR; incR;
  1328. Put10(0, Mov, RH-3, 0, y.a); Div0(x.r, RH-3, RH-2, RH-1);
  1329. Put0(Mov, x.r, 0, RH-1);
  1330. DEC(RH, 3)
  1331. ELSE ORS.Mark("bad modulus")
  1332. END
  1333. ELSE load(y);
  1334. IF check THEN Trap(LE, 6) END;
  1335. load0(0, x);
  1336. (*
  1337. Put0(Div, RH-2, x.r, y.r);
  1338. Put0(Mov+U, RH-2, 0, 0);
  1339. *)
  1340. incR; incR; Div0(x.r, y.r, RH-2, RH-1); DEC(RH, 2);
  1341. Put0(Mov, RH-2, 0, RH-1+2);
  1342. DEC(RH); x.r := RH-1
  1343. END
  1344. END
  1345. END DivOp;
  1346. (* Code generation for REAL operators *)
  1347. PROCEDURE RealOp*(op: INTEGER; VAR x, y: Item); (* x := x op y *)
  1348. BEGIN load0(0, x); load0(0, y);
  1349. IF op = ORS.plus THEN Put0(Fad, RH-2, x.r, y.r)
  1350. ELSIF op = ORS.minus THEN Put0(Fsb, RH-2, x.r, y.r)
  1351. ELSIF op = ORS.times THEN Put0(Fml, RH-2, x.r, y.r)
  1352. ELSIF op = ORS.rdiv THEN Put0(Fdv, RH-2, x.r, y.r)
  1353. END;
  1354. DEC(RH); x.r := RH-1
  1355. END RealOp;
  1356. (* Code generation for set operators *)
  1357. PROCEDURE Singleton*(VAR x: Item); (* x := {x} *)
  1358. BEGIN
  1359. IF x.mode = ORB.Const THEN x.a := LSL(1, x.a)
  1360. ELSE load0(0, x); Put10(0, Mov, RH, 0, 1); Put0(Lsl, x.r, RH, x.r)
  1361. END
  1362. END Singleton;
  1363. PROCEDURE Set*(VAR x, y: Item); (* x := {x .. y} *)
  1364. BEGIN
  1365. IF (x.mode = ORB.Const) & ( y.mode = ORB.Const) THEN
  1366. IF x.a <= y.a THEN x.a := LSL(2, y.a) - LSL(1, x.a) ELSE x.a := 0 END
  1367. ELSE
  1368. IF (x.mode = ORB.Const) & (x.a <= 16) THEN x.a := LSL(-1, x.a)
  1369. ELSE load0(0, x); Put10(0, Mov, RH, 0, -1); Put0(Lsl, x.r, RH, x.r)
  1370. END ;
  1371. IF (y.mode = ORB.Const) & (y.a < 16) THEN Put1(Mov, RH, 0, LSL(-2, y.a)); y.mode := Reg; y.r := RH; incR
  1372. ELSE load0(0, y); Put10(0, Mov, RH, 0, -2); Put0(Lsl, y.r, RH, y.r)
  1373. END ;
  1374. IF x.mode = ORB.Const THEN
  1375. IF x.a # 0 THEN Put10(0, Xor, y.r, y.r, -1); Put1a(And, RH-1, y.r, x.a) END ;
  1376. x.mode := Reg; x.r := RH-1
  1377. ELSE DEC(RH); Put0(Ann, RH-1, x.r, y.r);
  1378. ASSERT(x.mode = Reg); x.r := RH-1
  1379. END
  1380. END
  1381. END Set;
  1382. PROCEDURE In*(VAR x, y: Item); (* x := x IN y *)
  1383. BEGIN load0(0, y);
  1384. IF x.mode = ORB.Const THEN Put1(Ror, y.r, y.r, (x.a + 1) MOD 20H); DEC(RH)
  1385. ELSE load0(0, x); Put10(0, Add, x.r, x.r, 1); Put0(Ror, y.r, y.r, x.r); DEC(RH, 2)
  1386. END ;
  1387. SetCC(x, MI)
  1388. END In;
  1389. PROCEDURE SetOp*(op: LONGINT; VAR x, y: Item); (* x := x op y *)
  1390. VAR xset, yset: SET; (*x.type.form = Set*)
  1391. BEGIN
  1392. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
  1393. xset := SYSTEM.VAL(SET, x.a); yset := SYSTEM.VAL(SET, y.a);
  1394. IF op = ORS.plus THEN xset := xset + yset
  1395. ELSIF op = ORS.minus THEN xset := xset - yset
  1396. ELSIF op = ORS.times THEN xset := xset * yset
  1397. ELSIF op = ORS.rdiv THEN xset := xset / yset
  1398. END ;
  1399. x.a := SYSTEM.VAL(LONGINT, xset)
  1400. ELSIF y.mode = ORB.Const THEN
  1401. load0(0, x);
  1402. IF op = ORS.plus THEN Put1a(Ior, x.r, x.r, y.a)
  1403. ELSIF op = ORS.minus THEN Put1a(Ann, x.r, x.r, y.a)
  1404. ELSIF op = ORS.times THEN Put1a(And, x.r, x.r, y.a)
  1405. ELSIF op = ORS.rdiv THEN Put1a(Xor, x.r, x.r, y.a)
  1406. END ;
  1407. ELSE load0(0, x); load0(0, y);
  1408. IF op = ORS.plus THEN Put0(Ior, RH-2, x.r, y.r)
  1409. ELSIF op = ORS.minus THEN Put0(Ann, RH-2, x.r, y.r)
  1410. ELSIF op = ORS.times THEN Put0(And, RH-2, x.r, y.r)
  1411. ELSIF op = ORS.rdiv THEN Put0(Xor, RH-2, x.r, y.r)
  1412. END ;
  1413. DEC(RH); x.r := RH-1
  1414. END
  1415. END SetOp;
  1416. (* Code generation for relations *)
  1417. (*
  1418. PROCEDURE IsCmp00 (r: INTEGER): BOOLEAN;
  1419. BEGIN
  1420. RETURN ~ARMv6M.IsLThumb32(armcode[pc - 2]) & IsCMPIm(armcode[pc - 1]) & (armcode[pc - 1] DIV 100H MOD 8 = ER(r))
  1421. END IsCmp00;
  1422. PROCEDURE IntRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  1423. BEGIN
  1424. IF (y.mode = ORB.Const) & (y.type.form # ORB.Proc) THEN
  1425. load(x);
  1426. IF (y.a # 0) (* OR ~(op IN {ORS.eql, ORS.neq}) *) OR ~IsCmp00(x.r) THEN
  1427. IF IsCmp00(x.r) THEN DEC(pc) END;
  1428. Put1a(Cmp, x.r, x.r, y.a)
  1429. (* ELSE HALT(1) *)
  1430. END;
  1431. DEC(RH)
  1432. ELSE
  1433. IF (x.mode = Cond) OR (y.mode = Cond) THEN ORS.Mark("not implemented") END;
  1434. load0(0, x); load0(0, y); Put0(Cmp, x.r, x.r, y.r); DEC(RH, 2)
  1435. END;
  1436. SetCC(x, relmap[op - ORS.eql])
  1437. END IntRelation;
  1438. *)
  1439. PROCEDURE IntRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  1440. BEGIN
  1441. IF (y.mode = ORB.Const) & (y.type.form # ORB.Proc) THEN
  1442. load(x);
  1443. Put1a(Cmp, x.r, x.r, y.a);
  1444. DEC(RH)
  1445. ELSE
  1446. IF (x.mode = Cond) OR (y.mode = Cond) THEN ORS.Mark("not implemented") END;
  1447. load0(0, x); load0(0, y); Put0(Cmp, x.r, x.r, y.r); DEC(RH, 2)
  1448. END;
  1449. SetCC(x, relmap[op - ORS.eql])
  1450. END IntRelation;
  1451. (*
  1452. PROCEDURE SetRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  1453. BEGIN load0(0, x);
  1454. IF (op = ORS.eql) OR (op = ORS.neq) THEN
  1455. IF y.mode = ORB.Const THEN Put1a(Cmp, x.r, x.r, y.a); DEC(RH)
  1456. ELSE load0(0, y); Put0(Cmp, x.r, x.r, y.r); DEC(RH, 2)
  1457. END;
  1458. SetCC(x, relmap[op - ORS.eql])
  1459. ELSE ORS.Mark("illegal relation")
  1460. END
  1461. END SetRelation;
  1462. *)
  1463. PROCEDURE RealRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  1464. BEGIN
  1465. IF (y.mode = ORB.Const) & (y.a = 0) THEN
  1466. load(x); Put1a(Cmp, x.r, x.r, y.a);
  1467. DEC(RH)
  1468. ELSE load0(0, x); load0(0, y); Put0(Fsb, x.r, x.r, y.r); DEC(RH, 2)
  1469. END ;
  1470. SetCC(x, relmap[op - ORS.eql])
  1471. END RealRelation;
  1472. PROCEDURE StringRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  1473. (*x, y are char arrays or strings*)
  1474. VAR pc0, pc1: LONGINT;
  1475. BEGIN
  1476. IF x.type.form = ORB.String THEN loadStringAdr0(0, x) ELSE loadAdr0(0, x) END;
  1477. IF y.type.form = ORB.String THEN loadStringAdr0(0, y) ELSE loadAdr0(0, y) END;
  1478. pc0 := pc;
  1479. Put20(0, Ldr+1, RH, x.r, 0); Put10(0, Add, x.r, x.r, 1);
  1480. Put20(0, Ldr+1, RH+1, y.r, 0); Put10(0, Add, y.r, y.r, 1);
  1481. Put0(Cmp, RH+2, RH, RH+1); pc1 := pc; Put3orig(BC, NE, 0);
  1482. Put1(Cmp, RH+2, RH, 0); Put3orig(BC, NE, pc0 - pc - 1);
  1483. fix(pc1, pc - pc1 - 1);
  1484. DEC(RH, 2); SetCC(x, relmap[op - ORS.eql])
  1485. END StringRelation;
  1486. (* Code generation of Assignments *)
  1487. PROCEDURE StrToChar*(VAR x: Item);
  1488. BEGIN x.type := ORB.charType; DEC(strx, 4); x.a := ORD(str[x.a])
  1489. END StrToChar;
  1490. PROCEDURE Store*(VAR x, y: Item); (* x := y *)
  1491. VAR op: LONGINT;
  1492. BEGIN load0(0, y);
  1493. IF x.type.size = 1 THEN op := Str+1 ELSE op := Str END ;
  1494. IF x.mode = ORB.Var THEN
  1495. IF x.r > 0 THEN (*local*) Put2(op, y.r, SP, x.a + frame)
  1496. ELSE GetSB(x.r);
  1497. IF x.r # 0 THEN
  1498. Put2orig(op, ER(y.r), ER(SB), x.a)
  1499. ELSE Put2(op, y.r, SB, x.a)
  1500. END
  1501. END
  1502. ELSIF x.mode = ORB.Par THEN Put20(0, Ldr, RH, SP, x.a + frame); Put2(op, y.r, RH, x.b);
  1503. ELSIF x.mode = RegI THEN Put2(op, y.r, x.r, x.a); DEC(RH);
  1504. ELSE ORS.Mark("bad mode in Store")
  1505. END;
  1506. DEC(RH)
  1507. END Store;
  1508. PROCEDURE StoreStruct* (VAR x, y: Item); (* x := y, frame = 0 *)
  1509. VAR s, pc0, pc1: LONGINT;
  1510. BEGIN
  1511. IF y.type.size # 0 THEN
  1512. loadAdr0(0, x); loadAdr0(0, y);
  1513. pc0 := -1;
  1514. IF (x.type.form = ORB.Array) & (x.type.len > 0) THEN
  1515. IF y.type.len >= 0 THEN
  1516. IF x.type.size = y.type.size THEN Put10(0, Mov, RH, 0, (y.type.size+3) DIV 4)
  1517. ELSE ORS.Mark("different length/size, not implemented")
  1518. END
  1519. ELSE (*y is open array*) Put2(Ldr, RH, SP, y.a+4); s := y.type.base.size; (*element size*)
  1520. pc0 := pc; Put3orig(BC, EQ, 0);
  1521. IF s = 1 THEN Put10(0, Add, RH, RH, 3); Put10(0, Asr, RH, RH, 2)
  1522. ELSIF s # 4 THEN Put10(0, Mul, RH, RH, s DIV 4)
  1523. END;
  1524. IF check THEN
  1525. ASSERT(x.type.len >= 0);
  1526. Put10(0, Mov, RH+1, 0, (x.type.size+3) DIV 4); Put0(Cmp, RH+1, RH, RH+1); Trap(GT, 3)
  1527. END
  1528. END
  1529. ELSIF x.type.form = ORB.Record THEN Put10(0, Mov, RH, 0, x.type.size DIV 4)
  1530. ELSE ORS.Mark("inadmissible assignment")
  1531. END;
  1532. pc1 := pc;
  1533. Put20(0, Ldr, RH+1, y.r, 0); Put10(0, Add, y.r, y.r, 4);
  1534. Put2(Str, RH+1, x.r, 0); Put10(0, Add, x.r, x.r, 4);
  1535. Put1(Sub, RH, RH, 1); Put3orig(BC, NE, pc1 - pc - 1);
  1536. DEC(RH, 2); ASSERT(RH = 0);
  1537. IF pc0 # -1 THEN fix(pc0, pc - pc0 - 1) END
  1538. END;
  1539. RH := 0
  1540. END StoreStruct;
  1541. PROCEDURE CopyString* (VAR x, y: Item); (* x := y *)
  1542. VAR len, pc0: LONGINT;
  1543. BEGIN loadAdr0(0, x); len := x.type.len;
  1544. IF len >= 0 THEN
  1545. IF len < y.b THEN ORS.Mark("string too long") END
  1546. ELSIF check THEN Put20(0, Ldr, RH, SP, x.a+4); (*open array len, frame = 0*)
  1547. Put1(Cmp, RH, RH, y.b); Trap(LT, 3)
  1548. END;
  1549. loadStringAdr0(0, y);
  1550. pc0 := pc;
  1551. Put20(0, Ldr, RH, y.r, 0); Put10(0, Add, y.r, y.r, 4);
  1552. Put2(Str, RH, x.r, 0); Put10(0, Add, x.r, x.r, 4);
  1553. Put1(Asr, RH, RH, 24); Put3orig(BC, NE, pc0 - pc - 1); RH := 0
  1554. END CopyString;
  1555. (* Code generation for parameters *)
  1556. PROCEDURE OpenArrayParam*(VAR x: Item);
  1557. BEGIN loadAdr0(0, x);
  1558. IF x.type.len >= 0 THEN Put10(0, Mov, RH, 0, x.type.len) ELSE Put20(0, Ldr, RH, SP, x.a+4+frame) END;
  1559. incR
  1560. END OpenArrayParam;
  1561. PROCEDURE VarParam*(VAR x: Item; ftype: ORB.Type);
  1562. VAR xmd: INTEGER;
  1563. BEGIN xmd := x.mode; loadAdr0(0, x);
  1564. IF (ftype.form = ORB.Array) & (ftype.len < 0) THEN (*open array*)
  1565. IF x.type.len >= 0 THEN Put10(0, Mov, RH, 0, x.type.len) ELSE Put20(0, Ldr, RH, SP, x.a+4+frame) END;
  1566. incR
  1567. ELSIF ftype.form = ORB.Record THEN
  1568. IF xmd = ORB.Par THEN Put20(0, Ldr, RH, SP, x.a+4+frame); incR ELSE loadTypTagAdr0(0, x.type) END
  1569. END
  1570. END VarParam;
  1571. PROCEDURE ValueParam*(VAR x: Item);
  1572. BEGIN load0(0, x)
  1573. END ValueParam;
  1574. PROCEDURE StringParam*(VAR x: Item);
  1575. BEGIN loadStringAdr0(0, x); Put10(0, Mov, RH, 0, x.b); incR (*len*)
  1576. END StringParam;
  1577. (*For Statements*)
  1578. PROCEDURE For0*(VAR x, y: Item);
  1579. BEGIN load(y)
  1580. END For0;
  1581. PROCEDURE For1*(VAR x, y, z, w: Item; VAR L: LONGINT);
  1582. BEGIN
  1583. IF z.mode = ORB.Const THEN Put1a(Cmp, RH, y.r, z.a)
  1584. ELSE load0(0, z); Put0(Cmp, RH-1, y.r, z.r); DEC(RH)
  1585. END ;
  1586. L := pc;
  1587. IF w.a > 0 THEN Put3orig(BC, GT, 0)
  1588. ELSIF w.a < 0 THEN Put3orig(BC, LT, 0)
  1589. ELSE ORS.Mark("zero increment"); Put3orig(BC, MI, 0)
  1590. END ;
  1591. Store(x, y)
  1592. END For1;
  1593. PROCEDURE For2*(VAR x, y, w: Item);
  1594. BEGIN load0(0, x); DEC(RH); Put1a(Add, x.r, x.r, w.a)
  1595. END For2;
  1596. (* Branches, procedure calls, procedure prolog and epilog *)
  1597. PROCEDURE Here*(): LONGINT;
  1598. BEGIN invalSB; RETURN pc
  1599. END Here;
  1600. PROCEDURE FJump*(VAR L: LONGINT);
  1601. BEGIN Put3orig(BC, 7, L); L := pc-1
  1602. END FJump;
  1603. PROCEDURE CFJump*(VAR x: Item);
  1604. BEGIN
  1605. IF x.mode # Cond THEN loadCond(x) END ;
  1606. Put3orig(BC, negated(x.r), x.a); FixLink(x.b); x.a := pc-1
  1607. END CFJump;
  1608. PROCEDURE BJump*(L: LONGINT);
  1609. BEGIN Put3orig(BC, 7, L-pc-1)
  1610. END BJump;
  1611. PROCEDURE CBJump*(VAR x: Item; L: LONGINT);
  1612. BEGIN
  1613. IF x.mode # Cond THEN loadCond(x) END ;
  1614. Put3orig(BC, negated(x.r), L-pc-1); FixLink(x.b); FixLinkWith(x.a, L)
  1615. END CBJump;
  1616. PROCEDURE Fixup*(VAR x: Item);
  1617. BEGIN FixLink(x.a)
  1618. END Fixup;
  1619. PROCEDURE SaveRegs(r: LONGINT); (* R[0 .. r-1]*)
  1620. VAR r0: LONGINT;
  1621. BEGIN (*r > 0*) r0 := 0;
  1622. Put10(0, Sub, SP, SP, r*4); INC(frame, 4*r);
  1623. REPEAT Put2(Str, r0, SP, (r-r0-1)*4); INC(r0) UNTIL r0 = r
  1624. END SaveRegs;
  1625. PROCEDURE RestoreRegs(r: LONGINT); (*R[0 .. r-1]*)
  1626. VAR r0: LONGINT;
  1627. BEGIN (*r > 0*) r0 := r;
  1628. REPEAT DEC(r0); Put20(0, Ldr, r0, SP, (r-r0-1)*4) UNTIL r0 = 0;
  1629. Put10(0, Add, SP, SP, r*4); DEC(frame, 4*r)
  1630. END RestoreRegs;
  1631. PROCEDURE PrepCall*(VAR x: Item; VAR r: LONGINT);
  1632. BEGIN (*x.type.form = ORB.Proc*)
  1633. IF x.mode > ORB.Par THEN load(x) END ;
  1634. r := RH;
  1635. IF RH > 0 THEN SaveRegs(RH); RH := 0 END
  1636. END PrepCall;
  1637. PROCEDURE Call*(VAR x: Item; r: LONGINT);
  1638. CONST check = FALSE;
  1639. (* is not necessary:
  1640. HardFault trap (with pc=0) will occur,
  1641. because no Thumb flag in initialSP
  1642. *)
  1643. BEGIN (*x.type.form = ORB.Proc*)
  1644. IF x.mode = ORB.Const THEN
  1645. IF x.r >= 0 THEN Put3(BL, 7, (x.a DIV 4)-pc-1)
  1646. ELSE (*imported*)
  1647. (*
  1648. IF pc - fixorgP < 1000H THEN
  1649. *)
  1650. IF ((-x.r) DIV 10H = 0) (* mno *)
  1651. & (x.a DIV 100H = 0) (* pno *)
  1652. & ((pc-fixorgP) DIV 1000H = 0) (* disp *) THEN
  1653. (* will be fixed up by linker/loader *)
  1654. Put3orig(BL, 7, ((-x.r) * 100H + x.a) * 1000H + pc-fixorgP);
  1655. armcode[pc] := 00FFFFFFH; INC(pc);
  1656. fixorgP := pc-1
  1657. ELSE ORS.Mark("fixup impossible")
  1658. END
  1659. END
  1660. ELSE
  1661. IF x.mode <= ORB.Par THEN
  1662. IF check THEN load(x) ELSE load0(0, x) END;
  1663. DEC(RH)
  1664. ELSE
  1665. Put20(0, Ldr, RH, SP, 0); Put10(0, Add, SP, SP, 4);
  1666. IF check THEN Put1(Cmp, RH, RH, 0) END;
  1667. DEC(r); DEC(frame, 4)
  1668. END;
  1669. IF check THEN Trap(EQ, 5) END;
  1670. Put3(BLR, 7, RH)
  1671. END;
  1672. IF x.type.base.form = ORB.NoTyp THEN (*procedure*) RH := 0
  1673. ELSE (*function*)
  1674. RH := MT;
  1675. IF r > 0 THEN Put00(0, Mov, r, 0, 0); RestoreRegs(r) END;
  1676. x.mode := Reg; x.r := r; RH := r+1
  1677. END;
  1678. invalSB; RM := {0..31}
  1679. END Call;
  1680. PROCEDURE Enter* (parblksize, locblksize: LONGINT; int: BOOLEAN);
  1681. VAR a, r: LONGINT;
  1682. BEGIN invalSB; frame := 0;
  1683. enterPushFixup := pc;
  1684. IF ~int THEN (*procedure prolog*)
  1685. (* IF locblksize >= 10000H THEN ORS.Mark("too many locals") END; *)
  1686. ARMv6M.EmitPUSH(armcode, pc, {LNK});
  1687. a := parblksize0Proc; r := 0;
  1688. IF locblksize # parblksize0Proc THEN Put10(0, Sub, SP, SP, locblksize) END;
  1689. WHILE a < parblksize DO Put2(Str, r, SP, a); INC(r); INC(a, 4) END
  1690. ELSE (*interrupt procedure*)
  1691. (* IF locblksize > 0H THEN ORS.Mark("locals not allowed") END; *)
  1692. ARMv6M.EmitPUSH(armcode, pc, {LNK});
  1693. a := parblksize0Int; r := 0;
  1694. IF locblksize # parblksize0Int THEN Put10(0, Sub, SP, SP, locblksize) END;
  1695. WHILE a < parblksize DO Put2(Str, r, SP, a); INC(r); INC(a, 4) END
  1696. END;
  1697. RM := {}
  1698. END Enter;
  1699. PROCEDURE Fix (VAR code: ARRAY OF INTEGER; i: INTEGER);
  1700. VAR cond, off, pc0: INTEGER;
  1701. BEGIN
  1702. IF ORS.errcnt = 0 THEN
  1703. IF code[i] DIV 10000000H MOD 10H = 0EH THEN (* BC *)
  1704. cond := code[i] DIV 1000000H MOD 10H;
  1705. off := (code[i] MOD 1000000H * 100H) DIV 100H;
  1706. pc0 := pc; pc := i;
  1707. Put3(BC, cond, off);
  1708. IF ORS.errcnt = 0 THEN
  1709. ASSERT(pc - i = 1, 100)
  1710. END;
  1711. pc := pc0
  1712. END
  1713. END
  1714. END Fix;
  1715. PROCEDURE FixRng (from, to: INTEGER);
  1716. BEGIN
  1717. WHILE from < to DO
  1718. Fix(armcode, from); INC(from)
  1719. END
  1720. END FixRng;
  1721. PROCEDURE Return* (form: INTEGER; VAR x: Item; size: LONGINT; int: BOOLEAN);
  1722. VAR pc0: INTEGER;
  1723. BEGIN
  1724. IF form # ORB.NoTyp THEN load(x) END ;
  1725. IF ~int THEN (*procedure epilog*)
  1726. IF size # parblksize0Proc THEN Put10(0, Add, SP, SP, size) END;
  1727. IF LNK IN RM THEN
  1728. ARMv6M.EmitPOP(armcode, pc, {ARMv6M.PC})
  1729. ELSE
  1730. Put3(BR, 7, LNK);
  1731. pc0 := pc; pc := enterPushFixup;
  1732. ARMv6M.EmitNOP(armcode, pc);
  1733. pc := pc0
  1734. END
  1735. ELSE (*interrupt return*)
  1736. IF size # parblksize0Int THEN Put10(0, Add, SP, SP, size) END;
  1737. ARMv6M.EmitPOP(armcode, pc, ERs(RM) * {4..7} - {ER(MT)} + {ARMv6M.PC});
  1738. pc0 := pc; pc := enterPushFixup;
  1739. ARMv6M.EmitPUSH(armcode, pc, ERs(RM) * {4..7} - {ER(MT)} + {LNK});
  1740. pc := pc0
  1741. END;
  1742. RH := 0;
  1743. FixRng(enterPushFixup, pc)
  1744. END Return;
  1745. (* In-line code procedures*)
  1746. PROCEDURE Increment*(upordown: LONGINT; VAR x, y: Item);
  1747. VAR op, zr, v: LONGINT;
  1748. BEGIN (*frame = 0*)
  1749. IF upordown = 0 THEN op := Add ELSE op := Sub END ;
  1750. IF x.type = ORB.byteType THEN v := 1 ELSE v := 0 END ;
  1751. IF y.type.form = ORB.NoTyp THEN y.mode := ORB.Const; y.a := 1 END ;
  1752. IF (x.mode = ORB.Var) & (x.r > 0) THEN
  1753. zr := RH; Put20(0, Ldr+v, zr, SP, x.a); incR;
  1754. IF y.mode = ORB.Const THEN Put10(0, op, zr, zr, y.a) ELSE load0(0, y); Put00(0, op, zr, zr, y.r); DEC(RH) END ;
  1755. Put2(Str+v, zr, SP, x.a); DEC(RH)
  1756. ELSE loadAdr0(0, x); zr := RH; Put20(0, Ldr+v, RH, x.r, 0); incR;
  1757. IF y.mode = ORB.Const THEN Put10(0, op, zr, zr, y.a) ELSE load0(0, y); Put00(0, op, zr, zr, y.r); DEC(RH) END ;
  1758. Put2(Str+v, zr, x.r, 0); DEC(RH, 2)
  1759. END
  1760. END Increment;
  1761. PROCEDURE Include*(inorex: LONGINT; VAR x, y: Item);
  1762. VAR op, zr: LONGINT;
  1763. BEGIN loadAdr0(0, x); zr := RH; Put20(0, Ldr, RH, x.r, 0); incR;
  1764. IF inorex = 0 THEN op := Ior ELSE op := Ann END ;
  1765. IF y.mode = ORB.Const THEN Put10(0, op, zr, zr, LSL(1, y.a))
  1766. ELSE load0(0, y); Put10(0, Mov, RH, 0, 1); Put00(0, Lsl, y.r, RH, y.r); Put00(0, op, zr, zr, y.r); DEC(RH)
  1767. END ;
  1768. Put2(Str, zr, x.r, 0); DEC(RH, 2)
  1769. END Include;
  1770. PROCEDURE Assert*(VAR x: Item);
  1771. VAR cond: LONGINT;
  1772. BEGIN
  1773. IF x.mode # Cond THEN loadCond(x) END ;
  1774. IF x.a = 0 THEN cond := negated(x.r)
  1775. ELSE Put3orig(BC, x.r, x.b); FixLink(x.a); x.b := pc-1; cond := 7
  1776. END;
  1777. Trap(cond, 7); FixLink(x.b)
  1778. END Assert;
  1779. PROCEDURE New*(VAR x: Item);
  1780. BEGIN loadAdr0(0, x); loadTypTagAdr0(0, x.type.base); Trap(7, 0); RH := 0; invalSB
  1781. END New;
  1782. PROCEDURE Pack*(VAR x, y: Item);
  1783. VAR z: Item;
  1784. BEGIN z := x; load0(0, x); load0(0, y);
  1785. Put10(0, Lsl, y.r, y.r, 23); Put00(0, Add, x.r, x.r, y.r); DEC(RH); Store(z, x)
  1786. END Pack;
  1787. PROCEDURE Unpk*(VAR x, y: Item);
  1788. VAR z, e0: Item;
  1789. BEGIN z := x; load0(0, x); e0.mode := Reg; e0.r := RH; e0.type := ORB.intType;
  1790. Put10(0, Asr, RH, x.r, 23); Put10(0, Sub, RH, RH, 127); Store(y, e0); incR;
  1791. Put10(0, Lsl, RH, RH, 23); Put00(0, Sub, x.r, x.r, RH); Store(z, x)
  1792. END Unpk;
  1793. PROCEDURE Led*(VAR x: Item);
  1794. BEGIN (* load0(0, x); Put10(0, Mov, RH, 0, -60); Put2(Str, x.r, RH, 0); DEC(RH) *)
  1795. ORS.Mark("not supported")
  1796. END Led;
  1797. PROCEDURE Get*(VAR x, y: Item);
  1798. BEGIN load0(0, x); x.type := y.type; x.mode := RegI; x.a := 0; Store(y, x)
  1799. END Get;
  1800. PROCEDURE Put*(VAR x, y: Item);
  1801. BEGIN load0(0, x); x.type := y.type; x.mode := RegI; x.a := 0; Store(x, y)
  1802. END Put;
  1803. PROCEDURE Copy*(VAR x, y, z: Item);
  1804. VAR pc0, pc1: LONGINT;
  1805. BEGIN load0(0, x); load0(0, y);
  1806. pc0 := -1;
  1807. IF z.mode = ORB.Const THEN
  1808. IF z.a > 0 THEN load0(0, z) ELSE ORS.Mark("bad count") END
  1809. ELSE load(z);
  1810. IF check THEN Trap(LT, 3) END ;
  1811. pc0 := pc; Put3orig(BC, EQ, 0)
  1812. END;
  1813. pc1 := pc;
  1814. Put20(0, Ldr, RH, x.r, 0); Put10(0, Add, x.r, x.r, 4);
  1815. Put2(Str, RH, y.r, 0); Put10(0, Add, y.r, y.r, 4);
  1816. Put1(Sub, z.r, z.r, 1); Put3orig(BC, NE, pc1 - pc - 1); DEC(RH, 3);
  1817. IF pc0 # -1 THEN fix(pc0, pc - pc0 - 1) END
  1818. END Copy;
  1819. PROCEDURE LDPSR*(VAR x: Item);
  1820. BEGIN (*x.mode = Const*) Put3(0, 15, x.a + 20H)
  1821. END LDPSR;
  1822. PROCEDURE LDREG* (VAR x, y: Item);
  1823. BEGIN
  1824. IF x.mode = ORB.Const THEN
  1825. IF x.a IN {0..15} THEN
  1826. IF y.mode = ORB.Const THEN Put10(0, Mov, DR(x.a), 0, y.a)
  1827. ELSE load0(0, y); Put00(0, Mov, DR(x.a), 0, y.r); DEC(RH)
  1828. END
  1829. ELSE ORS.Mark("invalid register")
  1830. END
  1831. ELSE ORS.Mark("not supported")
  1832. END
  1833. END LDREG;
  1834. (*In-line code functions*)
  1835. PROCEDURE Abs*(VAR x: Item);
  1836. VAR pc0: LONGINT;
  1837. BEGIN
  1838. IF x.mode = ORB.Const THEN x.a := ABS(x.a)
  1839. ELSE load0(0, x);
  1840. IF x.type.form = ORB.Real THEN Put10(0, Lsl, x.r, x.r, 1); Put1(Ror, x.r, x.r, 1)
  1841. ELSE
  1842. Put1(Cmp, x.r, x.r, 0);
  1843. pc0 := pc; Put3orig(BC, GE, 0);
  1844. (* Put10(0, Mov, RH, 0, 0); Put0(Sub, x.r, RH, x.r) *)
  1845. RSBS0(x.r);
  1846. fix(pc0, pc - pc0 - 1)
  1847. END
  1848. END
  1849. END Abs;
  1850. PROCEDURE Odd*(VAR x: Item);
  1851. BEGIN load0(0, x); Put1(And, x.r, x.r, 1); SetCC(x, NE); DEC(RH)
  1852. END Odd;
  1853. PROCEDURE Floor*(VAR x: Item);
  1854. BEGIN load0(0, x); Put10(0, Mov+U, RH, 0, 4B00H); Put0(Fad+V, x.r, x.r, RH)
  1855. END Floor;
  1856. PROCEDURE Float*(VAR x: Item);
  1857. BEGIN load0(0, x); Put10(0, Mov+U, RH, 0, 4B00H); Put0(Fad+U, x.r, x.r, RH)
  1858. END Float;
  1859. PROCEDURE Ord*(VAR x: Item);
  1860. BEGIN
  1861. IF x.mode IN {ORB.Var, ORB.Par, RegI, Cond} THEN load(x) END
  1862. END Ord;
  1863. PROCEDURE Len*(VAR x: Item);
  1864. BEGIN
  1865. IF x.type.len >= 0 THEN
  1866. IF x.mode = RegI THEN DEC(RH) END;
  1867. x.mode := ORB.Const; x.a := x.type.len
  1868. ELSE (*open array*) Put2(Ldr, RH, SP, x.a + 4 + frame); x.mode := Reg; x.r := RH; incR
  1869. END
  1870. END Len;
  1871. PROCEDURE Shift*(fct: LONGINT; VAR x, y: Item);
  1872. VAR op: LONGINT;
  1873. BEGIN load0(0, x);
  1874. IF fct = 0 THEN op := Lsl ELSIF fct = 1 THEN op := Asr ELSE op := Ror END ;
  1875. IF y.mode = ORB.Const THEN Put1(op, x.r, x.r, y.a MOD 20H)
  1876. ELSE load0(0, y); Put0(op, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  1877. END
  1878. END Shift;
  1879. PROCEDURE ADC*(VAR x, y: Item);
  1880. BEGIN load0(0, x); load0(0, y); Put0(Add+U, x.r, x.r, y.r); DEC(RH)
  1881. END ADC;
  1882. PROCEDURE SBC*(VAR x, y: Item);
  1883. BEGIN load0(0, x); load0(0, y); Put0(Sub+U, x.r, x.r, y.r); DEC(RH)
  1884. END SBC;
  1885. PROCEDURE UML*(VAR x, y: Item);
  1886. BEGIN load0(0, x); load0(0, y); Put0(Mul+U, x.r, x.r, y.r); DEC(RH)
  1887. END UML;
  1888. PROCEDURE Bit*(VAR x, y: Item);
  1889. BEGIN load0(0, x); Put20(0, Ldr, x.r, x.r, 0);
  1890. IF y.mode = ORB.Const THEN Put1(Ror, x.r, x.r, y.a+1); DEC(RH)
  1891. ELSE load0(0, y); Put10(0, Add, y.r, y.r, 1); Put0(Ror, x.r, x.r, y.r); DEC(RH, 2)
  1892. END;
  1893. SetCC(x, MI)
  1894. END Bit;
  1895. PROCEDURE Register*(VAR x: Item);
  1896. BEGIN (*x.mode = Const*)
  1897. Put0(Mov, RH, 0, DR(x.a MOD 10H)); x.mode := Reg; x.r := RH; incR
  1898. END Register;
  1899. PROCEDURE H* (VAR x: Item);
  1900. BEGIN (*x.mode = Const*)
  1901. (* Put0(Mov+U + x.a MOD 2 * V, RH, 0, 0); *) ORS.Mark("not supported");
  1902. x.mode := Reg; x.r := RH; incR
  1903. END H;
  1904. PROCEDURE Adr*(VAR x: Item);
  1905. BEGIN
  1906. IF x.mode IN {ORB.Var, ORB.Par, RegI} THEN loadAdr(x)
  1907. ELSIF (x.mode = ORB.Const) & (x.type.form = ORB.Proc) THEN load(x)
  1908. ELSIF (x.mode = ORB.Const) & (x.type.form = ORB.String) THEN loadStringAdr(x)
  1909. ELSE ORS.Mark("not addressable")
  1910. END
  1911. END Adr;
  1912. PROCEDURE Condition*(VAR x: Item);
  1913. BEGIN (*x.mode = Const*) SetCC(x, x.a)
  1914. END Condition;
  1915. PROCEDURE Open* (v: INTEGER);
  1916. BEGIN pc := 0; tdx := 0; strx := 0; RH := 0; fixorgP := 0; fixorgD := 0; fixorgT := 0; check := v # 0; version := v;
  1917. IF v = 0 THEN
  1918. armcode[0] := 0; armcode[1] := 0;
  1919. (* CPU exceptions (NMI..SysTick) *)
  1920. pc := 4; WHILE pc < 40H DIV 2 DO
  1921. armcode[pc] := 1; INC(pc);
  1922. armcode[pc] := 0; INC(pc)
  1923. END;
  1924. (* IRQ 0..239 (Cortex-M4 allows up to 240 IRQs) *)
  1925. WHILE pc < 40H DIV 2 + 240 * 2 DO
  1926. armcode[pc] := 1; INC(pc);
  1927. armcode[pc] := 0; INC(pc)
  1928. END
  1929. ELSE ARMv6M.EmitNOP(armcode, pc) (* pc must be not zero (fixups) *)
  1930. END
  1931. END Open;
  1932. PROCEDURE SetDataSize* (dc: LONGINT);
  1933. BEGIN varsize := dc
  1934. END SetDataSize;
  1935. PROCEDURE Header*;
  1936. VAR i, cs: INTEGER;
  1937. BEGIN entry := pc*4;
  1938. IF version = 0 THEN (*RISC-0*)
  1939. armcode[2] := (entry DIV 2 + 1) MOD 10000H;
  1940. armcode[3] := (entry DIV 2 + 1) DIV 10000H MOD 10000H;
  1941. (* NXP checksum *)
  1942. cs := 0; i := 0;
  1943. WHILE i < 7 DO
  1944. cs := cs + armcode[2 * i] + 10000H * armcode[2 * i + 1];
  1945. INC(i)
  1946. END;
  1947. armcode[2 * i] := (-cs) MOD 10000H;
  1948. armcode[2 * i + 1] := (-cs) DIV 10000H MOD 10000H
  1949. ELSE ARMv6M.EmitPUSH(armcode, pc, {LNK}); invalSB
  1950. END
  1951. END Header;
  1952. PROCEDURE NofPtrs(typ: ORB.Type): LONGINT;
  1953. VAR fld: ORB.Object; n: LONGINT;
  1954. BEGIN
  1955. IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN n := 1
  1956. ELSIF typ.form = ORB.Record THEN
  1957. fld := typ.dsc; n := 0;
  1958. WHILE fld # NIL DO n := NofPtrs(fld.type) + n; fld := fld.next END
  1959. ELSIF typ.form = ORB.Array THEN n := NofPtrs(typ.base) * typ.len
  1960. ELSE n := 0
  1961. END ;
  1962. RETURN n
  1963. END NofPtrs;
  1964. PROCEDURE FindPtrs(VAR R: Files.Rider; typ: ORB.Type; adr: LONGINT);
  1965. VAR fld: ORB.Object; i, s: LONGINT;
  1966. BEGIN
  1967. IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN Files.WriteLInt(R, adr)
  1968. ELSIF typ.form = ORB.Record THEN
  1969. fld := typ.dsc;
  1970. WHILE fld # NIL DO FindPtrs(R, fld.type, fld.val + adr); fld := fld.next END
  1971. ELSIF typ.form = ORB.Array THEN
  1972. s := typ.base.size;
  1973. FOR i := 0 TO typ.len-1 DO FindPtrs(R, typ.base, i*s + adr) END
  1974. END
  1975. END FindPtrs;
  1976. PROCEDURE Close* (VAR modid: ORS.Ident; key, nofent: LONGINT);
  1977. VAR obj: ORB.Object;
  1978. i, comsize, nofimps, nofptrs, size: LONGINT;
  1979. name: ORS.Ident;
  1980. F: Files.File; R: Files.Rider;
  1981. BEGIN (*exit code*)
  1982. FixRng(0, pc);
  1983. IF version = 0 THEN Put3(BC, 7, -1) (*RISC-0*)
  1984. ELSE ARMv6M.EmitPOP(armcode, pc, {ARMv6M.PC})
  1985. END;
  1986. obj := ORB.topScope.next; nofimps := 0; comsize := 4; nofptrs := 0;
  1987. WHILE obj # NIL DO
  1988. IF (obj.class = ORB.Mod) & (obj.dsc # ORB.system) THEN INC(nofimps) (*count imports*)
  1989. ELSIF (obj.exno # 0) & (obj.class = ORB.Const) & (obj.type.form = ORB.Proc)
  1990. & (obj.type.nofpar = 0) & (obj.type.base = ORB.noType) THEN i := 0; (*count commands*)
  1991. WHILE obj.name[i] # 0X DO INC(i) END ;
  1992. i := (i+4) DIV 4 * 4; INC(comsize, i+4)
  1993. ELSIF obj.class = ORB.Var THEN INC(nofptrs, NofPtrs(obj.type)) (*count pointers*)
  1994. END;
  1995. obj := obj.next
  1996. END;
  1997. size := varsize + strx + comsize + (pc + nofimps + nofent + nofptrs + 1)*4; (*varsize includes type descriptors*)
  1998. ORB.MakeFileName(name, modid, ".a6m"); (*write code file*)
  1999. F := Files.New(name); Files.Set(R, F, 0); Files.WriteString(R, modid); Files.WriteLInt(R, key); Files.Write(R, CHR(version));
  2000. Files.WriteLInt(R, size);
  2001. obj := ORB.topScope.next;
  2002. WHILE (obj # NIL) & (obj.class = ORB.Mod) DO (*imports*)
  2003. IF obj.dsc # ORB.system THEN Files.WriteString(R, obj(ORB.Module).orgname); Files.WriteLInt(R, obj.val) END ;
  2004. obj := obj.next
  2005. END;
  2006. Files.Write(R, 0X);
  2007. Files.WriteLInt(R, tdx*4);
  2008. i := 0;
  2009. WHILE i < tdx DO Files.WriteLInt(R, data[i]); INC(i) END ; (*type descriptors*)
  2010. Files.WriteLInt(R, varsize - tdx*4); (*data*)
  2011. Files.WriteLInt(R, strx);
  2012. FOR i := 0 TO strx-1 DO Files.Write(R, str[i]) END ; (*strings*)
  2013. Files.WriteLInt(R, pc); (*code len*)
  2014. FOR i := 0 TO pc-1 DO
  2015. Files.WriteLInt(R, armcode[i])
  2016. END; (*program*)
  2017. obj := ORB.topScope.next;
  2018. WHILE obj # NIL DO (*commands*)
  2019. IF (obj.exno # 0) & (obj.class = ORB.Const) & (obj.type.form = ORB.Proc) &
  2020. (obj.type.nofpar = 0) & (obj.type.base = ORB.noType) THEN
  2021. Files.WriteString(R, obj.name); Files.WriteLInt(R, obj.val)
  2022. END;
  2023. obj := obj.next
  2024. END;
  2025. Files.Write(R, 0X);
  2026. Files.WriteLInt(R, nofent); Files.WriteLInt(R, entry);
  2027. obj := ORB.topScope.next;
  2028. WHILE obj # NIL DO (*entries*)
  2029. IF obj.exno # 0 THEN
  2030. IF (obj.class = ORB.Const) & (obj.type.form = ORB.Proc) OR (obj.class = ORB.Var) THEN
  2031. Files.WriteLInt(R, obj.val)
  2032. ELSIF obj.class = ORB.Typ THEN
  2033. IF obj.type.form = ORB.Record THEN Files.WriteLInt(R, obj.type.len MOD 10000H)
  2034. ELSIF (obj.type.form = ORB.Pointer) & ((obj.type.base.typobj = NIL) OR (obj.type.base.typobj.exno = 0)) THEN
  2035. Files.WriteLInt(R, obj.type.base.len MOD 10000H)
  2036. END
  2037. END
  2038. END;
  2039. obj := obj.next
  2040. END;
  2041. obj := ORB.topScope.next;
  2042. WHILE obj # NIL DO (*pointer variables*)
  2043. IF obj.class = ORB.Var THEN FindPtrs(R, obj.type, obj.val) END ;
  2044. obj := obj.next
  2045. END;
  2046. Files.WriteLInt(R, -1);
  2047. Files.WriteLInt(R, fixorgP); Files.WriteLInt(R, fixorgD); Files.WriteLInt(R, fixorgT); Files.WriteLInt(R, entry);
  2048. Files.Write(R, "O"); Files.Register(F)
  2049. END Close;
  2050. BEGIN
  2051. relmap[0] := 1; relmap[1] := 9; relmap[2] := 5; relmap[3] := 6; relmap[4] := 14; relmap[5] := 13
  2052. END O7ARMv6MG.