racpugas.pas 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  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 (actasmtoken<>AS_RSBRACKET) and (oper.opr.nregs<4) do
  783. begin
  784. if actasmtoken=AS_MINUS then
  785. begin
  786. consume(AS_MINUS);
  787. tempreg:=parsereg;
  788. if (getsupreg(tempreg)-getsupreg(oper.opr.basereg))>=4 then
  789. Message(asmr_e_a64_regset_too_large);
  790. oper.opr.nregs:=getsupreg(tempreg)-getsupreg(oper.opr.basereg)+1;
  791. if actasmtoken<>AS_COMMA then
  792. break;
  793. end;
  794. if actasmtoken=AS_COMMA then
  795. begin
  796. consume(AS_COMMA);
  797. tempreg:=parsereg;
  798. if (getsupreg(tempreg)-getsupreg(oper.opr.basereg))>=4 then
  799. Message(asmr_e_a64_regset_too_large);
  800. if getsupreg(tempreg)<>((getsupreg(oper.opr.basereg)+oper.opr.nregs) mod 32) then
  801. Message(asmr_e_a64_invalid_regset);
  802. inc(oper.opr.nregs);
  803. end
  804. else
  805. break;
  806. end;
  807. consume(AS_RSBRACKET);
  808. if actasmtoken=AS_LBRACKET then
  809. begin
  810. consume(AS_LBRACKET);
  811. oper.opr.regsetindex:=ParseRegIndex(actasmpattern);
  812. consume(AS_INTNUM);
  813. consume(AS_RBRACKET);
  814. end
  815. else
  816. oper.opr.regsetindex:=255;
  817. if not(actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  818. Message(asmr_e_syn_operand);
  819. end;
  820. AS_HASH: { Constant expression }
  821. Begin
  822. Consume(AS_HASH);
  823. BuildConstantOperand(oper);
  824. end;
  825. (*
  826. AS_INTNUM,
  827. AS_MINUS,
  828. AS_PLUS:
  829. Begin
  830. { Constant memory offset }
  831. { This must absolutely be followed by ( }
  832. oper.InitRef;
  833. oper.opr.ref.offset:=BuildConstExpression(True,False);
  834. if actasmtoken<>AS_LPAREN then
  835. begin
  836. ofs:=oper.opr.ref.offset;
  837. BuildConstantOperand(oper);
  838. inc(oper.opr.val,ofs);
  839. end
  840. else
  841. BuildReference(oper,is64bit);
  842. end;
  843. *)
  844. AS_ID: { A constant expression, or a Variable ref. }
  845. Begin
  846. { Condition code? }
  847. icond:=ToConditionCode(actasmpattern,true);
  848. if icond<>C_None then
  849. begin
  850. oper.opr.typ:=OPR_COND;
  851. oper.opr.cc:=icond;
  852. consume(AS_ID);
  853. end
  854. else
  855. { Local Label ? }
  856. if is_locallabel(actasmpattern) then
  857. begin
  858. CreateLocalLabel(actasmpattern,hl,false);
  859. Consume(AS_ID);
  860. AddLabelOperand(hl);
  861. end
  862. else
  863. { Check for label }
  864. if SearchLabel(actasmpattern,hl,false) then
  865. begin
  866. Consume(AS_ID);
  867. AddLabelOperand(hl);
  868. end
  869. else
  870. { probably a variable or normal expression }
  871. { or a procedure (such as in CALL ID) }
  872. begin
  873. { is it a constant ? }
  874. if SearchIConstant(actasmpattern,l) then
  875. begin
  876. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  877. Message(asmr_e_invalid_operand_type);
  878. BuildConstantOperand(oper);
  879. end
  880. else
  881. begin
  882. expr:=actasmpattern;
  883. Consume(AS_ID);
  884. { typecasting? }
  885. if (actasmtoken=AS_LPAREN) and
  886. SearchType(expr,typesize) then
  887. begin
  888. oper.hastype:=true;
  889. Consume(AS_LPAREN);
  890. BuildOperand(oper,is64bit);
  891. Consume(AS_RPAREN);
  892. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  893. oper.SetSize(typesize,true);
  894. end
  895. else
  896. begin
  897. if not(oper.SetupVar(expr,false)) then
  898. Begin
  899. { look for special symbols ... }
  900. if expr= '__HIGH' then
  901. begin
  902. consume(AS_LPAREN);
  903. if not oper.setupvar('high'+actasmpattern,false) then
  904. Message1(sym_e_unknown_id,'high'+actasmpattern);
  905. consume(AS_ID);
  906. consume(AS_RPAREN);
  907. end
  908. else
  909. if expr = '__RESULT' then
  910. oper.SetUpResult
  911. else
  912. if expr = '__SELF' then
  913. oper.SetupSelf
  914. else
  915. if expr = '__OLDEBP' then
  916. oper.SetupOldEBP
  917. else
  918. Message1(sym_e_unknown_id,expr);
  919. end
  920. else if oper.opr.typ<>OPR_LOCAL then
  921. begin
  922. oper.InitRef;
  923. MaybeAddGotAddrMode;
  924. end;
  925. end;
  926. end;
  927. if actasmtoken=AS_DOT then
  928. MaybeRecordOffset;
  929. { add a constant expression? }
  930. if (actasmtoken=AS_PLUS) then
  931. begin
  932. l:=BuildConstExpression(true,false);
  933. case oper.opr.typ of
  934. OPR_CONSTANT :
  935. inc(oper.opr.val,l);
  936. OPR_LOCAL :
  937. inc(oper.opr.localsymofs,l);
  938. OPR_REFERENCE :
  939. inc(oper.opr.ref.offset,l);
  940. else
  941. internalerror(2003092005);
  942. end;
  943. end
  944. end;
  945. { Do we have a indexing reference, then parse it also }
  946. if actasmtoken=AS_LPAREN then
  947. BuildReference(oper,is64bit);
  948. end;
  949. { Register, a variable reference or a constant reference }
  950. AS_REGISTER:
  951. Begin
  952. { save the type of register used. }
  953. tempreg:=parsereg;
  954. regindex:=255;
  955. if (getregtype(tempreg)=R_MMREGISTER) and
  956. (actasmtoken=AS_LBRACKET) then
  957. begin
  958. consume(AS_LBRACKET);
  959. regindex:=ParseRegIndex(actasmpattern);
  960. consume(AS_INTNUM);
  961. consume(AS_RBRACKET);
  962. end;
  963. if actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA] then
  964. begin
  965. if (oper.opr.typ<>OPR_NONE) then
  966. Message(asmr_e_invalid_operand_type);
  967. if regindex=255 then
  968. begin
  969. oper.opr.typ:=OPR_REGISTER;
  970. oper.opr.reg:=tempreg;
  971. end
  972. else
  973. begin
  974. oper.opr.typ:=OPR_INDEXEDREG;
  975. oper.opr.indexedreg:=tempreg;
  976. oper.opr.regindex:=regindex;
  977. end;
  978. end
  979. else
  980. Message(asmr_e_syn_operand);
  981. end;
  982. AS_end,
  983. AS_SEPARATOR,
  984. AS_COMMA: ;
  985. else
  986. Begin
  987. Message(asmr_e_syn_operand);
  988. Consume(actasmtoken);
  989. end;
  990. end; { end case }
  991. end;
  992. {*****************************************************************************
  993. taarch64attreader
  994. *****************************************************************************}
  995. procedure taarch64attreader.BuildOpCode(instr: taarch64instruction);
  996. var
  997. operandnum : longint;
  998. Begin
  999. { opcode }
  1000. if (actasmtoken<>AS_OPCODE) then
  1001. Begin
  1002. Message(asmr_e_invalid_or_missing_opcode);
  1003. RecoverConsume(true);
  1004. exit;
  1005. end;
  1006. { Fill the instr object with the current state }
  1007. with instr do
  1008. begin
  1009. Opcode:=ActOpcode;
  1010. condition:=ActCondition;
  1011. oppostfix:=actoppostfix;
  1012. end;
  1013. Consume(AS_OPCODE);
  1014. { We are reading operands, so opcode will be an AS_ID }
  1015. operandnum:=1;
  1016. { Zero operand opcode ? }
  1017. if actasmtoken in [AS_SEPARATOR,AS_end] then
  1018. begin
  1019. instr.Ops:=0;
  1020. exit;
  1021. end;
  1022. { Read the operands }
  1023. repeat
  1024. case actasmtoken of
  1025. AS_COMMA: { Operand delimiter }
  1026. Begin
  1027. { operandnum and not operandnum+1, because tinstruction is
  1028. one-based and taicpu is zero-based)
  1029. }
  1030. if can_be_shifter_operand(instr.opcode,operandnum) then
  1031. begin
  1032. Consume(AS_COMMA);
  1033. if not TryBuildShifterOp(instr,operandnum+1) then
  1034. Message(asmr_e_illegal_shifterop_syntax);
  1035. Inc(operandnum);
  1036. end
  1037. else
  1038. begin
  1039. if operandnum>Max_Operands then
  1040. Message(asmr_e_too_many_operands)
  1041. else
  1042. Inc(operandnum);
  1043. Consume(AS_COMMA);
  1044. end;
  1045. end;
  1046. AS_SEPARATOR,
  1047. AS_end : { End of asm operands for this opcode }
  1048. begin
  1049. break;
  1050. end;
  1051. else
  1052. begin
  1053. BuildOperand(taarch64operand(instr.operands[operandnum]),instr.Is64bit);
  1054. instr.Ops:=operandnum;
  1055. if instr.operands[operandnum].opr.typ=OPR_REFERENCE then
  1056. if simple_ref_type(instr.opcode,instr.cgsize,instr.oppostfix,instr.operands[operandnum].opr.ref)<>sr_simple then
  1057. Message(asmr_e_invalid_reference_syntax);
  1058. ;
  1059. end;
  1060. end; { end case }
  1061. until false;
  1062. end;
  1063. function taarch64attreader.is_asmopcode(const s: string):boolean;
  1064. const
  1065. { sorted by length so longer postfixes will match first }
  1066. postfix2strsorted : array[1..7] of string[3] = (
  1067. 'SB','SH','SW',
  1068. 'B','H','W',
  1069. 'S');
  1070. postfixsorted : array[1..7] of TOpPostfix = (
  1071. PF_SB,PF_SH,PF_SW,
  1072. PF_B,PF_H,PF_W,
  1073. PF_S);
  1074. { store replicate }
  1075. ldst14: array[boolean,boolean,'1'..'4'] of tasmop =
  1076. (((A_LD1,A_LD2,A_LD3,A_LD4),
  1077. (A_LD1R,A_LD2R,A_LD3R,A_LD4R)),
  1078. ((A_ST1,A_ST2,A_ST3,A_ST4),
  1079. (A_NONE,A_NONE,A_NONE,A_NONE)));
  1080. var
  1081. j : longint;
  1082. hs : string;
  1083. maxlen : longint;
  1084. Begin
  1085. { making s a value parameter would break other assembler readers }
  1086. hs:=s;
  1087. is_asmopcode:=false;
  1088. { clear opcode }
  1089. actopcode:=A_None;
  1090. actcondition:=C_None;
  1091. { b.cond ? }
  1092. if (length(hs)=4) and
  1093. (hs[1]='B') and
  1094. (hs[2]='.') then
  1095. begin
  1096. actopcode:=A_B;
  1097. actasmtoken:=AS_OPCODE;
  1098. actcondition:=ToConditionCode(copy(hs,3,length(actasmpattern)-2),false);
  1099. if actcondition<>C_None then
  1100. is_asmopcode:=true;
  1101. exit;
  1102. end;
  1103. (* ldN(r)/stN.size ? (shorthand for "ldN(r)/stN { Vx.size, Vy.size } ..."
  1104. supported by clang and possibly gas *)
  1105. actinsmmsubreg:=R_SUBNONE;
  1106. if (length(s)>=5) and
  1107. (((hs[1]='L') and
  1108. (hs[2]='D')) or
  1109. ((hs[1]='S') and
  1110. (hs[2]='T'))) and
  1111. (hs[3] in ['1'..'4']) and
  1112. ((hs[4]='.') or
  1113. ((hs[4]='R') and
  1114. (hs[5]='.'))) then
  1115. begin
  1116. actinsmmsubreg:=ParseArrangementSpecifier(copy(hs,4+ord(hs[4]='R'),255));
  1117. if actinsmmsubreg=R_SUBNONE then
  1118. exit;
  1119. actopcode:=ldst14[hs[1]='S',hs[4]='R',hs[3]];
  1120. actasmtoken:=AS_OPCODE;
  1121. if actopcode<>A_NONE then
  1122. is_asmopcode:=true;
  1123. exit;
  1124. end;
  1125. maxlen:=max(length(hs),7);
  1126. actopcode:=A_NONE;
  1127. for j:=maxlen downto 1 do
  1128. begin
  1129. actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j))));
  1130. if actopcode<>A_NONE then
  1131. begin
  1132. actasmtoken:=AS_OPCODE;
  1133. { strip op code }
  1134. delete(hs,1,j);
  1135. break;
  1136. end;
  1137. end;
  1138. if actopcode=A_NONE then
  1139. exit;
  1140. { check for postfix }
  1141. if length(hs)>0 then
  1142. begin
  1143. for j:=low(postfixsorted) to high(postfixsorted) do
  1144. begin
  1145. if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
  1146. begin
  1147. actoppostfix:=postfixsorted[j];
  1148. { strip postfix }
  1149. delete(hs,1,length(postfix2strsorted[j]));
  1150. break;
  1151. end;
  1152. end;
  1153. end;
  1154. { if we stripped all postfixes, it's a valid opcode }
  1155. is_asmopcode:=length(hs)=0;
  1156. end;
  1157. procedure taarch64attreader.ConvertCalljmp(instr: taarch64instruction);
  1158. var
  1159. newopr : toprrec;
  1160. begin
  1161. if instr.Operands[1].opr.typ=OPR_REFERENCE then
  1162. begin
  1163. newopr.typ:=OPR_SYMBOL;
  1164. newopr.symbol:=instr.Operands[1].opr.ref.symbol;
  1165. newopr.symofs:=instr.Operands[1].opr.ref.offset;
  1166. if (instr.Operands[1].opr.ref.base<>NR_NO) or
  1167. (instr.Operands[1].opr.ref.index<>NR_NO) or
  1168. (instr.Operands[1].opr.ref.refaddr<>addr_pic) then
  1169. Message(asmr_e_syn_operand);
  1170. instr.Operands[1].opr:=newopr;
  1171. end;
  1172. end;
  1173. procedure taarch64attreader.handleopcode;
  1174. var
  1175. instr: taarch64instruction;
  1176. begin
  1177. instr:=taarch64instruction.Create(taarch64operand);
  1178. BuildOpcode(instr);
  1179. if is_calljmp(instr.opcode) then
  1180. ConvertCalljmp(instr);
  1181. {
  1182. instr.AddReferenceSizes;
  1183. instr.SetInstructionOpsize;
  1184. instr.CheckOperandSizes;
  1185. }
  1186. instr.ConcatInstruction(curlist);
  1187. instr.Free;
  1188. actoppostfix:=PF_None;
  1189. end;
  1190. procedure taarch64attreader.handletargetdirective;
  1191. function maxoffset(ash:TAsmSehDirective):aint;
  1192. begin
  1193. case ash of
  1194. ash_savefplr,
  1195. ash_saveregp,
  1196. ash_savereg,
  1197. ash_savefregp,
  1198. ash_savefreg:
  1199. result:=504;
  1200. ash_savefplr_x,
  1201. ash_saveregp_x,
  1202. ash_savefregp_x:
  1203. result:=-512;
  1204. ash_savereg_x,
  1205. ash_savefreg_x:
  1206. result:=-256;
  1207. ash_addfp:
  1208. result:=2040;
  1209. else
  1210. internalerror(2020041204);
  1211. end;
  1212. end;
  1213. procedure add_reg_with_offset(ash:TAsmSehDirective;hreg:tregister;hnum:aint;neg:boolean);
  1214. begin
  1215. if (neg and ((hnum>0) or (hnum<maxoffset(ash)) or (((-hnum) and $7)<>0))) or
  1216. (not neg and ((hnum<0) or (hnum>maxoffset(ash)) or ((hnum and $7)<>0))) then
  1217. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[actsehdirective])
  1218. else
  1219. begin
  1220. if neg then
  1221. hnum:=-hnum;
  1222. if hreg=NR_NO then
  1223. curlist.concat(cai_seh_directive.create_offset(actsehdirective,hnum))
  1224. else
  1225. curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
  1226. end;
  1227. end;
  1228. var
  1229. hreg,
  1230. hreg2 : TRegister;
  1231. hnum : aint;
  1232. flags : integer;
  1233. ai : tai_seh_directive;
  1234. hs : string;
  1235. err : boolean;
  1236. begin
  1237. if actasmtoken<>AS_TARGET_DIRECTIVE then
  1238. InternalError(2020033102);
  1239. Consume(AS_TARGET_DIRECTIVE);
  1240. Include(current_procinfo.flags,pi_has_unwind_info);
  1241. case actsehdirective of
  1242. ash_nop,
  1243. ash_setfp,
  1244. ash_endprologue,
  1245. ash_handlerdata:
  1246. curlist.concat(cai_seh_directive.create(actsehdirective));
  1247. ash_handler:
  1248. begin
  1249. hs:=actasmpattern;
  1250. Consume(AS_ID);
  1251. flags:=0;
  1252. err:=false;
  1253. while actasmtoken=AS_COMMA do
  1254. begin
  1255. Consume(AS_COMMA);
  1256. if actasmtoken=AS_AT then
  1257. begin
  1258. Consume(AS_AT);
  1259. if actasmtoken=AS_ID then
  1260. begin
  1261. uppervar(actasmpattern);
  1262. if actasmpattern='EXCEPT' then
  1263. flags:=flags or 1
  1264. else if actasmpattern='UNWIND' then
  1265. flags:=flags or 2
  1266. else
  1267. err:=true;
  1268. Consume(AS_ID);
  1269. end
  1270. else
  1271. err:=true;
  1272. end
  1273. else
  1274. err:=true;
  1275. if err then
  1276. begin
  1277. Message(asmr_e_syntax_error);
  1278. RecoverConsume(false);
  1279. exit;
  1280. end;
  1281. end;
  1282. ai:=cai_seh_directive.create_name(ash_handler,hs);
  1283. ai.data.flags:=flags;
  1284. curlist.concat(ai);
  1285. end;
  1286. ash_savefplr,
  1287. ash_savefplr_x:
  1288. begin
  1289. hnum:=BuildConstExpression(false,false);
  1290. add_reg_with_offset(actsehdirective,NR_NO,hnum,actsehdirective=ash_savefplr_x);
  1291. end;
  1292. ash_savereg,
  1293. ash_savereg_x:
  1294. begin
  1295. hreg:=actasmregister;
  1296. Consume(AS_REGISTER);
  1297. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<19) 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_savereg_x);
  1302. end;
  1303. ash_saveregp,
  1304. ash_saveregp_x:
  1305. begin
  1306. hreg:=actasmregister;
  1307. consume(AS_REGISTER);
  1308. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<19) then
  1309. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1310. consume(AS_COMMA);
  1311. hreg2:=actasmregister;
  1312. consume(AS_REGISTER);
  1313. if (getregtype(hreg2)<>R_INTREGISTER) or (getsubreg(hreg2)<>R_SUBWHOLE) or (getsupreg(hreg2)<>getsupreg(hreg)+1) then
  1314. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1315. consume(AS_COMMA);
  1316. hnum:=BuildConstExpression(false,false);
  1317. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_saveregp_x);
  1318. end;
  1319. ash_savefreg,
  1320. ash_savefreg_x:
  1321. begin
  1322. hreg:=actasmregister;
  1323. Consume(AS_REGISTER);
  1324. if (getregtype(hreg)<>R_MMREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<8) 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_savefreg_x);
  1329. end;
  1330. ash_savefregp,
  1331. ash_savefregp_x:
  1332. begin
  1333. hreg:=actasmregister;
  1334. consume(AS_REGISTER);
  1335. if (getregtype(hreg)<>R_MMREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<8) then
  1336. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1337. consume(AS_COMMA);
  1338. hreg2:=actasmregister;
  1339. consume(AS_REGISTER);
  1340. if (getregtype(hreg2)<>R_MMREGISTER) or (getsubreg(hreg2)<>R_SUBWHOLE) or (getsupreg(hreg2)<>getsupreg(hreg)+1) then
  1341. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1342. consume(AS_COMMA);
  1343. hnum:=BuildConstExpression(false,false);
  1344. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_savefregp_x);
  1345. end;
  1346. ash_stackalloc:
  1347. begin
  1348. hnum:=BuildConstExpression(false,false);
  1349. if (hnum<0) or (hnum>$FFFFFF) or ((hnum and 7)<>0) then
  1350. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_stackalloc])
  1351. else
  1352. curlist.concat(cai_seh_directive.create_offset(ash_stackalloc,hnum));
  1353. end;
  1354. else
  1355. InternalError(2020033103);
  1356. end;
  1357. if actasmtoken<>AS_SEPARATOR then
  1358. Consume(AS_SEPARATOR);
  1359. end;
  1360. {*****************************************************************************
  1361. Initialize
  1362. *****************************************************************************}
  1363. const
  1364. asmmode_arm_att_info : tasmmodeinfo =
  1365. (
  1366. id : asmmode_arm_gas;
  1367. idtxt : 'GAS';
  1368. casmreader : taarch64attreader;
  1369. );
  1370. asmmode_arm_standard_info : tasmmodeinfo =
  1371. (
  1372. id : asmmode_standard;
  1373. idtxt : 'STANDARD';
  1374. casmreader : taarch64attreader;
  1375. );
  1376. initialization
  1377. RegisterAsmMode(asmmode_arm_att_info);
  1378. RegisterAsmMode(asmmode_arm_standard_info);
  1379. end.