raarmgas.pas 49 KB

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