MSP430.ob07 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764
  1. MODULE MSP430;
  2. IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX,
  3. UTILS, C := CONSOLE, PROG, RTL := MSP430RTL;
  4. CONST
  5. chkSTK* = 6;
  6. minRAM* = 128; maxRAM* = 2048;
  7. minROM* = 2048; maxROM* = 24576;
  8. StkReserve = RTL.StkReserve;
  9. IntVectorSize* = RTL.IntVectorSize;
  10. PC = 0; SP = 1; SR = 2; CG = 3;
  11. R4 = 4; R5 = 5; R6 = 6; R7 = 7;
  12. HP = RTL.HP;
  13. ACC = R4;
  14. opRRC = 1000H; opSWPB = 1080H; opRRA = 1100H; opSXT = 1180H;
  15. opPUSH = 1200H; opCALL = 1280H; opRETI = 1300H;
  16. opMOV = 04000H; opADD = 05000H; opADDC = 06000H; opSUBC = 07000H;
  17. opSUB = 08000H; opCMP = 09000H; opDADD = 0A000H; opBIT = 0B000H;
  18. opBIC = 0C000H; opBIS = 0D000H; opXOR = 0E000H; opAND = 0F000H;
  19. opJNE = 2000H; opJEQ = 2400H; opJNC = 2800H; opJC = 2C00H;
  20. opJN = 3000H; opJGE = 3400H; opJL = 3800H; opJMP = 3C00H;
  21. sREG = 0; sIDX = 16; sINDIR = 32; sINCR = 48; BW = 64; dIDX = 128;
  22. NOWORD = 10000H;
  23. RCODE = 0; RDATA = 1; RBSS = 2;
  24. je = 0; jne = je + 1;
  25. jge = 2; jl = jge + 1;
  26. jle = 4; jg = jle + 1;
  27. jb = 6;
  28. TYPE
  29. ANYCODE = POINTER TO RECORD (LISTS.ITEM)
  30. offset: INTEGER
  31. END;
  32. WORD = POINTER TO RECORD (ANYCODE)
  33. val: INTEGER
  34. END;
  35. LABEL = POINTER TO RECORD (ANYCODE)
  36. num: INTEGER
  37. END;
  38. JMP = POINTER TO RECORD (ANYCODE)
  39. cc, label: INTEGER;
  40. short: BOOLEAN
  41. END;
  42. CALL = POINTER TO RECORD (ANYCODE)
  43. label: INTEGER
  44. END;
  45. COMMAND = IL.COMMAND;
  46. RELOC = POINTER TO RECORD (LISTS.ITEM)
  47. section: INTEGER;
  48. WordPtr: WORD
  49. END;
  50. VAR
  51. R: REG.REGS;
  52. CodeList: LISTS.LIST;
  53. RelList: LISTS.LIST;
  54. mem: ARRAY 65536 OF BYTE;
  55. Labels: CHL.INTLIST;
  56. IV: ARRAY RTL.LenIV OF INTEGER;
  57. IdxWords: RECORD src, dst: INTEGER END;
  58. StkCnt, MaxStkCnt: INTEGER;
  59. PROCEDURE CheckProcDataSize* (VarSize, RamSize: INTEGER): BOOLEAN;
  60. RETURN (VarSize + 1) * 2 + StkReserve + RTL.VarSize < RamSize
  61. END CheckProcDataSize;
  62. PROCEDURE EmitLabel (L: INTEGER);
  63. VAR
  64. label: LABEL;
  65. BEGIN
  66. NEW(label);
  67. label.num := L;
  68. LISTS.push(CodeList, label)
  69. END EmitLabel;
  70. PROCEDURE EmitWord (val: INTEGER);
  71. VAR
  72. word: WORD;
  73. BEGIN
  74. IF val < 0 THEN
  75. ASSERT(val >= -32768);
  76. val := val MOD 65536
  77. ELSE
  78. ASSERT(val <= 65535)
  79. END;
  80. NEW(word);
  81. word.val := val;
  82. LISTS.push(CodeList, word)
  83. END EmitWord;
  84. PROCEDURE EmitJmp (cc, label: INTEGER);
  85. VAR
  86. jmp: JMP;
  87. BEGIN
  88. NEW(jmp);
  89. jmp.cc := cc;
  90. jmp.label := label;
  91. jmp.short := FALSE;
  92. LISTS.push(CodeList, jmp)
  93. END EmitJmp;
  94. PROCEDURE EmitCall (label: INTEGER);
  95. VAR
  96. call: CALL;
  97. BEGIN
  98. NEW(call);
  99. call.label := label;
  100. LISTS.push(CodeList, call)
  101. END EmitCall;
  102. PROCEDURE IncStk;
  103. BEGIN
  104. INC(StkCnt);
  105. MaxStkCnt := MAX(StkCnt, MaxStkCnt)
  106. END IncStk;
  107. PROCEDURE bw (b: BOOLEAN): INTEGER;
  108. RETURN BW * ORD(b)
  109. END bw;
  110. PROCEDURE src_x (x, Rn: INTEGER): INTEGER;
  111. VAR
  112. res: INTEGER;
  113. BEGIN
  114. IF (x = 0) & ~(Rn IN {PC, SR, CG}) THEN
  115. res := Rn * 256 + sINDIR
  116. ELSE
  117. IdxWords.src := x;
  118. res := Rn * 256 + sIDX
  119. END
  120. RETURN res
  121. END src_x;
  122. PROCEDURE dst_x (x, Rn: INTEGER): INTEGER;
  123. BEGIN
  124. IdxWords.dst := x
  125. RETURN Rn + dIDX
  126. END dst_x;
  127. PROCEDURE indir (Rn: INTEGER): INTEGER;
  128. RETURN Rn * 256 + sINDIR
  129. END indir;
  130. PROCEDURE incr (Rn: INTEGER): INTEGER;
  131. RETURN Rn * 256 + sINCR
  132. END incr;
  133. PROCEDURE imm (x: INTEGER): INTEGER;
  134. VAR
  135. res: INTEGER;
  136. BEGIN
  137. CASE x OF
  138. | 0: res := CG * 256
  139. | 1: res := CG * 256 + sIDX
  140. | 2: res := indir(CG)
  141. | 4: res := indir(SR)
  142. | 8: res := incr(SR)
  143. |-1: res := incr(CG)
  144. ELSE
  145. res := incr(PC);
  146. IdxWords.src := x
  147. END
  148. RETURN res
  149. END imm;
  150. PROCEDURE Op2 (op, src, dst: INTEGER);
  151. BEGIN
  152. ASSERT(BITS(op) - {6, 12..15} = {});
  153. ASSERT(BITS(src) - {4, 5, 8..11} = {});
  154. ASSERT(BITS(dst) - {0..3, 7} = {});
  155. EmitWord(op + src + dst);
  156. IF IdxWords.src # NOWORD THEN
  157. EmitWord(IdxWords.src);
  158. IdxWords.src := NOWORD
  159. END;
  160. IF IdxWords.dst # NOWORD THEN
  161. EmitWord(IdxWords.dst);
  162. IdxWords.dst := NOWORD
  163. END
  164. END Op2;
  165. PROCEDURE Op1 (op, reg, As: INTEGER);
  166. BEGIN
  167. EmitWord(op + reg + As)
  168. END Op1;
  169. PROCEDURE MovRR (src, dst: INTEGER);
  170. BEGIN
  171. Op2(opMOV, src * 256, dst)
  172. END MovRR;
  173. PROCEDURE PushImm (imm: INTEGER);
  174. BEGIN
  175. imm := UTILS.Long(imm);
  176. CASE imm OF
  177. | 0: Op1(opPUSH, CG, sREG)
  178. | 1: Op1(opPUSH, CG, sIDX)
  179. | 2: Op1(opPUSH, CG, sINDIR)
  180. |-1: Op1(opPUSH, CG, sINCR)
  181. ELSE
  182. Op1(opPUSH, PC, sINCR);
  183. EmitWord(imm)
  184. END;
  185. IncStk
  186. END PushImm;
  187. PROCEDURE PutWord (word: INTEGER; VAR adr: INTEGER);
  188. BEGIN
  189. ASSERT(~ODD(adr));
  190. ASSERT((0 <= word) & (word <= 65535));
  191. mem[adr] := word MOD 256;
  192. mem[adr + 1] := word DIV 256;
  193. INC(adr, 2)
  194. END PutWord;
  195. PROCEDURE NewLabel (): INTEGER;
  196. BEGIN
  197. CHL.PushInt(Labels, 0)
  198. RETURN IL.NewLabel()
  199. END NewLabel;
  200. PROCEDURE LabelOffs (n: INTEGER): INTEGER;
  201. RETURN CHL.GetInt(Labels, n)
  202. END LabelOffs;
  203. PROCEDURE Fixup (CodeAdr, IntVectorSize: INTEGER): INTEGER;
  204. VAR
  205. cmd: ANYCODE;
  206. adr: INTEGER;
  207. offset: INTEGER;
  208. diff: INTEGER;
  209. cc: INTEGER;
  210. shorted: BOOLEAN;
  211. BEGIN
  212. REPEAT
  213. shorted := FALSE;
  214. offset := CodeAdr DIV 2;
  215. cmd := CodeList.first(ANYCODE);
  216. WHILE cmd # NIL DO
  217. cmd.offset := offset;
  218. CASE cmd OF
  219. |LABEL: CHL.SetInt(Labels, cmd.num, offset)
  220. |JMP: INC(offset);
  221. IF ~cmd.short THEN
  222. INC(offset);
  223. IF cmd.cc # opJMP THEN
  224. INC(offset)
  225. END
  226. END
  227. |CALL: INC(offset, 2)
  228. |WORD: INC(offset)
  229. END;
  230. cmd := cmd.next(ANYCODE)
  231. END;
  232. cmd := CodeList.first(ANYCODE);
  233. WHILE cmd # NIL DO
  234. IF (cmd IS JMP) & ~cmd(JMP).short THEN
  235. diff := LabelOffs(cmd(JMP).label) - cmd.offset - 1;
  236. IF ABS(diff) <= 512 THEN
  237. cmd(JMP).short := TRUE;
  238. shorted := TRUE
  239. END
  240. END;
  241. cmd := cmd.next(ANYCODE)
  242. END
  243. UNTIL ~shorted;
  244. IF offset * 2 > 10000H - IntVectorSize THEN
  245. ERRORS.Error(203)
  246. END;
  247. adr := CodeAdr;
  248. cmd := CodeList.first(ANYCODE);
  249. WHILE cmd # NIL DO
  250. CASE cmd OF
  251. |LABEL:
  252. |JMP: IF ~cmd.short THEN
  253. CASE cmd.cc OF
  254. |opJNE: cc := opJEQ
  255. |opJEQ: cc := opJNE
  256. |opJNC: cc := opJC
  257. |opJC: cc := opJNC
  258. |opJGE: cc := opJL
  259. |opJL: cc := opJGE
  260. |opJMP: cc := opJMP
  261. END;
  262. IF cc # opJMP THEN
  263. PutWord(cc + 2, adr) (* jcc L *)
  264. END;
  265. PutWord(4030H, adr); (* MOV @PC+, PC *)
  266. PutWord(LabelOffs(cmd.label) * 2, adr)
  267. (* L: *)
  268. ELSE
  269. diff := LabelOffs(cmd.label) - cmd.offset - 1;
  270. ASSERT((-512 <= diff) & (diff <= 511));
  271. PutWord(cmd.cc + diff MOD 1024, adr)
  272. END
  273. |CALL: PutWord(12B0H, adr); (* CALL @PC+ *)
  274. PutWord(LabelOffs(cmd.label) * 2, adr)
  275. |WORD: PutWord(cmd.val, adr)
  276. END;
  277. cmd := cmd.next(ANYCODE)
  278. END
  279. RETURN adr - CodeAdr
  280. END Fixup;
  281. PROCEDURE Push (reg: INTEGER);
  282. BEGIN
  283. Op1(opPUSH, reg, sREG);
  284. IncStk
  285. END Push;
  286. PROCEDURE Pop (reg: INTEGER);
  287. BEGIN
  288. Op2(opMOV, incr(SP), reg);
  289. DEC(StkCnt)
  290. END Pop;
  291. PROCEDURE Test (reg: INTEGER);
  292. BEGIN
  293. Op2(opCMP, imm(0), reg)
  294. END Test;
  295. PROCEDURE Clear (reg: INTEGER);
  296. BEGIN
  297. Op2(opMOV, imm(0), reg)
  298. END Clear;
  299. PROCEDURE mov (dst, src: INTEGER);
  300. BEGIN
  301. MovRR(src, dst)
  302. END mov;
  303. PROCEDURE xchg (reg1, reg2: INTEGER);
  304. BEGIN
  305. Push(reg1);
  306. mov(reg1, reg2);
  307. Pop(reg2)
  308. END xchg;
  309. PROCEDURE Reloc (section: INTEGER);
  310. VAR
  311. reloc: RELOC;
  312. BEGIN
  313. NEW(reloc);
  314. reloc.section := section;
  315. reloc.WordPtr := CodeList.last(WORD);
  316. LISTS.push(RelList, reloc)
  317. END Reloc;
  318. PROCEDURE CallRTL (proc, params: INTEGER);
  319. BEGIN
  320. IncStk;
  321. DEC(StkCnt);
  322. EmitCall(RTL.rtl[proc].label);
  323. RTL.Used(proc);
  324. IF params > 0 THEN
  325. Op2(opADD, imm(params * 2), SP);
  326. DEC(StkCnt, params)
  327. END
  328. END CallRTL;
  329. PROCEDURE UnOp (VAR reg: INTEGER);
  330. BEGIN
  331. REG.UnOp(R, reg)
  332. END UnOp;
  333. PROCEDURE BinOp (VAR reg1, reg2: INTEGER);
  334. BEGIN
  335. REG.BinOp(R, reg1, reg2)
  336. END BinOp;
  337. PROCEDURE GetRegA;
  338. BEGIN
  339. ASSERT(REG.GetReg(R, ACC))
  340. END GetRegA;
  341. PROCEDURE drop;
  342. BEGIN
  343. REG.Drop(R)
  344. END drop;
  345. PROCEDURE GetAnyReg (): INTEGER;
  346. RETURN REG.GetAnyReg(R)
  347. END GetAnyReg;
  348. PROCEDURE PushAll (NumberOfParameters: INTEGER);
  349. BEGIN
  350. REG.PushAll(R);
  351. DEC(R.pushed, NumberOfParameters)
  352. END PushAll;
  353. PROCEDURE PushAll_1;
  354. BEGIN
  355. REG.PushAll_1(R)
  356. END PushAll_1;
  357. PROCEDURE cond (op: INTEGER): INTEGER;
  358. VAR
  359. res: INTEGER;
  360. BEGIN
  361. CASE op OF
  362. |IL.opGT, IL.opGTC: res := jg
  363. |IL.opGE, IL.opGEC: res := jge
  364. |IL.opLT, IL.opLTC: res := jl
  365. |IL.opLE, IL.opLEC: res := jle
  366. |IL.opEQ, IL.opEQC: res := je
  367. |IL.opNE, IL.opNEC: res := jne
  368. END
  369. RETURN res
  370. END cond;
  371. PROCEDURE jcc (cc, label: INTEGER);
  372. VAR
  373. L: INTEGER;
  374. BEGIN
  375. CASE cc OF
  376. |jne:
  377. EmitJmp(opJNE, label)
  378. |je:
  379. EmitJmp(opJEQ, label)
  380. |jge:
  381. EmitJmp(opJGE, label)
  382. |jl:
  383. EmitJmp(opJL, label)
  384. |jle:
  385. EmitJmp(opJL, label);
  386. EmitJmp(opJEQ, label)
  387. |jg:
  388. L := NewLabel();
  389. EmitJmp(opJEQ, L);
  390. EmitJmp(opJGE, label);
  391. EmitLabel(L)
  392. |jb:
  393. EmitJmp(opJNC, label)
  394. END
  395. END jcc;
  396. PROCEDURE setcc (cc, reg: INTEGER);
  397. VAR
  398. L: INTEGER;
  399. BEGIN
  400. L := NewLabel();
  401. Op2(opMOV, imm(1), reg);
  402. jcc(cc, L);
  403. Clear(reg);
  404. EmitLabel(L)
  405. END setcc;
  406. PROCEDURE Shift2 (op, reg, n: INTEGER);
  407. VAR
  408. reg2: INTEGER;
  409. BEGIN
  410. IF n >= 8 THEN
  411. CASE op OF
  412. |IL.opASR2: Op1(opSWPB, reg, sREG); Op1(opSXT, reg, sREG)
  413. |IL.opROR2: Op1(opSWPB, reg, sREG)
  414. |IL.opLSL2: Op1(opSWPB, reg, sREG); Op2(opBIC, imm(255), reg)
  415. |IL.opLSR2: Op2(opBIC, imm(255), reg); Op1(opSWPB, reg, sREG)
  416. END;
  417. DEC(n, 8)
  418. END;
  419. IF (op = IL.opROR2) & (n > 0) THEN
  420. reg2 := GetAnyReg();
  421. MovRR(reg, reg2)
  422. ELSE
  423. reg2 := -1
  424. END;
  425. WHILE n > 0 DO
  426. CASE op OF
  427. |IL.opASR2: Op1(opRRA, reg, sREG)
  428. |IL.opROR2: Op1(opRRC, reg2, sREG); Op1(opRRC, reg, sREG)
  429. |IL.opLSL2: Op2(opADD, reg * 256, reg)
  430. |IL.opLSR2: Op2(opBIC, imm(1), SR); Op1(opRRC, reg, sREG)
  431. END;
  432. DEC(n)
  433. END;
  434. IF reg2 # -1 THEN
  435. drop
  436. END
  437. END Shift2;
  438. PROCEDURE Neg (reg: INTEGER);
  439. BEGIN
  440. Op2(opXOR, imm(-1), reg);
  441. Op2(opADD, imm(1), reg)
  442. END Neg;
  443. PROCEDURE LocalOffset (offset: INTEGER): INTEGER;
  444. RETURN (offset + StkCnt - ORD(offset > 0)) * 2
  445. END LocalOffset;
  446. PROCEDURE LocalDst (offset: INTEGER): INTEGER;
  447. RETURN dst_x(LocalOffset(offset), SP)
  448. END LocalDst;
  449. PROCEDURE LocalSrc (offset: INTEGER): INTEGER;
  450. RETURN src_x(LocalOffset(offset), SP)
  451. END LocalSrc;
  452. PROCEDURE translate (chk_stk: BOOLEAN);
  453. VAR
  454. cmd, next: COMMAND;
  455. opcode, param1, param2, L, a, n, c1, c2: INTEGER;
  456. reg1, reg2: INTEGER;
  457. cc: INTEGER;
  458. word: WORD;
  459. BEGIN
  460. cmd := IL.codes.commands.first(COMMAND);
  461. WHILE cmd # NIL DO
  462. param1 := cmd.param1;
  463. param2 := cmd.param2;
  464. opcode := cmd.opcode;
  465. CASE opcode OF
  466. |IL.opJMP:
  467. EmitJmp(opJMP, param1)
  468. |IL.opCALL:
  469. IncStk;
  470. DEC(StkCnt);
  471. EmitCall(param1)
  472. |IL.opCALLP:
  473. IncStk;
  474. DEC(StkCnt);
  475. UnOp(reg1);
  476. Op1(opCALL, reg1, sREG);
  477. drop;
  478. ASSERT(R.top = -1)
  479. |IL.opPRECALL:
  480. PushAll(0)
  481. |IL.opLABEL:
  482. EmitLabel(param1)
  483. |IL.opSADR_PARAM:
  484. Op1(opPUSH, PC, sINCR);
  485. IncStk;
  486. EmitWord(param2);
  487. Reloc(RDATA)
  488. |IL.opERR:
  489. CallRTL(RTL._error, 2)
  490. |IL.opPUSHC:
  491. PushImm(param2)
  492. |IL.opONERR:
  493. DEC(StkCnt);
  494. EmitWord(0C232H); (* BIC #8, SR; DINT *)
  495. EmitWord(4303H); (* MOV R3, R3; NOP *)
  496. PushImm(param2);
  497. EmitJmp(opJMP, param1)
  498. |IL.opLEAVEC:
  499. Pop(PC)
  500. |IL.opENTER:
  501. ASSERT(R.top = -1);
  502. EmitLabel(param1);
  503. n := param2 MOD 65536;
  504. param2 := param2 DIV 65536;
  505. StkCnt := 0;
  506. IF chk_stk THEN
  507. L := NewLabel();
  508. Op2(opMOV, SP * 256, R4);
  509. Op2(opSUB, HP * 256, R4);
  510. Op2(opCMP, imm(StkReserve), R4);
  511. word := CodeList.last(WORD);
  512. jcc(jge, L);
  513. DEC(StkCnt);
  514. EmitWord(0C232H); (* BIC #8, SR; DINT *)
  515. EmitWord(4303H); (* MOV R3, R3; NOP *)
  516. PushImm(n);
  517. EmitJmp(opJMP, cmd.param3);
  518. EmitLabel(L)
  519. END;
  520. IF param2 > 8 THEN
  521. Op2(opMOV, imm(param2), R4);
  522. L := NewLabel();
  523. EmitLabel(L);
  524. Push(CG);
  525. Op2(opSUB, imm(1), R4);
  526. jcc(jne, L)
  527. ELSE
  528. FOR n := 1 TO param2 DO
  529. Push(CG)
  530. END
  531. END;
  532. StkCnt := param2;
  533. MaxStkCnt := StkCnt
  534. |IL.opLEAVE, IL.opLEAVER:
  535. ASSERT(param2 = 0);
  536. IF opcode = IL.opLEAVER THEN
  537. UnOp(reg1);
  538. IF reg1 # ACC THEN
  539. mov(ACC, reg1)
  540. END;
  541. drop
  542. END;
  543. ASSERT(R.top = -1);
  544. ASSERT(StkCnt = param1);
  545. IF chk_stk THEN
  546. INC(word.val, MaxStkCnt * 2)
  547. END;
  548. IF param1 > 0 THEN
  549. Op2(opADD, imm(param1 * 2), SP)
  550. END;
  551. Pop(PC)
  552. |IL.opRES:
  553. ASSERT(R.top = -1);
  554. GetRegA
  555. |IL.opCLEANUP:
  556. IF param2 # 0 THEN
  557. Op2(opADD, imm(param2 * 2), SP);
  558. DEC(StkCnt, param2)
  559. END
  560. |IL.opCONST:
  561. next := cmd.next(COMMAND);
  562. IF next.opcode = IL.opCONST THEN
  563. c1 := param2;
  564. c2 := next.param2;
  565. next := next.next(COMMAND);
  566. IF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN
  567. Op2(opMOV + bw(next.opcode = IL.opSAVE8), imm(c1), dst_x(c2, SR));
  568. cmd := next
  569. ELSE
  570. Op2(opMOV, imm(param2), GetAnyReg())
  571. END
  572. ELSIF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN
  573. UnOp(reg1);
  574. Op2(opMOV + bw(next.opcode = IL.opSAVE8), reg1 * 256, dst_x(param2, SR));
  575. drop;
  576. cmd := next
  577. ELSE
  578. Op2(opMOV, imm(param2), GetAnyReg())
  579. END
  580. |IL.opSADR:
  581. Op2(opMOV, incr(PC), GetAnyReg());
  582. EmitWord(param2);
  583. Reloc(RDATA)
  584. |IL.opGADR:
  585. Op2(opMOV, incr(PC), GetAnyReg());
  586. EmitWord(param2);
  587. Reloc(RBSS)
  588. |IL.opLADR:
  589. reg1 := GetAnyReg();
  590. n := LocalOffset(param2);
  591. Op2(opMOV, SP * 256, reg1);
  592. IF n # 0 THEN
  593. Op2(opADD, imm(n), reg1)
  594. END
  595. |IL.opLLOAD8:
  596. Op2(opMOV + BW, LocalSrc(param2), GetAnyReg())
  597. |IL.opLLOAD16, IL.opVADR:
  598. Op2(opMOV, LocalSrc(param2), GetAnyReg())
  599. |IL.opGLOAD8:
  600. Op2(opMOV + BW, src_x(param2, SR), GetAnyReg());
  601. Reloc(RBSS)
  602. |IL.opGLOAD16:
  603. Op2(opMOV, src_x(param2, SR), GetAnyReg());
  604. Reloc(RBSS)
  605. |IL.opLOAD8:
  606. UnOp(reg1);
  607. Op2(opMOV + BW, indir(reg1), reg1)
  608. |IL.opLOAD16:
  609. UnOp(reg1);
  610. Op2(opMOV, indir(reg1), reg1)
  611. |IL.opVLOAD8:
  612. reg1 := GetAnyReg();
  613. Op2(opMOV, LocalSrc(param2), reg1);
  614. Op2(opMOV + BW, indir(reg1), reg1)
  615. |IL.opVLOAD16:
  616. reg1 := GetAnyReg();
  617. Op2(opMOV, LocalSrc(param2), reg1);
  618. Op2(opMOV, indir(reg1), reg1)
  619. |IL.opSAVE, IL.opSAVE16:
  620. BinOp(reg2, reg1);
  621. Op2(opMOV, reg2 * 256, dst_x(0, reg1));
  622. drop;
  623. drop
  624. |IL.opSAVE8:
  625. BinOp(reg2, reg1);
  626. Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1));
  627. drop;
  628. drop
  629. |IL.opSAVE8C:
  630. UnOp(reg1);
  631. Op2(opMOV + BW, imm(param2), dst_x(0, reg1));
  632. drop
  633. |IL.opSAVE16C, IL.opSAVEC:
  634. UnOp(reg1);
  635. Op2(opMOV, imm(param2), dst_x(0, reg1));
  636. drop
  637. |IL.opUMINUS:
  638. UnOp(reg1);
  639. Neg(reg1)
  640. |IL.opADD:
  641. BinOp(reg1, reg2);
  642. Op2(opADD, reg2 * 256, reg1);
  643. drop
  644. |IL.opADDC:
  645. IF param2 # 0 THEN
  646. UnOp(reg1);
  647. Op2(opADD, imm(param2), reg1)
  648. END
  649. |IL.opSUB:
  650. BinOp(reg1, reg2);
  651. Op2(opSUB, reg2 * 256, reg1);
  652. drop
  653. |IL.opSUBR, IL.opSUBL:
  654. UnOp(reg1);
  655. IF param2 # 0 THEN
  656. Op2(opSUB, imm(param2), reg1)
  657. END;
  658. IF opcode = IL.opSUBL THEN
  659. Neg(reg1)
  660. END
  661. |IL.opLADR_SAVEC:
  662. Op2(opMOV, imm(param2), LocalDst(param1))
  663. |IL.opLADR_SAVE:
  664. UnOp(reg1);
  665. Op2(opMOV, reg1 * 256, LocalDst(param2));
  666. drop
  667. |IL.opGADR_SAVEC:
  668. Op2(opMOV, imm(param2), dst_x(param1, SR));
  669. Reloc(RBSS)
  670. |IL.opCONST_PARAM:
  671. PushImm(param2)
  672. |IL.opPARAM:
  673. IF param2 = 1 THEN
  674. UnOp(reg1);
  675. Push(reg1);
  676. drop
  677. ELSE
  678. ASSERT(R.top + 1 <= param2);
  679. PushAll(param2)
  680. END
  681. |IL.opEQ..IL.opGE,
  682. IL.opEQC..IL.opGEC:
  683. IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
  684. BinOp(reg1, reg2);
  685. Op2(opCMP, reg2 * 256, reg1);
  686. drop
  687. ELSE
  688. UnOp(reg1);
  689. Op2(opCMP, imm(param2), reg1)
  690. END;
  691. drop;
  692. cc := cond(opcode);
  693. next := cmd.next(COMMAND);
  694. IF next.opcode = IL.opJNZ THEN
  695. jcc(cc, next.param1);
  696. cmd := next
  697. ELSIF next.opcode = IL.opJZ THEN
  698. jcc(ORD(BITS(cc) / {0}), next.param1);
  699. cmd := next
  700. ELSE
  701. setcc(cc, GetAnyReg())
  702. END
  703. |IL.opNOP, IL.opAND, IL.opOR:
  704. |IL.opCODE:
  705. EmitWord(param2)
  706. |IL.opDROP:
  707. UnOp(reg1);
  708. drop
  709. |IL.opJNZ1:
  710. UnOp(reg1);
  711. Test(reg1);
  712. jcc(jne, param1)
  713. |IL.opJG:
  714. UnOp(reg1);
  715. Test(reg1);
  716. jcc(jg, param1)
  717. |IL.opJNZ:
  718. UnOp(reg1);
  719. Test(reg1);
  720. jcc(jne, param1);
  721. drop
  722. |IL.opJZ:
  723. UnOp(reg1);
  724. Test(reg1);
  725. jcc(je, param1);
  726. drop
  727. |IL.opNOT:
  728. UnOp(reg1);
  729. Test(reg1);
  730. setcc(je, reg1)
  731. |IL.opORD:
  732. UnOp(reg1);
  733. Test(reg1);
  734. setcc(jne, reg1)
  735. |IL.opGET:
  736. BinOp(reg1, reg2);
  737. drop;
  738. drop;
  739. Op2(opMOV + bw(param2 = 1), indir(reg1), dst_x(0, reg2))
  740. |IL.opGETC:
  741. UnOp(reg2);
  742. drop;
  743. Op2(opMOV + bw(param2 = 1), src_x(param1, SR), dst_x(0, reg2))
  744. |IL.opCHKIDX:
  745. UnOp(reg1);
  746. Op2(opCMP, imm(param2), reg1);
  747. jcc(jb, param1)
  748. |IL.opCHKIDX2:
  749. BinOp(reg1, reg2);
  750. IF param2 # -1 THEN
  751. Op2(opCMP, reg1 * 256, reg2);
  752. jcc(jb, param1)
  753. END;
  754. INCL(R.regs, reg1);
  755. DEC(R.top);
  756. R.stk[R.top] := reg2
  757. |IL.opINCC, IL.opINCCB:
  758. UnOp(reg1);
  759. Op2(opADD + bw(opcode = IL.opINCCB), imm(param2), dst_x(0, reg1));
  760. drop
  761. |IL.opDECCB:
  762. UnOp(reg1);
  763. Op2(opSUB + BW, imm(param2), dst_x(0, reg1));
  764. drop
  765. |IL.opINC, IL.opINCB:
  766. BinOp(reg1, reg2);
  767. Op2(opADD + bw(opcode = IL.opINCB), reg1 * 256, dst_x(0, reg2));
  768. drop;
  769. drop
  770. |IL.opDEC, IL.opDECB:
  771. BinOp(reg1, reg2);
  772. Op2(opSUB + bw(opcode = IL.opDECB), reg1 * 256, dst_x(0, reg2));
  773. drop;
  774. drop
  775. |IL.opLADR_INCC, IL.opLADR_INCCB:
  776. Op2(opADD + bw(opcode = IL.opLADR_INCCB), imm(param2), LocalDst(param1))
  777. |IL.opLADR_DECCB:
  778. Op2(opSUB + BW, imm(param2), LocalDst(param1))
  779. |IL.opLADR_INC, IL.opLADR_INCB:
  780. UnOp(reg1);
  781. Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, LocalDst(param2));
  782. drop
  783. |IL.opLADR_DEC, IL.opLADR_DECB:
  784. UnOp(reg1);
  785. Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, LocalDst(param2));
  786. drop
  787. |IL.opPUSHT:
  788. UnOp(reg1);
  789. Op2(opMOV, src_x(-2, reg1), GetAnyReg())
  790. |IL.opISREC:
  791. PushAll(2);
  792. PushImm(param2);
  793. CallRTL(RTL._guardrec, 3);
  794. GetRegA
  795. |IL.opIS:
  796. PushAll(1);
  797. PushImm(param2);
  798. CallRTL(RTL._is, 2);
  799. GetRegA
  800. |IL.opTYPEGR:
  801. PushAll(1);
  802. PushImm(param2);
  803. CallRTL(RTL._guardrec, 2);
  804. GetRegA
  805. |IL.opTYPEGP:
  806. UnOp(reg1);
  807. PushAll(0);
  808. Push(reg1);
  809. PushImm(param2);
  810. CallRTL(RTL._guard, 2);
  811. GetRegA
  812. |IL.opTYPEGD:
  813. UnOp(reg1);
  814. PushAll(0);
  815. Op1(opPUSH, reg1, sIDX);
  816. IncStk;
  817. EmitWord(-2);
  818. PushImm(param2);
  819. CallRTL(RTL._guardrec, 2);
  820. GetRegA
  821. |IL.opMULS:
  822. BinOp(reg1, reg2);
  823. Op2(opAND, reg2 * 256, reg1);
  824. drop
  825. |IL.opMULSC:
  826. UnOp(reg1);
  827. Op2(opAND, imm(param2), reg1)
  828. |IL.opDIVS:
  829. BinOp(reg1, reg2);
  830. Op2(opXOR, reg2 * 256, reg1);
  831. drop
  832. |IL.opDIVSC:
  833. UnOp(reg1);
  834. Op2(opXOR, imm(param2), reg1)
  835. |IL.opADDS:
  836. BinOp(reg1, reg2);
  837. Op2(opBIS, reg2 * 256, reg1);
  838. drop
  839. |IL.opSUBS:
  840. BinOp(reg1, reg2);
  841. Op2(opBIC, reg2 * 256, reg1);
  842. drop
  843. |IL.opADDSC:
  844. UnOp(reg1);
  845. Op2(opBIS, imm(param2), reg1)
  846. |IL.opSUBSL:
  847. UnOp(reg1);
  848. Op2(opXOR, imm(-1), reg1);
  849. Op2(opAND, imm(param2), reg1)
  850. |IL.opSUBSR:
  851. UnOp(reg1);
  852. Op2(opBIC, imm(param2), reg1)
  853. |IL.opUMINS:
  854. UnOp(reg1);
  855. Op2(opXOR, imm(-1), reg1)
  856. |IL.opLENGTH:
  857. PushAll(2);
  858. CallRTL(RTL._length, 2);
  859. GetRegA
  860. |IL.opMAX,IL.opMIN:
  861. BinOp(reg1, reg2);
  862. Op2(opCMP, reg2 * 256, reg1);
  863. IF opcode = IL.opMIN THEN
  864. cc := opJL + 1
  865. ELSE
  866. cc := opJGE + 1
  867. END;
  868. EmitWord(cc); (* jge/jl L *)
  869. MovRR(reg2, reg1);
  870. (* L: *)
  871. drop
  872. |IL.opMAXC, IL.opMINC:
  873. UnOp(reg1);
  874. Op2(opCMP, imm(param2), reg1);
  875. L := NewLabel();
  876. IF opcode = IL.opMINC THEN
  877. cc := jl
  878. ELSE
  879. cc := jge
  880. END;
  881. jcc(cc, L);
  882. Op2(opMOV, imm(param2), reg1);
  883. EmitLabel(L)
  884. |IL.opSWITCH:
  885. UnOp(reg1);
  886. IF param2 = 0 THEN
  887. reg2 := ACC
  888. ELSE
  889. reg2 := R5
  890. END;
  891. IF reg1 # reg2 THEN
  892. ASSERT(REG.GetReg(R, reg2));
  893. ASSERT(REG.Exchange(R, reg1, reg2));
  894. drop
  895. END;
  896. drop
  897. |IL.opENDSW:
  898. |IL.opCASEL:
  899. Op2(opCMP, imm(param1), ACC);
  900. jcc(jl, param2)
  901. |IL.opCASER:
  902. Op2(opCMP, imm(param1), ACC);
  903. jcc(jg, param2)
  904. |IL.opCASELR:
  905. Op2(opCMP, imm(param1), ACC);
  906. IF param2 = cmd.param3 THEN
  907. jcc(jne, param2)
  908. ELSE
  909. jcc(jl, param2);
  910. jcc(jg, cmd.param3)
  911. END
  912. |IL.opSBOOL:
  913. BinOp(reg2, reg1);
  914. Test(reg2);
  915. setcc(jne, reg2);
  916. Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1));
  917. drop;
  918. drop
  919. |IL.opSBOOLC:
  920. UnOp(reg1);
  921. Op2(opMOV + BW, imm(param2), dst_x(0, reg1));
  922. drop
  923. |IL.opEQS .. IL.opGES:
  924. PushAll(4);
  925. PushImm((opcode - IL.opEQS) * 12);
  926. CallRTL(RTL._strcmp, 5);
  927. GetRegA
  928. |IL.opLEN:
  929. UnOp(reg1);
  930. drop;
  931. EXCL(R.regs, reg1);
  932. WHILE param2 > 0 DO
  933. UnOp(reg2);
  934. drop;
  935. DEC(param2)
  936. END;
  937. INCL(R.regs, reg1);
  938. ASSERT(REG.GetReg(R, reg1))
  939. |IL.opLSL, IL.opASR, IL.opROR, IL.opLSR:
  940. PushAll(2);
  941. CASE opcode OF
  942. |IL.opLSL: CallRTL(RTL._lsl, 2)
  943. |IL.opASR: CallRTL(RTL._asr, 2)
  944. |IL.opROR: CallRTL(RTL._ror, 2)
  945. |IL.opLSR: CallRTL(RTL._lsr, 2)
  946. END;
  947. GetRegA
  948. |IL.opLSL1, IL.opASR1, IL.opROR1, IL.opLSR1:
  949. UnOp(reg1);
  950. PushAll_1;
  951. PushImm(param2);
  952. Push(reg1);
  953. drop;
  954. CASE opcode OF
  955. |IL.opLSL1: CallRTL(RTL._lsl, 2)
  956. |IL.opASR1: CallRTL(RTL._asr, 2)
  957. |IL.opROR1: CallRTL(RTL._ror, 2)
  958. |IL.opLSR1: CallRTL(RTL._lsr, 2)
  959. END;
  960. GetRegA
  961. |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
  962. param2 := param2 MOD 16;
  963. IF param2 # 0 THEN
  964. UnOp(reg1);
  965. Shift2(opcode, reg1, param2)
  966. END
  967. |IL.opMUL:
  968. PushAll(2);
  969. CallRTL(RTL._mul, 2);
  970. GetRegA
  971. |IL.opMULC:
  972. UnOp(reg1);
  973. a := param2;
  974. IF a > 1 THEN
  975. n := UTILS.Log2(a)
  976. ELSIF a < -1 THEN
  977. n := UTILS.Log2(-a)
  978. ELSE
  979. n := -1
  980. END;
  981. IF a = 1 THEN
  982. ELSIF a = -1 THEN
  983. Neg(reg1)
  984. ELSIF a = 0 THEN
  985. Clear(reg1)
  986. ELSE
  987. IF n > 0 THEN
  988. IF a < 0 THEN
  989. Neg(reg1)
  990. END;
  991. Shift2(IL.opLSL2, reg1, n)
  992. ELSE
  993. PushAll(1);
  994. PushImm(a);
  995. CallRTL(RTL._mul, 2);
  996. GetRegA
  997. END
  998. END
  999. |IL.opDIV:
  1000. PushAll(2);
  1001. CallRTL(RTL._divmod, 2);
  1002. GetRegA
  1003. |IL.opDIVR:
  1004. ASSERT(param2 > 0);
  1005. IF param2 > 1 THEN
  1006. n := UTILS.Log2(param2);
  1007. IF n > 0 THEN
  1008. UnOp(reg1);
  1009. Shift2(IL.opASR2, reg1, n)
  1010. ELSE
  1011. PushAll(1);
  1012. PushImm(param2);
  1013. CallRTL(RTL._divmod, 2);
  1014. GetRegA
  1015. END
  1016. END
  1017. |IL.opDIVL:
  1018. UnOp(reg1);
  1019. PushAll_1;
  1020. PushImm(param2);
  1021. Push(reg1);
  1022. drop;
  1023. CallRTL(RTL._divmod, 2);
  1024. GetRegA
  1025. |IL.opMOD:
  1026. PushAll(2);
  1027. CallRTL(RTL._divmod, 2);
  1028. ASSERT(REG.GetReg(R, R5))
  1029. |IL.opMODR:
  1030. ASSERT(param2 > 0);
  1031. IF param2 = 1 THEN
  1032. UnOp(reg1);
  1033. Clear(reg1)
  1034. ELSE
  1035. IF UTILS.Log2(param2) > 0 THEN
  1036. UnOp(reg1);
  1037. Op2(opAND, imm(param2 - 1), reg1)
  1038. ELSE
  1039. PushAll(1);
  1040. PushImm(param2);
  1041. CallRTL(RTL._divmod, 2);
  1042. ASSERT(REG.GetReg(R, R5))
  1043. END
  1044. END
  1045. |IL.opMODL:
  1046. UnOp(reg1);
  1047. PushAll_1;
  1048. PushImm(param2);
  1049. Push(reg1);
  1050. drop;
  1051. CallRTL(RTL._divmod, 2);
  1052. ASSERT(REG.GetReg(R, R5))
  1053. |IL.opCOPYS:
  1054. ASSERT(R.top = 3);
  1055. Push(R.stk[2]);
  1056. Push(R.stk[0]);
  1057. Op2(opCMP, R.stk[1] * 256, R.stk[3]);
  1058. EmitWord(3801H); (* JL L1 *)
  1059. MovRR(R.stk[1], R.stk[3]);
  1060. (* L1: *)
  1061. Push(R.stk[3]);
  1062. drop;
  1063. drop;
  1064. drop;
  1065. drop;
  1066. CallRTL(RTL._move, 3)
  1067. |IL.opCOPY:
  1068. PushAll(2);
  1069. PushImm(param2);
  1070. CallRTL(RTL._move, 3)
  1071. |IL.opMOVE:
  1072. PushAll(3);
  1073. CallRTL(RTL._move, 3)
  1074. |IL.opCOPYA:
  1075. PushAll(4);
  1076. PushImm(param2);
  1077. CallRTL(RTL._arrcpy, 5);
  1078. GetRegA
  1079. |IL.opROT:
  1080. PushAll(0);
  1081. MovRR(SP, ACC);
  1082. Push(ACC);
  1083. PushImm(param2);
  1084. CallRTL(RTL._rot, 2)
  1085. |IL.opSAVES:
  1086. UnOp(reg1);
  1087. PushAll_1;
  1088. Op1(opPUSH, PC, sINCR);
  1089. IncStk;
  1090. EmitWord(param2);
  1091. Reloc(RDATA);
  1092. Push(reg1);
  1093. drop;
  1094. PushImm(param1);
  1095. CallRTL(RTL._move, 3)
  1096. |IL.opCASET:
  1097. Push(R5);
  1098. Push(R5);
  1099. PushImm(param2);
  1100. CallRTL(RTL._guardrec, 2);
  1101. Pop(R5);
  1102. Test(ACC);
  1103. jcc(jne, param1)
  1104. |IL.opABS:
  1105. UnOp(reg1);
  1106. Test(reg1);
  1107. L := NewLabel();
  1108. jcc(jge, L);
  1109. Neg(reg1);
  1110. EmitLabel(L)
  1111. |IL.opEQB, IL.opNEB:
  1112. BinOp(reg1, reg2);
  1113. drop;
  1114. Test(reg1);
  1115. L := NewLabel();
  1116. jcc(je, L);
  1117. Op2(opMOV, imm(1), reg1);
  1118. EmitLabel(L);
  1119. Test(reg2);
  1120. L := NewLabel();
  1121. jcc(je, L);
  1122. Op2(opMOV, imm(1), reg2);
  1123. EmitLabel(L);
  1124. Op2(opCMP, reg2 * 256, reg1);
  1125. IF opcode = IL.opEQB THEN
  1126. setcc(je, reg1)
  1127. ELSE
  1128. setcc(jne, reg1)
  1129. END
  1130. |IL.opSAVEP:
  1131. UnOp(reg1);
  1132. Op2(opMOV, incr(PC), reg1 + dIDX);
  1133. EmitWord(param2);
  1134. Reloc(RCODE);
  1135. EmitWord(0);
  1136. drop
  1137. |IL.opPUSHP:
  1138. Op2(opMOV, incr(PC), GetAnyReg());
  1139. EmitWord(param2);
  1140. Reloc(RCODE)
  1141. |IL.opEQP, IL.opNEP:
  1142. UnOp(reg1);
  1143. Op2(opCMP, incr(PC), reg1);
  1144. EmitWord(param1);
  1145. Reloc(RCODE);
  1146. drop;
  1147. reg1 := GetAnyReg();
  1148. IF opcode = IL.opEQP THEN
  1149. setcc(je, reg1)
  1150. ELSIF opcode = IL.opNEP THEN
  1151. setcc(jne, reg1)
  1152. END
  1153. |IL.opVADR_PARAM:
  1154. reg1 := GetAnyReg();
  1155. Op2(opMOV, LocalSrc(param2), reg1);
  1156. Push(reg1);
  1157. drop
  1158. |IL.opNEW:
  1159. PushAll(1);
  1160. n := param2 + 2;
  1161. ASSERT(UTILS.Align(n, 2));
  1162. PushImm(n);
  1163. PushImm(param1);
  1164. CallRTL(RTL._new, 3)
  1165. |IL.opRSET:
  1166. PushAll(2);
  1167. CallRTL(RTL._set, 2);
  1168. GetRegA
  1169. |IL.opRSETR:
  1170. PushAll(1);
  1171. PushImm(param2);
  1172. CallRTL(RTL._set, 2);
  1173. GetRegA
  1174. |IL.opRSETL:
  1175. UnOp(reg1);
  1176. PushAll_1;
  1177. PushImm(param2);
  1178. Push(reg1);
  1179. drop;
  1180. CallRTL(RTL._set, 2);
  1181. GetRegA
  1182. |IL.opRSET1:
  1183. PushAll(1);
  1184. CallRTL(RTL._set1, 1);
  1185. GetRegA
  1186. |IL.opINCLC:
  1187. UnOp(reg1);
  1188. Op2(opBIS, imm(ORD({param2})), dst_x(0, reg1));
  1189. drop
  1190. |IL.opEXCLC:
  1191. UnOp(reg1);
  1192. Op2(opBIC, imm(ORD({param2})), dst_x(0, reg1));
  1193. drop
  1194. |IL.opIN:
  1195. PushAll(2);
  1196. CallRTL(RTL._in, 2);
  1197. GetRegA
  1198. |IL.opINR:
  1199. PushAll(1);
  1200. PushImm(param2);
  1201. CallRTL(RTL._in, 2);
  1202. GetRegA
  1203. |IL.opINL:
  1204. PushAll(1);
  1205. PushImm(param2);
  1206. CallRTL(RTL._in2, 2);
  1207. GetRegA
  1208. |IL.opINCL:
  1209. PushAll(2);
  1210. CallRTL(RTL._incl, 2)
  1211. |IL.opEXCL:
  1212. PushAll(2);
  1213. CallRTL(RTL._excl, 2)
  1214. |IL.opLADR_INCL, IL.opLADR_EXCL:
  1215. PushAll(1);
  1216. MovRR(SP, ACC);
  1217. n := LocalOffset(param2);
  1218. IF n # 0 THEN
  1219. Op2(opADD, imm(n), ACC)
  1220. END;
  1221. Push(ACC);
  1222. IF opcode = IL.opLADR_INCL THEN
  1223. CallRTL(RTL._incl, 2)
  1224. ELSIF opcode = IL.opLADR_EXCL THEN
  1225. CallRTL(RTL._excl, 2)
  1226. END
  1227. |IL.opLADR_INCLC:
  1228. Op2(opBIS, imm(ORD({param2})), LocalDst(param1))
  1229. |IL.opLADR_EXCLC:
  1230. Op2(opBIC, imm(ORD({param2})), LocalDst(param1))
  1231. END;
  1232. cmd := cmd.next(COMMAND)
  1233. END;
  1234. ASSERT(R.pushed = 0);
  1235. ASSERT(R.top = -1)
  1236. END translate;
  1237. PROCEDURE prolog;
  1238. VAR
  1239. i: INTEGER;
  1240. BEGIN
  1241. RTL.Init(EmitLabel, EmitWord, EmitCall);
  1242. FOR i := 0 TO LEN(RTL.rtl) - 1 DO
  1243. RTL.Set(i, NewLabel())
  1244. END;
  1245. IV[LEN(IV) - 1] := NewLabel();
  1246. EmitLabel(IV[LEN(IV) - 1]);
  1247. Op2(opMOV, incr(PC), SP);
  1248. EmitWord(0);
  1249. Op2(opMOV, incr(PC), HP);
  1250. EmitWord(0);
  1251. Op2(opMOV, imm(5A80H), dst_x(0120H, SR)); (* stop WDT *)
  1252. Op2(opMOV, imm(RTL.empty_proc), dst_x(0, SP));
  1253. Op2(opMOV, imm(RTL.empty_proc), dst_x(2, SP));
  1254. END prolog;
  1255. PROCEDURE epilog;
  1256. VAR
  1257. L1, i, n: INTEGER;
  1258. BEGIN
  1259. Op2(opBIS, imm(10H), SR); (* CPUOFF *)
  1260. L1 := NewLabel();
  1261. FOR i := 0 TO LEN(IV) - 2 DO
  1262. IV[i] := NewLabel();
  1263. EmitLabel(IV[i]);
  1264. PushImm(i);
  1265. IF i # LEN(IV) - 2 THEN
  1266. EmitJmp(opJMP, L1)
  1267. END
  1268. END;
  1269. EmitLabel(L1);
  1270. n := 0;
  1271. FOR i := 0 TO 15 DO
  1272. IF i IN R.regs THEN
  1273. Push(i);
  1274. INC(n)
  1275. END
  1276. END;
  1277. MovRR(SP, R4);
  1278. Op2(opADD, imm(n * 2), R4);
  1279. Push(R4);
  1280. Op1(opPUSH, R4, sINDIR);
  1281. Op1(opCALL, SR, sIDX); EmitWord(-RTL.VarSize); Reloc(RBSS); (* call int *)
  1282. Op2(opADD, imm(4), SP);
  1283. FOR i := 15 TO 0 BY -1 DO
  1284. IF i IN R.regs THEN
  1285. Pop(i)
  1286. END
  1287. END;
  1288. Op2(opADD, imm(2), SP);
  1289. Op1(opRETI, 0, 0);
  1290. RTL.Gen
  1291. END epilog;
  1292. PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
  1293. VAR
  1294. i, adr, heap, stack, TextSize, TypesSize, bits, n, val: INTEGER;
  1295. Code, Data, Bss: RECORD address, size: INTEGER END;
  1296. ram, rom: INTEGER;
  1297. reloc: RELOC;
  1298. BEGIN
  1299. IdxWords.src := NOWORD;
  1300. IdxWords.dst := NOWORD;
  1301. ram := options.ram;
  1302. rom := options.rom;
  1303. IF ODD(ram) THEN DEC(ram) END;
  1304. IF ODD(rom) THEN DEC(rom) END;
  1305. ram := MIN(MAX(ram, minRAM), maxRAM);
  1306. rom := MIN(MAX(rom, minROM), maxROM);
  1307. IF IL.codes.bss > ram - StkReserve - RTL.VarSize THEN
  1308. ERRORS.Error(204)
  1309. END;
  1310. Labels := CHL.CreateIntList();
  1311. FOR i := 1 TO IL.codes.lcount DO
  1312. CHL.PushInt(Labels, 0)
  1313. END;
  1314. CodeList := LISTS.create(NIL);
  1315. RelList := LISTS.create(NIL);
  1316. REG.Init(R, Push, Pop, mov, xchg, {R4, R5, R6, R7});
  1317. prolog;
  1318. translate(chkSTK IN options.checking);
  1319. epilog;
  1320. TypesSize := CHL.Length(IL.codes.types) * 2;
  1321. Data.size := CHL.Length(IL.codes.data);
  1322. IF ODD(Data.size) THEN
  1323. CHL.PushByte(IL.codes.data, 0);
  1324. INC(Data.size)
  1325. END;
  1326. Code.size := Fixup(0, IntVectorSize + TypesSize + Data.size);
  1327. Code.address := 10000H - (IntVectorSize + TypesSize + Data.size + Code.size);
  1328. IF Code.address < 10000H - rom THEN
  1329. ERRORS.Error(203)
  1330. END;
  1331. Code.size := Fixup(Code.address, IntVectorSize + TypesSize + Data.size);
  1332. Data.address := Code.address + Code.size;
  1333. TextSize := Code.size + Data.size;
  1334. IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN
  1335. ERRORS.Error(203)
  1336. END;
  1337. stack := RTL.ram + ram;
  1338. Bss.size := IL.codes.bss + IL.codes.bss MOD 2;
  1339. DEC(stack, Bss.size);
  1340. Bss.address := stack;
  1341. DEC(stack, RTL.VarSize);
  1342. heap := RTL.ram;
  1343. ASSERT(stack - heap >= StkReserve);
  1344. adr := Code.address + 2;
  1345. PutWord(stack, adr);
  1346. adr := Code.address + 6;
  1347. PutWord(heap, adr);
  1348. reloc := RelList.first(RELOC);
  1349. WHILE reloc # NIL DO
  1350. adr := reloc.WordPtr.offset * 2;
  1351. val := reloc.WordPtr.val;
  1352. CASE reloc.section OF
  1353. |RCODE: PutWord(LabelOffs(val) * 2, adr)
  1354. |RDATA: PutWord(val + Data.address, adr)
  1355. |RBSS: PutWord((val + Bss.address) MOD 65536, adr)
  1356. END;
  1357. reloc := reloc.next(RELOC)
  1358. END;
  1359. adr := Data.address;
  1360. FOR i := 0 TO Data.size - 1 DO
  1361. mem[adr] := CHL.GetByte(IL.codes.data, i);
  1362. INC(adr)
  1363. END;
  1364. FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO
  1365. PutWord(CHL.GetInt(IL.codes.types, i), adr)
  1366. END;
  1367. FOR i := 0 TO 15 DO
  1368. PutWord((33 - i) * i, adr);
  1369. END;
  1370. FOR n := 0 TO 15 DO
  1371. bits := ORD({0 .. n});
  1372. FOR i := 0 TO 15 - n DO
  1373. PutWord(bits, adr);
  1374. bits := LSL(bits, 1)
  1375. END
  1376. END;
  1377. PutWord(4130H, adr); (* RET *)
  1378. PutWord(stack, adr);
  1379. PutWord(0001H, adr); (* bsl signature (adr 0FFBEH) *)
  1380. FOR i := 0 TO LEN(IV) - 1 DO
  1381. PutWord(LabelOffs(IV[i]) * 2, adr)
  1382. END;
  1383. INC(TextSize, IntVectorSize + TypesSize + Code.address MOD 16);
  1384. INC(Bss.size, StkReserve + RTL.VarSize);
  1385. WR.Create(outname);
  1386. HEX.Data(mem, Code.address - Code.address MOD 16, TextSize);
  1387. HEX.End;
  1388. WR.Close;
  1389. C.Dashes;
  1390. C.String(" rom: "); C.Int(TextSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(TextSize * 100 DIV rom); C.StringLn("%)");
  1391. C.Ln;
  1392. C.String(" ram: "); C.Int(Bss.size); C.String(" of "); C.Int(ram); C.String(" ("); C.Int(Bss.size * 100 DIV ram); C.StringLn("%)")
  1393. END CodeGen;
  1394. END MSP430.