O7ARMv7MG.Mod 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794
  1. MODULE O7ARMv7MG; (* NW 18.4.2016 / 31.5.2019 code generator in Oberon-07 for RISC*)
  2. (* Modified for ARMv7-M by A. V. Shiryaev, 2018.05.25, 2019.10.21, 2021.08.08, 2023.06.21 *)
  3. (*
  4. http://www.inf.ethz.ch/personal/wirth/FPGA-relatedWork/RISC-Arch.pdf
  5. http://infocenter.arm.com/help/topic/com.arm.doc.ddi0439d/DDI0439D_cortex_m4_processor_r0p1_trm.pdf
  6. ARMv7-M Architecture Reference Manual
  7. https://web.eecs.umich.edu/~prabal/teaching/eecs373-f10/readings/ARMv7-M_ARM.pdf
  8. *)
  9. (*
  10. TODO:
  11. LEN(record.arrayOfChar):
  12. Reg Stack
  13. invalid code generated when no Reg Stack compile-time error
  14. implement "special feautures" (see RISC-Arch.pdf, section 4):
  15. implement MOV+U F0, c = 1 feature? save flags to register
  16. when it's required?
  17. MRS instruction
  18. check loadCond (IsFlagsUp0 related)
  19. implement LDPSR
  20. see PO.Applications.pdf, p. 47
  21. shifts...
  22. implementation limits:
  23. use long B and BC branches:
  24. use short B and BC where possible (see Put3orig(BC...)),
  25. else use long B and BC..
  26. optimizations:
  27. arrays assignment (see PO.Applications.pdf, 45):
  28. use special command instead of loop
  29. bits:
  30. SYSTEM.BIT(adr, bit)
  31. ...
  32. register procedures
  33. MovIm... https://github.com/aixp/ProjectOberon2013/commit/873fe7ef74a2c41592f9904ad7c3893e4a368d58
  34. NOTE:
  35. do not try to optimize CMP, BC -> CB[N]Z:
  36. fixups:
  37. fixup problems
  38. else:
  39. there is no places where to use
  40. do not remove redundant cmps in Put3 (fixup problems)
  41. *)
  42. IMPORT SYSTEM, Files, ORS := O7S, ORB := O7B, ARMv6M := O7ARMv6M, ARMv7M := O7ARMv7M;
  43. (*Code generator for Oberon compiler for RISC processor.
  44. Procedural interface to Parser OSAP; result in array "code".
  45. Procedure Close writes code-files*)
  46. TYPE
  47. LONGINT = INTEGER;
  48. BYTE = CHAR;
  49. CONST WordSize* = 4;
  50. parblksize0Proc* = 0; parblksize0Int* = 0;
  51. (* MT = 12; SB = 13; SP = 14; LNK = 15; (*dedicated registers*) *)
  52. MT = 11; SB = 12; SP = ARMv6M.SP; LNK = ARMv6M.LR;
  53. maxCode = 16000; maxStrx = 2400; maxTD = 160; C24 = 1000000H;
  54. Reg = 10; RegI = 11; Cond = 12; (*internal item modes*)
  55. (* fixup tags *)
  56. tagFixup = 00FFFFFFH; (* Add/Ldr/LdrB/Str/StrB *)
  57. tagBC = 00FFFFFEH;
  58. tagVLDR = 00FFFFFCH;
  59. tagBL = 00FFFFE0H;
  60. tagLdrSB = 00FFFFD0H;
  61. (*frequently used opcodes*) U = 2000H; V = 1000H;
  62. Mov = 0; Lsl = 1; Asr = 2; Ror= 3; And = 4; Ann = 5; Ior = 6; Xor = 7;
  63. Add = 8; Sub = 9; Cmp = 9; Mul = 10; Div = 11;
  64. Ldr = 8; Str = 10;
  65. BR = 0; BLR = 1; BC = 2; BL = 3;
  66. MI = 0; PL = 8; EQ = 1; NE = 9; LT = 5; GE = 13; LE = 6; GT = 14;
  67. TYPE Item* = RECORD
  68. mode*: INTEGER;
  69. type*: ORB.Type;
  70. a-, b-, r: LONGINT;
  71. rdo-: BOOLEAN (*read only*)
  72. END ;
  73. (* Item forms and meaning of fields:
  74. mode r a b
  75. --------------------------------
  76. Const - value (proc adr) (immediate value)
  77. Var base off - (direct adr)
  78. Par - off0 off1 (indirect adr)
  79. Reg regno (regno >= 100H: FPU register)
  80. RegI regno off -
  81. Cond cond Fchain Tchain *)
  82. VAR pc-, varsize: LONGINT; (*program counter, data index*)
  83. tdx, strx: LONGINT;
  84. entry: LONGINT; (*main entry point*)
  85. RH: LONGINT; (*available registers R[0] ... R[H-1]*)
  86. curSB: LONGINT; (*current static base in SB*)
  87. frame: LONGINT; (*frame offset changed in SaveRegs and RestoreRegs*)
  88. fixorgP, fixorgD, fixorgT: LONGINT; (*origins of lists of locations to be fixed up by loader*)
  89. check: BOOLEAN; (*emit run-time checks*)
  90. version: INTEGER; (* 0 = RISC-0, 1 = RISC-5 *)
  91. relmap: ARRAY 6 OF INTEGER; (*condition codes for relations*)
  92. armcode: ARRAY maxCode OF LONGINT;
  93. data: ARRAY maxTD OF LONGINT; (*type descriptors*)
  94. str: ARRAY maxStrx OF CHAR;
  95. RM: SET; (* registers modified *)
  96. enterPushFixup: INTEGER;
  97. FR: SET; (* for SaveRegs/RestoreRegs *)
  98. updateCarry: BOOLEAN;
  99. PROCEDURE BITS (x: INTEGER): SET;
  100. BEGIN
  101. RETURN SYSTEM.VAL(SET, x)
  102. END BITS;
  103. PROCEDURE ORDSET (x: SET): INTEGER;
  104. BEGIN
  105. RETURN SYSTEM.VAL(INTEGER, x)
  106. END ORDSET;
  107. PROCEDURE LSL (x, n: INTEGER): INTEGER;
  108. BEGIN RETURN SYSTEM.LSH(x, n)
  109. END LSL;
  110. (*instruction assemblers according to formats*)
  111. (* for fixups only *)
  112. PROCEDURE Put1orig (op, a, b, im: LONGINT);
  113. BEGIN (*emit format-1 instruction, -10000H <= im < 10000H*)
  114. IF im < 0 THEN INC(op, V) END;
  115. armcode[pc] := (((a+40H) * 10H + b) * 10H + op) * 10000H + (im MOD 10000H); INC(pc)
  116. END Put1orig;
  117. PROCEDURE Put2orig (op, a, b, off: LONGINT);
  118. BEGIN (*emit load/store instruction*)
  119. ASSERT(op DIV 10H = 0);
  120. ASSERT(a DIV 10H = 0);
  121. ASSERT(b DIV 10H = 0);
  122. (* ASSERT(off DIV 100000H = 0); *)
  123. ASSERT(off >= -80000H);
  124. ASSERT(off < 80000H);
  125. IF off < 0 THEN ORS.Mark("fixup not implemented") END;
  126. armcode[pc] := ((op * 10H + a) * 10H + b) * 100000H + (off MOD 100000H); INC(pc)
  127. END Put2orig;
  128. PROCEDURE Put3orig (op, cond, off: LONGINT);
  129. BEGIN (*emit branch instruction*)
  130. armcode[pc] := ((op+12) * 10H + cond) * 1000000H + (off MOD 1000000H); INC(pc);
  131. IF op = BC THEN (* armcode[pc] := tagBC; INC(pc) *)
  132. ELSIF op = BL THEN
  133. ASSERT(off >= 0);
  134. ASSERT(off DIV 10000000H = 0);
  135. armcode[pc] := tagBL + off DIV 1000000H;
  136. INC(pc)
  137. ELSE HALT(1)
  138. END
  139. END Put3orig;
  140. (*
  141. encode register
  142. NOTE:
  143. R0-R3, R12, LR: not need to save on interrupts
  144. R0-R7: best for Thumb-16 instructions
  145. *)
  146. PROCEDURE ER (a: INTEGER): INTEGER;
  147. BEGIN
  148. CASE a OF 0: RETURN ARMv6M.R0
  149. | 1: RETURN ARMv6M.R1
  150. | 2: RETURN ARMv6M.R2
  151. | 3: RETURN ARMv6M.R4
  152. | 4: RETURN ARMv6M.R5
  153. | 5: RETURN ARMv6M.R7
  154. | 6: RETURN ARMv6M.R12
  155. | 7: RETURN ARMv6M.R8
  156. | 8: RETURN ARMv6M.R9
  157. | 9: RETURN ARMv6M.R10
  158. | 10: RETURN ARMv6M.R11
  159. | MT: RETURN ARMv6M.R6
  160. | SB: RETURN ARMv6M.R3
  161. | SP: RETURN ARMv6M.SP
  162. | LNK: RETURN ARMv6M.LR
  163. | 15: RETURN ARMv6M.PC
  164. END
  165. END ER;
  166. PROCEDURE ERs (s: SET): SET;
  167. VAR r: SET; i: INTEGER;
  168. BEGIN
  169. r := {}; i := 0;
  170. WHILE i < 10H DO
  171. IF i IN s THEN INCL(r, ER(i)) END;
  172. INC(i)
  173. END;
  174. RETURN r
  175. END ERs;
  176. (* decode register *)
  177. PROCEDURE DR (a: INTEGER): INTEGER;
  178. BEGIN
  179. CASE a OF ARMv6M.R0: RETURN 0
  180. | ARMv6M.R1: RETURN 1
  181. | ARMv6M.R2: RETURN 2
  182. | ARMv6M.R3: RETURN SB
  183. | ARMv6M.R4: RETURN 3
  184. | ARMv6M.R5: RETURN 4
  185. | ARMv6M.R6: RETURN MT
  186. | ARMv6M.R7: RETURN 5
  187. | ARMv6M.R8: RETURN 7
  188. | ARMv6M.R9: RETURN 8
  189. | ARMv6M.R10: RETURN 9
  190. | ARMv6M.R11: RETURN 10
  191. | ARMv6M.R12: RETURN 6
  192. | ARMv6M.SP: RETURN SP
  193. | ARMv6M.LR: RETURN LNK
  194. | ARMv6M.PC: RETURN 15
  195. END
  196. END DR;
  197. PROCEDURE UpdateFlags (a: INTEGER);
  198. VAR isMI: BOOLEAN; i, imm3, imm8: INTEGER;
  199. BEGIN
  200. a := ER(a);
  201. IF a DIV 8 = 0 THEN
  202. ARMv6M.EmitCMPIm(armcode, pc, a, 0)
  203. ELSE
  204. ARMv7M.EncodeMI12(0, i, imm3, imm8, isMI);
  205. ASSERT(isMI, 100);
  206. ARMv7M.EmitCMPImW(armcode, pc, a, i, imm3, imm8)
  207. END
  208. END UpdateFlags;
  209. (* A6.7.17 *)
  210. PROCEDURE IsCMPIm (c: INTEGER): BOOLEAN;
  211. BEGIN
  212. RETURN c DIV 800H = 5
  213. END IsCMPIm;
  214. PROCEDURE RemoveRedundantCmp;
  215. VAR c: INTEGER;
  216. BEGIN
  217. IF (pc >= 2) & (armcode[pc - 1] DIV 10000H = 0) THEN
  218. IF ARMv6M.IsLThumb32(armcode[pc - 2]) THEN
  219. c := armcode[pc - 1] * 10000H + armcode[pc - 2];
  220. IF ARMv7M.IsCMPImW(c) & (c MOD 10H # 0FH) THEN
  221. DEC(pc, 2)
  222. END
  223. ELSIF IsCMPIm(armcode[pc - 1]) THEN
  224. DEC(pc)
  225. END
  226. END
  227. END RemoveRedundantCmp;
  228. (* emit RSBS a, a, #0 *)
  229. PROCEDURE RSBS0 (a: INTEGER);
  230. CONST S = 1;
  231. VAR i, imm3, imm8: INTEGER; isMI: BOOLEAN;
  232. BEGIN
  233. INCL(RM, a);
  234. a := ER(a);
  235. IF a DIV 8 = 0 THEN
  236. ARMv6M.EmitRSBS0(armcode, pc, a, a)
  237. ELSE
  238. ARMv7M.EncodeMI12(0, i, imm3, imm8, isMI); ASSERT(isMI, 100);
  239. ARMv7M.EmitRSBImW(armcode, pc, S, a, a, i, imm3, imm8)
  240. END
  241. END RSBS0;
  242. PROCEDURE Div0PosB (S: INTEGER; a, b, c: INTEGER);
  243. BEGIN
  244. ASSERT(S DIV 2 = 0, 20);
  245. (* A7.7.125: SDIV; encoding T1 ARMv7-M *)
  246. ASSERT(a IN {0..12,14}, 21);
  247. ASSERT(b IN {0..12,14}, 22);
  248. ASSERT(c IN {0..12,14}, 23);
  249. ARMv7M.EmitLMLMAAD(armcode, pc, 1, ER(b), 0F0H + ER(a), 0FH, ER(c));
  250. (* NOTE: overflow: 80000000H / 0FFFFFFFFH = 80000000H *)
  251. IF S = 1 THEN
  252. UpdateFlags(a)
  253. END
  254. END Div0PosB;
  255. PROCEDURE ^ Put10 (S: INTEGER; op, a, b, im: LONGINT);
  256. PROCEDURE ^ fix (at, with: LONGINT);
  257. PROCEDURE Div0NegB (S: INTEGER; a, b, c: INTEGER);
  258. VAR r: INTEGER;
  259. BEGIN
  260. IF a = c THEN
  261. r := RH;
  262. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  263. IF (b < MT) & (r <= b) THEN r := b + 1 END;
  264. ASSERT(r < MT, 100)
  265. ELSE r := a
  266. END;
  267. Put10(0, Add, r, b, 1);
  268. Div0PosB(0, a, r, c);
  269. Put10(S, Sub, a, a, 1)
  270. END Div0NegB;
  271. PROCEDURE Div0 (S: INTEGER; a, b, c: INTEGER);
  272. VAR pc0, pc1: LONGINT;
  273. BEGIN
  274. Put10(1, Cmp, b, b, 0);
  275. pc0 := pc; Put3orig(BC, GE, 0);
  276. Div0NegB(S, a, b, c);
  277. pc1 := pc; Put3orig(BC, 7, 0);
  278. fix(pc0, pc - pc0 - 1);
  279. Div0PosB(S, a, b, c);
  280. fix(pc1, pc - pc1 - 1)
  281. END Div0;
  282. (* op # Mov: R.a := R.b op R.c; op = Mov: R.a := R.c *)
  283. (* S=1: change NZCV according R.a after *)
  284. PROCEDURE Put00 (S: INTEGER; op, a, b, c: LONGINT);
  285. VAR u, v: BOOLEAN;
  286. r: INTEGER;
  287. BEGIN (*emit format-0 instruction
  288. code[pc] := ((a*10H + b) * 10H + op) * 10000H + c; *)
  289. ASSERT(S IN {0,1}, 20);
  290. IF ORS.errcnt = 0 THEN
  291. u := 13 IN BITS(op);
  292. IF u THEN DEC(op, U) END;
  293. v := 12 IN BITS(op);
  294. IF v THEN DEC(op, V) END;
  295. ASSERT(op DIV 10H = 0, 21);
  296. ASSERT(a DIV 10H = 0, 22);
  297. ASSERT(b DIV 10H = 0, 23);
  298. ASSERT(c DIV 10H = 0, 24);
  299. INCL(RM, a);
  300. IF ~((op IN {Add,Sub}) & u) THEN RemoveRedundantCmp END;
  301. CASE op MOD 10H OF Mov: (* R.a := R.c *)
  302. ASSERT(~v, 100);
  303. IF ~u THEN
  304. IF (ER(a) DIV 8 = 0) & ((ER(c) DIV 8 = 0) OR ((c = SP) & (S = 0))) THEN
  305. IF c = SP THEN
  306. ARMv6M.EmitADDSPIm(armcode, pc, ER(a), 0)
  307. ELSE
  308. ARMv6M.EmitMOVSR(armcode, pc, ER(a), ER(c))
  309. END
  310. ELSIF c = SP THEN
  311. (* A7.7.5: ADD (SP plus immediate); encoding T3 ARMv7-M *)
  312. ASSERT(a # 15, 103);
  313. ARMv7M.EmitDPMI(armcode, pc, 0, 16 + S, ER(c), 0, ER(a), 0)
  314. (* S = 1: N, Z, C, V will be updated *) (* NOTE: C *)
  315. ELSE
  316. (* A7.7.76: MOV (register); encoding T3 ARMv7-M *)
  317. ASSERT(~((S = 1) & ((a IN {13,15}) OR (c IN {13,15}))), 101);
  318. ASSERT(~((S = 0) & ((a = 15) OR (c = 15) OR (a = 13) & (c = 13))), 102);
  319. ARMv7M.EmitDPSR(armcode, pc, 2, S, 0FH, 0, ER(a), ER(c))
  320. (* S = 1: N, Z will be updated *)
  321. END
  322. ELSE
  323. ASSERT(b = 0, 101);
  324. ASSERT(c IN {0,1}, 102);
  325. IF c = 0 THEN
  326. HALT(103)
  327. ELSE (* c = 1 *)
  328. HALT(126) (* TODO *)
  329. END
  330. END
  331. | Lsl: (* R.a := R.b <- R.c *)
  332. ASSERT(~u, 104);
  333. ASSERT(~v, 105);
  334. IF (ER(a) DIV 8 = 0) & (a = b) & (ER(c) DIV 8 = 0) THEN
  335. ARMv6M.EmitLSLSR(armcode, pc, ER(a), ER(c))
  336. ELSE
  337. (* A7.7.68: LSL (register); encoding T2 ARMv7-M *)
  338. ASSERT(~(a IN {13,15}), 106);
  339. ASSERT(~(b IN {13,15}), 107);
  340. ASSERT(~(c IN {13,15}), 108);
  341. ARMv7M.EmitDPR(armcode, pc, 0 + S, ER(b), ER(a), 0, ER(c))
  342. (* S=1: N, Z, C will be updated *)
  343. END
  344. | Asr: (* R.a := R.b -> R.c *)
  345. ASSERT(~u, 109);
  346. ASSERT(~v, 110);
  347. IF (ER(a) DIV 8 = 0) & (a = b) & (ER(c) DIV 8 = 0) THEN
  348. ARMv6M.EmitASRSR(armcode, pc, ER(a), ER(c))
  349. ELSE
  350. (* A7.7.11: ASR (register); encoding T2 ARMv7-M *)
  351. ASSERT(~(a IN {13,15}), 111);
  352. ASSERT(~(b IN {13,15}), 112);
  353. ASSERT(~(c IN {13,15}), 113);
  354. ARMv7M.EmitDPR(armcode, pc, 4 + S, ER(b), ER(a), 0, ER(c))
  355. (* S=1: N, Z, C will be updated *)
  356. END
  357. | Ror: (* R.a := R.b rot R.c *)
  358. ASSERT(~u, 114);
  359. ASSERT(~v, 115);
  360. IF (ER(a) DIV 8 = 0) & (a = b) & (ER(c) DIV 8 = 0) THEN
  361. ARMv6M.EmitRORSR(armcode, pc, ER(a), ER(c))
  362. ELSE
  363. (* A7.7.115: ROR (register); encoding T2 ARMv7-M *)
  364. ASSERT(~(a IN {13,15}), 116);
  365. ASSERT(~(b IN {13,15}), 117);
  366. ASSERT(~(c IN {13,15}), 118);
  367. ARMv7M.EmitDPR(armcode, pc, 6 + S, ER(b), ER(a), 0, ER(c))
  368. (* S=1: N, Z, C will be updated *)
  369. END
  370. | And: (* R.a := R.b & R.c *)
  371. ASSERT(~u, 119);
  372. ASSERT(~v, 120);
  373. IF (ER(a) DIV 8 = 0) & (a = b) & (ER(c) DIV 8 = 0) THEN
  374. ARMv6M.EmitANDSR(armcode, pc, ER(a), ER(c))
  375. ELSIF (ER(a) DIV 8 = 0) & (a = c) & (ER(b) DIV 8 = 0) THEN
  376. ARMv6M.EmitANDSR(armcode, pc, ER(a), ER(b))
  377. ELSIF b = c THEN HALT(1) (* R.a := R.b *)
  378. ELSE
  379. (* A7.7.9: AND (register); encoding T2 ARMv7-M *)
  380. ASSERT(~(a IN {13,15}), 121);
  381. ASSERT(~(b IN {13,15}), 122);
  382. ASSERT(~(c IN {13,15}), 123);
  383. ARMv7M.EmitDPSR(armcode, pc, 0, S, ER(b), 0, ER(a), ER(c)) (* shift = 0 *)
  384. (* S=1: N, Z, C will be updated *)
  385. END
  386. | Ann: (* R.a := R.b & ~R.c *)
  387. ASSERT(~u, 124);
  388. ASSERT(~v, 125);
  389. ASSERT(b # c, 100); (* in this case, emit R.a := 0 *)
  390. IF (ER(a) DIV 8 = 0) & (a = b) & (ER(c) DIV 8 = 0) THEN (* R.a := R.a & ~R.c *)
  391. ARMv6M.EmitBICSR(armcode, pc, ER(a), ER(c))
  392. ELSE
  393. (* A7.7.16: BIC (register); encoding T2 ARMv7-M *)
  394. ASSERT(~(a IN {13,15}), 106);
  395. ASSERT(~(b IN {13,15}), 107);
  396. ASSERT(~(c IN {13,15}), 108);
  397. ARMv7M.EmitDPSR(armcode, pc, 1, S, ER(b), 0, ER(a), ER(c)) (* shift = 0 *)
  398. (* S=1: N, Z, C will be updated *)
  399. END
  400. | Ior: (* R.a := R.b or R.c *)
  401. ASSERT(~u, 104);
  402. ASSERT(~v, 105);
  403. IF (ER(a) DIV 8 = 0) & (a = b) & (ER(c) DIV 8 = 0) THEN
  404. ARMv6M.EmitORRSR(armcode, pc, ER(a), ER(c))
  405. ELSIF (ER(a) DIV 8 = 0) & (a = c) & (ER(b) DIV 8 = 0) THEN
  406. ARMv6M.EmitORRSR(armcode, pc, ER(a), ER(b))
  407. ELSIF b = c THEN HALT(1) (* R.a := R.b *)
  408. ELSE
  409. (* A7.7.91: ORR (register); encoding T2 ARMv7-M *)
  410. ASSERT(~(a IN {13,15}), 111);
  411. ASSERT(~(b IN {13,15}), 112);
  412. ASSERT(~(c IN {13,15}), 113);
  413. ARMv7M.EmitDPSR(armcode, pc, 2, S, ER(b), 0, ER(a), ER(c)) (* shift = 0 *)
  414. (* S=1: N, Z, C will be updated *)
  415. END
  416. | Xor: (* R.a := R.b xor R.c *)
  417. ASSERT(~u, 109);
  418. ASSERT(~v, 110);
  419. IF (ER(a) DIV 8 = 0) & (a = b) & (ER(c) DIV 8 = 0) THEN
  420. ARMv6M.EmitEORSR(armcode, pc, ER(a), ER(c))
  421. ELSIF (ER(a) DIV 8 = 0) & (a = c) & (ER(b) DIV 8 = 0) THEN
  422. ARMv6M.EmitEORSR(armcode, pc, ER(a), ER(b))
  423. ELSIF b = c THEN HALT(1)
  424. ELSE
  425. (* A7.7.35: EOR (register); encoding T2 ARMv7-M *)
  426. ASSERT(~(a IN {13,15}), 116);
  427. ASSERT(~(b IN {13,15}), 117);
  428. ASSERT(~(c IN {13,15}), 118);
  429. ARMv7M.EmitDPSR(armcode, pc, 4, S, ER(b), 0, ER(a), ER(c)) (* shift = 0 *)
  430. (* S=1: N, Z, C will be updated *)
  431. END
  432. | Add: (* R.a := R.b + R.c *)
  433. ASSERT(~v, 114);
  434. ASSERT(a # 15, 120);
  435. ASSERT(~(c IN {13,15}), 121);
  436. IF ~u THEN
  437. IF (ER(a) IN {0..7}) & (ER(b) IN {0..7}) & (ER(c) IN {0..7}) THEN
  438. ARMv6M.EmitADDSR(armcode, pc, ER(a), ER(b), ER(c))
  439. ELSIF (b = SP) & (S = 0) THEN
  440. ARMv6M.EmitADDSPR(armcode, pc, ER(a), ER(c))
  441. ELSIF ((a = b) OR (a = c)) & (S = 0) THEN
  442. IF a = b THEN
  443. ARMv6M.EmitADDR(armcode, pc, ER(a), ER(c))
  444. ELSE (* a = c *)
  445. ARMv6M.EmitADDR(armcode, pc, ER(a), ER(b))
  446. END
  447. ELSE
  448. ASSERT(b # 15, 122);
  449. ASSERT((b = 13) OR (a # 13), 123);
  450. (* A7.7.4: ADD (register); encoding T3 ARMv7-M *)
  451. (* A7.7.6: ADD (SP plus register); encoding T3 ARMv7-M *)
  452. ARMv7M.EmitDPSR(armcode, pc, 8, S, ER(b), 0, ER(a), ER(c)) (* shift = 0 *)
  453. (* S=1: N, Z, C, V will be updated *)
  454. END
  455. ELSE (* with carry *)
  456. IF (ER(a) DIV 8 = 0) & (a = b) & (ER(c) DIV 8 = 0) THEN
  457. ARMv6M.EmitADCSR(armcode, pc, ER(a), ER(c))
  458. ELSIF (ER(a) DIV 8 = 0) & (a = c) & (ER(b) DIV 8 = 0) THEN
  459. ARMv6M.EmitADCSR(armcode, pc, ER(a), ER(b))
  460. ELSE
  461. ASSERT(~(b IN {13,15}), 124);
  462. (* A7.7.2: ADC(register); encoding T2 ARMv7-M *)
  463. ARMv7M.EmitDPSR(armcode, pc, 10, S, ER(b), 0, ER(a), ER(c))
  464. (* S=1: N, Z, C, V will be updated *)
  465. END
  466. END
  467. | Sub: (* R.a := R.b - R.c *)
  468. ASSERT(~v, 119);
  469. ASSERT(a # 15, 100);
  470. ASSERT(~(c IN {13,15}), 101);
  471. IF ~u THEN
  472. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & (ER(c) DIV 8 = 0) THEN
  473. ARMv6M.EmitSUBSR(armcode, pc, ER(a), ER(b), ER(c))
  474. ELSE
  475. ASSERT(b # 15, 122);
  476. ASSERT((b = 13) OR (a # 13), 123);
  477. (* A7.7.172: SUB (register); encoding T2 ARMv7-M *)
  478. (* A7.7.174: SUB (SP minus register); encoding T1 *)
  479. ARMv7M.EmitDPSR(armcode, pc, 13, S, ER(b), 0, ER(a), ER(c))
  480. (* S=1: N, Z, C, V will be updated *)
  481. END
  482. ELSE (* with carry *)
  483. IF (ER(a) DIV 8 = 0) & (a = b) & (ER(c) DIV 8 = 0) THEN
  484. ARMv6M.EmitSBCSR(armcode, pc, ER(a), ER(c))
  485. ELSE
  486. ASSERT(~(b IN {13,15}), 123);
  487. (* A7.7.123: SBC (register); encoding T2 ARMv7-M *)
  488. ARMv7M.EmitDPSR(armcode, pc, 11, S, ER(b), 0, ER(a), ER(c))
  489. (* S=1: N, Z, C, V will be updated *)
  490. END
  491. END
  492. | Mul: (* R.a := R.b * R.c *)
  493. ASSERT(~v, 124);
  494. IF ~u THEN
  495. IF (a # b) & (a = c) THEN r := b; b := c; c := r END;
  496. IF (a = b) & (ER(a) DIV 8 = 0) & (ER(c) DIV 8 = 0) THEN
  497. (* NOTE:
  498. low word of result does not depend on sign of operands *)
  499. ARMv6M.EmitMULSR(armcode, pc, ER(a), ER(c))
  500. ELSE
  501. (* NOTE:
  502. low word of result does not depend on sign of operands *)
  503. ARMv7M.EmitMUL(armcode, pc, ER(a), ER(b), ER(c));
  504. IF S = 1 THEN
  505. UpdateFlags(a)
  506. END
  507. END
  508. ELSE
  509. HALT(126)
  510. END
  511. | Div: (* R.a := R.b div R.c *)
  512. ASSERT(~u, 103);
  513. ASSERT(~v, 104);
  514. Div0(S, a, b, c)
  515. END
  516. END
  517. END Put00;
  518. PROCEDURE Put0 (op, a, b, c: INTEGER);
  519. BEGIN
  520. Put00(1, op, a, b, c)
  521. END Put0;
  522. (* R.a := im *)
  523. (* NOTE: ARMv7MLinker.MovIm0 *)
  524. PROCEDURE MovIm (S: INTEGER; a: INTEGER; im: INTEGER);
  525. VAR shift: INTEGER;
  526. isLR: BOOLEAN;
  527. imInv: INTEGER; isMI: BOOLEAN; i, imm3, imm8, imm4: INTEGER;
  528. BEGIN
  529. ASSERT(S IN {0,1}, 20);
  530. ASSERT(a IN {0..14}, 21);
  531. INCL(RM, a);
  532. IF a # SP THEN
  533. isLR := ER(a) DIV 8 = 0;
  534. IF isLR & (im DIV 100H = 0) THEN
  535. ARMv6M.EmitMOVSIm(armcode, pc, ER(a), im)
  536. ELSE
  537. ARMv7M.EncodeMI12(im, i, imm3, imm8, isMI);
  538. IF isMI THEN
  539. (* A7.7.75: MOV (immediate); encoding T2 ARMv7-M *)
  540. ARMv7M.EmitDPMI(armcode, pc, i, 4 + S, 0FH, imm3, ER(a), imm8)
  541. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  542. ELSE
  543. imInv := ORDSET(BITS(im) / {0..31});
  544. ARMv7M.EncodeMI12(imInv, i, imm3, imm8, isMI);
  545. IF isMI THEN
  546. (* A7.7.84: MVN (immediate); encoding T1 ARMv7-M *)
  547. ARMv7M.EmitDPMI(armcode, pc, i, 6 + S, 0FH, imm3, ER(a), imm8)
  548. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  549. ELSIF isLR & (im > 255) & (im <= 255 + 255) THEN
  550. ARMv6M.EmitMOVSIm(armcode, pc, ER(a), 255);
  551. ARMv6M.EmitADDSIm(armcode, pc, ER(a), ER(a), im - 255)
  552. ELSE
  553. shift := 8;
  554. WHILE (shift < 32) & (SYSTEM.ROT(im DIV 100H * 100H, -shift) DIV 100H # 0) DO INC(shift) END;
  555. IF isLR & (shift < 32) THEN
  556. ASSERT(im =
  557. SYSTEM.LSH(SYSTEM.ROT(im DIV 100H * 100H, -shift), shift)
  558. + im MOD 100H);
  559. ARMv6M.EmitMOVSIm(armcode, pc, ER(a), SYSTEM.ROT(im DIV 100H * 100H, -shift));
  560. ARMv6M.EmitLSLSIm(armcode, pc, ER(a), ER(a), shift);
  561. ARMv6M.EmitADDSIm(armcode, pc, ER(a), ER(a), im MOD 100H)
  562. ELSE
  563. (* TODO: 3 ops: mov; (add, lsl), (lsl, sub), (lsl, sub) | MI12; add, lsl, sub *)
  564. IF isLR & (im MOD 10000H DIV 100H = 0) THEN
  565. ARMv6M.EmitMOVSIm(armcode, pc, ER(a), im MOD 10000H)
  566. ELSE
  567. (* A7.7.75: MOV (immediate); encoding T3 ARMv7-M *)
  568. imm4 := im DIV 1000H MOD 10H;
  569. i := im DIV 800H MOD 2;
  570. imm3 := im DIV 100H MOD 8;
  571. imm8 := im MOD 100H;
  572. ARMv7M.EmitDPPBI(armcode, pc, i, 4, imm4, imm3 * 1000H + ER(a) * 100H + imm8)
  573. END;
  574. im := im DIV 10000H;
  575. IF im # 0 THEN
  576. (* A7.7.78: MOVT; encoding T1 ARMv7 *)
  577. imm4 := im DIV 1000H MOD 10H;
  578. i := im DIV 800H MOD 2;
  579. imm3 := im DIV 100H MOD 8;
  580. imm8 := im MOD 100H;
  581. ARMv7M.EmitDPPBI(armcode, pc, i, 12, imm4, imm3 * 1000H + ER(a) * 100H + imm8)
  582. END;
  583. IF S = 1 THEN
  584. UpdateFlags(a)
  585. END
  586. END
  587. END
  588. END
  589. END
  590. ELSE (* a = SP *)
  591. ASSERT(RH < MT, 100);
  592. ASSERT(RH # SP, 101);
  593. MovIm(S, RH, im);
  594. Put00(S, Mov, SP, 0, RH)
  595. END
  596. END MovIm;
  597. (* op # Mov: R.a := R.b op im; op = Mov: R.a := im *)
  598. (* change NZCV according R.a after *)
  599. PROCEDURE Put10 (S: INTEGER; op, a, b, im: LONGINT);
  600. VAR u, v: BOOLEAN;
  601. isMI: BOOLEAN; i, imm3, imm8: INTEGER;
  602. imm2: INTEGER;
  603. imInv: INTEGER;
  604. r: INTEGER;
  605. BEGIN (*emit format-1 instruction, -10000H <= im < 10000H
  606. IF im < 0 THEN INC(op, V) END ;
  607. code[pc] := (((a+40H) * 10H + b) * 10H + op) * 10000H + (im MOD 10000H); INC(pc) *)
  608. ASSERT(S IN {0,1}, 20);
  609. IF ORS.errcnt = 0 THEN
  610. v := 12 IN BITS(op);
  611. IF v THEN DEC(op, V) END;
  612. ASSERT(~v, 100);
  613. u := 13 IN BITS(op);
  614. IF u THEN
  615. ASSERT(im DIV 10000H = 0, 21);
  616. DEC(op, U);
  617. ASSERT(op = Mov, 100);
  618. im := im * 10000H
  619. END;
  620. IF op MOD 10H = Ann THEN
  621. op := (op DIV 10H) * 10H + And;
  622. im := ORDSET(BITS(im) / {0..31}) (* im := ~im *)
  623. END;
  624. (* im: any const *)
  625. ASSERT(op DIV 10H = 0, 22);
  626. ASSERT(a DIV 10H = 0, 23);
  627. ASSERT(b DIV 10H = 0, 24);
  628. IF ~((op = Cmp) & (a = b) & (im = 0)) THEN (* ~Cmp *)
  629. INCL(RM, a)
  630. END;
  631. RemoveRedundantCmp;
  632. op := op MOD 10H;
  633. IF op IN {Lsl,Asr,Ror} THEN
  634. IF im = 0 THEN
  635. Put00(S, Mov, a, 0, b)
  636. ELSIF (im = 32) & (op = Ror) & (S = 1) THEN
  637. IF a = b THEN
  638. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  639. ASSERT(r < MT, 100);
  640. MovIm(0, r, im);
  641. Put00(S, op, a, b, r)
  642. ELSE
  643. MovIm(0, a, im);
  644. Put00(S, op, a, b, a)
  645. END
  646. ELSE
  647. ASSERT(~(a IN {13,15}), 100);
  648. ASSERT(~(b IN {13,15}), 101);
  649. ASSERT(im DIV 32 = 0, 126);
  650. imm3 := im DIV 4; imm2 := im MOD 4;
  651. CASE op OF Lsl: (* R.a := R.b <- im *)
  652. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) THEN
  653. ARMv6M.EmitLSLSIm(armcode, pc, ER(a), ER(b), im)
  654. ELSE
  655. (* A7.7.67: LSL (immediate); encoding T2 ARMv7-M *)
  656. ARMv7M.EmitDPSR(armcode, pc, 2, S, 0FH, imm3, ER(a), imm2 * 40H + ER(b))
  657. (* S=1: N, Z, C will be updated *)
  658. END
  659. | Asr: (* R.a := R.b -> im *)
  660. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) THEN
  661. ARMv6M.EmitASRSIm(armcode, pc, ER(a), ER(b), im)
  662. ELSE
  663. (* A7.7.10: ASR (immediate); encoding T2 ARMv7-M *)
  664. ARMv7M.EmitDPSR(armcode, pc, 2, S, 0FH, imm3, ER(a), imm2 * 40H + 20H + ER(b))
  665. (* S=1: N, Z, C will be updated *)
  666. END
  667. | Ror: (* R.a := R.b rot im *)
  668. ARMv7M.EmitRORIm(armcode, pc, S, ER(a), ER(b), im)
  669. (* S=1: N, Z, C will be updated *)
  670. END
  671. END
  672. ELSIF op = Mov THEN
  673. MovIm(S, a, im)
  674. ELSE
  675. ARMv7M.EncodeMI12(im, i, imm3, imm8, isMI);
  676. CASE op OF And: (* R.a := R.b & im *)
  677. IF isMI THEN
  678. (* A7.7.8: AND (immediate); encoding T1 ARMv7-M *)
  679. ASSERT(~(a IN {13,15}), 100);
  680. ASSERT(~(b IN {13,15}), 101);
  681. ARMv7M.EmitDPMI(armcode, pc, i, S, ER(b), imm3, ER(a), imm8)
  682. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  683. ELSE
  684. imInv := ORDSET(BITS(im) / {0..31});
  685. ARMv7M.EncodeMI12(imInv, i, imm3, imm8, isMI);
  686. IF isMI THEN
  687. (* A7.7.15: BIC (immediate); encoding T1 ARMv7-M *)
  688. ASSERT(~(a IN {13,15}), 100);
  689. ASSERT(~(b IN {13,15}), 102);
  690. ARMv7M.EmitDPMI(armcode, pc, i, 2 + S, ER(b), imm3, ER(a), imm8)
  691. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  692. ELSE
  693. (* TODO: MOV, ORN optimization(s) possible?... *)
  694. IF a = b THEN
  695. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  696. ASSERT(r < MT, 102);
  697. MovIm(0, r, im);
  698. Put00(S, op, a, b, r)
  699. ELSE
  700. MovIm(0, a, im);
  701. Put00(S, op, a, b, a)
  702. END
  703. END
  704. END
  705. | Ior: (* R.a := R.b or im *)
  706. IF isMI THEN
  707. (* A7.7.90: ORR (immediate); encoding T1 ARMv7-M *)
  708. ASSERT(~(a IN {13,15}), 100);
  709. ASSERT(~(b IN {13,15}), 102);
  710. ARMv7M.EmitDPMI(armcode, pc, i, 4 + S, ER(b), imm3, ER(a), imm8)
  711. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  712. ELSE (* try R.a := R.b or~ ~im *)
  713. imInv := ORDSET(BITS(im) / {0..31});
  714. ARMv7M.EncodeMI12(imInv, i, imm3, imm8, isMI);
  715. IF isMI THEN
  716. (* A7.7.88: ORN (immediate); encoding T1 ARMv7-M *)
  717. ASSERT(~(a IN {13,15}), 100);
  718. ASSERT(~(b IN {13,15}), 102);
  719. ARMv7M.EmitDPMI(armcode, pc, i, 6 + S, ER(b), imm3, ER(a), imm8)
  720. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  721. ELSE
  722. (* TODO: MOV, ORN optimization(s) possible?... *)
  723. IF a = b THEN
  724. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  725. ASSERT(r < MT, 102);
  726. MovIm(0, r, im);
  727. Put00(S, op, a, b, r)
  728. ELSE
  729. MovIm(0, a, im);
  730. Put00(S, op, a, b, a)
  731. END
  732. END
  733. END
  734. | Xor: (* R.a := R.b xor im *)
  735. IF isMI THEN
  736. (* A7.7.34: EOR (immediate); encoding T1 ARMv7-M *)
  737. ASSERT(~(a IN {13,15}), 100);
  738. ASSERT(~(b IN {13,15}), 103);
  739. ARMv7M.EmitDPMI(armcode, pc, i, 8 + S, ER(b), imm3, ER(a), imm8)
  740. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  741. ELSIF a = b THEN
  742. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  743. ASSERT(r < MT, 102);
  744. MovIm(0, r, im);
  745. Put00(S, op, a, b, r)
  746. ELSE
  747. MovIm(0, a, im);
  748. Put00(S, op, a, b, a)
  749. END
  750. | Add: (* R.a := R.b + im *)
  751. ASSERT(a # 15, 104);
  752. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & ((im DIV 8 = 0) OR (im DIV 100H = 0) & (a = b)) THEN
  753. ARMv6M.EmitADDSIm(armcode, pc, ER(a), ER(b), im)
  754. ELSIF (b = SP) & (im MOD 4 = 0) & (S = 0) & (((a = SP) & (im DIV 200H = 0)) OR ((ER(a) DIV 8 = 0) & (im DIV 400H = 0))) THEN
  755. ARMv6M.EmitADDSPIm(armcode, pc, ER(a), im DIV 4)
  756. ELSIF isMI THEN
  757. ASSERT(b # 15, 105);
  758. ASSERT((b = 13) OR (a # 13), 106);
  759. (* A7.7.3: ADD (immediate); encoding T3 ARMv7-M *)
  760. (* A7.7.5: ADD (SP plus immediate); encoding T3 ARMv7-M *)
  761. ARMv7M.EmitDPMI(armcode, pc, i, 16 + S, ER(b), imm3, ER(a), imm8)
  762. (* S = 1: N, Z, C, V will be updated *) (* NOTE: C *)
  763. ELSIF im DIV 1000H = 0 THEN
  764. ASSERT((b = 13) OR ((b # 15) & (a # 13)), 107);
  765. (* A7.7.3: ADD (immediate); encoding T4 ARMv7-M *)
  766. (* A7.7.5: ADD (SP plus immediate); encoding T4 ARMv7-M *)
  767. i := im DIV 800H;
  768. imm3 := im DIV 100H MOD 8;
  769. imm8 := im MOD 100H;
  770. ARMv7M.EmitDPPBI(armcode, pc, i, 0, ER(b), imm3 * 1000H + ER(a) * 100H + imm8);
  771. IF S = 1 THEN
  772. UpdateFlags(a)
  773. END
  774. ELSIF a = b THEN
  775. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  776. ASSERT(r < MT, 108);
  777. MovIm(0, r, im);
  778. Put00(S, op, a, b, r)
  779. ELSE
  780. MovIm(0, a, im);
  781. Put00(S, op, a, b, a)
  782. END
  783. | Sub: (* R.a := R.b - im *)
  784. ASSERT(a # 15, 107);
  785. IF (a = b) & (im = 0) THEN (* Cmp *)
  786. ASSERT(S = 1, 100);
  787. UpdateFlags(a)
  788. ELSIF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & ((im DIV 8 = 0) OR (im DIV 100H = 0) & (a = b)) THEN
  789. ARMv6M.EmitSUBSIm(armcode, pc, ER(a), ER(b), im)
  790. ELSIF (a = SP) & (b = SP) & (im MOD 4 = 0) & (S = 0) & (im DIV 200H = 0) THEN
  791. ARMv6M.EmitSUBSPIm(armcode, pc, im DIV 4)
  792. ELSIF isMI THEN
  793. ASSERT(b # 15, 108);
  794. ASSERT((b = 13) OR (a # 13), 109);
  795. (* A7.7.171: SUB (immediate); encoding T3 ARMv7-M *)
  796. (* A7.7.173: SUB (SP minus immediate); encoding T2 ARMv7-M *)
  797. ARMv7M.EmitDPMI(armcode, pc, i, 1AH + S, ER(b), imm3, ER(a), imm8)
  798. (* S=1: N, Z, C, V will be updated *) (* NOTE: C *)
  799. ELSIF (im DIV 1000H = 0) & ((S = 0) OR ~updateCarry) THEN
  800. ASSERT((b = 13) OR ((b # 15) & (a # 13)), 110);
  801. (* A7.7.171: SUB (immediate); encoding T4 ARMv7-M *)
  802. (* A7.7.173: SUB (SP minus immediate); encoding T3 ARMv7-M *)
  803. i := im DIV 800H;
  804. imm3 := im DIV 100H MOD 8;
  805. imm8 := im MOD 100H;
  806. ARMv7M.EmitDPPBI(armcode, pc, i, 10, ER(b), imm3 * 1000H + ER(a) * 100H + imm8);
  807. IF S = 1 THEN
  808. ASSERT(~updateCarry);
  809. UpdateFlags(a)
  810. (* NOTE: in this case C flag updated incorrectly *)
  811. END
  812. ELSIF a = b THEN
  813. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  814. ASSERT(r < MT, 111);
  815. MovIm(0, r, im);
  816. Put00(S, op, a, b, r)
  817. ELSE
  818. MovIm(0, a, im);
  819. Put00(S, op, a, b, a)
  820. END
  821. | Mul: (* R.a := R.b * im *)
  822. IF a = b THEN
  823. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  824. ASSERT(r < MT, 112);
  825. MovIm(0, r, im);
  826. Put00(S, op, a, b, r)
  827. ELSE
  828. MovIm(0, a, im);
  829. Put00(S, op, a, b, a)
  830. END
  831. | Div: (* R.a := R.b div im *)
  832. IF a = b THEN
  833. r := RH; IF (a < MT) & (r <= a) THEN r := a + 1 END;
  834. ASSERT(r < MT, 113);
  835. MovIm(0, r, im);
  836. Put00(S, op, a, b, r)
  837. ELSE
  838. MovIm(0, a, im);
  839. Put00(S, op, a, b, a)
  840. END
  841. END
  842. END
  843. END
  844. END Put10;
  845. PROCEDURE Put1 (op, a, b, im: INTEGER);
  846. BEGIN
  847. Put10(1, op, a, b, im)
  848. END Put1;
  849. PROCEDURE Put1a (op, a, b, im: LONGINT);
  850. BEGIN (*same as Put1, but with range test -10000H <= im < 10000H
  851. IF (im >= -10000H) & (im <= 0FFFFH) THEN Put1(op, a, b, im)
  852. ELSE Put1(Mov+U, RH, 0, im DIV 10000H);
  853. IF im MOD 10000H # 0 THEN Put1(Ior, RH, RH, im MOD 10000H) END ;
  854. Put0(op, a, b, RH)
  855. END *)
  856. ASSERT(op DIV 10H = 0, 20);
  857. Put1(op, a, b, im)
  858. END Put1a;
  859. PROCEDURE Put20 (S: INTEGER; op, a, b, off: LONGINT);
  860. VAR v: BOOLEAN;
  861. r: INTEGER;
  862. BEGIN (*emit load/store instruction
  863. code[pc] := ((op * 10H + a) * 10H + b) * 100000H + (off MOD 100000H); INC(pc) *)
  864. ASSERT(S IN {0,1}, 20);
  865. IF ORS.errcnt = 0 THEN
  866. ASSERT(b DIV 10H = 0, 21);
  867. (*
  868. ASSERT(off >= 0, 22);
  869. ASSERT(off < 100000H, 23);
  870. *)
  871. ASSERT(off >= -80000H, 22);
  872. ASSERT(off < 80000H, 23);
  873. v := ODD(op); IF v THEN DEC(op) END;
  874. RemoveRedundantCmp;
  875. IF op = Ldr THEN (* R.a := Mem[R.b + off] *)
  876. ASSERT(a DIV 10H = 0, 24);
  877. (* http://www.st.com/web/en/resource/technical/document/errata_sheet/DM00037591.pdf, section 1.1 *)
  878. ASSERT(ER(a) # SP);
  879. INCL(RM, a);
  880. IF ~v THEN (* load word *)
  881. ASSERT(off MOD 4 = 0, 100);
  882. IF off < 0 THEN
  883. ARMv7M.EmitLWImWNeg(armcode, pc, ER(a), ER(b), -off)
  884. ELSIF (ER(a) DIV 8 = 0) & (((b = SP) & (off DIV 400H = 0)) OR ((ER(b) DIV 8 = 0) & (off DIV 4 DIV 32 = 0))) THEN
  885. ARMv6M.EmitLDRIm(armcode, pc, ER(a), ER(b), off DIV 4)
  886. ELSIF off < 1000H THEN
  887. ARMv7M.EmitLWImW(armcode, pc, ER(a), ER(b), off)
  888. ELSE
  889. IF a = b THEN
  890. r := RH;
  891. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  892. ASSERT(r < MT, 101)
  893. ELSE
  894. r := a
  895. END;
  896. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & (ER(r) DIV 8 = 0) THEN
  897. MovIm(0, r, off);
  898. ARMv6M.EmitLDRR(armcode, pc, ER(a), ER(b), ER(r))
  899. ELSIF off MOD 8 = 0 THEN
  900. MovIm(0, r, off DIV 8);
  901. ARMv7M.EmitLWRW(armcode, pc, ER(a), ER(b), ER(r), 3)
  902. ELSE
  903. MovIm(0, r, off DIV 4);
  904. ARMv7M.EmitLWRW(armcode, pc, ER(a), ER(b), ER(r), 2)
  905. END
  906. END
  907. ELSE (* load byte *)
  908. IF off < 0 THEN
  909. HALT(126)
  910. ELSIF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & (off DIV 32 = 0) THEN
  911. ARMv6M.EmitLDRBIm(armcode, pc, ER(a), ER(b), off)
  912. ELSIF off < 1000H THEN
  913. ARMv7M.EmitLBImW(armcode, pc, ER(a), ER(b), off)
  914. ELSE
  915. IF a = b THEN
  916. r := RH;
  917. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  918. ASSERT(r < MT, 101)
  919. ELSE
  920. r := a
  921. END;
  922. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & (ER(r) DIV 8 = 0) THEN
  923. MovIm(0, r, off);
  924. ARMv6M.EmitLDRBR(armcode, pc, ER(a), ER(b), ER(r))
  925. ELSIF off MOD 8 = 0 THEN
  926. MovIm(0, r, off DIV 8);
  927. ARMv7M.EmitLBRW(armcode, pc, ER(a), ER(b), ER(r), 3)
  928. ELSIF off MOD 4 = 0 THEN
  929. MovIm(0, r, off DIV 4);
  930. ARMv7M.EmitLBRW(armcode, pc, ER(a), ER(b), ER(r), 2)
  931. ELSIF off MOD 2 = 0 THEN
  932. MovIm(0, r, off DIV 2);
  933. ARMv7M.EmitLBRW(armcode, pc, ER(a), ER(b), ER(r), 1)
  934. ELSE
  935. MovIm(0, r, off);
  936. ARMv7M.EmitLBRW(armcode, pc, ER(a), ER(b), ER(r), 0)
  937. END
  938. END
  939. END;
  940. IF S = 1 THEN UpdateFlags(a) END
  941. ELSIF op = Str THEN (* Mem[R.b + off] := R.a *)
  942. ASSERT(off >= 0, 126);
  943. IF ~v THEN (* store word *)
  944. ASSERT(off MOD 4 = 0, 102);
  945. IF a >= 100H THEN (* FPU register *)
  946. DEC(a, 100H);
  947. IF off DIV 400H = 0 THEN
  948. ARMv7M.EmitVSTR(armcode, pc, ER(a), ER(b), 1, off DIV 4)
  949. ELSE
  950. ARMv7M.EmitVMOVSPR(armcode, pc, 1, ER(a), ER(a));
  951. INCL(RM, a);
  952. Put20(S, op, a, b, off)
  953. END
  954. ELSIF (ER(a) DIV 8 = 0) & (((b = SP) & (off DIV 400H = 0)) OR ((ER(b) DIV 8 = 0) & (off DIV 4 DIV 32 = 0))) THEN
  955. ARMv6M.EmitSTRIm(armcode, pc, ER(a), ER(b), off DIV 4)
  956. ELSIF off < 1000H THEN
  957. ARMv7M.EmitSWImW(armcode, pc, ER(a), ER(b), off)
  958. ELSE
  959. r := RH;
  960. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  961. IF (b < MT) & (r <= b) THEN r := b + 1 END;
  962. ASSERT(r < MT, 101);
  963. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & (ER(r) DIV 8 = 0) THEN
  964. MovIm(0, r, off);
  965. ARMv6M.EmitSTRR(armcode, pc, ER(a), ER(b), ER(r))
  966. ELSIF off MOD 8 = 0 THEN
  967. MovIm(0, r, off DIV 8);
  968. ARMv7M.EmitSWRW(armcode, pc, ER(a), ER(b), ER(r), 3)
  969. ELSE
  970. MovIm(0, r, off DIV 4);
  971. ARMv7M.EmitSWRW(armcode, pc, ER(a), ER(b), ER(r), 2)
  972. END
  973. END
  974. ELSE (* store byte *)
  975. ASSERT(a DIV 10H = 0, 100);
  976. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & (off DIV 32 = 0) THEN
  977. ARMv6M.EmitSTRBIm(armcode, pc, ER(a), ER(b), off)
  978. ELSIF off < 1000H THEN
  979. ARMv7M.EmitSBImW(armcode, pc, ER(a), ER(b), off)
  980. ELSE
  981. r := RH;
  982. IF (a < MT) & (r <= a) THEN r := a + 1 END;
  983. IF (b < MT) & (r <= b) THEN r := b + 1 END;
  984. ASSERT(r < MT, 101);
  985. IF (ER(a) DIV 8 = 0) & (ER(b) DIV 8 = 0) & (ER(r) DIV 8 = 0) THEN
  986. MovIm(0, r, off);
  987. ARMv6M.EmitSTRBR(armcode, pc, ER(a), ER(b), ER(r))
  988. ELSIF off MOD 8 = 0 THEN
  989. MovIm(0, r, off DIV 8);
  990. ARMv7M.EmitSBRW(armcode, pc, ER(a), ER(b), ER(r), 3)
  991. ELSIF off MOD 4 = 0 THEN
  992. MovIm(0, r, off DIV 4);
  993. ARMv7M.EmitSBRW(armcode, pc, ER(a), ER(b), ER(r), 2)
  994. ELSIF off MOD 2 = 0 THEN
  995. MovIm(0, r, off DIV 2);
  996. ARMv7M.EmitSBRW(armcode, pc, ER(a), ER(b), ER(r), 1)
  997. ELSE
  998. MovIm(0, r, off);
  999. ARMv7M.EmitSBRW(armcode, pc, ER(a), ER(b), ER(r), 0)
  1000. END
  1001. END
  1002. END
  1003. ELSE HALT(1) (* invalid operation *)
  1004. END
  1005. END
  1006. END Put20;
  1007. PROCEDURE Put2 (op, a, b, off: INTEGER);
  1008. BEGIN
  1009. Put20(1, op, a, b, off)
  1010. END Put2;
  1011. PROCEDURE CondRISCToARM (cond: INTEGER): INTEGER;
  1012. BEGIN
  1013. CASE cond OF MI: RETURN ARMv6M.MI
  1014. | EQ: RETURN ARMv6M.EQ
  1015. | 2: RETURN ARMv6M.CC
  1016. | LT: RETURN ARMv6M.LT
  1017. | LE: RETURN ARMv6M.LE
  1018. | 7: RETURN ARMv6M.AL
  1019. | PL: RETURN ARMv6M.PL
  1020. | NE: RETURN ARMv6M.NE
  1021. | 10: RETURN ARMv6M.CS
  1022. | GE: RETURN ARMv6M.GE
  1023. | GT: RETURN ARMv6M.GT
  1024. (* | 15: RETURN 15 *)
  1025. END
  1026. END CondRISCToARM;
  1027. (*
  1028. PROCEDURE CondARMToRISC (armcond: INTEGER): INTEGER;
  1029. BEGIN
  1030. CASE armcond OF ARMv6M.EQ: RETURN EQ
  1031. | ARMv6M.NE: RETURN NE
  1032. | ARMv6M.CS: RETURN 10
  1033. | ARMv6M.CC: RETURN 2
  1034. | ARMv6M.MI: RETURN MI
  1035. | ARMv6M.PL: RETURN PL
  1036. | ARMv6M.GE: RETURN GE
  1037. | ARMv6M.LT: RETURN LT
  1038. | ARMv6M.GT: RETURN GT
  1039. | ARMv6M.LE: RETURN LE
  1040. | ARMv6M.AL: RETURN 7
  1041. (* | 15: RETURN 15 *)
  1042. END
  1043. END CondARMToRISC;
  1044. *)
  1045. PROCEDURE ^ negated(cond: LONGINT): LONGINT;
  1046. PROCEDURE Put3 (op, cond, off: LONGINT);
  1047. VAR S, imm10, J1, J2, imm11, imm6: INTEGER;
  1048. pc0, pc1: INTEGER;
  1049. BEGIN (*emit branch instruction
  1050. code[pc] := ((op+12) * 10H + cond) * 1000000H + (off MOD 1000000H); INC(pc) *)
  1051. IF ORS.errcnt = 0 THEN
  1052. ASSERT(op DIV 4 = 0, 20);
  1053. ASSERT(cond DIV 10H = 0, 21);
  1054. CASE op OF BR: (* if cond, then PC := R.c *)
  1055. IF off IN {0..15} THEN
  1056. ASSERT(cond = 7, 102);
  1057. ARMv6M.EmitBX(armcode, pc, ER(off))
  1058. ELSIF off = 10H THEN
  1059. (* return from interrupt *)
  1060. HALT(126)
  1061. ELSE HALT(1)
  1062. END
  1063. | BLR:
  1064. IF off MOD 10H = MT THEN (* Trap or New *)
  1065. off := off DIV 10H MOD 10000000H;
  1066. (* see Kernel.Trap, System.Trap *)
  1067. IF off MOD 10H = 0 THEN (* New *)
  1068. ASSERT(cond = 7, 100);
  1069. (* NOTE: New() arguments in R0, R1 *)
  1070. ARMv6M.EmitSVC(armcode, pc, off MOD 10H)
  1071. ELSIF cond = 7 THEN
  1072. MovIm(0, 1, off DIV 10H); (* R1 := ORS.Pos *)
  1073. ARMv6M.EmitSVC(armcode, pc, off MOD 10H)
  1074. ELSE
  1075. pc0 := pc; Put3(BC, 0, 0);
  1076. MovIm(0, 1, off DIV 10H); (* R1 := ORS.Pos *)
  1077. ARMv6M.EmitSVC(armcode, pc, off MOD 10H);
  1078. pc1 := pc;
  1079. pc := pc0;
  1080. Put3(BC, negated(cond), pc1 - pc0 - 1);
  1081. pc := pc1
  1082. END
  1083. ELSE (* if cond, then LNK := PC+1; PC := R.c *)
  1084. ASSERT(off DIV 10H = 0, 101);
  1085. ASSERT(cond = 7, 102);
  1086. ASSERT(off # 15, 103);
  1087. INCL(RM, LNK);
  1088. ARMv6M.EmitBLX(armcode, pc, ER(off))
  1089. END
  1090. | BC: (* if cond, then PC := PC+1+offset *)
  1091. ASSERT(off >= -800000H, 102);
  1092. ASSERT(off < 800000H, 103);
  1093. DEC(off);
  1094. IF cond = 7 THEN
  1095. IF (off >= -1024) & (off <= 1023) THEN
  1096. ARMv6M.EmitB(armcode, pc, off)
  1097. ELSE
  1098. (*
  1099. (* A7.7.12: B; encoding T4 ARMv7-M *)
  1100. ARMv6M.EncodeBLabel24(off, S, imm10, J1, J2, imm11);
  1101. ARMv7M.EmitBAMC(armcode, pc, S * 40H + imm10 DIV 10H, imm10 MOD 10H, J1 * 2 + 1, J2 * 800H + imm11)
  1102. *)
  1103. ORS.Mark("unconditional branch is too long")
  1104. END
  1105. ELSIF cond = 15 THEN
  1106. ARMv6M.EmitNOP(armcode, pc)
  1107. ELSE
  1108. cond := CondRISCToARM(cond);
  1109. IF (off >= -128) & (off <= 127) THEN
  1110. ARMv6M.EmitBC(armcode, pc, cond, off)
  1111. ELSE
  1112. (*
  1113. (* A7.7.12: B; encoding T3 ARMv7-M *)
  1114. ARMv7M.EncodeBLabel20(off, S, imm6, J1, J2, imm11);
  1115. ARMv7M.EmitBAMC(armcode, pc, S * 40H + cond * 4 + imm6 DIV 10H, imm6 MOD 10H, J1 * 2, J2 * 800H + imm11)
  1116. *)
  1117. ORS.Mark("conditional branch is too long")
  1118. END
  1119. END
  1120. | BL: (* if cond, then LNK := PC+1; PC := PC+1+offset *)
  1121. ASSERT(off >= -800000H, 104);
  1122. ASSERT(off < 800000H, 105);
  1123. INCL(RM, LNK);
  1124. IF cond # 7 THEN
  1125. HALT(126)
  1126. ELSE
  1127. IF off # 0 THEN DEC(off) END;
  1128. ARMv6M.EmitBL(armcode, pc, off)
  1129. END
  1130. END
  1131. END
  1132. END Put3;
  1133. PROCEDURE incR;
  1134. BEGIN
  1135. EXCL(FR, RH);
  1136. IF RH < MT-1 THEN INC(RH) ELSE ORS.Mark("register stack overflow") END
  1137. END incR;
  1138. PROCEDURE CheckRegs*;
  1139. BEGIN
  1140. IF RH # 0 THEN ORS.Mark("Reg Stack"); RH := 0 END ;
  1141. IF pc >= maxCode - 40 THEN ORS.Mark("program too long") END;
  1142. IF frame # 0 THEN ORS.Mark("frame error"); frame := 0 END
  1143. END CheckRegs;
  1144. PROCEDURE SetCC(VAR x: Item; n: LONGINT);
  1145. BEGIN x.mode := Cond; x.a := 0; x.b := 0; x.r := n
  1146. END SetCC;
  1147. PROCEDURE Trap(cond, num: LONGINT);
  1148. BEGIN Put3(BLR, cond, ORS.Pos()*100H + num*10H + MT)
  1149. END Trap;
  1150. (*handling of forward reference, fixups of branch addresses and constant tables*)
  1151. PROCEDURE negated(cond: LONGINT): LONGINT;
  1152. BEGIN
  1153. IF cond < 8 THEN cond := cond+8 ELSE cond := cond-8 END ;
  1154. RETURN cond
  1155. END negated;
  1156. PROCEDURE invalSB;
  1157. BEGIN curSB := 1
  1158. END invalSB;
  1159. (*
  1160. PROCEDURE fix(at, with: LONGINT);
  1161. BEGIN
  1162. IF armcode[at] DIV 10000000H MOD 10H = 0EH (* BC *) THEN
  1163. HALT(1);
  1164. ASSERT(armcode[at+1] = tagBC, 100);
  1165. armcode[at] := armcode[at] DIV C24 * C24 + (with MOD C24)
  1166. ELSE
  1167. ASSERT(armcode[at] = tagBC, 101);
  1168. ASSERT(armcode[at-1] DIV 10000000H MOD 10H = 0EH, 102); (* BC *)
  1169. armcode[at-1] := armcode[at-1] DIV C24 * C24 + (with MOD C24)
  1170. END
  1171. END fix;
  1172. PROCEDURE FixLink*(L: LONGINT);
  1173. VAR L1: LONGINT;
  1174. BEGIN invalSB;
  1175. WHILE L # 0 DO
  1176. IF armcode[L] DIV 10000000H MOD 10H = 0EH (* BC *) THEN
  1177. HALT(1);
  1178. ASSERT(armcode[L+1] = tagBC, 100);
  1179. L1 := armcode[L] MOD 40000H;
  1180. fix(L, pc-L-1)
  1181. ELSE
  1182. ASSERT(armcode[L] = tagBC, 101);
  1183. ASSERT(armcode[L-1] DIV 10000000H MOD 10H = 0EH, 102); (* BC *)
  1184. L1 := armcode[L-1] MOD 40000H;
  1185. fix(L, pc-L-1+1)
  1186. END;
  1187. L := L1
  1188. END
  1189. END FixLink;
  1190. PROCEDURE FixLinkWith (L0, dst: LONGINT);
  1191. VAR L1: LONGINT;
  1192. BEGIN
  1193. WHILE L0 # 0 DO
  1194. IF armcode[L0] DIV 10000000H MOD 10H = 0EH THEN (* BC *)
  1195. ASSERT(armcode[L0+1] = tagBC, 101);
  1196. L1 := armcode[L0] MOD C24;
  1197. armcode[L0] := armcode[L0] DIV C24 * C24 + ((dst - L0 - 1) MOD C24)
  1198. ELSE
  1199. ASSERT(armcode[L0] = tagBC, 101);
  1200. ASSERT(armcode[L0-1] DIV 10000000H MOD 10H = 0EH, 102); (* BC *)
  1201. L1 := armcode[L0-1] MOD C24;
  1202. armcode[L0-1] := armcode[L0-1] DIV C24 * C24 + ((dst - L0 - 1 + 1) MOD C24)
  1203. END;
  1204. L0 := L1
  1205. END
  1206. END FixLinkWith;
  1207. PROCEDURE merged (L0, L1: LONGINT): LONGINT;
  1208. VAR L2, L3: LONGINT;
  1209. BEGIN
  1210. IF L0 # 0 THEN L3 := L0;
  1211. HALT(126);
  1212. REPEAT L2 := L3;
  1213. ASSERT(armcode[L2] DIV 10000000H MOD 10H = 0EH, 100); (* BC *)
  1214. ASSERT(armcode[L2+1] = tagBC, 101);
  1215. L3 := armcode[L2] MOD 40000H UNTIL L3 = 0;
  1216. ASSERT(armcode[L2] DIV 10000000H MOD 10H = 0EH, 102); (* BC *)
  1217. ASSERT(armcode[L2+1] = tagBC, 103);
  1218. armcode[L2] := armcode[L2] + L1; L1 := L0
  1219. END;
  1220. RETURN L1
  1221. END merged;
  1222. *)
  1223. PROCEDURE fix (at, with: LONGINT);
  1224. BEGIN
  1225. IF ORS.errcnt = 0 THEN
  1226. ASSERT(armcode[at] DIV 10000000H MOD 10H = 0EH, 100) (* BC *)
  1227. END;
  1228. armcode[at] := armcode[at] DIV C24 * C24 + (with MOD C24)
  1229. END fix;
  1230. PROCEDURE FixOne*(at: LONGINT);
  1231. BEGIN fix(at, pc-at-1)
  1232. END FixOne;
  1233. PROCEDURE FixLink*(L: LONGINT);
  1234. VAR L1: LONGINT;
  1235. BEGIN invalSB;
  1236. WHILE L # 0 DO L1 := armcode[L] MOD 40000H; fix(L, pc-L-1); L := L1 END
  1237. END FixLink;
  1238. PROCEDURE FixLinkWith (L0, dst: LONGINT);
  1239. VAR L1: LONGINT;
  1240. BEGIN
  1241. WHILE L0 # 0 DO
  1242. L1 := armcode[L0] MOD C24;
  1243. armcode[L0] := armcode[L0] DIV C24 * C24 + ((dst - L0 - 1) MOD C24); L0 := L1
  1244. END
  1245. END FixLinkWith;
  1246. PROCEDURE merged (L0, L1: LONGINT): LONGINT;
  1247. VAR L2, L3: LONGINT;
  1248. BEGIN
  1249. IF L0 # 0 THEN L3 := L0;
  1250. REPEAT L2 := L3; L3 := armcode[L2] MOD 40000H UNTIL L3 = 0;
  1251. armcode[L2] := armcode[L2] + L1; L1 := L0
  1252. END;
  1253. RETURN L1
  1254. END merged;
  1255. (* loading of operands and addresses into registers *)
  1256. PROCEDURE GetSB (base: LONGINT);
  1257. BEGIN
  1258. IF (version # 0) & ((base # curSB) OR (base # 0)) THEN
  1259. (* will be fixed up by linker/loader *)
  1260. INCL(RM, SB);
  1261. IF (-base) DIV 100H = 0 (* mno *) THEN
  1262. Put2orig(Ldr, ER(SB), (-base) MOD 10H, pc-fixorgD); fixorgD := pc-1; curSB := base;
  1263. armcode[pc] := tagLdrSB + (-base) DIV 10H; INC(pc)
  1264. ELSE ORS.Mark("fixup impossible")
  1265. END
  1266. END
  1267. END GetSB;
  1268. PROCEDURE NilCheck;
  1269. BEGIN IF check THEN Trap(EQ, 4) END
  1270. END NilCheck;
  1271. PROCEDURE load0 (S: INTEGER; VAR x: Item);
  1272. VAR op, pc0, pc1: LONGINT;
  1273. BEGIN
  1274. ASSERT(S IN {0,1}, 20);
  1275. IF x.type.size = 1 THEN op := Ldr+1 ELSE op := Ldr END ;
  1276. IF x.mode # Reg THEN
  1277. IF x.mode = ORB.Const THEN
  1278. IF x.type.form = ORB.Proc THEN
  1279. IF x.r > 0 THEN ORS.Mark("not allowed")
  1280. ELSIF x.r = 0 THEN Put3(BL, 7, 0);
  1281. ASSERT(x.a MOD 2 = 0, 100);
  1282. Put10(S, Sub, RH, LNK, (pc*4 - x.a) DIV 2)
  1283. ELSE GetSB(x.r);
  1284. INCL(RM, RH);
  1285. Put1orig(Add, ER(RH), ER(SB), x.a + 100H); (*mark as progbase-relative*)
  1286. armcode[pc] := tagFixup; INC(pc)
  1287. END
  1288. (*
  1289. ELSIF (x.a <= 0FFFFH) & (x.a >= -10000H) THEN Put1(Mov, RH, 0, x.a)
  1290. ELSE Put1(Mov+U, RH, 0, x.a DIV 10000H MOD 10000H);
  1291. IF x.a MOD 10000H # 0 THEN Put1(Ior, RH, RH, x.a MOD 10000H) END
  1292. *)
  1293. ELSE Put10(S, Mov, RH, 0, x.a)
  1294. END;
  1295. x.r := RH; incR
  1296. ELSIF x.mode = ORB.Var THEN
  1297. IF x.r > 0 THEN (*local*) Put20(S, op, RH, SP, x.a + frame)
  1298. ELSE GetSB(x.r);
  1299. IF x.r # 0 THEN
  1300. INCL(RM, RH);
  1301. Put2orig(op, ER(RH), ER(SB), x.a);
  1302. armcode[pc] := tagFixup; INC(pc);
  1303. IF S = 1 THEN UpdateFlags(RH) END
  1304. ELSE Put20(S, op, RH, SB, x.a)
  1305. END
  1306. END;
  1307. x.r := RH; incR
  1308. 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
  1309. ELSIF x.mode = RegI THEN Put20(S, op, x.r, x.r, x.a)
  1310. ELSIF x.mode = Cond THEN
  1311. pc0 := pc; Put3orig(BC, negated(x.r), 0);
  1312. FixLink(x.b); Put10(S, Mov, RH, 0, 1);
  1313. pc1 := pc; Put3orig(BC, 7, 0);
  1314. fix(pc0, pc - pc0 - 1);
  1315. FixLink(x.a); Put10(S, Mov, RH, 0, 0);
  1316. fix(pc1, pc - pc1 - 1);
  1317. x.r := RH; incR
  1318. END;
  1319. x.mode := Reg
  1320. END
  1321. END load0;
  1322. PROCEDURE load (VAR x: Item);
  1323. BEGIN
  1324. load0(1, x)
  1325. END load;
  1326. PROCEDURE loadReal (VAR x: Item);
  1327. VAR im: INTEGER;
  1328. BEGIN
  1329. RemoveRedundantCmp;
  1330. IF x.mode = ORB.Var THEN
  1331. IF x.r > 0 (* local *) THEN
  1332. im := x.a + frame; ASSERT(im MOD 4 = 0, 100);
  1333. ARMv7M.EmitVLDR(armcode, pc, ER(RH), ER(SP), 1, im DIV 4)
  1334. ELSE GetSB(x.r);
  1335. IF x.r # 0 THEN
  1336. INCL(RM, RH);
  1337. ASSERT(x.type.size = 4, 101);
  1338. Put2orig(Ldr, ER(RH), ER(SB), x.a);
  1339. armcode[pc] := tagVLDR; INC(pc)
  1340. ELSE
  1341. ASSERT(x.a MOD 4 = 0, 102);
  1342. IF x.a DIV 400H = 0 THEN
  1343. ARMv7M.EmitVLDR(armcode, pc, ER(RH), ER(SB), 1, x.a DIV 4)
  1344. ELSE
  1345. Put20(0, Ldr, RH, SB, x.a);
  1346. ARMv7M.EmitVMOVSPR(armcode, pc, 0, ER(RH), ER(RH))
  1347. END
  1348. END
  1349. END;
  1350. x.r := RH + 100H; incR; INCL(FR, x.r - 100H); x.mode := Reg
  1351. ELSIF x.mode = ORB.Par THEN
  1352. Put20(0, Ldr, RH, SP, x.a + frame);
  1353. ASSERT(x.b MOD 4 = 0, 103);
  1354. ARMv7M.EmitVLDR(armcode, pc, ER(RH), ER(RH), 1, x.b DIV 4);
  1355. x.r := RH + 100H; incR; INCL(FR, x.r - 100H); x.mode := Reg
  1356. ELSE
  1357. load0(0, x)
  1358. END;
  1359. IF (x.mode = Reg) & (x.r < 100H) THEN
  1360. ARMv7M.EmitVMOVSPR(armcode, pc, 0, ER(x.r), ER(x.r));
  1361. INCL(FR, x.r); x.r := x.r + 100H
  1362. END
  1363. END loadReal;
  1364. PROCEDURE loadAdr0 (S: INTEGER; VAR x: Item);
  1365. BEGIN
  1366. IF x.mode = ORB.Var THEN
  1367. IF x.r > 0 THEN (*local*) Put10(S, Add, RH, SP, x.a + frame)
  1368. ELSE GetSB(x.r);
  1369. IF x.r # 0 THEN
  1370. INCL(RM, RH);
  1371. Put1orig(Add, ER(RH), ER(SB), x.a);
  1372. armcode[pc] := tagFixup; INC(pc)
  1373. ELSE Put10(S, Add, RH, SB, x.a)
  1374. END
  1375. END;
  1376. x.r := RH; incR
  1377. ELSIF x.mode = ORB.Par THEN
  1378. IF x.b # 0 THEN Put20(0, Ldr, RH, SP, x.a + frame);
  1379. Put10(S, Add, RH, RH, x.b)
  1380. ELSE Put20(S, Ldr, RH, SP, x.a + frame)
  1381. END;
  1382. x.r := RH; incR
  1383. ELSIF x.mode = RegI THEN
  1384. IF x.a # 0 THEN Put10(S, Add, x.r, x.r, x.a) END
  1385. ELSE ORS.Mark("address error")
  1386. END;
  1387. x.mode := Reg
  1388. END loadAdr0;
  1389. PROCEDURE loadAdr (VAR x: Item);
  1390. BEGIN
  1391. loadAdr0(1, x)
  1392. END loadAdr;
  1393. PROCEDURE IsFlagsUp0 (r: INTEGER): BOOLEAN;
  1394. VAR res: BOOLEAN; c: INTEGER;
  1395. BEGIN
  1396. r := ER(r); ASSERT(r # 15, 100);
  1397. IF r DIV 8 = 0 THEN
  1398. res := ~ARMv6M.IsLThumb32(armcode[pc - 2]) & IsCMPIm(armcode[pc - 1]);
  1399. ASSERT(~res OR (armcode[pc - 1] DIV 100H MOD 8 = r), 101)
  1400. ELSIF ARMv6M.IsLThumb32(armcode[pc - 2]) THEN
  1401. ASSERT(armcode[pc - 1] DIV 10000H = 0, 102);
  1402. c := 10000H * armcode[pc - 1] + armcode[pc - 2];
  1403. res := ARMv7M.IsCMPImW(c);
  1404. ASSERT(~res OR (c MOD 10H = r), 103)
  1405. ELSE
  1406. res := FALSE
  1407. END;
  1408. RETURN res
  1409. END IsFlagsUp0;
  1410. PROCEDURE loadCond (VAR x: Item);
  1411. BEGIN
  1412. IF x.type.form = ORB.Bool THEN
  1413. IF x.mode = ORB.Const THEN x.r := 15 - x.a*8
  1414. ELSE load(x);
  1415. IF ~IsFlagsUp0(x.r) THEN
  1416. Put1(Cmp, x.r, x.r, 0)
  1417. (* ELSE HALT(1) *)
  1418. END;
  1419. x.r := NE; DEC(RH)
  1420. END ;
  1421. x.mode := Cond; x.a := 0; x.b := 0
  1422. ELSE ORS.Mark("not Boolean?")
  1423. END
  1424. END loadCond;
  1425. PROCEDURE loadTypTagAdr0 (S: INTEGER; T: ORB.Type);
  1426. VAR x: Item;
  1427. BEGIN x.mode := ORB.Var; x.a := T.len; x.r := -T.mno; loadAdr0(S, x)
  1428. END loadTypTagAdr0;
  1429. PROCEDURE loadTypTagAdr (T: ORB.Type);
  1430. BEGIN
  1431. loadTypTagAdr0(1, T)
  1432. END loadTypTagAdr;
  1433. PROCEDURE loadStringAdr0 (S: INTEGER; VAR x: Item);
  1434. BEGIN GetSB(0); Put10(S, Add, RH, SB, varsize+x.a); x.mode := Reg; x.r := RH; incR
  1435. END loadStringAdr0;
  1436. PROCEDURE loadStringAdr (VAR x: Item);
  1437. BEGIN
  1438. loadStringAdr0(1, x)
  1439. END loadStringAdr;
  1440. (* Items: Conversion from constants or from Objects on the Heap to Items on the Stack*)
  1441. PROCEDURE MakeConstItem*(VAR x: Item; typ: ORB.Type; val: LONGINT);
  1442. BEGIN x.mode := ORB.Const; x.type := typ; x.a := val
  1443. END MakeConstItem;
  1444. PROCEDURE MakeRealItem*(VAR x: Item; val: REAL);
  1445. BEGIN x.mode := ORB.Const; x.type := ORB.realType; x.a := SYSTEM.VAL(LONGINT, val)
  1446. END MakeRealItem;
  1447. PROCEDURE MakeStringItem*(VAR x: Item; len: LONGINT); (*copies string from ORS-buffer to ORG-string array*)
  1448. VAR i: LONGINT;
  1449. BEGIN x.mode := ORB.Const; x.type := ORB.strType; x.a := strx; x.b := len; i := 0;
  1450. IF strx + len + 4 < maxStrx THEN
  1451. WHILE len > 0 DO str[strx] := ORS.str[i]; INC(strx); INC(i); DEC(len) END ;
  1452. WHILE strx MOD 4 # 0 DO str[strx] := 0X; INC(strx) END
  1453. ELSE ORS.Mark("too many strings")
  1454. END
  1455. END MakeStringItem;
  1456. PROCEDURE MakeItem*(VAR x: Item; y: ORB.Object; curlev: LONGINT);
  1457. BEGIN x.mode := y.class; x.type := y.type; x.a := y.val; x.rdo := y.rdo;
  1458. IF y.class = ORB.Par THEN x.b := 0
  1459. (* ELSIF y.class = ORB.Typ THEN x.a := y.type.len; x.r := -y.lev *)
  1460. ELSIF (y.class = ORB.Const) & (y.type.form = ORB.String) THEN x.b := y.lev (*len*)
  1461. ELSE x.r := y.lev
  1462. END ;
  1463. IF (y.lev > 0) & (y.lev # curlev) & (y.class # ORB.Const) THEN ORS.Mark("not accessible") END
  1464. END MakeItem;
  1465. (* Code generation for Selectors, Variables, Constants *)
  1466. PROCEDURE Field*(VAR x: Item; y: ORB.Object); (* x := x.y *)
  1467. BEGIN;
  1468. IF x.mode = ORB.Var THEN
  1469. IF x.r >= 0 THEN x.a := x.a + y.val
  1470. ELSE loadAdr(x); x.mode := RegI; x.a := y.val
  1471. END
  1472. ELSIF x.mode = RegI THEN x.a := x.a + y.val
  1473. ELSIF x.mode = ORB.Par THEN x.b := x.b + y.val
  1474. END
  1475. END Field;
  1476. PROCEDURE Index*(VAR x, y: Item); (* x := x[y] *)
  1477. VAR s, lim: LONGINT;
  1478. BEGIN s := x.type.base.size; lim := x.type.len;
  1479. IF (y.mode = ORB.Const) & (lim >= 0) THEN
  1480. IF (y.a < 0) OR (y.a >= lim) THEN ORS.Mark("bad index") END ;
  1481. IF x.mode IN {ORB.Var, RegI} THEN
  1482. (*
  1483. x.a := y.a * s + x.a
  1484. *)
  1485. IF x.mode = ORB.Var THEN
  1486. IF x.r >= 0 THEN x.a := y.a * s + x.a
  1487. ELSE loadAdr(x); x.mode := RegI; x.a := y.a * s
  1488. END
  1489. ELSE (* x.mode = RegI *) x.a := y.a * s + x.a
  1490. END
  1491. ELSIF x.mode = ORB.Par THEN x.b := y.a * s + x.b
  1492. END
  1493. ELSE load0(0, y);
  1494. IF check THEN (*check array bounds*)
  1495. updateCarry := TRUE;
  1496. IF lim >= 0 THEN Put1a(Cmp, RH, y.r, lim)
  1497. ELSE (*open array*)
  1498. IF x.mode IN {ORB.Var, ORB.Par} THEN Put20(0, Ldr, RH, SP, x.a+4+frame); Put0(Cmp, RH, y.r, RH)
  1499. ELSE ORS.Mark("error in Index")
  1500. END
  1501. END;
  1502. updateCarry := FALSE;
  1503. Trap(10, 1) (*BCC*)
  1504. END ;
  1505. 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 ;
  1506. IF x.mode = ORB.Var THEN
  1507. IF x.r > 0 THEN Put0(Add, y.r, SP, y.r); INC(x.a, frame)
  1508. ELSE GetSB(x.r);
  1509. IF x.r = 0 THEN Put0(Add, y.r, SB, y.r)
  1510. ELSE
  1511. INCL(RM, RH); Put1orig(Add, ER(RH), ER(SB), x.a);
  1512. armcode[pc] := tagFixup; INC(pc);
  1513. Put0(Add, y.r, RH, y.r); x.a := 0
  1514. END
  1515. END;
  1516. x.r := y.r; x.mode := RegI
  1517. ELSIF x.mode = ORB.Par THEN
  1518. Put20(0, Ldr, RH, SP, x.a + frame);
  1519. Put0(Add, y.r, RH, y.r); x.mode := RegI; x.r := y.r; x.a := x.b
  1520. ELSIF x.mode = RegI THEN Put0(Add, x.r, x.r, y.r); DEC(RH)
  1521. ELSE HALT(100)
  1522. (* if reached, then restore back:
  1523. load0(0,y) -> load(y)
  1524. IF s = 4...: Put10(0 -> Put1( ; Put10(0->Put1a
  1525. *)
  1526. END
  1527. END
  1528. END Index;
  1529. PROCEDURE DeRef*(VAR x: Item);
  1530. BEGIN
  1531. IF x.mode = ORB.Var THEN
  1532. IF x.r > 0 THEN (*local*) Put2(Ldr, RH, SP, x.a + frame) ELSE GetSB(x.r);
  1533. IF x.r # 0 THEN
  1534. INCL(RM, RH);
  1535. Put2orig(Ldr, ER(RH), ER(SB), x.a);
  1536. armcode[pc] := tagFixup; INC(pc);
  1537. UpdateFlags(RH)
  1538. ELSE Put2(Ldr, RH, SB, x.a)
  1539. END
  1540. END;
  1541. NilCheck; x.r := RH; incR
  1542. ELSIF x.mode = ORB.Par THEN
  1543. Put20(0, Ldr, RH, SP, x.a + frame); Put2(Ldr, RH, RH, x.b); NilCheck; x.r := RH; incR
  1544. ELSIF x.mode = RegI THEN Put2(Ldr, x.r, x.r, x.a); NilCheck
  1545. ELSIF x.mode # Reg THEN ORS.Mark("bad mode in DeRef")
  1546. END ;
  1547. x.mode := RegI; x.a := 0; x.b := 0
  1548. END DeRef;
  1549. PROCEDURE Q(T: ORB.Type; VAR dcw: LONGINT);
  1550. BEGIN (*one entry of type descriptor extension table*)
  1551. IF T.base # NIL THEN
  1552. ASSERT(T.mno DIV 100H = 0);
  1553. ASSERT(T.len DIV 1000H = 0);
  1554. ASSERT((dcw - fixorgT) DIV 1000H = 0);
  1555. Q(T.base, dcw); data[dcw] := (T.mno*1000H + T.len) * 1000H + dcw - fixorgT;
  1556. fixorgT := dcw; INC(dcw)
  1557. END
  1558. END Q;
  1559. PROCEDURE FindPtrFlds(typ: ORB.Type; off: LONGINT; VAR dcw: LONGINT);
  1560. VAR fld: ORB.Object; i, s: LONGINT;
  1561. BEGIN
  1562. IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN data[dcw] := off; INC(dcw)
  1563. ELSIF typ.form = ORB.Record THEN
  1564. fld := typ.dsc;
  1565. WHILE fld # NIL DO FindPtrFlds(fld.type, fld.val + off, dcw); fld := fld.next END
  1566. ELSIF typ.form = ORB.Array THEN
  1567. s := typ.base.size;
  1568. FOR i := 0 TO typ.len-1 DO FindPtrFlds(typ.base, i*s + off, dcw) END
  1569. END
  1570. END FindPtrFlds;
  1571. PROCEDURE BuildTD*(T: ORB.Type; VAR dc: LONGINT);
  1572. VAR dcw, k, s: LONGINT; (*dcw = word address*)
  1573. BEGIN dcw := dc DIV 4; s := T.size; (*convert size for heap allocation*)
  1574. IF s <= 24 THEN s := 32 ELSIF s <= 56 THEN s := 64 ELSIF s <= 120 THEN s := 128
  1575. ELSE s := (s+263) DIV 256 * 256
  1576. END ;
  1577. T.len := dc; data[dcw] := s; INC(dcw); (*len used as address*)
  1578. k := T.nofpar; (*extension level!*)
  1579. IF k > 3 THEN ORS.Mark("ext level too large")
  1580. ELSE Q(T, dcw);
  1581. WHILE k < 3 DO data[dcw] := -1; INC(dcw); INC(k) END
  1582. END ;
  1583. FindPtrFlds(T, 0, dcw); data[dcw] := -1; INC(dcw); tdx := dcw; dc := dcw*4;
  1584. IF tdx >= maxTD THEN ORS.Mark("too many record types"); tdx := 0 END
  1585. END BuildTD;
  1586. PROCEDURE TypeTest* (VAR x: Item; T: ORB.Type; varpar, isguard: BOOLEAN);
  1587. VAR pc0: LONGINT;
  1588. BEGIN
  1589. IF T = NIL THEN
  1590. IF x.mode >= Reg THEN DEC(RH) END;
  1591. SetCC(x, 7)
  1592. ELSE (*fetch tag into RH*)
  1593. IF varpar THEN Put20(0, Ldr, RH, SP, x.a+4+frame)
  1594. ELSE load(x);
  1595. pc0 := pc; Put3orig(BC, EQ, 0); (*NIL belongs to every pointer type*)
  1596. Put20(0, Ldr, RH, x.r, -8)
  1597. END ;
  1598. Put20(0, Ldr, RH, RH, T.nofpar*4); incR;
  1599. loadTypTagAdr0(0, T); (*tag of T*)
  1600. Put0(Cmp, RH-1, RH-1, RH-2); DEC(RH, 2);
  1601. IF ~varpar THEN fix(pc0, pc - pc0 - 1) END;
  1602. IF isguard THEN
  1603. IF check THEN Trap(NE, 2) END
  1604. ELSE SetCC(x, EQ);
  1605. IF ~varpar THEN DEC(RH) END
  1606. END
  1607. END
  1608. END TypeTest;
  1609. (* Code generation for Boolean operators *)
  1610. PROCEDURE Not*(VAR x: Item); (* x := ~x *)
  1611. VAR t: LONGINT;
  1612. BEGIN
  1613. IF x.mode # Cond THEN loadCond(x) END ;
  1614. x.r := negated(x.r); t := x.a; x.a := x.b; x.b := t
  1615. END Not;
  1616. PROCEDURE And1*(VAR x: Item); (* x := x & *)
  1617. BEGIN
  1618. IF x.mode # Cond THEN loadCond(x) END ;
  1619. Put3orig(BC, negated(x.r), x.a); x.a := pc-1; FixLink(x.b); x.b := 0
  1620. END And1;
  1621. PROCEDURE And2*(VAR x, y: Item);
  1622. BEGIN
  1623. IF y.mode # Cond THEN loadCond(y) END ;
  1624. x.a := merged(y.a, x.a); x.b := y.b; x.r := y.r
  1625. END And2;
  1626. PROCEDURE Or1*(VAR x: Item); (* x := x OR *)
  1627. BEGIN
  1628. IF x.mode # Cond THEN loadCond(x) END ;
  1629. Put3orig(BC, x.r, x.b); x.b := pc-1; FixLink(x.a); x.a := 0
  1630. END Or1;
  1631. PROCEDURE Or2*(VAR x, y: Item);
  1632. BEGIN
  1633. IF y.mode # Cond THEN loadCond(y) END ;
  1634. x.a := y.a; x.b := merged(y.b, x.b); x.r := y.r
  1635. END Or2;
  1636. (* Code generation for arithmetic operators *)
  1637. PROCEDURE Neg*(VAR x: Item); (* x := -x *)
  1638. BEGIN
  1639. IF x.type.form = ORB.Int THEN
  1640. IF x.mode = ORB.Const THEN x.a := -x.a
  1641. ELSE load0(0, x);
  1642. (* Put10(0, Mov, RH, 0, 0); Put0(Sub, x.r, RH, x.r) *)
  1643. RSBS0(x.r)
  1644. END
  1645. ELSIF x.type.form = ORB.Real THEN
  1646. IF x.mode = ORB.Const THEN x.a := x.a + 7FFFFFFFH + 1
  1647. ELSE
  1648. (* load0(0, x); Put10(0, Mov, RH, 0, 0); Put0(Fsb, x.r, RH, x.r) *)
  1649. loadReal(x);
  1650. ARMv7M.EmitVNEG(armcode, pc, ER(x.r - 100H), ER(x.r - 100H))
  1651. END
  1652. ELSE (*form = Set*)
  1653. IF x.mode = ORB.Const THEN x.a := -x.a-1
  1654. ELSE load0(0, x); Put1(Xor, x.r, x.r, -1)
  1655. END
  1656. END
  1657. END Neg;
  1658. PROCEDURE AddOp*(op: LONGINT; VAR x, y: Item); (* x := x +- y *)
  1659. BEGIN
  1660. IF op = ORS.plus THEN
  1661. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN x.a := x.a + y.a
  1662. ELSIF y.mode = ORB.Const THEN
  1663. IF y.a # 0 THEN load0(0, x); Put1a(Add, x.r, x.r, y.a)
  1664. ELSE load(x)
  1665. END
  1666. ELSE load0(0, x); load0(0, y); Put0(Add, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  1667. END
  1668. ELSE (*op = ORS.minus*)
  1669. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN x.a := x.a - y.a
  1670. ELSIF y.mode = ORB.Const THEN
  1671. IF y.a # 0 THEN load0(0, x); Put1a(Sub, x.r, x.r, y.a)
  1672. ELSE load(x)
  1673. END
  1674. ELSE load0(0, x); load0(0, y); Put0(Sub, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  1675. END
  1676. END
  1677. END AddOp;
  1678. PROCEDURE log2(m: LONGINT; VAR e: LONGINT): LONGINT;
  1679. BEGIN e := 0;
  1680. WHILE ~ODD(m) DO m := m DIV 2; INC(e) END ;
  1681. RETURN m
  1682. END log2;
  1683. PROCEDURE MulOp*(VAR x, y: Item); (* x := x * y *)
  1684. VAR e: LONGINT;
  1685. BEGIN
  1686. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN x.a := x.a * y.a
  1687. ELSIF (y.mode = ORB.Const) & (y.a >= 2) & (log2(y.a, e) = 1) THEN load0(0, x); Put1(Lsl, x.r, x.r, e)
  1688. ELSIF y.mode = ORB.Const THEN load0(0, x); Put1a(Mul, x.r, x.r, y.a)
  1689. 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
  1690. ELSIF x.mode = ORB.Const THEN load0(0, y); Put1a(Mul, y.r, y.r, x.a); x.mode := Reg; x.r := y.r
  1691. ELSE load0(0, x); load0(0, y); Put0(Mul, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  1692. END
  1693. END MulOp;
  1694. (* R.d := R.a - R.n * R.m *)
  1695. PROCEDURE MLS (S: INTEGER; d, n, m, a: INTEGER);
  1696. BEGIN
  1697. ASSERT(S DIV 2 = 0, 20);
  1698. INCL(RM, d);
  1699. ARMv7M.EmitMLS(armcode, pc, ER(d), ER(n), ER(m), ER(a));
  1700. IF S = 1 THEN UpdateFlags(d) END
  1701. END MLS;
  1702. PROCEDURE DivOp*(op: LONGINT; VAR x, y: Item); (* x := x op y *)
  1703. VAR e: LONGINT;
  1704. BEGIN
  1705. IF op = ORS.div THEN
  1706. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
  1707. IF y.a > 0 THEN x.a := x.a DIV y.a ELSE ORS.Mark("bad divisor") END
  1708. ELSIF (y.mode = ORB.Const) & (y.a >= 2) & (log2(y.a, e) = 1) THEN load0(0, x); Put1(Asr, x.r, x.r, e)
  1709. ELSIF y.mode = ORB.Const THEN
  1710. IF y.a > 0 THEN load0(0, x); Put1a(Div, x.r, x.r, y.a) ELSE ORS.Mark("bad divisor") END
  1711. ELSE load(y);
  1712. IF check THEN Trap(LE, 6) END ;
  1713. load0(0, x); Put0(Div, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  1714. END
  1715. ELSE (*op = ORS.mod*)
  1716. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
  1717. IF y.a > 0 THEN x.a := x.a MOD y.a ELSE ORS.Mark("bad modulus") END
  1718. ELSIF (y.mode = ORB.Const) & (y.a >= 2) & (log2(y.a, e) = 1) THEN load0(0, x);
  1719. 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
  1720. ELSIF y.mode = ORB.Const THEN
  1721. IF y.a > 0 THEN
  1722. load0(0, x);
  1723. (*
  1724. Put1a(Div, x.r, x.r, y.a);
  1725. Put0(Mov+U, x.r, 0, 0)
  1726. *)
  1727. incR; incR;
  1728. Put10(0, Mov, RH-2, 0, y.a);
  1729. Put00(0, Div, RH-1, x.r, RH-2);
  1730. (*
  1731. Put00(0, Mul, RH-2, RH-2, RH-1);
  1732. Put0(Sub, x.r, x.r, RH-2);
  1733. *)
  1734. MLS(1, x.r, RH-2, RH-1, x.r);
  1735. DEC(RH, 2)
  1736. ELSE ORS.Mark("bad modulus")
  1737. END
  1738. ELSE load(y);
  1739. IF check THEN Trap(LE, 6) END;
  1740. load0(0, x);
  1741. (*
  1742. Put0(Div, RH-2, x.r, y.r);
  1743. Put0(Mov+U, RH-2, 0, 0);
  1744. *)
  1745. incR;
  1746. Put00(0, Div, RH-1, x.r, y.r);
  1747. (*
  1748. Put00(0, Mul, RH-1, RH-1, y.r);
  1749. Put0(Sub, RH-2-1, x.r, RH-1);
  1750. *)
  1751. MLS(1, RH-2-1, RH-1, y.r, x.r);
  1752. DEC(RH);
  1753. DEC(RH); x.r := RH-1
  1754. END
  1755. END
  1756. END DivOp;
  1757. (* Code generation for REAL operators *)
  1758. PROCEDURE RealOp*(op: INTEGER; VAR x, y: Item); (* x := x op y *)
  1759. BEGIN
  1760. (*
  1761. load0(0, x); load0(0, y);
  1762. IF op = ORS.plus THEN Put0(Fad, RH-2, x.r, y.r)
  1763. ELSIF op = ORS.minus THEN Put0(Fsb, RH-2, x.r, y.r)
  1764. ELSIF op = ORS.times THEN Put0(Fml, RH-2, x.r, y.r)
  1765. ELSIF op = ORS.rdiv THEN Put0(Fdv, RH-2, x.r, y.r)
  1766. END;
  1767. DEC(RH); x.r := RH-1
  1768. *)
  1769. loadReal(x); loadReal(y);
  1770. IF op = ORS.plus THEN
  1771. ARMv7M.EmitVADD(armcode, pc,
  1772. ER(RH-2), ER(x.r - 100H), ER(y.r - 100H))
  1773. ELSIF op = ORS.minus THEN
  1774. ARMv7M.EmitVSUB(armcode, pc,
  1775. ER(RH-2), ER(x.r - 100H), ER(y.r - 100H))
  1776. ELSIF op = ORS.times THEN
  1777. ARMv7M.EmitVMUL(armcode, pc,
  1778. ER(RH-2), ER(x.r - 100H), ER(y.r - 100H))
  1779. ELSIF op = ORS.rdiv THEN
  1780. ARMv7M.EmitVDIV(armcode, pc,
  1781. ER(RH-2), ER(x.r - 100H), ER(y.r - 100H))
  1782. END;
  1783. DEC(RH); x.r := RH-1+100H; INCL(FR, RH-1)
  1784. END RealOp;
  1785. (* Code generation for set operators *)
  1786. PROCEDURE Singleton*(VAR x: Item); (* x := {x} *)
  1787. BEGIN
  1788. IF x.mode = ORB.Const THEN x.a := LSL(1, x.a)
  1789. ELSE load0(0, x); Put10(0, Mov, RH, 0, 1); Put0(Lsl, x.r, RH, x.r)
  1790. END
  1791. END Singleton;
  1792. PROCEDURE Set*(VAR x, y: Item); (* x := {x .. y} *)
  1793. BEGIN
  1794. IF (x.mode = ORB.Const) & ( y.mode = ORB.Const) THEN
  1795. IF x.a <= y.a THEN x.a := LSL(2, y.a) - LSL(1, x.a) ELSE x.a := 0 END
  1796. ELSE
  1797. IF (x.mode = ORB.Const) & (x.a <= 16) THEN x.a := LSL(-1, x.a)
  1798. ELSE load0(0, x); Put10(0, Mov, RH, 0, -1); Put0(Lsl, x.r, RH, x.r)
  1799. END ;
  1800. IF (y.mode = ORB.Const) & (y.a < 16) THEN Put1(Mov, RH, 0, LSL(-2, y.a)); y.mode := Reg; y.r := RH; incR
  1801. ELSE load0(0, y); Put10(0, Mov, RH, 0, -2); Put0(Lsl, y.r, RH, y.r)
  1802. END ;
  1803. IF x.mode = ORB.Const THEN
  1804. IF x.a # 0 THEN Put10(0, Xor, y.r, y.r, -1); Put1a(And, RH-1, y.r, x.a) END ;
  1805. x.mode := Reg; x.r := RH-1
  1806. ELSE DEC(RH); Put0(Ann, RH-1, x.r, y.r);
  1807. ASSERT(x.mode = Reg); x.r := RH-1
  1808. END
  1809. END
  1810. END Set;
  1811. PROCEDURE In*(VAR x, y: Item); (* x := x IN y *)
  1812. BEGIN load0(0, y);
  1813. IF x.mode = ORB.Const THEN Put1(Ror, y.r, y.r, (x.a + 1) MOD 20H); DEC(RH)
  1814. ELSE load0(0, x); Put10(0, Add, x.r, x.r, 1); Put0(Ror, y.r, y.r, x.r); DEC(RH, 2)
  1815. END ;
  1816. SetCC(x, MI)
  1817. END In;
  1818. PROCEDURE SetOp*(op: LONGINT; VAR x, y: Item); (* x := x op y *)
  1819. VAR xset, yset: SET; (*x.type.form = Set*)
  1820. BEGIN
  1821. IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
  1822. xset := SYSTEM.VAL(SET, x.a); yset := SYSTEM.VAL(SET, y.a);
  1823. IF op = ORS.plus THEN xset := xset + yset
  1824. ELSIF op = ORS.minus THEN xset := xset - yset
  1825. ELSIF op = ORS.times THEN xset := xset * yset
  1826. ELSIF op = ORS.rdiv THEN xset := xset / yset
  1827. END ;
  1828. x.a := SYSTEM.VAL(LONGINT, xset)
  1829. ELSIF y.mode = ORB.Const THEN
  1830. load0(0, x);
  1831. IF op = ORS.plus THEN Put1a(Ior, x.r, x.r, y.a)
  1832. ELSIF op = ORS.minus THEN Put1a(Ann, x.r, x.r, y.a)
  1833. ELSIF op = ORS.times THEN Put1a(And, x.r, x.r, y.a)
  1834. ELSIF op = ORS.rdiv THEN Put1a(Xor, x.r, x.r, y.a)
  1835. END ;
  1836. ELSE load0(0, x); load0(0, y);
  1837. IF op = ORS.plus THEN Put0(Ior, RH-2, x.r, y.r)
  1838. ELSIF op = ORS.minus THEN Put0(Ann, RH-2, x.r, y.r)
  1839. ELSIF op = ORS.times THEN Put0(And, RH-2, x.r, y.r)
  1840. ELSIF op = ORS.rdiv THEN Put0(Xor, RH-2, x.r, y.r)
  1841. END ;
  1842. DEC(RH); x.r := RH-1
  1843. END
  1844. END SetOp;
  1845. (* Code generation for relations *)
  1846. PROCEDURE IntRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  1847. BEGIN
  1848. IF (y.mode = ORB.Const) & (y.type.form # ORB.Proc) THEN
  1849. load(x);
  1850. Put1a(Cmp, x.r, x.r, y.a);
  1851. DEC(RH)
  1852. ELSE
  1853. IF (x.mode = Cond) OR (y.mode = Cond) THEN ORS.Mark("not implemented") END;
  1854. load0(0, x); load0(0, y); Put0(Cmp, x.r, x.r, y.r); DEC(RH, 2)
  1855. END;
  1856. SetCC(x, relmap[op - ORS.eql])
  1857. END IntRelation;
  1858. (*
  1859. PROCEDURE SetRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  1860. BEGIN load0(0, x);
  1861. IF (op = ORS.eql) OR (op = ORS.neq) THEN
  1862. IF y.mode = ORB.Const THEN Put1a(Cmp, x.r, x.r, y.a); DEC(RH)
  1863. ELSE load0(0, y); Put0(Cmp, x.r, x.r, y.r); DEC(RH, 2)
  1864. END;
  1865. SetCC(x, relmap[op - ORS.eql])
  1866. ELSE ORS.Mark("illegal relation")
  1867. END
  1868. END SetRelation;
  1869. *)
  1870. PROCEDURE FPUToARMReg (VAR x: Item);
  1871. BEGIN
  1872. IF (x.mode = Reg) & (x.r >= 100H) THEN
  1873. x.r := x.r - 100H;
  1874. EXCL(FR, x.r);
  1875. INCL(RM, x.r);
  1876. ARMv7M.EmitVMOVSPR(armcode, pc, 1, ER(x.r), ER(x.r))
  1877. END
  1878. END FPUToARMReg;
  1879. PROCEDURE RealRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  1880. BEGIN
  1881. IF (y.mode = ORB.Const) & (y.a = 0) THEN
  1882. IF (x.mode = Reg) & (x.r >= 100H) THEN
  1883. FPUToARMReg(x);
  1884. UpdateFlags(x.r)
  1885. ELSE load(x); Put1a(Cmp, x.r, x.r, y.a)
  1886. END;
  1887. DEC(RH)
  1888. ELSE
  1889. loadReal(x); loadReal(y);
  1890. ARMv7M.EmitVCMPER(armcode, pc, 1, ER(x.r - 100H), ER(y.r - 100H));
  1891. ARMv7M.EmitVMRS(armcode, pc, 15 (* APSR_nzcv *));
  1892. DEC(RH, 2)
  1893. END;
  1894. SetCC(x, relmap[op - ORS.eql])
  1895. END RealRelation;
  1896. PROCEDURE StringRelation*(op: INTEGER; VAR x, y: Item); (* x := x < y *)
  1897. (*x, y are char arrays or strings*)
  1898. VAR pc0, pc1: LONGINT;
  1899. BEGIN
  1900. IF x.type.form = ORB.String THEN loadStringAdr0(0, x) ELSE loadAdr0(0, x) END;
  1901. IF y.type.form = ORB.String THEN loadStringAdr0(0, y) ELSE loadAdr0(0, y) END;
  1902. pc0 := pc;
  1903. Put20(0, Ldr+1, RH, x.r, 0); Put10(0, Add, x.r, x.r, 1);
  1904. Put20(0, Ldr+1, RH+1, y.r, 0); Put10(0, Add, y.r, y.r, 1);
  1905. Put0(Cmp, RH+2, RH, RH+1); pc1 := pc; Put3orig(BC, NE, 0);
  1906. Put1(Cmp, RH+2, RH, 0); Put3orig(BC, NE, pc0 - pc - 1);
  1907. fix(pc1, pc - pc1 - 1);
  1908. DEC(RH, 2); SetCC(x, relmap[op - ORS.eql])
  1909. END StringRelation;
  1910. (* Code generation of Assignments *)
  1911. PROCEDURE StrToChar*(VAR x: Item);
  1912. BEGIN x.type := ORB.charType; DEC(strx, 4); x.a := ORD(str[x.a])
  1913. END StrToChar;
  1914. PROCEDURE Store*(VAR x, y: Item); (* x := y *)
  1915. VAR op: LONGINT;
  1916. BEGIN load0(0, y);
  1917. IF x.type.size = 1 THEN op := Str+1 ELSE op := Str END ;
  1918. IF x.mode = ORB.Var THEN
  1919. IF x.r > 0 THEN (*local*) Put2(op, y.r, SP, x.a + frame)
  1920. ELSE
  1921. IF x.r # 0 THEN FPUToARMReg(y) END;
  1922. GetSB(x.r);
  1923. IF x.r # 0 THEN
  1924. Put2orig(op, ER(y.r), ER(SB), x.a);
  1925. armcode[pc] := tagFixup; INC(pc)
  1926. ELSE Put2(op, y.r, SB, x.a)
  1927. END
  1928. END
  1929. ELSIF x.mode = ORB.Par THEN Put20(0, Ldr, RH, SP, x.a + frame); Put2(op, y.r, RH, x.b);
  1930. ELSIF x.mode = RegI THEN Put2(op, y.r, x.r, x.a); DEC(RH);
  1931. ELSE ORS.Mark("bad mode in Store")
  1932. END;
  1933. DEC(RH)
  1934. END Store;
  1935. PROCEDURE StoreStruct* (VAR x, y: Item); (* x := y, frame = 0 *)
  1936. VAR s, pc0, pc1: LONGINT;
  1937. BEGIN
  1938. IF y.type.size # 0 THEN
  1939. loadAdr0(0, x); loadAdr0(0, y);
  1940. pc0 := -1;
  1941. IF (x.type.form = ORB.Array) & (x.type.len > 0) THEN
  1942. IF y.type.len >= 0 THEN
  1943. IF x.type.size = y.type.size THEN Put10(0, Mov, RH, 0, (y.type.size+3) DIV 4)
  1944. ELSE ORS.Mark("different length/size, not implemented")
  1945. END
  1946. ELSE (*y is open array*) Put2(Ldr, RH, SP, y.a+4); s := y.type.base.size; (*element size*)
  1947. pc0 := pc; Put3orig(BC, EQ, 0);
  1948. IF s = 1 THEN Put10(0, Add, RH, RH, 3); Put10(0, Asr, RH, RH, 2)
  1949. ELSIF s # 4 THEN Put10(0, Mul, RH, RH, s DIV 4)
  1950. END;
  1951. IF check THEN
  1952. ASSERT(x.type.len >= 0);
  1953. Put10(0, Mov, RH+1, 0, (x.type.size+3) DIV 4); Put0(Cmp, RH+1, RH, RH+1); Trap(GT, 3)
  1954. END
  1955. END
  1956. ELSIF x.type.form = ORB.Record THEN Put10(0, Mov, RH, 0, x.type.size DIV 4)
  1957. ELSE ORS.Mark("inadmissible assignment")
  1958. END;
  1959. pc1 := pc;
  1960. Put20(0, Ldr, RH+1, y.r, 0); Put10(0, Add, y.r, y.r, 4);
  1961. Put2(Str, RH+1, x.r, 0); Put10(0, Add, x.r, x.r, 4);
  1962. Put1(Sub, RH, RH, 1); Put3orig(BC, NE, pc1 - pc - 1);
  1963. DEC(RH, 2); ASSERT(RH = 0);
  1964. IF pc0 # -1 THEN fix(pc0, pc - pc0 - 1) END
  1965. END;
  1966. RH := 0
  1967. END StoreStruct;
  1968. PROCEDURE CopyString* (VAR x, y: Item); (* x := y *)
  1969. VAR len, pc0: LONGINT;
  1970. BEGIN loadAdr0(0, x); len := x.type.len;
  1971. IF len >= 0 THEN
  1972. IF len < y.b THEN ORS.Mark("string too long") END
  1973. ELSIF check THEN Put20(0, Ldr, RH, SP, x.a+4); (*open array len, frame = 0*)
  1974. Put1(Cmp, RH, RH, y.b); Trap(LT, 3)
  1975. END;
  1976. loadStringAdr0(0, y);
  1977. pc0 := pc;
  1978. Put20(0, Ldr, RH, y.r, 0); Put10(0, Add, y.r, y.r, 4);
  1979. Put2(Str, RH, x.r, 0); Put10(0, Add, x.r, x.r, 4);
  1980. Put1(Asr, RH, RH, 24); Put3orig(BC, NE, pc0 - pc - 1); RH := 0
  1981. END CopyString;
  1982. (* Code generation for parameters *)
  1983. PROCEDURE OpenArrayParam*(VAR x: Item);
  1984. BEGIN loadAdr0(0, x);
  1985. 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;
  1986. incR
  1987. END OpenArrayParam;
  1988. PROCEDURE VarParam*(VAR x: Item; ftype: ORB.Type);
  1989. VAR xmd: INTEGER;
  1990. BEGIN xmd := x.mode; loadAdr0(0, x);
  1991. IF (ftype.form = ORB.Array) & (ftype.len < 0) THEN (*open array*)
  1992. 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;
  1993. incR
  1994. ELSIF ftype.form = ORB.Record THEN
  1995. IF xmd = ORB.Par THEN Put20(0, Ldr, RH, SP, x.a+4+frame); incR ELSE loadTypTagAdr0(0, x.type) END
  1996. END
  1997. END VarParam;
  1998. PROCEDURE ValueParam*(VAR x: Item);
  1999. BEGIN load0(0, x); FPUToARMReg(x)
  2000. END ValueParam;
  2001. PROCEDURE StringParam*(VAR x: Item);
  2002. BEGIN loadStringAdr0(0, x); Put10(0, Mov, RH, 0, x.b); incR (*len*)
  2003. END StringParam;
  2004. (*For Statements*)
  2005. PROCEDURE For0*(VAR x, y: Item);
  2006. BEGIN load(y)
  2007. END For0;
  2008. PROCEDURE For1*(VAR x, y, z, w: Item; VAR L: LONGINT);
  2009. BEGIN
  2010. IF z.mode = ORB.Const THEN Put1a(Cmp, RH, y.r, z.a)
  2011. ELSE load0(0, z); Put0(Cmp, RH-1, y.r, z.r); DEC(RH)
  2012. END ;
  2013. L := pc;
  2014. IF w.a > 0 THEN Put3orig(BC, GT, 0)
  2015. ELSIF w.a < 0 THEN Put3orig(BC, LT, 0)
  2016. ELSE ORS.Mark("zero increment"); Put3orig(BC, MI, 0)
  2017. END;
  2018. Store(x, y)
  2019. END For1;
  2020. PROCEDURE For2*(VAR x, y, w: Item);
  2021. BEGIN load0(0, x); DEC(RH); Put1a(Add, x.r, x.r, w.a)
  2022. END For2;
  2023. (* Branches, procedure calls, procedure prolog and epilog *)
  2024. PROCEDURE Here*(): LONGINT;
  2025. BEGIN invalSB; RETURN pc
  2026. END Here;
  2027. PROCEDURE FJump*(VAR L: LONGINT);
  2028. BEGIN Put3orig(BC, 7, L); L := pc-1
  2029. END FJump;
  2030. PROCEDURE CFJump*(VAR x: Item);
  2031. BEGIN
  2032. IF x.mode # Cond THEN loadCond(x) END ;
  2033. Put3orig(BC, negated(x.r), x.a); FixLink(x.b); x.a := pc-1
  2034. END CFJump;
  2035. PROCEDURE BJump*(L: LONGINT);
  2036. BEGIN Put3orig(BC, 7, L-pc-1)
  2037. END BJump;
  2038. PROCEDURE CBJump*(VAR x: Item; L: LONGINT);
  2039. BEGIN
  2040. IF x.mode # Cond THEN loadCond(x) END ;
  2041. Put3orig(BC, negated(x.r), L-pc-1); FixLink(x.b); FixLinkWith(x.a, L)
  2042. END CBJump;
  2043. PROCEDURE Fixup*(VAR x: Item);
  2044. BEGIN FixLink(x.a)
  2045. END Fixup;
  2046. PROCEDURE SaveRegs(r: LONGINT); (* R[0 .. r-1]*)
  2047. VAR r0: LONGINT;
  2048. BEGIN (*r > 0*) r0 := 0;
  2049. Put10(0, Sub, SP, SP, r*4); INC(frame, 4*r);
  2050. REPEAT
  2051. IF r0 IN FR THEN Put2(Str, r0 + 100H, SP, (r-r0-1)*4)
  2052. ELSE Put2(Str, r0, SP, (r-r0-1)*4)
  2053. END;
  2054. INC(r0)
  2055. UNTIL r0 = r
  2056. END SaveRegs;
  2057. PROCEDURE RestoreRegs(r: LONGINT); (*R[0 .. r-1]*)
  2058. VAR r0: LONGINT;
  2059. BEGIN (*r > 0*) r0 := r;
  2060. REPEAT DEC(r0);
  2061. IF r0 IN FR THEN
  2062. ARMv7M.EmitVLDR(armcode, pc, ER(r0), ER(SP), 1, r-r0-1)
  2063. ELSE Put20(0, Ldr, r0, SP, (r-r0-1)*4)
  2064. END
  2065. UNTIL r0 = 0;
  2066. Put10(0, Add, SP, SP, r*4); DEC(frame, 4*r)
  2067. END RestoreRegs;
  2068. PROCEDURE PrepCall*(VAR x: Item; VAR r: LONGINT);
  2069. BEGIN (*x.type.form = ORB.Proc*)
  2070. IF x.mode > ORB.Par THEN load(x) END;
  2071. ASSERT(RH < 16); ASSERT(FR * {16..31} = {});
  2072. IF RH = 0 THEN r := 0
  2073. ELSE r := RH + 16 * ORDSET(FR * {0..RH-1})
  2074. END;
  2075. IF RH > 0 THEN SaveRegs(RH); RH := 0 END
  2076. END PrepCall;
  2077. PROCEDURE Call*(VAR x: Item; r: LONGINT);
  2078. CONST check = FALSE;
  2079. (* is not necessary:
  2080. HardFault trap (with pc=0) will occur,
  2081. because no Thumb flag in initialSP
  2082. *)
  2083. BEGIN (*x.type.form = ORB.Proc*)
  2084. IF x.mode = ORB.Const THEN
  2085. IF x.r >= 0 THEN Put3(BL, 7, (x.a DIV 4)-pc-1)
  2086. ELSE (*imported*)
  2087. (*
  2088. IF pc - fixorgP < 1000H THEN
  2089. *)
  2090. IF ((-x.r) DIV 100H = 0) (* mno *)
  2091. & (x.a DIV 100H = 0) (* pno *)
  2092. & ((pc-fixorgP) DIV 1000H = 0) (* disp *) THEN
  2093. (* will be fixed up by linker/loader *)
  2094. Put3orig(BL, 7, ((-x.r) * 100H + x.a) * 1000H + pc-fixorgP);
  2095. fixorgP := pc-1
  2096. ELSE ORS.Mark("fixup impossible")
  2097. END
  2098. END
  2099. ELSE
  2100. IF x.mode <= ORB.Par THEN
  2101. IF check THEN load(x) ELSE load0(0, x) END;
  2102. DEC(RH)
  2103. ELSE
  2104. Put20(0, Ldr, RH, SP, 0); Put10(0, Add, SP, SP, 4);
  2105. IF check THEN Put1(Cmp, RH, RH, 0) END;
  2106. DEC(r); DEC(frame, 4)
  2107. END;
  2108. IF check THEN Trap(EQ, 5) END;
  2109. Put3(BLR, 7, RH)
  2110. END;
  2111. IF x.type.base.form = ORB.NoTyp THEN (*procedure*) RH := 0
  2112. ELSE (*function*)
  2113. FR := BITS(r DIV 16); ASSERT(FR * {16..31} = {}); r := r MOD 16;
  2114. RH := MT;
  2115. IF r > 0 THEN Put00(0, Mov, r, 0, 0); RestoreRegs(r) END;
  2116. x.mode := Reg; x.r := r; RH := r+1
  2117. END;
  2118. invalSB; RM := {0..31}
  2119. END Call;
  2120. PROCEDURE Enter* (parblksize, locblksize: LONGINT; int: BOOLEAN);
  2121. VAR a, r: LONGINT;
  2122. BEGIN invalSB; frame := 0;
  2123. enterPushFixup := pc;
  2124. IF ~int THEN (*procedure prolog*)
  2125. (* IF locblksize >= 10000H THEN ORS.Mark("too many locals") END; *)
  2126. ARMv6M.EmitPUSH(armcode, pc, {LNK});
  2127. a := parblksize0Proc; r := 0;
  2128. IF locblksize # parblksize0Proc THEN Put10(0, Sub, SP, SP, locblksize) END;
  2129. WHILE a < parblksize DO Put2(Str, r, SP, a); INC(r); INC(a, 4) END
  2130. ELSE (*interrupt procedure*)
  2131. (* IF locblksize > 0H THEN ORS.Mark("locals not allowed") END; *)
  2132. ARMv7M.EmitPUSHW(armcode, pc, {LNK});
  2133. a := parblksize0Int; r := 0;
  2134. IF locblksize # parblksize0Int THEN Put10(0, Sub, SP, SP, locblksize) END;
  2135. WHILE a < parblksize DO Put2(Str, r, SP, a); INC(r); INC(a, 4) END
  2136. END;
  2137. RM := {}
  2138. END Enter;
  2139. (*
  2140. PROCEDURE Fix (VAR code: ARRAY OF INTEGER; i: INTEGER);
  2141. VAR cond, off, pc0: INTEGER;
  2142. BEGIN
  2143. IF ORS.errcnt = 0 THEN
  2144. IF code[i] DIV 10000000H MOD 10H = 0EH THEN (* BC *)
  2145. ASSERT(code[i+1] = tagBC, 100);
  2146. cond := code[i] DIV 1000000H MOD 10H;
  2147. off := (code[i] MOD 1000000H * 100H) DIV 100H;
  2148. pc0 := pc; pc := i;
  2149. Put3(BC, cond, off);
  2150. IF pc - i = 1 THEN ARMv6M.EmitNOP(armcode, pc) END;
  2151. IF ORS.errcnt = 0 THEN
  2152. ASSERT(pc - i = 2, 101)
  2153. END;
  2154. pc := pc0
  2155. END
  2156. END
  2157. END Fix;
  2158. *)
  2159. PROCEDURE Fix (VAR code: ARRAY OF INTEGER; i: INTEGER);
  2160. VAR cond, off, pc0: INTEGER;
  2161. BEGIN
  2162. IF ORS.errcnt = 0 THEN
  2163. IF code[i] DIV 10000000H MOD 10H = 0EH THEN (* BC *)
  2164. cond := code[i] DIV 1000000H MOD 10H;
  2165. off := (code[i] MOD 1000000H * 100H) DIV 100H;
  2166. pc0 := pc; pc := i;
  2167. Put3(BC, cond, off);
  2168. IF ORS.errcnt = 0 THEN
  2169. ASSERT(pc - i = 1, 100)
  2170. END;
  2171. pc := pc0
  2172. END
  2173. END
  2174. END Fix;
  2175. PROCEDURE FixRng (from, to: INTEGER);
  2176. BEGIN
  2177. WHILE from < to DO
  2178. Fix(armcode, from); INC(from)
  2179. END
  2180. END FixRng;
  2181. PROCEDURE Return* (form: INTEGER; VAR x: Item; size: LONGINT; int: BOOLEAN);
  2182. VAR pc0: INTEGER;
  2183. BEGIN
  2184. IF form # ORB.NoTyp THEN load(x); FPUToARMReg(x) END ;
  2185. IF ~int THEN (*procedure epilog*)
  2186. IF size # parblksize0Proc THEN Put10(0, Add, SP, SP, size) END;
  2187. IF LNK IN RM THEN
  2188. ARMv6M.EmitPOP(armcode, pc, {ARMv6M.PC})
  2189. ELSE
  2190. Put3(BR, 7, LNK);
  2191. pc0 := pc; pc := enterPushFixup;
  2192. ARMv6M.EmitNOP(armcode, pc);
  2193. pc := pc0
  2194. END
  2195. ELSE (*interrupt return*)
  2196. IF size # parblksize0Int THEN Put10(0, Add, SP, SP, size) END;
  2197. ARMv7M.EmitPOPW(armcode, pc, ERs(RM) * {4..11} - {ER(MT)} + {ARMv6M.PC});
  2198. pc0 := pc; pc := enterPushFixup;
  2199. ARMv7M.EmitPUSHW(armcode, pc, ERs(RM) * {4..11} - {ER(MT)} + {LNK});
  2200. pc := pc0
  2201. END;
  2202. RH := 0;
  2203. FixRng(enterPushFixup, pc)
  2204. END Return;
  2205. (* In-line code procedures*)
  2206. PROCEDURE Increment*(upordown: LONGINT; VAR x, y: Item);
  2207. VAR op, zr, v: LONGINT;
  2208. BEGIN (*frame = 0*)
  2209. IF upordown = 0 THEN op := Add ELSE op := Sub END ;
  2210. IF x.type = ORB.byteType THEN v := 1 ELSE v := 0 END ;
  2211. IF y.type.form = ORB.NoTyp THEN y.mode := ORB.Const; y.a := 1 END ;
  2212. IF (x.mode = ORB.Var) & (x.r > 0) THEN
  2213. zr := RH; Put20(0, Ldr+v, zr, SP, x.a); incR;
  2214. 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 ;
  2215. Put2(Str+v, zr, SP, x.a); DEC(RH)
  2216. ELSE loadAdr0(0, x); zr := RH; Put20(0, Ldr+v, RH, x.r, 0); incR;
  2217. 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 ;
  2218. Put2(Str+v, zr, x.r, 0); DEC(RH, 2)
  2219. END
  2220. END Increment;
  2221. PROCEDURE Include*(inorex: LONGINT; VAR x, y: Item);
  2222. VAR op, zr: LONGINT;
  2223. BEGIN loadAdr0(0, x); zr := RH; Put20(0, Ldr, RH, x.r, 0); incR;
  2224. IF inorex = 0 THEN op := Ior ELSE op := Ann END ;
  2225. IF y.mode = ORB.Const THEN Put10(0, op, zr, zr, LSL(1, y.a))
  2226. 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)
  2227. END ;
  2228. Put2(Str, zr, x.r, 0); DEC(RH, 2)
  2229. END Include;
  2230. PROCEDURE Assert*(VAR x: Item);
  2231. VAR cond: LONGINT;
  2232. BEGIN
  2233. IF x.mode # Cond THEN loadCond(x) END ;
  2234. IF x.a = 0 THEN cond := negated(x.r)
  2235. ELSE Put3orig(BC, x.r, x.b); FixLink(x.a); x.b := pc-1; cond := 7
  2236. END;
  2237. Trap(cond, 7); FixLink(x.b)
  2238. END Assert;
  2239. PROCEDURE New*(VAR x: Item);
  2240. BEGIN loadAdr0(0, x); loadTypTagAdr0(0, x.type.base); Trap(7, 0); RH := 0; invalSB
  2241. END New;
  2242. PROCEDURE Pack*(VAR x, y: Item);
  2243. VAR z: Item;
  2244. BEGIN z := x; load0(0, x); load0(0, y);
  2245. Put10(0, Lsl, y.r, y.r, 23); Put00(0, Add, x.r, x.r, y.r); DEC(RH); Store(z, x)
  2246. END Pack;
  2247. PROCEDURE Unpk*(VAR x, y: Item);
  2248. VAR z, e0: Item;
  2249. BEGIN z := x; load0(0, x); e0.mode := Reg; e0.r := RH; e0.type := ORB.intType;
  2250. Put10(0, Asr, RH, x.r, 23); Put10(0, Sub, RH, RH, 127); Store(y, e0); incR;
  2251. Put10(0, Lsl, RH, RH, 23); Put00(0, Sub, x.r, x.r, RH); Store(z, x)
  2252. END Unpk;
  2253. PROCEDURE Led*(VAR x: Item);
  2254. BEGIN (* load0(0, x); Put10(0, Mov, RH, 0, -60); Put2(Str, x.r, RH, 0); DEC(RH) *)
  2255. ORS.Mark("not supported")
  2256. END Led;
  2257. PROCEDURE Get*(VAR x, y: Item);
  2258. BEGIN load0(0, x); x.type := y.type; x.mode := RegI; x.a := 0; Store(y, x)
  2259. END Get;
  2260. PROCEDURE Put*(VAR x, y: Item);
  2261. BEGIN load0(0, x); x.type := y.type; x.mode := RegI; x.a := 0; Store(x, y)
  2262. END Put;
  2263. PROCEDURE Copy*(VAR x, y, z: Item);
  2264. VAR pc0, pc1: LONGINT;
  2265. BEGIN load0(0, x); load0(0, y);
  2266. pc0 := -1;
  2267. IF z.mode = ORB.Const THEN
  2268. IF z.a > 0 THEN load0(0, z) ELSE ORS.Mark("bad count") END
  2269. ELSE load(z);
  2270. IF check THEN Trap(LT, 3) END ;
  2271. pc0 := pc; Put3orig(BC, EQ, 0)
  2272. END;
  2273. pc1 := pc;
  2274. Put20(0, Ldr, RH, x.r, 0); Put10(0, Add, x.r, x.r, 4);
  2275. Put2(Str, RH, y.r, 0); Put10(0, Add, y.r, y.r, 4);
  2276. Put1(Sub, z.r, z.r, 1); Put3orig(BC, NE, pc1 - pc - 1); DEC(RH, 3);
  2277. IF pc0 # -1 THEN fix(pc0, pc - pc0 - 1) END
  2278. END Copy;
  2279. PROCEDURE LDPSR*(VAR x: Item);
  2280. BEGIN (*x.mode = Const*) Put3(0, 15, x.a + 20H)
  2281. END LDPSR;
  2282. PROCEDURE LDREG* (VAR x, y: Item);
  2283. BEGIN
  2284. IF x.mode = ORB.Const THEN
  2285. IF x.a IN {0..15} THEN
  2286. IF y.mode = ORB.Const THEN Put10(0, Mov, DR(x.a), 0, y.a)
  2287. ELSE load0(0, y); Put00(0, Mov, DR(x.a), 0, y.r); DEC(RH)
  2288. END
  2289. ELSE ORS.Mark("invalid register")
  2290. END
  2291. ELSE ORS.Mark("not supported")
  2292. END
  2293. END LDREG;
  2294. (*In-line code functions*)
  2295. PROCEDURE Abs*(VAR x: Item);
  2296. VAR pc0: LONGINT;
  2297. BEGIN
  2298. IF x.mode = ORB.Const THEN x.a := ABS(x.a)
  2299. ELSIF x.type.form = ORB.Real THEN
  2300. (* load0(0, x); Put10(0, Lsl, x.r, x.r, 1); Put1(Ror, x.r, x.r, 1) *)
  2301. loadReal(x);
  2302. ARMv7M.EmitVABS(armcode, pc, ER(x.r - 100H), ER(x.r - 100H))
  2303. ELSE
  2304. load0(0, x);
  2305. Put1(Cmp, x.r, x.r, 0);
  2306. pc0 := pc; Put3orig(BC, GE, 0);
  2307. (* Put10(0, Mov, RH, 0, 0); Put0(Sub, x.r, RH, x.r) *)
  2308. RSBS0(x.r);
  2309. fix(pc0, pc - pc0 - 1)
  2310. END
  2311. END Abs;
  2312. PROCEDURE Odd*(VAR x: Item);
  2313. BEGIN load0(0, x); Put1(And, x.r, x.r, 1); SetCC(x, NE); DEC(RH)
  2314. END Odd;
  2315. (* this is Trunc
  2316. PROCEDURE Floor*(VAR x: Item);
  2317. BEGIN
  2318. (*
  2319. load0(0, x); Put10(0, Mov+U, RH, 0, 4B00H); Put0(Fad+V, x.r, x.r, RH)
  2320. *)
  2321. loadReal(x);
  2322. ARMv7M.EmitVCVTRInt(armcode, pc,
  2323. TRUE, FALSE, TRUE, ER(x.r - 100H), ER(x.r - 100H));
  2324. FPUToARMReg(x)
  2325. END Floor;
  2326. *)
  2327. PROCEDURE Floor*(VAR x: Item);
  2328. CONST S = 0;
  2329. VAR i, imm3, imm8: INTEGER;
  2330. ok: BOOLEAN;
  2331. BEGIN
  2332. (*
  2333. load0(0, x); Put10(0, Mov+U, RH, 0, 4B00H); Put0(Fad+V, x.r, x.r, RH)
  2334. *)
  2335. loadReal(x);
  2336. ASSERT(RH < MT, 100);
  2337. ASSERT(RH # SP, 101);
  2338. (* save FPSCR *)
  2339. ARMv7M.EmitVMRS(armcode, pc, ER(RH));
  2340. (* FPSCR.RMode := RM (A2.6.2) *)
  2341. (* FPSCR - {22,23} *)
  2342. ARMv7M.EncodeMI12(0C00000H, i, imm3, imm8, ok);
  2343. ASSERT(ok, 102);
  2344. ARMv7M.EmitDPMI(armcode, pc,
  2345. i, 2 + S, ER(RH), imm3, ER(x.r - 100H), imm8);
  2346. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  2347. (* FPSCR - {22} + {23} *)
  2348. ARMv7M.EncodeMI12(800000H, i, imm3, imm8, ok);
  2349. ASSERT(ok, 103);
  2350. ARMv7M.EmitDPMI(armcode, pc,
  2351. i, 4 + S, ER(x.r - 100H), imm3, ER(x.r - 100H), imm8);
  2352. (* S=1: N, Z, C will be updated *) (* NOTE: C *)
  2353. (* FPSCR := FPSCR - {22} + {23} *)
  2354. ARMv7M.EmitVMSR(armcode, pc, ER(x.r - 100H));
  2355. ARMv7M.EmitVCVTRInt(armcode, pc,
  2356. TRUE, TRUE, TRUE, ER(x.r - 100H), ER(x.r - 100H));
  2357. (* restore saved FPSCR *)
  2358. ARMv7M.EmitVMSR(armcode, pc, ER(RH));
  2359. FPUToARMReg(x)
  2360. END Floor;
  2361. PROCEDURE Float*(VAR x: Item);
  2362. BEGIN
  2363. (*
  2364. load0(0, x); Put10(0, Mov+U, RH, 0, 4B00H); Put0(Fad+U, x.r, x.r, RH)
  2365. *)
  2366. loadReal(x);
  2367. ARMv7M.EmitVCVTRInt(armcode, pc,
  2368. FALSE, FALSE, TRUE, ER(x.r - 100H), ER(x.r - 100H))
  2369. END Float;
  2370. PROCEDURE Ord*(VAR x: Item);
  2371. BEGIN
  2372. IF x.mode IN {ORB.Var, ORB.Par, RegI, Cond} THEN load(x) END
  2373. END Ord;
  2374. PROCEDURE Len*(VAR x: Item);
  2375. BEGIN
  2376. IF x.type.len >= 0 THEN
  2377. IF x.mode = RegI THEN DEC(RH) END;
  2378. x.mode := ORB.Const; x.a := x.type.len
  2379. ELSE (*open array*) Put2(Ldr, RH, SP, x.a + 4 + frame); x.mode := Reg; x.r := RH; incR
  2380. END
  2381. END Len;
  2382. PROCEDURE Shift*(fct: LONGINT; VAR x, y: Item);
  2383. VAR op: LONGINT;
  2384. BEGIN load0(0, x);
  2385. IF fct = 0 THEN op := Lsl ELSIF fct = 1 THEN op := Asr ELSE op := Ror END ;
  2386. IF y.mode = ORB.Const THEN Put1(op, x.r, x.r, y.a MOD 20H)
  2387. ELSE load0(0, y); Put0(op, RH-2, x.r, y.r); DEC(RH); x.r := RH-1
  2388. END
  2389. END Shift;
  2390. PROCEDURE ADC*(VAR x, y: Item);
  2391. BEGIN load0(0, x); load0(0, y); Put0(Add+U, x.r, x.r, y.r); DEC(RH)
  2392. END ADC;
  2393. PROCEDURE SBC*(VAR x, y: Item);
  2394. BEGIN load0(0, x); load0(0, y); Put0(Sub+U, x.r, x.r, y.r); DEC(RH)
  2395. END SBC;
  2396. PROCEDURE UML*(VAR x, y: Item);
  2397. BEGIN load0(0, x); load0(0, y); Put0(Mul+U, x.r, x.r, y.r); DEC(RH)
  2398. END UML;
  2399. PROCEDURE Bit*(VAR x, y: Item);
  2400. BEGIN load0(0, x); Put20(0, Ldr, x.r, x.r, 0);
  2401. IF y.mode = ORB.Const THEN Put1(Ror, x.r, x.r, y.a+1); DEC(RH)
  2402. ELSE load0(0, y); Put10(0, Add, y.r, y.r, 1); Put0(Ror, x.r, x.r, y.r); DEC(RH, 2)
  2403. END;
  2404. SetCC(x, MI)
  2405. END Bit;
  2406. PROCEDURE Register*(VAR x: Item);
  2407. BEGIN (*x.mode = Const*)
  2408. Put0(Mov, RH, 0, DR(x.a MOD 10H)); x.mode := Reg; x.r := RH; incR
  2409. END Register;
  2410. PROCEDURE H* (VAR x: Item);
  2411. BEGIN (*x.mode = Const*)
  2412. (* Put0(Mov+U + x.a MOD 2 * V, RH, 0, 0); *) ORS.Mark("not supported");
  2413. x.mode := Reg; x.r := RH; incR
  2414. END H;
  2415. PROCEDURE Adr*(VAR x: Item);
  2416. BEGIN
  2417. IF x.mode IN {ORB.Var, ORB.Par, RegI} THEN loadAdr(x)
  2418. ELSIF (x.mode = ORB.Const) & (x.type.form = ORB.Proc) THEN load(x)
  2419. ELSIF (x.mode = ORB.Const) & (x.type.form = ORB.String) THEN loadStringAdr(x)
  2420. ELSE ORS.Mark("not addressable")
  2421. END
  2422. END Adr;
  2423. PROCEDURE Condition*(VAR x: Item);
  2424. BEGIN (*x.mode = Const*) SetCC(x, x.a)
  2425. END Condition;
  2426. PROCEDURE Open* (v: INTEGER);
  2427. BEGIN pc := 0; tdx := 0; strx := 0; RH := 0; FR := {}; updateCarry := FALSE; fixorgP := 0; fixorgD := 0; fixorgT := 0; check := v # 0; version := v;
  2428. IF v = 0 THEN
  2429. armcode[0] := 0; armcode[1] := 0;
  2430. (* CPU exceptions (NMI..SysTick) *)
  2431. pc := 4; WHILE pc < 40H DIV 2 DO
  2432. armcode[pc] := 1; INC(pc);
  2433. armcode[pc] := 0; INC(pc)
  2434. END;
  2435. (* IRQ 0..239 (Cortex-M4 allows up to 240 IRQs) *)
  2436. WHILE pc < 40H DIV 2 + 240 * 2 DO
  2437. armcode[pc] := 1; INC(pc);
  2438. armcode[pc] := 0; INC(pc)
  2439. END
  2440. ELSE ARMv6M.EmitNOP(armcode, pc) (* pc must be not zero (fixups) *)
  2441. END
  2442. END Open;
  2443. PROCEDURE SetDataSize* (dc: LONGINT);
  2444. BEGIN varsize := dc
  2445. END SetDataSize;
  2446. PROCEDURE Header*;
  2447. VAR i, cs: INTEGER;
  2448. BEGIN entry := pc*4;
  2449. IF version = 0 THEN (*RISC-0*)
  2450. armcode[2] := (entry DIV 2 + 1) MOD 10000H;
  2451. armcode[3] := (entry DIV 2 + 1) DIV 10000H MOD 10000H;
  2452. (* NXP checksum *)
  2453. cs := 0; i := 0;
  2454. WHILE i < 7 DO
  2455. cs := cs + armcode[2 * i] + 10000H * armcode[2 * i + 1];
  2456. INC(i)
  2457. END;
  2458. armcode[2 * i] := (-cs) MOD 10000H;
  2459. armcode[2 * i + 1] := (-cs) DIV 10000H MOD 10000H
  2460. ELSE ARMv6M.EmitPUSH(armcode, pc, {LNK}); invalSB
  2461. END
  2462. END Header;
  2463. PROCEDURE NofPtrs(typ: ORB.Type): LONGINT;
  2464. VAR fld: ORB.Object; n: LONGINT;
  2465. BEGIN
  2466. IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN n := 1
  2467. ELSIF typ.form = ORB.Record THEN
  2468. fld := typ.dsc; n := 0;
  2469. WHILE fld # NIL DO n := NofPtrs(fld.type) + n; fld := fld.next END
  2470. ELSIF typ.form = ORB.Array THEN n := NofPtrs(typ.base) * typ.len
  2471. ELSE n := 0
  2472. END ;
  2473. RETURN n
  2474. END NofPtrs;
  2475. PROCEDURE FindPtrs(VAR R: Files.Rider; typ: ORB.Type; adr: LONGINT);
  2476. VAR fld: ORB.Object; i, s: LONGINT;
  2477. BEGIN
  2478. IF (typ.form = ORB.Pointer) OR (typ.form = ORB.NilTyp) THEN Files.WriteLInt(R, adr)
  2479. ELSIF typ.form = ORB.Record THEN
  2480. fld := typ.dsc;
  2481. WHILE fld # NIL DO FindPtrs(R, fld.type, fld.val + adr); fld := fld.next END
  2482. ELSIF typ.form = ORB.Array THEN
  2483. s := typ.base.size;
  2484. FOR i := 0 TO typ.len-1 DO FindPtrs(R, typ.base, i*s + adr) END
  2485. END
  2486. END FindPtrs;
  2487. PROCEDURE Close* (VAR modid: ORS.Ident; key, nofent: LONGINT);
  2488. VAR obj: ORB.Object;
  2489. i, comsize, nofimps, nofptrs, size: LONGINT;
  2490. name: ORS.Ident;
  2491. F: Files.File; R: Files.Rider;
  2492. BEGIN (*exit code*)
  2493. FixRng(0, pc);
  2494. IF version = 0 THEN Put3(BC, 7, -1) (*RISC-0*)
  2495. ELSE ARMv6M.EmitPOP(armcode, pc, {ARMv6M.PC})
  2496. END;
  2497. obj := ORB.topScope.next; nofimps := 0; comsize := 4; nofptrs := 0;
  2498. WHILE obj # NIL DO
  2499. IF (obj.class = ORB.Mod) & (obj.dsc # ORB.system) THEN INC(nofimps) (*count imports*)
  2500. ELSIF (obj.exno # 0) & (obj.class = ORB.Const) & (obj.type.form = ORB.Proc)
  2501. & (obj.type.nofpar = 0) & (obj.type.base = ORB.noType) THEN i := 0; (*count commands*)
  2502. WHILE obj.name[i] # 0X DO INC(i) END ;
  2503. i := (i+4) DIV 4 * 4; INC(comsize, i+4)
  2504. ELSIF obj.class = ORB.Var THEN INC(nofptrs, NofPtrs(obj.type)) (*count pointers*)
  2505. END;
  2506. obj := obj.next
  2507. END;
  2508. size := varsize + strx + comsize + (pc + nofimps + nofent + nofptrs + 1)*4; (*varsize includes type descriptors*)
  2509. ORB.MakeFileName(name, modid, ".a7m"); (*write code file*)
  2510. F := Files.New(name); Files.Set(R, F, 0); Files.WriteString(R, modid); Files.WriteLInt(R, key); Files.Write(R, CHR(version));
  2511. Files.WriteLInt(R, size);
  2512. obj := ORB.topScope.next;
  2513. WHILE (obj # NIL) & (obj.class = ORB.Mod) DO (*imports*)
  2514. IF obj.dsc # ORB.system THEN Files.WriteString(R, obj(ORB.Module).orgname); Files.WriteLInt(R, obj.val) END ;
  2515. obj := obj.next
  2516. END;
  2517. Files.Write(R, 0X);
  2518. Files.WriteLInt(R, tdx*4);
  2519. i := 0;
  2520. WHILE i < tdx DO Files.WriteLInt(R, data[i]); INC(i) END ; (*type descriptors*)
  2521. Files.WriteLInt(R, varsize - tdx*4); (*data*)
  2522. Files.WriteLInt(R, strx);
  2523. FOR i := 0 TO strx-1 DO Files.Write(R, str[i]) END ; (*strings*)
  2524. Files.WriteLInt(R, pc); (*code len*)
  2525. FOR i := 0 TO pc-1 DO
  2526. Files.WriteLInt(R, armcode[i])
  2527. END; (*program*)
  2528. obj := ORB.topScope.next;
  2529. WHILE obj # NIL DO (*commands*)
  2530. IF (obj.exno # 0) & (obj.class = ORB.Const) & (obj.type.form = ORB.Proc) &
  2531. (obj.type.nofpar = 0) & (obj.type.base = ORB.noType) THEN
  2532. Files.WriteString(R, obj.name); Files.WriteLInt(R, obj.val)
  2533. END;
  2534. obj := obj.next
  2535. END;
  2536. Files.Write(R, 0X);
  2537. Files.WriteLInt(R, nofent); Files.WriteLInt(R, entry);
  2538. obj := ORB.topScope.next;
  2539. WHILE obj # NIL DO (*entries*)
  2540. IF obj.exno # 0 THEN
  2541. IF (obj.class = ORB.Const) & (obj.type.form = ORB.Proc) OR (obj.class = ORB.Var) THEN
  2542. Files.WriteLInt(R, obj.val)
  2543. ELSIF obj.class = ORB.Typ THEN
  2544. IF obj.type.form = ORB.Record THEN Files.WriteLInt(R, obj.type.len MOD 10000H)
  2545. ELSIF (obj.type.form = ORB.Pointer) & ((obj.type.base.typobj = NIL) OR (obj.type.base.typobj.exno = 0)) THEN
  2546. Files.WriteLInt(R, obj.type.base.len MOD 10000H)
  2547. END
  2548. END
  2549. END;
  2550. obj := obj.next
  2551. END;
  2552. obj := ORB.topScope.next;
  2553. WHILE obj # NIL DO (*pointer variables*)
  2554. IF obj.class = ORB.Var THEN FindPtrs(R, obj.type, obj.val) END ;
  2555. obj := obj.next
  2556. END;
  2557. Files.WriteLInt(R, -1);
  2558. Files.WriteLInt(R, fixorgP); Files.WriteLInt(R, fixorgD); Files.WriteLInt(R, fixorgT); Files.WriteLInt(R, entry);
  2559. Files.Write(R, "O"); Files.Register(F)
  2560. END Close;
  2561. BEGIN
  2562. relmap[0] := 1; relmap[1] := 9; relmap[2] := 5; relmap[3] := 6; relmap[4] := 14; relmap[5] := 13
  2563. END O7ARMv7MG.