raarmgas.pas 50 KB

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