raarmgas.pas 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536
  1. {
  2. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  3. Does the parsing for the ARM GNU AS styled inline assembler.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. Unit raarmgas;
  18. {$i fpcdefs.inc}
  19. Interface
  20. uses
  21. raatt,raarm,
  22. cpubase;
  23. type
  24. tarmattreader = class(tattreader)
  25. actoppostfix : TOpPostfix;
  26. actwideformat : boolean;
  27. function is_asmopcode(const s: string):boolean;override;
  28. function is_register(const s:string):boolean;override;
  29. function is_targetdirective(const s: string): boolean; override;
  30. procedure handleopcode;override;
  31. procedure BuildReference(oper : tarmoperand);
  32. procedure BuildOperand(oper : tarmoperand);
  33. procedure BuildSpecialreg(oper : tarmoperand);
  34. function TryBuildShifterOp(oper : tarmoperand) : boolean;
  35. procedure BuildOpCode(instr : tarminstruction);
  36. procedure ReadSym(oper : tarmoperand);
  37. procedure ConvertCalljmp(instr : tarminstruction);
  38. procedure HandleTargetDirective; override;
  39. protected
  40. function is_unified: boolean; virtual;
  41. end;
  42. tarmunifiedattreader = class(tarmattreader)
  43. protected
  44. function is_unified: boolean; override;
  45. end;
  46. Implementation
  47. uses
  48. { helpers }
  49. cutils,
  50. { global }
  51. globtype,globals,verbose,
  52. systems,aasmbase,aasmtai,aasmdata,aasmcpu,
  53. { symtable }
  54. symconst,symsym,symdef,
  55. procinfo,
  56. rabase,rautils,
  57. cgbase,cgutils,paramgr;
  58. function tarmunifiedattreader.is_unified: boolean;
  59. begin
  60. result:=true;
  61. end;
  62. function tarmattreader.is_register(const s:string):boolean;
  63. type
  64. treg2str = record
  65. name : string[3];
  66. reg : tregister;
  67. end;
  68. const
  69. extraregs : array[0..19+16] of treg2str = (
  70. (name: 'A1'; reg : NR_R0),
  71. (name: 'A2'; reg : NR_R1),
  72. (name: 'A3'; reg : NR_R2),
  73. (name: 'A4'; reg : NR_R3),
  74. (name: 'V1'; reg : NR_R4),
  75. (name: 'V2'; reg : NR_R5),
  76. (name: 'V3'; reg : NR_R6),
  77. (name: 'V4'; reg : NR_R7),
  78. (name: 'V5'; reg : NR_R8),
  79. (name: 'V6'; reg : NR_R9),
  80. (name: 'V7'; reg : NR_R10),
  81. (name: 'V8'; reg : NR_R11),
  82. (name: 'WR'; reg : NR_R7),
  83. (name: 'SB'; reg : NR_R9),
  84. (name: 'SL'; reg : NR_R10),
  85. (name: 'FP'; reg : NR_R11),
  86. (name: 'IP'; reg : NR_R12),
  87. (name: 'SP'; reg : NR_R13),
  88. (name: 'LR'; reg : NR_R14),
  89. (name: 'PC'; reg : NR_R15),
  90. (name: 'C0'; reg : NR_CR0),
  91. (name: 'C1'; reg : NR_CR1),
  92. (name: 'C2'; reg : NR_CR2),
  93. (name: 'C3'; reg : NR_CR3),
  94. (name: 'C4'; reg : NR_CR4),
  95. (name: 'C5'; reg : NR_CR5),
  96. (name: 'C6'; reg : NR_CR6),
  97. (name: 'C7'; reg : NR_CR7),
  98. (name: 'C8'; reg : NR_CR8),
  99. (name: 'C9'; reg : NR_CR9),
  100. (name: 'C10'; reg : NR_CR10),
  101. (name: 'C11'; reg : NR_CR11),
  102. (name: 'C12'; reg : NR_CR12),
  103. (name: 'C13'; reg : NR_CR13),
  104. (name: 'C14'; reg : NR_CR14),
  105. (name: 'C15'; reg : NR_CR15)
  106. );
  107. var
  108. i : longint;
  109. begin
  110. result:=inherited is_register(s);
  111. { reg found?
  112. possible aliases are always 2 char
  113. }
  114. if result or (not (length(s) in [2,3])) then
  115. exit;
  116. for i:=low(extraregs) to high(extraregs) do
  117. begin
  118. if s=extraregs[i].name then
  119. begin
  120. actasmregister:=extraregs[i].reg;
  121. result:=true;
  122. actasmtoken:=AS_REGISTER;
  123. exit;
  124. end;
  125. end;
  126. end;
  127. function tarmattreader.is_targetdirective(const s: string): boolean;
  128. begin
  129. case s of
  130. '.force_thumb',
  131. '.thumb_func',
  132. '.code',
  133. '.thumb_set':
  134. result:=true
  135. else
  136. Result:=inherited is_targetdirective(s);
  137. end;
  138. end;
  139. procedure tarmattreader.ReadSym(oper : tarmoperand);
  140. var
  141. tempstr, mangledname : string;
  142. typesize,l,k : tcgint;
  143. begin
  144. tempstr:=actasmpattern;
  145. Consume(AS_ID);
  146. { typecasting? }
  147. if (actasmtoken=AS_LPAREN) and
  148. SearchType(tempstr,typesize) then
  149. begin
  150. oper.hastype:=true;
  151. Consume(AS_LPAREN);
  152. BuildOperand(oper);
  153. Consume(AS_RPAREN);
  154. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  155. oper.SetSize(typesize,true);
  156. end
  157. else
  158. if not oper.SetupVar(tempstr,false) then
  159. Message1(sym_e_unknown_id,tempstr);
  160. { record.field ? }
  161. if actasmtoken=AS_DOT then
  162. begin
  163. BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
  164. if (mangledname<>'') then
  165. Message(asmr_e_invalid_reference_syntax);
  166. inc(oper.opr.ref.offset,l);
  167. end;
  168. end;
  169. Procedure tarmattreader.BuildReference(oper : tarmoperand);
  170. procedure do_error;
  171. begin
  172. Message(asmr_e_invalid_reference_syntax);
  173. RecoverConsume(false);
  174. end;
  175. procedure test_end(require_rbracket : boolean);
  176. begin
  177. if require_rbracket then begin
  178. if not(actasmtoken=AS_RBRACKET) then
  179. begin
  180. do_error;
  181. exit;
  182. end
  183. else
  184. Consume(AS_RBRACKET);
  185. if (actasmtoken=AS_NOT) then
  186. begin
  187. oper.opr.ref.addressmode:=AM_PREINDEXED;
  188. Consume(AS_NOT);
  189. end;
  190. end;
  191. if not(actasmtoken in [AS_SEPARATOR,AS_end]) then
  192. do_error
  193. else
  194. begin
  195. {$IFDEF debugasmreader}
  196. writeln('TEST_end_FINAL_OK. Created the following ref:');
  197. writeln('oper.opr.ref.shiftimm=',oper.opr.ref.shiftimm);
  198. writeln('oper.opr.ref.shiftmode=',ord(oper.opr.ref.shiftmode));
  199. writeln('oper.opr.ref.index=',ord(oper.opr.ref.index));
  200. writeln('oper.opr.ref.base=',ord(oper.opr.ref.base));
  201. writeln('oper.opr.ref.signindex=',ord(oper.opr.ref.signindex));
  202. writeln('oper.opr.ref.addressmode=',ord(oper.opr.ref.addressmode));
  203. writeln;
  204. {$endIF debugasmreader}
  205. end;
  206. end;
  207. function is_shifter_ref_operation(var a : tshiftmode) : boolean;
  208. begin
  209. a := SM_NONE;
  210. if (actasmpattern='LSL') then
  211. a := SM_LSL
  212. else if (actasmpattern='LSR') then
  213. a := SM_LSR
  214. else if (actasmpattern='ASR') then
  215. a := SM_ASR
  216. else if (actasmpattern='ROR') then
  217. a := SM_ROR
  218. else if (actasmpattern='RRX') then
  219. a := SM_RRX;
  220. is_shifter_ref_operation := not(a=SM_NONE);
  221. end;
  222. procedure read_index_shift(require_rbracket : boolean);
  223. var
  224. shift : aint;
  225. begin
  226. case actasmtoken of
  227. AS_COMMA :
  228. begin
  229. Consume(AS_COMMA);
  230. if not(actasmtoken=AS_ID) then
  231. do_error;
  232. if is_shifter_ref_operation(oper.opr.ref.shiftmode) then
  233. begin
  234. Consume(AS_ID);
  235. if not(oper.opr.ref.shiftmode=SM_RRX) then
  236. begin
  237. if not(actasmtoken=AS_HASH) then
  238. do_error;
  239. Consume(AS_HASH);
  240. shift := BuildConstExpression(false,true);
  241. if (shift<0) or (shift>32) then
  242. do_error;
  243. oper.opr.ref.shiftimm := shift;
  244. test_end(require_rbracket);
  245. end
  246. else
  247. test_end(require_rbracket);
  248. end
  249. else
  250. begin
  251. do_error;
  252. exit;
  253. end;
  254. end;
  255. AS_RBRACKET :
  256. if require_rbracket then
  257. test_end(require_rbracket)
  258. else
  259. begin
  260. do_error;
  261. exit;
  262. end;
  263. AS_SEPARATOR,AS_END :
  264. if not require_rbracket then
  265. test_end(false)
  266. else
  267. do_error;
  268. else
  269. begin
  270. do_error;
  271. exit;
  272. end;
  273. end;
  274. end;
  275. procedure read_index(require_rbracket : boolean);
  276. var
  277. recname : string;
  278. o_int,s_int : tcgint;
  279. begin
  280. case actasmtoken of
  281. AS_REGISTER :
  282. begin
  283. oper.opr.ref.index:=actasmregister;
  284. Consume(AS_REGISTER);
  285. read_index_shift(require_rbracket);
  286. exit;
  287. end;
  288. AS_PLUS,AS_MINUS :
  289. begin
  290. if actasmtoken=AS_PLUS then
  291. begin
  292. Consume(AS_PLUS);
  293. end
  294. else
  295. begin
  296. oper.opr.ref.signindex := -1;
  297. Consume(AS_MINUS);
  298. end;
  299. if actasmtoken=AS_REGISTER then
  300. begin
  301. oper.opr.ref.index:=actasmregister;
  302. Consume(AS_REGISTER);
  303. read_index_shift(require_rbracket);
  304. exit;
  305. end
  306. else
  307. begin
  308. do_error;
  309. exit;
  310. end;
  311. test_end(require_rbracket);
  312. exit;
  313. end;
  314. AS_HASH : // constant
  315. begin
  316. Consume(AS_HASH);
  317. o_int := BuildConstExpression(false,true);
  318. if (o_int>4095) or (o_int<-4095) then
  319. begin
  320. Message(asmr_e_constant_out_of_bounds);
  321. RecoverConsume(false);
  322. exit;
  323. end
  324. else
  325. begin
  326. inc(oper.opr.ref.offset,o_int);
  327. test_end(require_rbracket);
  328. exit;
  329. end;
  330. end;
  331. AS_ID :
  332. begin
  333. recname := actasmpattern;
  334. Consume(AS_ID);
  335. BuildRecordOffsetSize(recname,o_int,s_int,recname,false);
  336. if (o_int>4095)or(o_int<-4095) then
  337. begin
  338. Message(asmr_e_constant_out_of_bounds);
  339. RecoverConsume(false);
  340. exit;
  341. end
  342. else
  343. begin
  344. inc(oper.opr.ref.offset,o_int);
  345. test_end(require_rbracket);
  346. exit;
  347. end;
  348. end;
  349. AS_AT:
  350. begin
  351. do_error;
  352. exit;
  353. end;
  354. AS_DOT : // local label
  355. begin
  356. oper.opr.ref.signindex := BuildConstExpression(true,false);
  357. test_end(require_rbracket);
  358. exit;
  359. end;
  360. AS_RBRACKET :
  361. begin
  362. if require_rbracket then
  363. begin
  364. test_end(require_rbracket);
  365. exit;
  366. end
  367. else
  368. begin
  369. do_error; // unexpected rbracket
  370. exit;
  371. end;
  372. end;
  373. AS_SEPARATOR,AS_end :
  374. begin
  375. if not require_rbracket then
  376. begin
  377. test_end(false);
  378. exit;
  379. end
  380. else
  381. begin
  382. do_error;
  383. exit;
  384. end;
  385. end;
  386. else
  387. begin
  388. // unexpected token
  389. do_error;
  390. exit;
  391. end;
  392. end; // case
  393. end;
  394. procedure try_prepostindexed;
  395. begin
  396. Consume(AS_RBRACKET);
  397. case actasmtoken of
  398. AS_COMMA :
  399. begin // post-indexed
  400. Consume(AS_COMMA);
  401. oper.opr.ref.addressmode:=AM_POSTINDEXED;
  402. read_index(false);
  403. exit;
  404. end;
  405. AS_NOT :
  406. begin // pre-indexed
  407. Consume(AS_NOT);
  408. oper.opr.ref.addressmode:=AM_PREINDEXED;
  409. test_end(false);
  410. exit;
  411. end;
  412. else
  413. begin
  414. test_end(false);
  415. exit;
  416. end;
  417. end; // case
  418. end;
  419. var
  420. lab : TASMLABEL;
  421. begin
  422. Consume(AS_LBRACKET);
  423. oper.opr.ref.addressmode:=AM_OFFSET; // assume "neither PRE nor POST inc"
  424. if actasmtoken=AS_REGISTER then
  425. begin
  426. oper.opr.ref.base:=actasmregister;
  427. Consume(AS_REGISTER);
  428. case actasmtoken of
  429. AS_RBRACKET :
  430. begin
  431. try_prepostindexed;
  432. exit;
  433. end;
  434. AS_COMMA :
  435. begin
  436. Consume(AS_COMMA);
  437. read_index(true);
  438. exit;
  439. end;
  440. else
  441. begin
  442. Message(asmr_e_invalid_reference_syntax);
  443. RecoverConsume(false);
  444. end;
  445. end;
  446. end
  447. else
  448. {
  449. if base isn't a register, r15=PC is implied base, so it must be a local label.
  450. pascal constants don't make sense, because implied r15
  451. record offsets probably don't make sense, too (a record offset of code?)
  452. TODO: However, we could make the Stackpointer implied.
  453. }
  454. Begin
  455. case actasmtoken of
  456. AS_ID :
  457. begin
  458. if is_locallabel(actasmpattern) then
  459. begin
  460. CreateLocalLabel(actasmpattern,lab,false);
  461. oper.opr.ref.symbol := lab;
  462. oper.opr.ref.base := NR_PC;
  463. Consume(AS_ID);
  464. test_end(true);
  465. exit;
  466. end
  467. else
  468. begin
  469. // TODO: Stackpointer implied,
  470. Message(asmr_e_invalid_reference_syntax);
  471. RecoverConsume(false);
  472. exit;
  473. end;
  474. end;
  475. else
  476. begin // elsecase
  477. Message(asmr_e_invalid_reference_syntax);
  478. RecoverConsume(false);
  479. exit;
  480. end;
  481. end;
  482. end;
  483. end;
  484. function tarmattreader.TryBuildShifterOp(oper : tarmoperand) : boolean;
  485. procedure handlepara(sm : tshiftmode);
  486. begin
  487. consume(AS_ID);
  488. fillchar(oper.opr,sizeof(oper.opr),0);
  489. oper.opr.typ:=OPR_SHIFTEROP;
  490. oper.opr.shifterop.shiftmode:=sm;
  491. if sm<>SM_RRX then
  492. begin
  493. case actasmtoken of
  494. AS_REGISTER:
  495. begin
  496. oper.opr.shifterop.rs:=actasmregister;
  497. consume(AS_REGISTER);
  498. end;
  499. AS_HASH:
  500. begin
  501. consume(AS_HASH);
  502. oper.opr.shifterop.shiftimm:=BuildConstExpression(false,false);
  503. end;
  504. else
  505. Message(asmr_e_illegal_shifterop_syntax);
  506. end;
  507. end;
  508. end;
  509. begin
  510. result:=true;
  511. if (actasmtoken=AS_ID) then
  512. begin
  513. if (actasmpattern='LSL') then
  514. handlepara(SM_LSL)
  515. else if (actasmpattern='LSR') then
  516. handlepara(SM_LSR)
  517. else if (actasmpattern='ASR') then
  518. handlepara(SM_ASR)
  519. else if (actasmpattern='ROR') then
  520. handlepara(SM_ROR)
  521. else if (actasmpattern='RRX') then
  522. handlepara(SM_RRX)
  523. else
  524. result:=false;
  525. end
  526. else
  527. result:=false;
  528. end;
  529. Procedure tarmattreader.BuildOperand(oper : tarmoperand);
  530. var
  531. expr : string;
  532. typesize,l : tcgint;
  533. procedure AddLabelOperand(hl:tasmlabel);
  534. begin
  535. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  536. is_calljmp(actopcode) then
  537. begin
  538. oper.opr.typ:=OPR_SYMBOL;
  539. oper.opr.symbol:=hl;
  540. end
  541. else
  542. begin
  543. oper.InitRef;
  544. oper.opr.ref.symbol:=hl;
  545. oper.opr.ref.base:=NR_PC;
  546. if (actasmtoken in [AS_PLUS, AS_MINUS]) then
  547. begin
  548. l:=BuildConstExpression(true,false);
  549. oper.opr.ref.offset:=l;
  550. end;
  551. end;
  552. end;
  553. procedure MaybeRecordOffset;
  554. var
  555. mangledname: string;
  556. hasdot : boolean;
  557. l,
  558. toffset,
  559. tsize : tcgint;
  560. begin
  561. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  562. exit;
  563. l:=0;
  564. mangledname:='';
  565. hasdot:=(actasmtoken=AS_DOT);
  566. if hasdot then
  567. begin
  568. if expr<>'' then
  569. begin
  570. BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
  571. if (oper.opr.typ<>OPR_CONSTANT) and
  572. (mangledname<>'') then
  573. Message(asmr_e_wrong_sym_type);
  574. inc(l,toffset);
  575. oper.SetSize(tsize,true);
  576. end;
  577. end;
  578. if actasmtoken in [AS_PLUS,AS_MINUS] then
  579. inc(l,BuildConstExpression(true,false));
  580. case oper.opr.typ of
  581. OPR_LOCAL :
  582. begin
  583. { don't allow direct access to fields of parameters, because that
  584. will generate buggy code. Allow it only for explicit typecasting }
  585. if hasdot and
  586. (not oper.hastype) then
  587. checklocalsubscript(oper.opr.localsym);
  588. inc(oper.opr.localsymofs,l)
  589. end;
  590. OPR_CONSTANT :
  591. inc(oper.opr.val,l);
  592. OPR_REFERENCE :
  593. if (mangledname<>'') then
  594. begin
  595. if (oper.opr.val<>0) then
  596. Message(asmr_e_wrong_sym_type);
  597. oper.opr.typ:=OPR_SYMBOL;
  598. oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname,AT_FUNCTION);
  599. end
  600. else
  601. inc(oper.opr.val,l);
  602. OPR_SYMBOL:
  603. Message(asmr_e_invalid_symbol_ref);
  604. else
  605. internalerror(200309221);
  606. end;
  607. end;
  608. function MaybeBuildReference:boolean;
  609. { Try to create a reference, if not a reference is found then false
  610. is returned }
  611. begin
  612. MaybeBuildReference:=true;
  613. case actasmtoken of
  614. AS_INTNUM,
  615. AS_MINUS,
  616. AS_PLUS:
  617. Begin
  618. oper.opr.ref.offset:=BuildConstExpression(True,False);
  619. if actasmtoken<>AS_LPAREN then
  620. Message(asmr_e_invalid_reference_syntax)
  621. else
  622. BuildReference(oper);
  623. end;
  624. AS_LPAREN:
  625. BuildReference(oper);
  626. AS_ID: { only a variable is allowed ... }
  627. Begin
  628. ReadSym(oper);
  629. case actasmtoken of
  630. AS_end,
  631. AS_SEPARATOR,
  632. AS_COMMA: ;
  633. AS_LPAREN:
  634. BuildReference(oper);
  635. else
  636. Begin
  637. Message(asmr_e_invalid_reference_syntax);
  638. Consume(actasmtoken);
  639. end;
  640. end; {end case }
  641. end;
  642. else
  643. MaybeBuildReference:=false;
  644. end; { end case }
  645. end;
  646. function is_ConditionCode(hs: string): boolean;
  647. var icond: tasmcond;
  648. begin
  649. is_ConditionCode := false;
  650. case actopcode of
  651. A_IT,A_ITE,A_ITT,
  652. A_ITEE,A_ITTE,A_ITET,A_ITTT,
  653. A_ITEEE,A_ITTEE,A_ITETE,A_ITTTE,A_ITEET,A_ITTET,A_ITETT,A_ITTTT:
  654. begin
  655. { search for condition, conditions are always 2 chars }
  656. if length(hs)>1 then
  657. begin
  658. for icond:=low(tasmcond) to high(tasmcond) do
  659. begin
  660. if copy(hs,1,2)=uppercond2str[icond] then
  661. begin
  662. //actcondition:=icond;
  663. oper.opr.typ := OPR_COND;
  664. oper.opr.cc := icond;
  665. exit(true);
  666. end;
  667. end;
  668. end;
  669. end;
  670. else
  671. ;
  672. end;
  673. end;
  674. function is_modeflag(hs : string): boolean;
  675. var
  676. i: longint;
  677. flags: tcpumodeflags;
  678. begin
  679. is_modeflag := false;
  680. flags:=[];
  681. hs:=lower(hs);
  682. if (actopcode in [A_CPSID,A_CPSIE]) and (length(hs) >= 1) then
  683. begin
  684. for i:=1 to length(hs) do
  685. begin
  686. case hs[i] of
  687. 'a':
  688. Include(flags,mfA);
  689. 'f':
  690. Include(flags,mfF);
  691. 'i':
  692. Include(flags,mfI);
  693. else
  694. exit;
  695. end;
  696. end;
  697. oper.opr.typ := OPR_MODEFLAGS;
  698. oper.opr.flags := flags;
  699. exit(true);
  700. end;
  701. end;
  702. procedure BuildDirectRef;
  703. function GetConstLabel(const symname: string; ofs: aint): TAsmLabel;
  704. var
  705. hp: tai;
  706. newconst: tai_const;
  707. lab: TAsmLabel;
  708. begin
  709. if symname<>'' then
  710. newconst:=tai_const.Createname(symname,ofs)
  711. else
  712. newconst:=tai_const.Create_32bit(ofs);
  713. hp:=tai(current_procinfo.aktlocaldata.First);
  714. while assigned(hp) do
  715. begin
  716. if hp.typ=ait_const then
  717. begin
  718. if (tai_const(hp).sym=newconst.sym) and
  719. (tai_const(hp).value=newconst.value) and
  720. assigned(hp.Previous) and
  721. (tai(hp.previous).typ=ait_label) then
  722. begin
  723. newconst.Free;
  724. result:=tai_label(hp.Previous).labsym;
  725. exit;
  726. end;
  727. end;
  728. hp:=tai(hp.Next);
  729. end;
  730. current_asmdata.getjumplabel(lab);
  731. current_procinfo.aktlocaldata.concat(tai_align.create(4));
  732. current_procinfo.aktlocaldata.concat(tai_label.create(lab));
  733. current_procinfo.aktlocaldata.concat(newconst);
  734. result:=lab;
  735. end;
  736. var
  737. symtype: TAsmsymtype;
  738. sym: string;
  739. val: tcgint;
  740. begin
  741. case actasmtoken of
  742. AS_INTNUM,
  743. AS_ID:
  744. begin
  745. BuildConstSymbolExpression(true,false,false,val,sym,symtype);
  746. if symtype=AT_NONE then
  747. sym:='';
  748. reference_reset(oper.opr.ref,4,[]);
  749. oper.opr.ref.base:=NR_PC;
  750. oper.opr.ref.symbol:=GetConstLabel(sym,val);
  751. end;
  752. else
  753. ;
  754. end;
  755. end;
  756. function getregsetindex(reg: tregister): integer;
  757. begin
  758. if getsubreg(reg)=R_SUBFS then
  759. begin
  760. result:=getsupreg(reg)*2;
  761. if result>32 then
  762. result:=result-63;
  763. end
  764. else
  765. result:=getsupreg(reg);
  766. end;
  767. var
  768. tempreg : tregister;
  769. ireg : tsuperregister;
  770. regtype: tregistertype;
  771. subreg: tsubregister;
  772. hl : tasmlabel;
  773. {ofs : longint;}
  774. registerset : tcpuregisterset;
  775. Begin
  776. expr:='';
  777. case actasmtoken of
  778. AS_LBRACKET: { Memory reference or constant expression }
  779. Begin
  780. oper.InitRef;
  781. BuildReference(oper);
  782. end;
  783. AS_HASH: { Constant expression }
  784. Begin
  785. Consume(AS_HASH);
  786. BuildConstantOperand(oper);
  787. end;
  788. AS_EQUAL:
  789. begin
  790. case actopcode of
  791. A_LDRBT,A_LDRB,A_LDR,A_LDRH,A_LDRSB,A_LDRSH,A_LDRT,
  792. A_LDREX,A_LDREXB,A_LDREXD,A_LDREXH:
  793. begin
  794. consume(AS_EQUAL);
  795. oper.InitRef;
  796. BuildDirectRef;
  797. end;
  798. else
  799. Message(asmr_e_invalid_opcode_and_operand);
  800. end;
  801. end;
  802. (*
  803. AS_INTNUM,
  804. AS_MINUS,
  805. AS_PLUS:
  806. Begin
  807. { Constant memory offset }
  808. { This must absolutely be followed by ( }
  809. oper.InitRef;
  810. oper.opr.ref.offset:=BuildConstExpression(True,False);
  811. if actasmtoken<>AS_LPAREN then
  812. begin
  813. ofs:=oper.opr.ref.offset;
  814. BuildConstantOperand(oper);
  815. inc(oper.opr.val,ofs);
  816. end
  817. else
  818. BuildReference(oper);
  819. end;
  820. *)
  821. AS_ID: { A constant expression, or a Variable ref. }
  822. Begin
  823. if is_modeflag(actasmpattern) then
  824. begin
  825. consume(AS_ID);
  826. end
  827. else
  828. { Condition code? }
  829. if is_conditioncode(actasmpattern) then
  830. begin
  831. consume(AS_ID);
  832. end
  833. else
  834. { Local Label ? }
  835. if is_locallabel(actasmpattern) then
  836. begin
  837. CreateLocalLabel(actasmpattern,hl,false);
  838. Consume(AS_ID);
  839. AddLabelOperand(hl);
  840. end
  841. else
  842. { Check for label }
  843. if SearchLabel(actasmpattern,hl,false) then
  844. begin
  845. Consume(AS_ID);
  846. AddLabelOperand(hl);
  847. end
  848. else
  849. { probably a variable or normal expression }
  850. { or a procedure (such as in CALL ID) }
  851. Begin
  852. { is it a constant ? }
  853. if SearchIConstant(actasmpattern,l) then
  854. Begin
  855. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  856. Message(asmr_e_invalid_operand_type);
  857. BuildConstantOperand(oper);
  858. end
  859. else
  860. begin
  861. expr:=actasmpattern;
  862. Consume(AS_ID);
  863. { typecasting? }
  864. if (actasmtoken=AS_LPAREN) and
  865. SearchType(expr,typesize) then
  866. begin
  867. oper.hastype:=true;
  868. Consume(AS_LPAREN);
  869. BuildOperand(oper);
  870. Consume(AS_RPAREN);
  871. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  872. oper.SetSize(typesize,true);
  873. end
  874. else
  875. begin
  876. if not(oper.SetupVar(expr,false)) then
  877. Begin
  878. { look for special symbols ... }
  879. if expr= '__HIGH' then
  880. begin
  881. consume(AS_LPAREN);
  882. if not oper.setupvar('high'+actasmpattern,false) then
  883. Message1(sym_e_unknown_id,'high'+actasmpattern);
  884. consume(AS_ID);
  885. consume(AS_RPAREN);
  886. end
  887. else
  888. if expr = '__RESULT' then
  889. oper.SetUpResult
  890. else
  891. if expr = '__SELF' then
  892. oper.SetupSelf
  893. else
  894. if expr = '__OLDEBP' then
  895. oper.SetupOldEBP
  896. else
  897. Message1(sym_e_unknown_id,expr);
  898. end;
  899. end;
  900. end;
  901. if actasmtoken=AS_DOT then
  902. MaybeRecordOffset;
  903. { add a constant expression? }
  904. if (actasmtoken=AS_PLUS) then
  905. begin
  906. l:=BuildConstExpression(true,false);
  907. case oper.opr.typ of
  908. OPR_CONSTANT :
  909. inc(oper.opr.val,l);
  910. OPR_LOCAL :
  911. inc(oper.opr.localsymofs,l);
  912. OPR_REFERENCE :
  913. inc(oper.opr.ref.offset,l);
  914. else
  915. internalerror(2003092021);
  916. end;
  917. end
  918. end;
  919. { Do we have a indexing reference, then parse it also }
  920. if actasmtoken=AS_LPAREN then
  921. BuildReference(oper);
  922. end;
  923. { Register, a variable reference or a constant reference }
  924. AS_REGISTER:
  925. Begin
  926. { save the type of register used. }
  927. tempreg:=actasmregister;
  928. Consume(AS_REGISTER);
  929. if (actasmtoken in [AS_end,AS_SEPARATOR,AS_COMMA]) then
  930. Begin
  931. if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
  932. Message(asmr_e_invalid_operand_type);
  933. oper.opr.typ:=OPR_REGISTER;
  934. oper.opr.reg:=tempreg;
  935. end
  936. else if (actasmtoken=AS_NOT) and (actopcode in [A_LDM,A_STM,A_FLDM,A_FSTM,A_VLDM,A_VSTM,A_SRS,A_RFE]) then
  937. begin
  938. consume(AS_NOT);
  939. oper.opr.typ:=OPR_REFERENCE;
  940. oper.opr.ref.addressmode:=AM_PREINDEXED;
  941. oper.opr.ref.index:=tempreg;
  942. end
  943. else
  944. Message(asmr_e_syn_operand);
  945. end;
  946. { Registerset }
  947. AS_LSBRACKET:
  948. begin
  949. consume(AS_LSBRACKET);
  950. registerset:=[];
  951. regtype:=R_INVALIDREGISTER;
  952. subreg:=R_SUBNONE;
  953. while actasmtoken<>AS_RSBRACKET do
  954. begin
  955. if actasmtoken=AS_REGISTER then
  956. begin
  957. include(registerset,getregsetindex(actasmregister));
  958. if regtype<>R_INVALIDREGISTER then
  959. begin
  960. if (getregtype(actasmregister)<>regtype) or
  961. (getsubreg(actasmregister)<>subreg) then
  962. Message(asmr_e_mixing_regtypes);
  963. end
  964. else
  965. begin
  966. regtype:=getregtype(actasmregister);
  967. subreg:=getsubreg(actasmregister);
  968. end;
  969. tempreg:=actasmregister;
  970. consume(AS_REGISTER);
  971. if actasmtoken=AS_MINUS then
  972. begin
  973. consume(AS_MINUS);
  974. for ireg:=getregsetindex(tempreg) to getregsetindex(actasmregister) do
  975. include(registerset,ireg);
  976. consume(AS_REGISTER);
  977. end;
  978. end
  979. else
  980. consume(AS_REGISTER);
  981. if actasmtoken=AS_COMMA then
  982. consume(AS_COMMA)
  983. else
  984. break;
  985. end;
  986. consume(AS_RSBRACKET);
  987. oper.opr.typ:=OPR_REGSET;
  988. oper.opr.regtype:=regtype;
  989. oper.opr.subreg:=subreg;
  990. oper.opr.regset:=registerset;
  991. if actasmtoken=AS_XOR then
  992. begin
  993. consume(AS_XOR);
  994. oper.opr.usermode:=true;
  995. end
  996. else
  997. oper.opr.usermode:=false;
  998. if (registerset=[]) then
  999. Message(asmr_e_empty_regset);
  1000. end;
  1001. AS_end,
  1002. AS_SEPARATOR,
  1003. AS_COMMA: ;
  1004. else
  1005. Begin
  1006. Message(asmr_e_syn_operand);
  1007. Consume(actasmtoken);
  1008. end;
  1009. end; { end case }
  1010. end;
  1011. procedure tarmattreader.BuildSpecialreg(oper: tarmoperand);
  1012. var
  1013. hs, reg : String;
  1014. ch : char;
  1015. i, t : longint;
  1016. hreg : tregister;
  1017. flags : tspecialregflags;
  1018. begin
  1019. hreg:=NR_NO;
  1020. case actasmtoken of
  1021. AS_REGISTER:
  1022. begin
  1023. oper.opr.typ:=OPR_REGISTER;
  1024. oper.opr.reg:=actasmregister;
  1025. Consume(AS_REGISTER);
  1026. end;
  1027. AS_ID:
  1028. begin
  1029. t := pos('_', actasmpattern);
  1030. if t > 0 then
  1031. begin
  1032. hs:=lower(actasmpattern);
  1033. reg:=copy(hs, 1, t-1);
  1034. delete(hs, 1, t);
  1035. if length(hs) < 1 then
  1036. Message(asmr_e_invalid_operand_type);
  1037. if reg = 'cpsr' then
  1038. hreg:=NR_CPSR
  1039. else if reg='spsr' then
  1040. hreg:=NR_SPSR
  1041. else
  1042. Message(asmr_e_invalid_register);
  1043. flags:=[];
  1044. for i := 1 to length(hs) do
  1045. begin
  1046. ch:=hs[i];
  1047. if ch='c' then
  1048. include(flags, srC)
  1049. else if ch='x' then
  1050. include(flags, srX)
  1051. else if ch='f' then
  1052. include(flags, srF)
  1053. else if ch='s' then
  1054. include(flags, srS)
  1055. else
  1056. message(asmr_e_invalid_operand_type);
  1057. end;
  1058. oper.opr.typ:=OPR_SPECIALREG;
  1059. oper.opr.specialreg:=hreg;
  1060. oper.opr.specialregflags:=flags;
  1061. consume(AS_ID);
  1062. end
  1063. else
  1064. Message(asmr_e_invalid_operand_type); // Otherwise it would have been seen as a AS_REGISTER
  1065. end;
  1066. else
  1067. Message(asmr_e_invalid_operand_type);
  1068. end;
  1069. end;
  1070. {*****************************************************************************
  1071. tarmattreader
  1072. *****************************************************************************}
  1073. procedure tarmattreader.BuildOpCode(instr : tarminstruction);
  1074. var
  1075. operandnum : longint;
  1076. Begin
  1077. { opcode }
  1078. if (actasmtoken<>AS_OPCODE) then
  1079. Begin
  1080. Message(asmr_e_invalid_or_missing_opcode);
  1081. RecoverConsume(true);
  1082. exit;
  1083. end;
  1084. { Fill the instr object with the current state }
  1085. with instr do
  1086. begin
  1087. Opcode:=ActOpcode;
  1088. condition:=ActCondition;
  1089. oppostfix:=actoppostfix;
  1090. wideformat:=actwideformat;
  1091. end;
  1092. { We are reading operands, so opcode will be an AS_ID }
  1093. operandnum:=1;
  1094. Consume(AS_OPCODE);
  1095. { Zero operand opcode ? }
  1096. if actasmtoken in [AS_SEPARATOR,AS_end] then
  1097. begin
  1098. operandnum:=0;
  1099. exit;
  1100. end;
  1101. { Read the operands }
  1102. repeat
  1103. case actasmtoken of
  1104. AS_COMMA: { Operand delimiter }
  1105. Begin
  1106. if ((instr.opcode in [A_MOV,A_MVN,A_CMP,A_CMN,A_TST,A_TEQ,
  1107. A_UXTB,A_UXTH,A_UXTB16,
  1108. A_SXTB,A_SXTH,A_SXTB16]) and
  1109. (operandnum=2)) or
  1110. ((operandnum=3) and not(instr.opcode in [A_UMLAL,A_UMULL,A_SMLAL,A_SMULL,A_MLA,A_UMAAL,A_MLS,
  1111. A_SMLABB,A_SMLABT,A_SMLATB,A_SMLATT,A_SMMLA,A_SMMLS,A_SMLAD,A_SMLALD,A_SMLSD,
  1112. A_SMLALBB,A_SMLALBT,A_SMLALTB,A_SMLALTT,A_SMLSLD,
  1113. A_SMLAWB,A_SMLAWT,
  1114. A_MRC,A_MCR,A_MCRR,A_MRRC,A_MRC2,A_MCR2,A_MCRR2,A_MRRC2,
  1115. A_STREXD,A_STRD,
  1116. A_USADA8,
  1117. A_VMOV,
  1118. A_SBFX,A_UBFX,A_BFI])) then
  1119. begin
  1120. Consume(AS_COMMA);
  1121. if not(TryBuildShifterOp(instr.Operands[operandnum+1] as tarmoperand)) then
  1122. Message(asmr_e_illegal_shifterop_syntax);
  1123. Inc(operandnum);
  1124. end
  1125. else
  1126. begin
  1127. if operandnum>Max_Operands then
  1128. Message(asmr_e_too_many_operands)
  1129. else
  1130. Inc(operandnum);
  1131. Consume(AS_COMMA);
  1132. end;
  1133. end;
  1134. AS_SEPARATOR,
  1135. AS_end : { End of asm operands for this opcode }
  1136. begin
  1137. break;
  1138. end;
  1139. else
  1140. if ((instr.opcode = A_MRS) and (operandnum = 2)) or
  1141. ((instr.opcode = A_MSR) and (operandnum = 1)) then
  1142. BuildSpecialreg(instr.Operands[operandnum] as tarmoperand)
  1143. else
  1144. BuildOperand(instr.Operands[operandnum] as tarmoperand);
  1145. end; { end case }
  1146. until false;
  1147. instr.Ops:=operandnum;
  1148. end;
  1149. function tarmattreader.is_asmopcode(const s: string):boolean;
  1150. const
  1151. { sorted by length so longer postfixes will match first }
  1152. postfix2strsorted : array[1..70] of string[9] = (
  1153. '.F32.S32','.F32.U32','.S32.F32','.U32.F32','.F64.S32','.F64.U32','.S32.F64','.U32.F64',
  1154. '.F32.S16','.F32.U16','.S16.F32','.U16.F32','.F64.S16','.F64.U16','.S16.F64','.U16.F64',
  1155. '.F32.F64','.F64.F32',
  1156. '.I16','.I32','.I64','.S16','.S32','.S64','.U16','.U32','.U64','.F32','.F64',
  1157. 'IAD','DBD','FDD','EAD','IAS','DBS','FDS','EAS','IAX','DBX','FDX','EAX',
  1158. '.16','.32','.64','.I8','.S8','.U8','.P8',
  1159. 'EP','SB','BT','SH','IA','IB','DA','DB','FD','FA','ED','EA',
  1160. '.8','S','D','E','P','X','R','B','H','T');
  1161. postfixsorted : array[1..70] of TOpPostfix = (
  1162. PF_F32S32,PF_F32U32,PF_S32F32,PF_U32F32,PF_F64S32,PF_F64U32,PF_S32F64,PF_U32F64,
  1163. PF_F32S16,PF_F32U16,PF_S16F32,PF_U16F32,PF_F64S16,PF_F64U16,PF_S16F64,PF_U16F64,
  1164. PF_F32F64,PF_F64F32,
  1165. PF_I16,PF_I32,
  1166. PF_I64,PF_S16,PF_S32,PF_S64,PF_U16,PF_U32,PF_U64,PF_F32,
  1167. PF_F64,PF_IAD,PF_DBD,PF_FDD,PF_EAD,
  1168. PF_IAS,PF_DBS,PF_FDS,PF_EAS,PF_IAX,
  1169. PF_DBX,PF_FDX,PF_EAX,PF_16,PF_32,
  1170. PF_64,PF_I8,PF_S8,PF_U8,PF_P8,
  1171. PF_EP,PF_SB,PF_BT,PF_SH,PF_IA,
  1172. PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,
  1173. PF_ED,PF_EA,PF_8,PF_S,PF_D,PF_E,
  1174. PF_P,PF_X,PF_R,PF_B,PF_H,PF_T);
  1175. var
  1176. j, j2 : longint;
  1177. hs,hs2 : string;
  1178. maxlen : longint;
  1179. icond : tasmcond;
  1180. Begin
  1181. { making s a value parameter would break other assembler readers }
  1182. hs:=s;
  1183. is_asmopcode:=false;
  1184. { clear op code }
  1185. actopcode:=A_None;
  1186. actcondition:=C_None;
  1187. { first, handle B else BLS is read wrong }
  1188. if ((hs[1]='B') and (length(hs)=3)) then
  1189. begin
  1190. for icond:=low(tasmcond) to high(tasmcond) do
  1191. begin
  1192. if copy(hs,2,3)=uppercond2str[icond] then
  1193. begin
  1194. actopcode:=A_B;
  1195. actasmtoken:=AS_OPCODE;
  1196. actcondition:=icond;
  1197. is_asmopcode:=true;
  1198. exit;
  1199. end;
  1200. end;
  1201. end;
  1202. maxlen:=min(length(hs),6);
  1203. actopcode:=A_NONE;
  1204. j2:=maxlen;
  1205. hs2:=hs;
  1206. while j2>=1 do
  1207. begin
  1208. hs:=hs2;
  1209. while j2>=1 do
  1210. begin
  1211. actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j2))));
  1212. if actopcode<>A_NONE then
  1213. begin
  1214. actasmtoken:=AS_OPCODE;
  1215. { strip op code }
  1216. delete(hs,1,j2);
  1217. dec(j2);
  1218. break;
  1219. end;
  1220. dec(j2);
  1221. end;
  1222. if actopcode=A_NONE then
  1223. exit;
  1224. if is_unified then
  1225. begin
  1226. { check for postfix }
  1227. if (length(hs)>0) and (actoppostfix=PF_None) then
  1228. begin
  1229. for j:=low(postfixsorted) to high(postfixsorted) do
  1230. begin
  1231. if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
  1232. begin
  1233. if not ((length(hs)-length(postfix2strsorted[j])) in [0,2,4]) then
  1234. continue;
  1235. actoppostfix:=postfixsorted[j];
  1236. { strip postfix }
  1237. delete(hs,1,length(postfix2strsorted[j]));
  1238. break;
  1239. end;
  1240. end;
  1241. end;
  1242. { search for condition, conditions are always 2 chars }
  1243. if length(hs)>1 then
  1244. begin
  1245. for icond:=low(tasmcond) to high(tasmcond) do
  1246. begin
  1247. if copy(hs,1,2)=uppercond2str[icond] then
  1248. begin
  1249. actcondition:=icond;
  1250. { strip condition }
  1251. delete(hs,1,2);
  1252. break;
  1253. end;
  1254. end;
  1255. end;
  1256. { check for postfix }
  1257. if (length(hs)>0) and (actoppostfix=PF_None) then
  1258. begin
  1259. for j:=low(postfixsorted) to high(postfixsorted) do
  1260. begin
  1261. if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
  1262. begin
  1263. if not ((length(hs)-length(postfix2strsorted[j])) = 0) then
  1264. continue;
  1265. actoppostfix:=postfixsorted[j];
  1266. { strip postfix }
  1267. delete(hs,1,length(postfix2strsorted[j]));
  1268. break;
  1269. end;
  1270. end;
  1271. end;
  1272. end
  1273. else
  1274. begin
  1275. { search for condition, conditions are always 2 chars }
  1276. if length(hs)>1 then
  1277. begin
  1278. for icond:=low(tasmcond) to high(tasmcond) do
  1279. begin
  1280. if copy(hs,1,2)=uppercond2str[icond] then
  1281. begin
  1282. actcondition:=icond;
  1283. { strip condition }
  1284. delete(hs,1,2);
  1285. break;
  1286. end;
  1287. end;
  1288. end;
  1289. { check for postfix }
  1290. if (length(hs)>0) and (actoppostfix=PF_None) then
  1291. begin
  1292. for j:=low(postfixsorted) to high(postfixsorted) do
  1293. begin
  1294. if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
  1295. begin
  1296. actoppostfix:=postfixsorted[j];
  1297. { strip postfix }
  1298. delete(hs,1,length(postfix2strsorted[j]));
  1299. break;
  1300. end;
  1301. end;
  1302. end;
  1303. end;
  1304. { check for format postfix }
  1305. if length(hs)>0 then
  1306. begin
  1307. if copy(hs,1,2) = '.W' then
  1308. begin
  1309. actwideformat:=true;
  1310. delete(hs,1,2);
  1311. end;
  1312. end;
  1313. { if we stripped all postfixes, it's a valid opcode }
  1314. is_asmopcode:=length(hs)=0;
  1315. if is_asmopcode = true then
  1316. break;
  1317. end;
  1318. end;
  1319. procedure tarmattreader.ConvertCalljmp(instr : tarminstruction);
  1320. var
  1321. newopr : toprrec;
  1322. begin
  1323. if instr.Operands[1].opr.typ=OPR_REFERENCE then
  1324. begin
  1325. newopr.typ:=OPR_SYMBOL;
  1326. newopr.symbol:=instr.Operands[1].opr.ref.symbol;
  1327. newopr.symofs:=instr.Operands[1].opr.ref.offset;
  1328. if (instr.Operands[1].opr.ref.base<>NR_NO) or
  1329. (instr.Operands[1].opr.ref.index<>NR_NO) then
  1330. Message(asmr_e_syn_operand);
  1331. instr.Operands[1].opr:=newopr;
  1332. end;
  1333. end;
  1334. procedure tarmattreader.HandleTargetDirective;
  1335. var
  1336. symname,
  1337. symval : String;
  1338. val : tcgint;
  1339. symtyp : TAsmsymtype;
  1340. begin
  1341. case actasmpattern of
  1342. '.thumb_set':
  1343. begin
  1344. consume(AS_TARGET_DIRECTIVE);
  1345. BuildConstSymbolExpression(true,false,false, val,symname,symtyp);
  1346. Consume(AS_COMMA);
  1347. BuildConstSymbolExpression(true,false,false, val,symval,symtyp);
  1348. curList.concat(tai_symbolpair.create(spk_thumb_set,symname,symval));
  1349. end;
  1350. '.code':
  1351. begin
  1352. consume(AS_TARGET_DIRECTIVE);
  1353. val:=BuildConstExpression(false,false);
  1354. if not(val in [16,32]) then
  1355. Message(asmr_e_invalid_code_value);
  1356. curList.concat(tai_directive.create(asd_code,tostr(val)));
  1357. end;
  1358. '.thumb_func':
  1359. begin
  1360. consume(AS_TARGET_DIRECTIVE);
  1361. curList.concat(tai_directive.create(asd_thumb_func,''));
  1362. end;
  1363. '.force_thumb':
  1364. begin
  1365. consume(AS_TARGET_DIRECTIVE);
  1366. curList.concat(tai_directive.create(asd_force_thumb,''));
  1367. end
  1368. else
  1369. inherited HandleTargetDirective;
  1370. end;
  1371. end;
  1372. function tarmattreader.is_unified: boolean;
  1373. begin
  1374. result:=false;
  1375. end;
  1376. procedure tarmattreader.handleopcode;
  1377. var
  1378. instr : tarminstruction;
  1379. begin
  1380. instr:=TarmInstruction.Create(TarmOperand);
  1381. BuildOpcode(instr);
  1382. if is_calljmp(instr.opcode) then
  1383. ConvertCalljmp(instr);
  1384. {
  1385. instr.AddReferenceSizes;
  1386. instr.SetInstructionOpsize;
  1387. instr.CheckOperandSizes;
  1388. }
  1389. instr.ConcatInstruction(curlist);
  1390. instr.Free;
  1391. actoppostfix:=PF_None;
  1392. actwideformat:=false;
  1393. end;
  1394. {*****************************************************************************
  1395. Initialize
  1396. *****************************************************************************}
  1397. const
  1398. asmmode_arm_att_info : tasmmodeinfo =
  1399. (
  1400. id : asmmode_arm_gas;
  1401. idtxt : 'DIVIDED';
  1402. casmreader : tarmattreader;
  1403. );
  1404. asmmode_arm_att_unified_info : tasmmodeinfo =
  1405. (
  1406. id : asmmode_arm_gas_unified;
  1407. idtxt : 'UNIFIED';
  1408. casmreader : tarmunifiedattreader;
  1409. );
  1410. asmmode_arm_standard_info : tasmmodeinfo =
  1411. (
  1412. id : asmmode_standard;
  1413. idtxt : 'STANDARD';
  1414. casmreader : tarmattreader;
  1415. );
  1416. initialization
  1417. RegisterAsmMode(asmmode_arm_att_info);
  1418. RegisterAsmMode(asmmode_arm_att_unified_info);
  1419. RegisterAsmMode(asmmode_arm_standard_info);
  1420. end.