racpugas.pas 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458
  1. {
  2. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  3. Copyright (c) 2014 by Jonas Maebe
  4. Does the parsing for the AArch64 GNU AS styled inline assembler.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. Unit racpugas;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses
  22. raatt,racpu,
  23. aasmtai,
  24. cgbase,cpubase;
  25. type
  26. { taarch64attreader }
  27. taarch64attreader = class(tattreader)
  28. actoppostfix : TOpPostfix;
  29. actinsmmsubreg : TSubRegister;
  30. actsehdirective : TAsmSehDirective;
  31. function is_asmopcode(const s: string):boolean;override;
  32. function is_register(const s:string):boolean;override;
  33. function is_targetdirective(const s: string): boolean;override;
  34. procedure handleopcode;override;
  35. procedure handletargetdirective; override;
  36. protected
  37. procedure BuildReference(oper: taarch64operand; is64bit: boolean);
  38. procedure BuildOperand(oper: taarch64operand; is64bit: boolean);
  39. function TryBuildShifterOp(instr: taarch64instruction; opnr: longint) : boolean;
  40. procedure BuildOpCode(instr: taarch64instruction);
  41. procedure ReadSym(oper: taarch64operand; is64bit: boolean);
  42. procedure ConvertCalljmp(instr: taarch64instruction);
  43. function ToConditionCode(const hs: string; is_operand: boolean): tasmcond;
  44. function ParseArrangementSpecifier(const hs: string): TSubRegister;
  45. function ParseRegIndex(const hs: string): byte;
  46. end;
  47. Implementation
  48. uses
  49. { helpers }
  50. cutils,
  51. { global }
  52. globtype,verbose,
  53. systems,aasmbase,aasmdata,aasmcpu,
  54. { symtable }
  55. symconst,symsym,symdef,
  56. procinfo,
  57. rabase,rautils,
  58. cgutils,paramgr;
  59. function taarch64attreader.is_register(const s:string):boolean;
  60. type
  61. treg2str = record
  62. name : string[3];
  63. reg : tregister;
  64. end;
  65. const
  66. extraregs : array[0..4] of treg2str = (
  67. (name: 'FP' ; reg: NR_FP),
  68. (name: 'LR' ; reg: NR_LR),
  69. (name: 'XR' ; reg: NR_XR),
  70. (name: 'IP0'; reg: NR_IP0),
  71. (name: 'IP1'; reg: NR_IP1));
  72. var
  73. i : longint;
  74. begin
  75. result:=inherited is_register(s);
  76. { reg found?
  77. possible aliases are always 2 chars
  78. }
  79. if result or not(length(s) in [2]) then
  80. exit;
  81. for i:=low(extraregs) to high(extraregs) do
  82. begin
  83. if s=extraregs[i].name then
  84. begin
  85. actasmregister:=extraregs[i].reg;
  86. result:=true;
  87. actasmtoken:=AS_REGISTER;
  88. exit;
  89. end;
  90. end;
  91. end;
  92. const
  93. { Aarch64 subset of SEH directives. .seh_proc, .seh_endproc and .seh_endepilogue
  94. excluded because they are generated automatically when needed. }
  95. recognized_directives: set of TAsmSehDirective=[
  96. ash_endprologue,ash_handler,ash_handlerdata,
  97. ash_stackalloc,ash_nop,ash_savefplr,ash_savefplr_x,
  98. ash_savereg,ash_savereg_x,ash_saveregp,ash_saveregp_x,
  99. ash_savefreg,ash_savefreg_x,ash_savefregp,ash_savefregp_x,
  100. ash_setfp,ash_addfp
  101. ];
  102. function taarch64attreader.is_targetdirective(const s: string): boolean;
  103. var
  104. i: TAsmSehDirective;
  105. begin
  106. result:=false;
  107. if target_info.system<>system_aarch64_win64 then
  108. exit;
  109. for i:=low(TAsmSehDirective) to high(TAsmSehDirective) do
  110. begin
  111. if not (i in recognized_directives) then
  112. continue;
  113. if s=sehdirectivestr[i] then
  114. begin
  115. actsehdirective:=i;
  116. result:=true;
  117. break;
  118. end;
  119. end;
  120. { allow SEH directives only in pure assember routines }
  121. if result and not (po_assembler in current_procinfo.procdef.procoptions) then
  122. begin
  123. Message(asmr_e_seh_in_pure_asm_only);
  124. result:=false;
  125. end;
  126. end;
  127. procedure taarch64attreader.ReadSym(oper: taarch64operand; is64bit: boolean);
  128. var
  129. tempstr, mangledname : string;
  130. typesize,l,k: aint;
  131. begin
  132. tempstr:=actasmpattern;
  133. Consume(AS_ID);
  134. { typecasting? }
  135. if (actasmtoken=AS_LPAREN) and
  136. SearchType(tempstr,typesize) then
  137. begin
  138. oper.hastype:=true;
  139. Consume(AS_LPAREN);
  140. BuildOperand(oper,is64bit);
  141. Consume(AS_RPAREN);
  142. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  143. oper.SetSize(typesize,true);
  144. end
  145. else
  146. if not oper.SetupVar(tempstr,false) then
  147. Message1(sym_e_unknown_id,tempstr);
  148. { record.field ? }
  149. if actasmtoken=AS_DOT then
  150. begin
  151. BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
  152. if (mangledname<>'') then
  153. Message(asmr_e_invalid_reference_syntax);
  154. inc(oper.opr.ref.offset,l);
  155. end;
  156. end;
  157. Procedure taarch64attreader.BuildReference(oper: taarch64operand; is64bit: boolean);
  158. procedure do_error;
  159. begin
  160. Message(asmr_e_invalid_reference_syntax);
  161. RecoverConsume(false);
  162. end;
  163. procedure test_end(require_rbracket : boolean);
  164. begin
  165. if require_rbracket then begin
  166. if not(actasmtoken=AS_RBRACKET) then
  167. begin
  168. do_error;
  169. exit;
  170. end
  171. else
  172. Consume(AS_RBRACKET);
  173. if (actasmtoken=AS_NOT) then
  174. begin
  175. oper.opr.ref.addressmode:=AM_PREINDEXED;
  176. Consume(AS_NOT);
  177. end;
  178. end;
  179. if not(actasmtoken in [AS_SEPARATOR,AS_end]) then
  180. do_error
  181. else
  182. begin
  183. {$IFDEF debugasmreader}
  184. writeln('TEST_end_FINAL_OK. Created the following ref:');
  185. writeln('oper.opr.ref.shiftimm=',oper.opr.ref.shiftimm);
  186. writeln('oper.opr.ref.shiftmode=',ord(oper.opr.ref.shiftmode));
  187. writeln('oper.opr.ref.index=',ord(oper.opr.ref.index));
  188. writeln('oper.opr.ref.base=',ord(oper.opr.ref.base));
  189. writeln('oper.opr.ref.signindex=',ord(oper.opr.ref.signindex));
  190. writeln('oper.opr.ref.addressmode=',ord(oper.opr.ref.addressmode));
  191. writeln;
  192. {$endIF debugasmreader}
  193. end;
  194. end;
  195. function is_shifter_ref_operation(var a : tshiftmode) : boolean;
  196. begin
  197. a:=SM_NONE;
  198. if (actasmpattern='LSL') then
  199. a:=SM_LSL
  200. else if (actasmpattern='UXTW') then
  201. a:=SM_UXTW
  202. else if (actasmpattern='SXTW') then
  203. a:=SM_SXTW
  204. else if (actasmpattern='SXTX') then
  205. a:=SM_SXTX;
  206. is_shifter_ref_operation:=not(a=SM_NONE);
  207. end;
  208. procedure read_index_shift(require_rbracket : boolean);
  209. var
  210. shift: aint;
  211. begin
  212. case actasmtoken of
  213. AS_COMMA :
  214. begin
  215. Consume(AS_COMMA);
  216. if not(actasmtoken=AS_ID) then
  217. do_error;
  218. if is_shifter_ref_operation(oper.opr.ref.shiftmode) then
  219. begin
  220. Consume(actasmtoken);
  221. if actasmtoken=AS_HASH then
  222. begin
  223. Consume(AS_HASH);
  224. shift:=BuildConstExpression(false,true);
  225. if not(shift in [0,2+ord(is64bit)]) then
  226. do_error;
  227. oper.opr.ref.shiftimm:=shift;
  228. test_end(require_rbracket);
  229. end;
  230. end
  231. else
  232. begin
  233. do_error;
  234. exit;
  235. end;
  236. end;
  237. AS_RBRACKET :
  238. if require_rbracket then
  239. test_end(require_rbracket)
  240. else
  241. begin
  242. do_error;
  243. exit;
  244. end;
  245. AS_SEPARATOR,AS_END :
  246. if not require_rbracket then
  247. test_end(false)
  248. else
  249. do_error;
  250. else
  251. begin
  252. do_error;
  253. exit;
  254. end;
  255. end;
  256. end;
  257. procedure read_index(require_rbracket : boolean);
  258. var
  259. recname : string;
  260. o_int,s_int : aint;
  261. begin
  262. case actasmtoken of
  263. AS_REGISTER :
  264. begin
  265. if getsupreg(actasmregister)=RS_XZR then
  266. Message1(asmr_e_invalid_ref_register,actasmpattern);
  267. oper.opr.ref.index:=actasmregister;
  268. Consume(AS_REGISTER);
  269. read_index_shift(require_rbracket);
  270. exit;
  271. end;
  272. AS_HASH : // constant
  273. begin
  274. Consume(AS_HASH);
  275. (*
  276. if actasmtoken=AS_COLON then
  277. begin
  278. consume(AS_COLON);
  279. { GNU-style lower 12 bits of address of non-GOT-based
  280. access }
  281. if (actasmpattern='LO12') then
  282. begin
  283. consume(actasmtoken);
  284. consume(AS_COLON);
  285. if not oper.SetupVar(actasmpattern,false) then
  286. begin
  287. do_error;
  288. exit
  289. end;
  290. consume(AS_ID);
  291. oper.opr.ref.refaddr:=addr_??? (not gotpageoffset);
  292. end
  293. else
  294. begin
  295. do_error;
  296. exit
  297. end;
  298. end
  299. else
  300. *)
  301. begin
  302. o_int:=BuildConstExpression(false,true);
  303. inc(oper.opr.ref.offset,o_int);
  304. end;
  305. test_end(require_rbracket);
  306. exit;
  307. end;
  308. AS_ID :
  309. begin
  310. recname:=actasmpattern;
  311. Consume(AS_ID);
  312. { Apple-style got page offset }
  313. if actasmtoken=AS_AT then
  314. begin
  315. if not oper.SetupVar(recname,false) then
  316. begin
  317. do_error;
  318. exit
  319. end;
  320. consume(AS_AT);
  321. if actasmpattern='GOTPAGEOFF' then
  322. begin
  323. consume(actasmtoken);
  324. oper.opr.ref.refaddr:=addr_gotpageoffset;
  325. end
  326. else if actasmpattern='PAGEOFF' then
  327. begin
  328. consume(actasmtoken);
  329. oper.opr.ref.refaddr:=addr_pageoffset;
  330. end
  331. else
  332. begin
  333. do_error;
  334. exit
  335. end;
  336. end
  337. else
  338. begin
  339. BuildRecordOffsetSize(recname,o_int,s_int,recname,false);
  340. inc(oper.opr.ref.offset,o_int);
  341. end;
  342. test_end(require_rbracket);
  343. exit;
  344. end;
  345. AS_AT:
  346. begin
  347. do_error;
  348. exit;
  349. end;
  350. AS_RBRACKET :
  351. begin
  352. if require_rbracket then
  353. begin
  354. test_end(require_rbracket);
  355. exit;
  356. end
  357. else
  358. begin
  359. do_error; // unexpected rbracket
  360. exit;
  361. end;
  362. end;
  363. AS_SEPARATOR,AS_end :
  364. begin
  365. if not require_rbracket then
  366. begin
  367. test_end(false);
  368. exit;
  369. end
  370. else
  371. begin
  372. do_error;
  373. exit;
  374. end;
  375. end;
  376. else
  377. begin
  378. // unexpected token
  379. do_error;
  380. exit;
  381. end;
  382. end; // case
  383. end;
  384. procedure try_prepostindexed;
  385. begin
  386. Consume(AS_RBRACKET);
  387. case actasmtoken of
  388. AS_COMMA :
  389. begin // post-indexed
  390. Consume(AS_COMMA);
  391. oper.opr.ref.addressmode:=AM_POSTINDEXED;
  392. read_index(false);
  393. exit;
  394. end;
  395. AS_NOT :
  396. begin // pre-indexed
  397. Consume(AS_NOT);
  398. oper.opr.ref.addressmode:=AM_PREINDEXED;
  399. test_end(false);
  400. exit;
  401. end;
  402. else
  403. begin
  404. test_end(false);
  405. exit;
  406. end;
  407. end; // case
  408. end;
  409. begin
  410. Consume(AS_LBRACKET);
  411. oper.opr.ref.addressmode:=AM_OFFSET; // assume "neither PRE nor POST inc"
  412. if actasmtoken=AS_REGISTER then
  413. begin
  414. if getsupreg(actasmregister)=RS_XZR then
  415. Message1(asmr_e_invalid_ref_register,actasmpattern);
  416. oper.opr.ref.base:=actasmregister;
  417. Consume(AS_REGISTER);
  418. case actasmtoken of
  419. AS_RBRACKET :
  420. begin
  421. try_prepostindexed;
  422. exit;
  423. end;
  424. AS_COMMA :
  425. begin
  426. Consume(AS_COMMA);
  427. read_index(true);
  428. exit;
  429. end;
  430. else
  431. begin
  432. Message(asmr_e_invalid_reference_syntax);
  433. RecoverConsume(false);
  434. end;
  435. end;
  436. end
  437. else
  438. Begin
  439. case actasmtoken of
  440. AS_ID :
  441. begin
  442. { TODO: local variables and parameters }
  443. Message(asmr_e_invalid_reference_syntax);
  444. RecoverConsume(false);
  445. exit;
  446. end;
  447. else
  448. begin // elsecase
  449. Message(asmr_e_invalid_reference_syntax);
  450. RecoverConsume(false);
  451. exit;
  452. end;
  453. end;
  454. end;
  455. end;
  456. function taarch64attreader.TryBuildShifterOp(instr: taarch64instruction; opnr: longint): boolean;
  457. procedure handlepara(sm : tshiftmode);
  458. begin
  459. consume(AS_ID);
  460. fillchar(instr.operands[opnr].opr,sizeof(instr.operands[opnr].opr),0);
  461. instr.operands[opnr].opr.typ:=OPR_SHIFTEROP;
  462. instr.operands[opnr].opr.shifterop.shiftmode:=sm;
  463. if (sm=SM_LSL) or
  464. (actasmtoken=AS_HASH) then
  465. begin
  466. consume(AS_HASH);
  467. instr.operands[opnr].opr.shifterop.shiftimm:=BuildConstExpression(false,false);
  468. end;
  469. end;
  470. const
  471. shiftmode2str: array[SM_LSL..SM_SXTX] of string[4] =
  472. ('LSL','LSR','ASR','ROR',
  473. 'UXTB','UXTH','UXTW','UXTX',
  474. 'SXTB','SXTH','SXTW','SXTX');
  475. var
  476. sm: tshiftmode;
  477. i: longint;
  478. usessp,
  479. useszr: boolean;
  480. begin
  481. result:=false;
  482. if (actasmtoken=AS_ID) then
  483. begin
  484. for sm:=low(shiftmode2str) to high(shiftmode2str) do
  485. if actasmpattern=shiftmode2str[sm] then
  486. begin
  487. handlepara(sm);
  488. if instr.operands[1].opr.typ=OPR_REGISTER then
  489. begin
  490. { the possible shifter ops depend on whether this
  491. instruction uses sp and/or zr }
  492. usessp:=false;
  493. useszr:=false;
  494. for i:=low(instr.operands) to pred(opnr) do
  495. begin
  496. if (instr.operands[i].opr.typ=OPR_REGISTER) then
  497. case getsupreg(instr.operands[i].opr.reg) of
  498. RS_XZR:
  499. useszr:=true;
  500. RS_SP:
  501. usessp:=true;
  502. end;
  503. end;
  504. result:=valid_shifter_operand(instr.opcode,useszr,usessp,instr.Is64bit,sm,instr.operands[opnr].opr.shifterop.shiftimm);
  505. if result then
  506. instr.Ops:=opnr;
  507. end;
  508. break;
  509. end;
  510. end;
  511. end;
  512. function taarch64attreader.ToConditionCode(const hs: string; is_operand: boolean): tasmcond;
  513. {$push}{$j-}
  514. const
  515. extracond2str: array[C_HS..C_LO] of string[2] = ('CS','CC');
  516. {$pop}
  517. begin
  518. case actopcode of
  519. A_CSEL,A_CSINC,A_CSINV,A_CSNEG,A_CSET,A_CSETM,
  520. A_CINC,A_CINV,A_CNEG,A_CCMN,A_CCMP,
  521. A_B:
  522. begin
  523. { search for condition, conditions are always 2 chars }
  524. if (is_operand<>(actopcode=A_B)) and
  525. (length(hs)>1) then
  526. begin
  527. { workaround for DFA bug }
  528. result:=low(tasmcond);
  529. for result:=low(uppercond2str) to high(uppercond2str) do
  530. begin
  531. if hs=uppercond2str[result] then
  532. exit;
  533. end;
  534. for result:=low(extracond2str) to high(extracond2str) do
  535. begin
  536. if hs=extracond2str[result] then
  537. exit;
  538. end;
  539. end;
  540. end;
  541. else
  542. ;
  543. end;
  544. result:=C_None;
  545. end;
  546. function taarch64attreader.ParseArrangementSpecifier(const hs: string): TSubRegister;
  547. {$push}{$j-}
  548. const
  549. arrangements: array[R_SUBMM8B..R_SUBMM2D] of string[4] =
  550. ('.8B','.16B','.4H','.8H','.2S','.4S','.1D','.2D');
  551. {$pop}
  552. begin
  553. if length(hs)>2 then
  554. begin
  555. for result:=low(arrangements) to high(arrangements) do
  556. if hs=arrangements[result] then
  557. exit;
  558. result:=R_SUBNONE;
  559. end
  560. else
  561. case hs of
  562. '.B': result:=R_SUBMMB1;
  563. '.H': result:=R_SUBMMH1;
  564. '.S': result:=R_SUBMMS1;
  565. '.D': result:=R_SUBMMD1;
  566. else
  567. result:=R_SUBNONE;
  568. end
  569. end;
  570. function taarch64attreader.ParseRegIndex(const hs: string): byte;
  571. var
  572. b: cardinal;
  573. error: longint;
  574. begin
  575. b:=0;
  576. val(hs,b,error);
  577. if (error<>0) then
  578. Message(asmr_e_syn_constant)
  579. else if b > 31 then
  580. begin
  581. Message(asmr_e_constant_out_of_bounds);
  582. b:=0;
  583. end;
  584. result:=b;
  585. end;
  586. Procedure taarch64attreader.BuildOperand(oper: taarch64operand; is64bit: boolean);
  587. var
  588. expr: string;
  589. typesize, l: aint;
  590. procedure MaybeAddGotAddrMode;
  591. begin
  592. if actasmtoken=AS_AT then
  593. begin
  594. consume(AS_AT);
  595. if actasmpattern='GOTPAGE' then
  596. oper.opr.ref.refaddr:=addr_gotpage
  597. else if actasmpattern='GOTPAGEOFF' then
  598. oper.opr.ref.refaddr:=addr_gotpageoffset
  599. else if actasmpattern='PAGE' then
  600. oper.opr.ref.refaddr:=addr_page
  601. else if actasmpattern='PAGEOFF' then
  602. oper.opr.ref.refaddr:=addr_pageoffset
  603. else
  604. Message(asmr_e_expr_illegal);
  605. consume(actasmtoken);
  606. end
  607. else
  608. oper.opr.ref.refaddr:=addr_pic;
  609. end;
  610. procedure AddLabelOperand(hl:tasmlabel);
  611. begin
  612. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  613. is_calljmp(actopcode) then
  614. begin
  615. oper.opr.typ:=OPR_SYMBOL;
  616. oper.opr.symbol:=hl;
  617. end
  618. else if (actopcode=A_ADR) or
  619. (actopcode=A_ADRP) or
  620. (actopcode=A_LDR) then
  621. begin
  622. oper.InitRef;
  623. MaybeAddGotAddrMode;
  624. oper.opr.ref.symbol:=hl;
  625. if (actasmtoken in [AS_PLUS, AS_MINUS]) then
  626. begin
  627. l:=BuildConstExpression(true,false);
  628. oper.opr.ref.offset:=l;
  629. end;
  630. end;
  631. end;
  632. procedure MaybeRecordOffset;
  633. var
  634. mangledname: string;
  635. hasdot : boolean;
  636. l,
  637. toffset,
  638. tsize : aint;
  639. begin
  640. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  641. exit;
  642. l:=0;
  643. mangledname:='';
  644. hasdot:=(actasmtoken=AS_DOT);
  645. if hasdot then
  646. begin
  647. if expr<>'' then
  648. begin
  649. BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
  650. if (oper.opr.typ<>OPR_CONSTANT) and
  651. (mangledname<>'') then
  652. Message(asmr_e_wrong_sym_type);
  653. inc(l,toffset);
  654. oper.SetSize(tsize,true);
  655. end;
  656. end;
  657. if actasmtoken in [AS_PLUS,AS_MINUS] then
  658. inc(l,BuildConstExpression(true,false));
  659. case oper.opr.typ of
  660. OPR_LOCAL :
  661. begin
  662. { don't allow direct access to fields of parameters, because that
  663. will generate buggy code. Allow it only for explicit typecasting }
  664. if hasdot and
  665. (not oper.hastype) then
  666. checklocalsubscript(oper.opr.localsym);
  667. inc(oper.opr.localsymofs,l)
  668. end;
  669. OPR_CONSTANT :
  670. inc(oper.opr.val,l);
  671. OPR_REFERENCE :
  672. if (mangledname<>'') then
  673. begin
  674. if (oper.opr.val<>0) then
  675. Message(asmr_e_wrong_sym_type);
  676. oper.opr.typ:=OPR_SYMBOL;
  677. oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname,AT_FUNCTION);
  678. end
  679. else
  680. inc(oper.opr.val,l);
  681. OPR_SYMBOL:
  682. Message(asmr_e_invalid_symbol_ref);
  683. else
  684. internalerror(200309221);
  685. end;
  686. end;
  687. function MaybeBuildReference(is64bit: boolean):boolean;
  688. { Try to create a reference, if not a reference is found then false
  689. is returned }
  690. begin
  691. MaybeBuildReference:=true;
  692. case actasmtoken of
  693. AS_INTNUM,
  694. AS_MINUS,
  695. AS_PLUS:
  696. Begin
  697. oper.opr.ref.offset:=BuildConstExpression(True,False);
  698. if actasmtoken<>AS_LPAREN then
  699. Message(asmr_e_invalid_reference_syntax)
  700. else
  701. BuildReference(oper,is64bit);
  702. end;
  703. AS_LPAREN:
  704. BuildReference(oper,is64bit);
  705. AS_ID: { only a variable is allowed ... }
  706. Begin
  707. ReadSym(oper,is64bit);
  708. case actasmtoken of
  709. AS_end,
  710. AS_SEPARATOR,
  711. AS_COMMA: ;
  712. AS_LPAREN:
  713. BuildReference(oper,is64bit);
  714. else
  715. Begin
  716. Message(asmr_e_invalid_reference_syntax);
  717. Consume(actasmtoken);
  718. end;
  719. end; {end case }
  720. end;
  721. else
  722. MaybeBuildReference:=false;
  723. end; { end case }
  724. end;
  725. function parsereg: tregister;
  726. var
  727. subreg: tsubregister;
  728. begin
  729. result:=actasmregister;
  730. Consume(AS_REGISTER);
  731. if (actasmtoken=AS_ID) and
  732. (actasmpattern[1]='.') then
  733. begin
  734. subreg:=ParseArrangementSpecifier(upper(actasmpattern));
  735. if (subreg<>R_SUBNONE) and
  736. (getregtype(result)=R_MMREGISTER) and
  737. ((actinsmmsubreg=R_SUBNONE) or
  738. (actinsmmsubreg=subreg)) then
  739. begin
  740. setsubreg(result,subreg);
  741. { they all have to be the same }
  742. actinsmmsubreg:=subreg;
  743. end
  744. else
  745. Message1(asmr_e_invalid_arrangement,actasmpattern);
  746. Consume(AS_ID);
  747. end
  748. else if (getregtype(result)=R_MMREGISTER) then
  749. begin
  750. if actinsmmsubreg<>R_SUBNONE then
  751. begin
  752. if (getsubreg(result)=R_SUBNONE) or
  753. (getsubreg(result)=actinsmmsubreg) then
  754. setsubreg(result,actinsmmsubreg)
  755. else
  756. Message1(asmr_e_invalid_arrangement,actasmpattern);
  757. end
  758. else if getsubreg(result)=R_SUBNONE then
  759. { Vxx without an arrangement is invalid, use Qxx to specify the entire 128 bits}
  760. Message1(asmr_e_invalid_arrangement,'');
  761. end;
  762. end;
  763. var
  764. tempreg: tregister;
  765. hl: tasmlabel;
  766. icond: tasmcond;
  767. regindex: byte;
  768. Begin
  769. expr:='';
  770. case actasmtoken of
  771. AS_LBRACKET: { Memory reference or constant expression }
  772. Begin
  773. oper.InitRef;
  774. BuildReference(oper,is64bit);
  775. end;
  776. AS_LSBRACKET: { register set }
  777. begin
  778. consume(AS_LSBRACKET);
  779. oper.opr.typ:=OPR_REGSET;
  780. oper.opr.basereg:=parsereg;
  781. oper.opr.nregs:=1;
  782. while (oper.opr.nregs<4) and
  783. (actasmtoken=AS_COMMA) do
  784. begin
  785. consume(AS_COMMA);
  786. tempreg:=parsereg;
  787. if getsupreg(tempreg)<>((getsupreg(oper.opr.basereg)+oper.opr.nregs) mod 32) then
  788. Message(asmr_e_a64_invalid_regset);
  789. inc(oper.opr.nregs);
  790. end;
  791. consume(AS_RSBRACKET);
  792. if actasmtoken=AS_LBRACKET then
  793. begin
  794. consume(AS_LBRACKET);
  795. oper.opr.regsetindex:=ParseRegIndex(actasmpattern);
  796. consume(AS_INTNUM);
  797. consume(AS_RBRACKET);
  798. end
  799. else
  800. oper.opr.regsetindex:=255;
  801. if not(actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  802. Message(asmr_e_syn_operand);
  803. end;
  804. AS_HASH: { Constant expression }
  805. Begin
  806. Consume(AS_HASH);
  807. BuildConstantOperand(oper);
  808. end;
  809. (*
  810. AS_INTNUM,
  811. AS_MINUS,
  812. AS_PLUS:
  813. Begin
  814. { Constant memory offset }
  815. { This must absolutely be followed by ( }
  816. oper.InitRef;
  817. oper.opr.ref.offset:=BuildConstExpression(True,False);
  818. if actasmtoken<>AS_LPAREN then
  819. begin
  820. ofs:=oper.opr.ref.offset;
  821. BuildConstantOperand(oper);
  822. inc(oper.opr.val,ofs);
  823. end
  824. else
  825. BuildReference(oper,is64bit);
  826. end;
  827. *)
  828. AS_ID: { A constant expression, or a Variable ref. }
  829. Begin
  830. { Condition code? }
  831. icond:=ToConditionCode(actasmpattern,true);
  832. if icond<>C_None then
  833. begin
  834. oper.opr.typ:=OPR_COND;
  835. oper.opr.cc:=icond;
  836. consume(AS_ID);
  837. end
  838. else
  839. { Local Label ? }
  840. if is_locallabel(actasmpattern) then
  841. begin
  842. CreateLocalLabel(actasmpattern,hl,false);
  843. Consume(AS_ID);
  844. AddLabelOperand(hl);
  845. end
  846. else
  847. { Check for label }
  848. if SearchLabel(actasmpattern,hl,false) then
  849. begin
  850. Consume(AS_ID);
  851. AddLabelOperand(hl);
  852. end
  853. else
  854. { probably a variable or normal expression }
  855. { or a procedure (such as in CALL ID) }
  856. begin
  857. { is it a constant ? }
  858. if SearchIConstant(actasmpattern,l) then
  859. begin
  860. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  861. Message(asmr_e_invalid_operand_type);
  862. BuildConstantOperand(oper);
  863. end
  864. else
  865. begin
  866. expr:=actasmpattern;
  867. Consume(AS_ID);
  868. { typecasting? }
  869. if (actasmtoken=AS_LPAREN) and
  870. SearchType(expr,typesize) then
  871. begin
  872. oper.hastype:=true;
  873. Consume(AS_LPAREN);
  874. BuildOperand(oper,is64bit);
  875. Consume(AS_RPAREN);
  876. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  877. oper.SetSize(typesize,true);
  878. end
  879. else
  880. begin
  881. if not(oper.SetupVar(expr,false)) then
  882. Begin
  883. { look for special symbols ... }
  884. if expr= '__HIGH' then
  885. begin
  886. consume(AS_LPAREN);
  887. if not oper.setupvar('high'+actasmpattern,false) then
  888. Message1(sym_e_unknown_id,'high'+actasmpattern);
  889. consume(AS_ID);
  890. consume(AS_RPAREN);
  891. end
  892. else
  893. if expr = '__RESULT' then
  894. oper.SetUpResult
  895. else
  896. if expr = '__SELF' then
  897. oper.SetupSelf
  898. else
  899. if expr = '__OLDEBP' then
  900. oper.SetupOldEBP
  901. else
  902. Message1(sym_e_unknown_id,expr);
  903. end
  904. else if oper.opr.typ<>OPR_LOCAL then
  905. begin
  906. oper.InitRef;
  907. MaybeAddGotAddrMode;
  908. end;
  909. end;
  910. end;
  911. if actasmtoken=AS_DOT then
  912. MaybeRecordOffset;
  913. { add a constant expression? }
  914. if (actasmtoken=AS_PLUS) then
  915. begin
  916. l:=BuildConstExpression(true,false);
  917. case oper.opr.typ of
  918. OPR_CONSTANT :
  919. inc(oper.opr.val,l);
  920. OPR_LOCAL :
  921. inc(oper.opr.localsymofs,l);
  922. OPR_REFERENCE :
  923. inc(oper.opr.ref.offset,l);
  924. else
  925. internalerror(2003092005);
  926. end;
  927. end
  928. end;
  929. { Do we have a indexing reference, then parse it also }
  930. if actasmtoken=AS_LPAREN then
  931. BuildReference(oper,is64bit);
  932. end;
  933. { Register, a variable reference or a constant reference }
  934. AS_REGISTER:
  935. Begin
  936. { save the type of register used. }
  937. tempreg:=parsereg;
  938. regindex:=255;
  939. if (getregtype(tempreg)=R_MMREGISTER) and
  940. (actasmtoken=AS_LBRACKET) then
  941. begin
  942. consume(AS_LBRACKET);
  943. regindex:=ParseRegIndex(actasmpattern);
  944. consume(AS_INTNUM);
  945. consume(AS_RBRACKET);
  946. end;
  947. if actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA] then
  948. begin
  949. if (oper.opr.typ<>OPR_NONE) then
  950. Message(asmr_e_invalid_operand_type);
  951. if regindex=255 then
  952. begin
  953. oper.opr.typ:=OPR_REGISTER;
  954. oper.opr.reg:=tempreg;
  955. end
  956. else
  957. begin
  958. oper.opr.typ:=OPR_INDEXEDREG;
  959. oper.opr.indexedreg:=tempreg;
  960. oper.opr.regindex:=regindex;
  961. end;
  962. end
  963. else
  964. Message(asmr_e_syn_operand);
  965. end;
  966. AS_end,
  967. AS_SEPARATOR,
  968. AS_COMMA: ;
  969. else
  970. Begin
  971. Message(asmr_e_syn_operand);
  972. Consume(actasmtoken);
  973. end;
  974. end; { end case }
  975. end;
  976. {*****************************************************************************
  977. taarch64attreader
  978. *****************************************************************************}
  979. procedure taarch64attreader.BuildOpCode(instr: taarch64instruction);
  980. var
  981. operandnum : longint;
  982. Begin
  983. { opcode }
  984. if (actasmtoken<>AS_OPCODE) then
  985. Begin
  986. Message(asmr_e_invalid_or_missing_opcode);
  987. RecoverConsume(true);
  988. exit;
  989. end;
  990. { Fill the instr object with the current state }
  991. with instr do
  992. begin
  993. Opcode:=ActOpcode;
  994. condition:=ActCondition;
  995. oppostfix:=actoppostfix;
  996. end;
  997. Consume(AS_OPCODE);
  998. { We are reading operands, so opcode will be an AS_ID }
  999. operandnum:=1;
  1000. { Zero operand opcode ? }
  1001. if actasmtoken in [AS_SEPARATOR,AS_end] then
  1002. begin
  1003. instr.Ops:=0;
  1004. exit;
  1005. end;
  1006. { Read the operands }
  1007. repeat
  1008. case actasmtoken of
  1009. AS_COMMA: { Operand delimiter }
  1010. Begin
  1011. { operandnum and not operandnum+1, because tinstruction is
  1012. one-based and taicpu is zero-based)
  1013. }
  1014. if can_be_shifter_operand(instr.opcode,operandnum) then
  1015. begin
  1016. Consume(AS_COMMA);
  1017. if not TryBuildShifterOp(instr,operandnum+1) then
  1018. Message(asmr_e_illegal_shifterop_syntax);
  1019. Inc(operandnum);
  1020. end
  1021. else
  1022. begin
  1023. if operandnum>Max_Operands then
  1024. Message(asmr_e_too_many_operands)
  1025. else
  1026. Inc(operandnum);
  1027. Consume(AS_COMMA);
  1028. end;
  1029. end;
  1030. AS_SEPARATOR,
  1031. AS_end : { End of asm operands for this opcode }
  1032. begin
  1033. break;
  1034. end;
  1035. else
  1036. begin
  1037. BuildOperand(taarch64operand(instr.operands[operandnum]),instr.Is64bit);
  1038. instr.Ops:=operandnum;
  1039. if instr.operands[operandnum].opr.typ=OPR_REFERENCE then
  1040. if simple_ref_type(instr.opcode,instr.cgsize,instr.oppostfix,instr.operands[operandnum].opr.ref)<>sr_simple then
  1041. Message(asmr_e_invalid_reference_syntax);
  1042. ;
  1043. end;
  1044. end; { end case }
  1045. until false;
  1046. end;
  1047. function taarch64attreader.is_asmopcode(const s: string):boolean;
  1048. const
  1049. { sorted by length so longer postfixes will match first }
  1050. postfix2strsorted : array[1..7] of string[3] = (
  1051. 'SB','SH','SW',
  1052. 'B','H','W',
  1053. 'S');
  1054. postfixsorted : array[1..7] of TOpPostfix = (
  1055. PF_SB,PF_SH,PF_SW,
  1056. PF_B,PF_H,PF_W,
  1057. PF_S);
  1058. { store replicate }
  1059. ldst14: array[boolean,boolean,'1'..'4'] of tasmop =
  1060. (((A_LD1,A_LD2,A_LD3,A_LD4),
  1061. (A_LD1R,A_LD2R,A_LD3R,A_LD4R)),
  1062. ((A_ST1,A_ST2,A_ST3,A_ST4),
  1063. (A_NONE,A_NONE,A_NONE,A_NONE)));
  1064. var
  1065. j : longint;
  1066. hs : string;
  1067. maxlen : longint;
  1068. Begin
  1069. { making s a value parameter would break other assembler readers }
  1070. hs:=s;
  1071. is_asmopcode:=false;
  1072. { clear opcode }
  1073. actopcode:=A_None;
  1074. actcondition:=C_None;
  1075. { b.cond ? }
  1076. if (length(hs)=4) and
  1077. (hs[1]='B') and
  1078. (hs[2]='.') then
  1079. begin
  1080. actopcode:=A_B;
  1081. actasmtoken:=AS_OPCODE;
  1082. actcondition:=ToConditionCode(copy(hs,3,length(actasmpattern)-2),false);
  1083. if actcondition<>C_None then
  1084. is_asmopcode:=true;
  1085. exit;
  1086. end;
  1087. (* ldN(r)/stN.size ? (shorthand for "ldN(r)/stN { Vx.size, Vy.size } ..."
  1088. supported by clang and possibly gas *)
  1089. actinsmmsubreg:=R_SUBNONE;
  1090. if (length(s)>=5) and
  1091. (((hs[1]='L') and
  1092. (hs[2]='D')) or
  1093. ((hs[1]='S') and
  1094. (hs[2]='T'))) and
  1095. (hs[3] in ['1'..'4']) and
  1096. ((hs[4]='.') or
  1097. ((hs[4]='R') and
  1098. (hs[5]='.'))) then
  1099. begin
  1100. actinsmmsubreg:=ParseArrangementSpecifier(copy(hs,4+ord(hs[4]='R'),255));
  1101. if actinsmmsubreg=R_SUBNONE then
  1102. exit;
  1103. actopcode:=ldst14[hs[1]='S',hs[4]='R',hs[3]];
  1104. actasmtoken:=AS_OPCODE;
  1105. if actopcode<>A_NONE then
  1106. is_asmopcode:=true;
  1107. exit;
  1108. end;
  1109. maxlen:=max(length(hs),7);
  1110. actopcode:=A_NONE;
  1111. for j:=maxlen downto 1 do
  1112. begin
  1113. actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j))));
  1114. if actopcode<>A_NONE then
  1115. begin
  1116. actasmtoken:=AS_OPCODE;
  1117. { strip op code }
  1118. delete(hs,1,j);
  1119. break;
  1120. end;
  1121. end;
  1122. if actopcode=A_NONE then
  1123. exit;
  1124. { check for postfix }
  1125. if length(hs)>0 then
  1126. begin
  1127. for j:=low(postfixsorted) to high(postfixsorted) do
  1128. begin
  1129. if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
  1130. begin
  1131. actoppostfix:=postfixsorted[j];
  1132. { strip postfix }
  1133. delete(hs,1,length(postfix2strsorted[j]));
  1134. break;
  1135. end;
  1136. end;
  1137. end;
  1138. { if we stripped all postfixes, it's a valid opcode }
  1139. is_asmopcode:=length(hs)=0;
  1140. end;
  1141. procedure taarch64attreader.ConvertCalljmp(instr: taarch64instruction);
  1142. var
  1143. newopr : toprrec;
  1144. begin
  1145. if instr.Operands[1].opr.typ=OPR_REFERENCE then
  1146. begin
  1147. newopr.typ:=OPR_SYMBOL;
  1148. newopr.symbol:=instr.Operands[1].opr.ref.symbol;
  1149. newopr.symofs:=instr.Operands[1].opr.ref.offset;
  1150. if (instr.Operands[1].opr.ref.base<>NR_NO) or
  1151. (instr.Operands[1].opr.ref.index<>NR_NO) or
  1152. (instr.Operands[1].opr.ref.refaddr<>addr_pic) then
  1153. Message(asmr_e_syn_operand);
  1154. instr.Operands[1].opr:=newopr;
  1155. end;
  1156. end;
  1157. procedure taarch64attreader.handleopcode;
  1158. var
  1159. instr: taarch64instruction;
  1160. begin
  1161. instr:=taarch64instruction.Create(taarch64operand);
  1162. BuildOpcode(instr);
  1163. if is_calljmp(instr.opcode) then
  1164. ConvertCalljmp(instr);
  1165. {
  1166. instr.AddReferenceSizes;
  1167. instr.SetInstructionOpsize;
  1168. instr.CheckOperandSizes;
  1169. }
  1170. instr.ConcatInstruction(curlist);
  1171. instr.Free;
  1172. actoppostfix:=PF_None;
  1173. end;
  1174. procedure taarch64attreader.handletargetdirective;
  1175. function maxoffset(ash:TAsmSehDirective):aint;
  1176. begin
  1177. case ash of
  1178. ash_savefplr,
  1179. ash_saveregp,
  1180. ash_savereg,
  1181. ash_savefregp,
  1182. ash_savefreg:
  1183. result:=504;
  1184. ash_savefplr_x,
  1185. ash_saveregp_x,
  1186. ash_savefregp_x:
  1187. result:=-512;
  1188. ash_savereg_x,
  1189. ash_savefreg_x:
  1190. result:=-256;
  1191. ash_addfp:
  1192. result:=2040;
  1193. else
  1194. internalerror(2020041204);
  1195. end;
  1196. end;
  1197. procedure add_reg_with_offset(ash:TAsmSehDirective;hreg:tregister;hnum:aint;neg:boolean);
  1198. begin
  1199. if (neg and ((hnum>0) or (hnum<maxoffset(ash)) or (((-hnum) and $7)<>0))) or
  1200. (not neg and ((hnum<0) or (hnum>maxoffset(ash)) or ((hnum and $7)<>0))) then
  1201. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[actsehdirective])
  1202. else
  1203. begin
  1204. if neg then
  1205. hnum:=-hnum;
  1206. if hreg=NR_NO then
  1207. curlist.concat(cai_seh_directive.create_offset(actsehdirective,hnum))
  1208. else
  1209. curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
  1210. end;
  1211. end;
  1212. var
  1213. hreg,
  1214. hreg2 : TRegister;
  1215. hnum : aint;
  1216. flags : integer;
  1217. ai : tai_seh_directive;
  1218. hs : string;
  1219. err : boolean;
  1220. begin
  1221. if actasmtoken<>AS_TARGET_DIRECTIVE then
  1222. InternalError(2020033102);
  1223. Consume(AS_TARGET_DIRECTIVE);
  1224. Include(current_procinfo.flags,pi_has_unwind_info);
  1225. case actsehdirective of
  1226. ash_nop,
  1227. ash_setfp,
  1228. ash_endprologue,
  1229. ash_handlerdata:
  1230. curlist.concat(cai_seh_directive.create(actsehdirective));
  1231. ash_handler:
  1232. begin
  1233. hs:=actasmpattern;
  1234. Consume(AS_ID);
  1235. flags:=0;
  1236. err:=false;
  1237. while actasmtoken=AS_COMMA do
  1238. begin
  1239. Consume(AS_COMMA);
  1240. if actasmtoken=AS_AT then
  1241. begin
  1242. Consume(AS_AT);
  1243. if actasmtoken=AS_ID then
  1244. begin
  1245. uppervar(actasmpattern);
  1246. if actasmpattern='EXCEPT' then
  1247. flags:=flags or 1
  1248. else if actasmpattern='UNWIND' then
  1249. flags:=flags or 2
  1250. else
  1251. err:=true;
  1252. Consume(AS_ID);
  1253. end
  1254. else
  1255. err:=true;
  1256. end
  1257. else
  1258. err:=true;
  1259. if err then
  1260. begin
  1261. Message(asmr_e_syntax_error);
  1262. RecoverConsume(false);
  1263. exit;
  1264. end;
  1265. end;
  1266. ai:=cai_seh_directive.create_name(ash_handler,hs);
  1267. ai.data.flags:=flags;
  1268. curlist.concat(ai);
  1269. end;
  1270. ash_savefplr,
  1271. ash_savefplr_x:
  1272. begin
  1273. hnum:=BuildConstExpression(false,false);
  1274. add_reg_with_offset(actsehdirective,NR_NO,hnum,actsehdirective=ash_savefplr_x);
  1275. end;
  1276. ash_savereg,
  1277. ash_savereg_x:
  1278. begin
  1279. hreg:=actasmregister;
  1280. Consume(AS_REGISTER);
  1281. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<19) then
  1282. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1283. Consume(AS_COMMA);
  1284. hnum:=BuildConstExpression(false,false);
  1285. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_savereg_x);
  1286. end;
  1287. ash_saveregp,
  1288. ash_saveregp_x:
  1289. begin
  1290. hreg:=actasmregister;
  1291. consume(AS_REGISTER);
  1292. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<19) then
  1293. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1294. consume(AS_COMMA);
  1295. hreg2:=actasmregister;
  1296. consume(AS_REGISTER);
  1297. if (getregtype(hreg2)<>R_INTREGISTER) or (getsubreg(hreg2)<>R_SUBWHOLE) or (getsupreg(hreg2)<>getsupreg(hreg)+1) then
  1298. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1299. consume(AS_COMMA);
  1300. hnum:=BuildConstExpression(false,false);
  1301. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_saveregp_x);
  1302. end;
  1303. ash_savefreg,
  1304. ash_savefreg_x:
  1305. begin
  1306. hreg:=actasmregister;
  1307. Consume(AS_REGISTER);
  1308. if (getregtype(hreg)<>R_MMREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<8) then
  1309. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1310. Consume(AS_COMMA);
  1311. hnum:=BuildConstExpression(false,false);
  1312. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_savefreg_x);
  1313. end;
  1314. ash_savefregp,
  1315. ash_savefregp_x:
  1316. begin
  1317. hreg:=actasmregister;
  1318. consume(AS_REGISTER);
  1319. if (getregtype(hreg)<>R_MMREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<8) then
  1320. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1321. consume(AS_COMMA);
  1322. hreg2:=actasmregister;
  1323. consume(AS_REGISTER);
  1324. if (getregtype(hreg2)<>R_MMREGISTER) or (getsubreg(hreg2)<>R_SUBWHOLE) or (getsupreg(hreg2)<>getsupreg(hreg)+1) then
  1325. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1326. consume(AS_COMMA);
  1327. hnum:=BuildConstExpression(false,false);
  1328. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_savefregp_x);
  1329. end;
  1330. ash_stackalloc:
  1331. begin
  1332. hnum:=BuildConstExpression(false,false);
  1333. if (hnum<0) or (hnum>$FFFFFF) or ((hnum and 7)<>0) then
  1334. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_stackalloc])
  1335. else
  1336. curlist.concat(cai_seh_directive.create_offset(ash_stackalloc,hnum));
  1337. end;
  1338. else
  1339. InternalError(2020033103);
  1340. end;
  1341. if actasmtoken<>AS_SEPARATOR then
  1342. Consume(AS_SEPARATOR);
  1343. end;
  1344. {*****************************************************************************
  1345. Initialize
  1346. *****************************************************************************}
  1347. const
  1348. asmmode_arm_att_info : tasmmodeinfo =
  1349. (
  1350. id : asmmode_arm_gas;
  1351. idtxt : 'GAS';
  1352. casmreader : taarch64attreader;
  1353. );
  1354. asmmode_arm_standard_info : tasmmodeinfo =
  1355. (
  1356. id : asmmode_standard;
  1357. idtxt : 'STANDARD';
  1358. casmreader : taarch64attreader;
  1359. );
  1360. initialization
  1361. RegisterAsmMode(asmmode_arm_att_info);
  1362. RegisterAsmMode(asmmode_arm_standard_info);
  1363. end.