racpugas.pas 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477
  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_FCCMP,A_FCCMPE,
  522. A_B:
  523. begin
  524. { search for condition, conditions are always 2 chars }
  525. if (is_operand<>(actopcode=A_B)) and
  526. (length(hs)>1) then
  527. begin
  528. { workaround for DFA bug }
  529. result:=low(tasmcond);
  530. for result:=low(uppercond2str) to high(uppercond2str) do
  531. begin
  532. if hs=uppercond2str[result] then
  533. exit;
  534. end;
  535. for result:=low(extracond2str) to high(extracond2str) do
  536. begin
  537. if hs=extracond2str[result] then
  538. exit;
  539. end;
  540. end;
  541. end;
  542. else
  543. ;
  544. end;
  545. result:=C_None;
  546. end;
  547. function taarch64attreader.ParseArrangementSpecifier(const hs: string): TSubRegister;
  548. {$push}{$j-}
  549. const
  550. arrangements: array[R_SUBMM8B..R_SUBMM2D] of string[4] =
  551. ('.8B','.16B','.4H','.8H','.2S','.4S','.1D','.2D');
  552. {$pop}
  553. begin
  554. if length(hs)>2 then
  555. begin
  556. for result:=low(arrangements) to high(arrangements) do
  557. if hs=arrangements[result] then
  558. exit;
  559. result:=R_SUBNONE;
  560. end
  561. else
  562. case hs of
  563. '.B': result:=R_SUBMMB1;
  564. '.H': result:=R_SUBMMH1;
  565. '.S': result:=R_SUBMMS1;
  566. '.D': result:=R_SUBMMD1;
  567. else
  568. result:=R_SUBNONE;
  569. end
  570. end;
  571. function taarch64attreader.ParseRegIndex(const hs: string): byte;
  572. var
  573. b: cardinal;
  574. error: longint;
  575. begin
  576. b:=0;
  577. val(hs,b,error);
  578. if (error<>0) then
  579. Message(asmr_e_syn_constant)
  580. else if b > 31 then
  581. begin
  582. Message(asmr_e_constant_out_of_bounds);
  583. b:=0;
  584. end;
  585. result:=b;
  586. end;
  587. Procedure taarch64attreader.BuildOperand(oper: taarch64operand; is64bit: boolean);
  588. var
  589. expr: string;
  590. typesize, l: aint;
  591. procedure MaybeAddGotAddrMode;
  592. begin
  593. if actasmtoken=AS_AT then
  594. begin
  595. consume(AS_AT);
  596. if actasmpattern='GOTPAGE' then
  597. oper.opr.ref.refaddr:=addr_gotpage
  598. else if actasmpattern='GOTPAGEOFF' then
  599. oper.opr.ref.refaddr:=addr_gotpageoffset
  600. else if actasmpattern='PAGE' then
  601. oper.opr.ref.refaddr:=addr_page
  602. else if actasmpattern='PAGEOFF' then
  603. oper.opr.ref.refaddr:=addr_pageoffset
  604. else
  605. Message(asmr_e_expr_illegal);
  606. consume(actasmtoken);
  607. end
  608. else
  609. oper.opr.ref.refaddr:=addr_pic;
  610. end;
  611. procedure AddLabelOperand(hl:tasmlabel);
  612. begin
  613. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  614. is_calljmp(actopcode) then
  615. begin
  616. oper.opr.typ:=OPR_SYMBOL;
  617. oper.opr.symbol:=hl;
  618. end
  619. else if (actopcode=A_ADR) or
  620. (actopcode=A_ADRP) or
  621. (actopcode=A_LDR) then
  622. begin
  623. oper.InitRef;
  624. MaybeAddGotAddrMode;
  625. oper.opr.ref.symbol:=hl;
  626. if (actasmtoken in [AS_PLUS, AS_MINUS]) then
  627. begin
  628. l:=BuildConstExpression(true,false);
  629. oper.opr.ref.offset:=l;
  630. end;
  631. end;
  632. end;
  633. procedure MaybeRecordOffset;
  634. var
  635. mangledname: string;
  636. hasdot : boolean;
  637. l,
  638. toffset,
  639. tsize : aint;
  640. begin
  641. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  642. exit;
  643. l:=0;
  644. mangledname:='';
  645. hasdot:=(actasmtoken=AS_DOT);
  646. if hasdot then
  647. begin
  648. if expr<>'' then
  649. begin
  650. BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
  651. if (oper.opr.typ<>OPR_CONSTANT) and
  652. (mangledname<>'') then
  653. Message(asmr_e_wrong_sym_type);
  654. inc(l,toffset);
  655. oper.SetSize(tsize,true);
  656. end;
  657. end;
  658. if actasmtoken in [AS_PLUS,AS_MINUS] then
  659. inc(l,BuildConstExpression(true,false));
  660. case oper.opr.typ of
  661. OPR_LOCAL :
  662. begin
  663. { don't allow direct access to fields of parameters, because that
  664. will generate buggy code. Allow it only for explicit typecasting }
  665. if hasdot and
  666. (not oper.hastype) then
  667. checklocalsubscript(oper.opr.localsym);
  668. inc(oper.opr.localsymofs,l)
  669. end;
  670. OPR_CONSTANT :
  671. inc(oper.opr.val,l);
  672. OPR_REFERENCE :
  673. if (mangledname<>'') then
  674. begin
  675. if (oper.opr.val<>0) then
  676. Message(asmr_e_wrong_sym_type);
  677. oper.opr.typ:=OPR_SYMBOL;
  678. oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname,AT_FUNCTION);
  679. end
  680. else
  681. inc(oper.opr.val,l);
  682. OPR_SYMBOL:
  683. Message(asmr_e_invalid_symbol_ref);
  684. else
  685. internalerror(200309221);
  686. end;
  687. end;
  688. function MaybeBuildReference(is64bit: boolean):boolean;
  689. { Try to create a reference, if not a reference is found then false
  690. is returned }
  691. begin
  692. MaybeBuildReference:=true;
  693. case actasmtoken of
  694. AS_INTNUM,
  695. AS_MINUS,
  696. AS_PLUS:
  697. Begin
  698. oper.opr.ref.offset:=BuildConstExpression(True,False);
  699. if actasmtoken<>AS_LPAREN then
  700. Message(asmr_e_invalid_reference_syntax)
  701. else
  702. BuildReference(oper,is64bit);
  703. end;
  704. AS_LPAREN:
  705. BuildReference(oper,is64bit);
  706. AS_ID: { only a variable is allowed ... }
  707. Begin
  708. ReadSym(oper,is64bit);
  709. case actasmtoken of
  710. AS_end,
  711. AS_SEPARATOR,
  712. AS_COMMA: ;
  713. AS_LPAREN:
  714. BuildReference(oper,is64bit);
  715. else
  716. Begin
  717. Message(asmr_e_invalid_reference_syntax);
  718. Consume(actasmtoken);
  719. end;
  720. end; {end case }
  721. end;
  722. else
  723. MaybeBuildReference:=false;
  724. end; { end case }
  725. end;
  726. function parsereg: tregister;
  727. var
  728. subreg: tsubregister;
  729. begin
  730. result:=actasmregister;
  731. Consume(AS_REGISTER);
  732. if (actasmtoken=AS_ID) and
  733. (actasmpattern[1]='.') then
  734. begin
  735. subreg:=ParseArrangementSpecifier(upper(actasmpattern));
  736. if (subreg<>R_SUBNONE) and
  737. (getregtype(result)=R_MMREGISTER) and
  738. ((actinsmmsubreg=R_SUBNONE) or
  739. (actinsmmsubreg=subreg)) then
  740. begin
  741. setsubreg(result,subreg);
  742. { they all have to be the same }
  743. actinsmmsubreg:=subreg;
  744. end
  745. else
  746. Message1(asmr_e_invalid_arrangement,actasmpattern);
  747. Consume(AS_ID);
  748. end
  749. else if (getregtype(result)=R_MMREGISTER) then
  750. begin
  751. if actinsmmsubreg<>R_SUBNONE then
  752. begin
  753. if (getsubreg(result)=R_SUBNONE) or
  754. (getsubreg(result)=actinsmmsubreg) then
  755. setsubreg(result,actinsmmsubreg)
  756. else
  757. Message1(asmr_e_invalid_arrangement,actasmpattern);
  758. end
  759. else if getsubreg(result)=R_SUBNONE then
  760. { Vxx without an arrangement is invalid, use Qxx to specify the entire 128 bits}
  761. Message1(asmr_e_invalid_arrangement,'');
  762. end;
  763. end;
  764. var
  765. tempreg: tregister;
  766. hl: tasmlabel;
  767. icond: tasmcond;
  768. regindex: byte;
  769. Begin
  770. expr:='';
  771. case actasmtoken of
  772. AS_LBRACKET: { Memory reference or constant expression }
  773. Begin
  774. oper.InitRef;
  775. BuildReference(oper,is64bit);
  776. end;
  777. AS_LSBRACKET: { register set }
  778. begin
  779. consume(AS_LSBRACKET);
  780. oper.opr.typ:=OPR_REGSET;
  781. oper.opr.basereg:=parsereg;
  782. oper.opr.nregs:=1;
  783. while (actasmtoken<>AS_RSBRACKET) and (oper.opr.nregs<4) do
  784. begin
  785. if actasmtoken=AS_MINUS then
  786. begin
  787. consume(AS_MINUS);
  788. tempreg:=parsereg;
  789. if (getsupreg(tempreg)-getsupreg(oper.opr.basereg))>=4 then
  790. Message(asmr_e_a64_regset_too_large);
  791. oper.opr.nregs:=getsupreg(tempreg)-getsupreg(oper.opr.basereg)+1;
  792. if actasmtoken<>AS_COMMA then
  793. break;
  794. end;
  795. if actasmtoken=AS_COMMA then
  796. begin
  797. consume(AS_COMMA);
  798. tempreg:=parsereg;
  799. if (getsupreg(tempreg)-getsupreg(oper.opr.basereg))>=4 then
  800. Message(asmr_e_a64_regset_too_large);
  801. if getsupreg(tempreg)<>((getsupreg(oper.opr.basereg)+oper.opr.nregs) mod 32) then
  802. Message(asmr_e_a64_invalid_regset);
  803. inc(oper.opr.nregs);
  804. end
  805. else
  806. break;
  807. end;
  808. consume(AS_RSBRACKET);
  809. if actasmtoken=AS_LBRACKET then
  810. begin
  811. consume(AS_LBRACKET);
  812. oper.opr.regsetindex:=ParseRegIndex(actasmpattern);
  813. consume(AS_INTNUM);
  814. consume(AS_RBRACKET);
  815. end
  816. else
  817. oper.opr.regsetindex:=255;
  818. if not(actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  819. Message(asmr_e_syn_operand);
  820. end;
  821. AS_HASH: { Constant expression }
  822. Begin
  823. Consume(AS_HASH);
  824. BuildConstantOperand(oper);
  825. end;
  826. (*
  827. AS_INTNUM,
  828. AS_MINUS,
  829. AS_PLUS:
  830. Begin
  831. { Constant memory offset }
  832. { This must absolutely be followed by ( }
  833. oper.InitRef;
  834. oper.opr.ref.offset:=BuildConstExpression(True,False);
  835. if actasmtoken<>AS_LPAREN then
  836. begin
  837. ofs:=oper.opr.ref.offset;
  838. BuildConstantOperand(oper);
  839. inc(oper.opr.val,ofs);
  840. end
  841. else
  842. BuildReference(oper,is64bit);
  843. end;
  844. *)
  845. AS_ID: { A constant expression, or a Variable ref. }
  846. Begin
  847. { Condition code? }
  848. icond:=ToConditionCode(actasmpattern,true);
  849. if icond<>C_None then
  850. begin
  851. oper.opr.typ:=OPR_COND;
  852. oper.opr.cc:=icond;
  853. consume(AS_ID);
  854. end
  855. else
  856. { Local Label ? }
  857. if is_locallabel(actasmpattern) then
  858. begin
  859. CreateLocalLabel(actasmpattern,hl,false);
  860. Consume(AS_ID);
  861. AddLabelOperand(hl);
  862. end
  863. else
  864. { Check for label }
  865. if SearchLabel(actasmpattern,hl,false) then
  866. begin
  867. Consume(AS_ID);
  868. AddLabelOperand(hl);
  869. end
  870. else
  871. { probably a variable or normal expression }
  872. { or a procedure (such as in CALL ID) }
  873. begin
  874. { is it a constant ? }
  875. if SearchIConstant(actasmpattern,l) then
  876. begin
  877. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  878. Message(asmr_e_invalid_operand_type);
  879. BuildConstantOperand(oper);
  880. end
  881. else
  882. begin
  883. expr:=actasmpattern;
  884. Consume(AS_ID);
  885. { typecasting? }
  886. if (actasmtoken=AS_LPAREN) and
  887. SearchType(expr,typesize) then
  888. begin
  889. oper.hastype:=true;
  890. Consume(AS_LPAREN);
  891. BuildOperand(oper,is64bit);
  892. Consume(AS_RPAREN);
  893. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  894. oper.SetSize(typesize,true);
  895. end
  896. else
  897. begin
  898. if not(oper.SetupVar(expr,false)) then
  899. Begin
  900. { look for special symbols ... }
  901. if expr= '__HIGH' then
  902. begin
  903. consume(AS_LPAREN);
  904. if not oper.setupvar('high'+actasmpattern,false) then
  905. Message1(sym_e_unknown_id,'high'+actasmpattern);
  906. consume(AS_ID);
  907. consume(AS_RPAREN);
  908. end
  909. else
  910. if expr = '__RESULT' then
  911. oper.SetUpResult
  912. else
  913. if expr = '__SELF' then
  914. oper.SetupSelf
  915. else
  916. if expr = '__OLDEBP' then
  917. oper.SetupOldEBP
  918. else
  919. Message1(sym_e_unknown_id,expr);
  920. end
  921. else if oper.opr.typ<>OPR_LOCAL then
  922. begin
  923. oper.InitRef;
  924. MaybeAddGotAddrMode;
  925. end;
  926. end;
  927. end;
  928. if actasmtoken=AS_DOT then
  929. MaybeRecordOffset;
  930. { add a constant expression? }
  931. if (actasmtoken=AS_PLUS) then
  932. begin
  933. l:=BuildConstExpression(true,false);
  934. case oper.opr.typ of
  935. OPR_CONSTANT :
  936. inc(oper.opr.val,l);
  937. OPR_LOCAL :
  938. inc(oper.opr.localsymofs,l);
  939. OPR_REFERENCE :
  940. inc(oper.opr.ref.offset,l);
  941. else
  942. internalerror(2003092005);
  943. end;
  944. end
  945. end;
  946. { Do we have a indexing reference, then parse it also }
  947. if actasmtoken=AS_LPAREN then
  948. BuildReference(oper,is64bit);
  949. end;
  950. { Register, a variable reference or a constant reference }
  951. AS_REGISTER:
  952. Begin
  953. { save the type of register used. }
  954. tempreg:=parsereg;
  955. regindex:=255;
  956. if (getregtype(tempreg)=R_MMREGISTER) and
  957. (actasmtoken=AS_LBRACKET) then
  958. begin
  959. consume(AS_LBRACKET);
  960. regindex:=ParseRegIndex(actasmpattern);
  961. consume(AS_INTNUM);
  962. consume(AS_RBRACKET);
  963. end;
  964. if actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA] then
  965. begin
  966. if (oper.opr.typ<>OPR_NONE) then
  967. Message(asmr_e_invalid_operand_type);
  968. if regindex=255 then
  969. begin
  970. oper.opr.typ:=OPR_REGISTER;
  971. oper.opr.reg:=tempreg;
  972. end
  973. else
  974. begin
  975. oper.opr.typ:=OPR_INDEXEDREG;
  976. oper.opr.indexedreg:=tempreg;
  977. oper.opr.regindex:=regindex;
  978. end;
  979. end
  980. else
  981. Message(asmr_e_syn_operand);
  982. end;
  983. AS_end,
  984. AS_SEPARATOR,
  985. AS_COMMA: ;
  986. else
  987. Begin
  988. Message(asmr_e_syn_operand);
  989. Consume(actasmtoken);
  990. end;
  991. end; { end case }
  992. end;
  993. {*****************************************************************************
  994. taarch64attreader
  995. *****************************************************************************}
  996. procedure taarch64attreader.BuildOpCode(instr: taarch64instruction);
  997. var
  998. operandnum : longint;
  999. Begin
  1000. { opcode }
  1001. if (actasmtoken<>AS_OPCODE) then
  1002. Begin
  1003. Message(asmr_e_invalid_or_missing_opcode);
  1004. RecoverConsume(true);
  1005. exit;
  1006. end;
  1007. { Fill the instr object with the current state }
  1008. with instr do
  1009. begin
  1010. Opcode:=ActOpcode;
  1011. condition:=ActCondition;
  1012. oppostfix:=actoppostfix;
  1013. end;
  1014. Consume(AS_OPCODE);
  1015. { We are reading operands, so opcode will be an AS_ID }
  1016. operandnum:=1;
  1017. { Zero operand opcode ? }
  1018. if actasmtoken in [AS_SEPARATOR,AS_end] then
  1019. begin
  1020. instr.Ops:=0;
  1021. exit;
  1022. end;
  1023. { Read the operands }
  1024. repeat
  1025. case actasmtoken of
  1026. AS_COMMA: { Operand delimiter }
  1027. Begin
  1028. { operandnum and not operandnum+1, because tinstruction is
  1029. one-based and taicpu is zero-based)
  1030. }
  1031. if can_be_shifter_operand(instr.opcode,operandnum) then
  1032. begin
  1033. Consume(AS_COMMA);
  1034. if not TryBuildShifterOp(instr,operandnum+1) then
  1035. Message(asmr_e_illegal_shifterop_syntax);
  1036. Inc(operandnum);
  1037. end
  1038. else
  1039. begin
  1040. if operandnum>Max_Operands then
  1041. Message(asmr_e_too_many_operands)
  1042. else
  1043. Inc(operandnum);
  1044. Consume(AS_COMMA);
  1045. end;
  1046. end;
  1047. AS_SEPARATOR,
  1048. AS_end : { End of asm operands for this opcode }
  1049. begin
  1050. break;
  1051. end;
  1052. else
  1053. begin
  1054. BuildOperand(taarch64operand(instr.operands[operandnum]),instr.Is64bit);
  1055. instr.Ops:=operandnum;
  1056. if instr.operands[operandnum].opr.typ=OPR_REFERENCE then
  1057. if simple_ref_type(instr.opcode,instr.cgsize,instr.oppostfix,instr.operands[operandnum].opr.ref)<>sr_simple then
  1058. Message(asmr_e_invalid_reference_syntax);
  1059. ;
  1060. end;
  1061. end; { end case }
  1062. until false;
  1063. end;
  1064. function taarch64attreader.is_asmopcode(const s: string):boolean;
  1065. const
  1066. { sorted by length so longer postfixes will match first }
  1067. postfix2strsorted : array[1..7] of string[3] = (
  1068. 'SB','SH','SW',
  1069. 'B','H','W',
  1070. 'S');
  1071. postfixsorted : array[1..7] of TOpPostfix = (
  1072. PF_SB,PF_SH,PF_SW,
  1073. PF_B,PF_H,PF_W,
  1074. PF_S);
  1075. { store replicate }
  1076. ldst14: array[boolean,boolean,'1'..'4'] of tasmop =
  1077. (((A_LD1,A_LD2,A_LD3,A_LD4),
  1078. (A_LD1R,A_LD2R,A_LD3R,A_LD4R)),
  1079. ((A_ST1,A_ST2,A_ST3,A_ST4),
  1080. (A_NONE,A_NONE,A_NONE,A_NONE)));
  1081. var
  1082. j : longint;
  1083. hs : string;
  1084. maxlen : longint;
  1085. Begin
  1086. { making s a value parameter would break other assembler readers }
  1087. hs:=s;
  1088. is_asmopcode:=false;
  1089. { clear opcode }
  1090. actopcode:=A_None;
  1091. actcondition:=C_None;
  1092. { b.cond ? }
  1093. if (length(hs)=4) and
  1094. (hs[1]='B') and
  1095. (hs[2]='.') then
  1096. begin
  1097. actopcode:=A_B;
  1098. actasmtoken:=AS_OPCODE;
  1099. actcondition:=ToConditionCode(copy(hs,3,length(actasmpattern)-2),false);
  1100. if actcondition<>C_None then
  1101. is_asmopcode:=true;
  1102. exit;
  1103. end;
  1104. (* ldN(r)/stN.size ? (shorthand for "ldN(r)/stN { Vx.size, Vy.size } ..."
  1105. supported by clang and possibly gas *)
  1106. actinsmmsubreg:=R_SUBNONE;
  1107. if (length(s)>=5) and
  1108. (((hs[1]='L') and
  1109. (hs[2]='D')) or
  1110. ((hs[1]='S') and
  1111. (hs[2]='T'))) and
  1112. (hs[3] in ['1'..'4']) and
  1113. ((hs[4]='.') or
  1114. ((hs[4]='R') and
  1115. (hs[5]='.'))) then
  1116. begin
  1117. actinsmmsubreg:=ParseArrangementSpecifier(copy(hs,4+ord(hs[4]='R'),255));
  1118. if actinsmmsubreg=R_SUBNONE then
  1119. exit;
  1120. actopcode:=ldst14[hs[1]='S',hs[4]='R',hs[3]];
  1121. actasmtoken:=AS_OPCODE;
  1122. if actopcode<>A_NONE then
  1123. is_asmopcode:=true;
  1124. exit;
  1125. end;
  1126. maxlen:=max(length(hs),7);
  1127. actopcode:=A_NONE;
  1128. for j:=maxlen downto 1 do
  1129. begin
  1130. actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j))));
  1131. if actopcode<>A_NONE then
  1132. begin
  1133. actasmtoken:=AS_OPCODE;
  1134. { strip op code }
  1135. delete(hs,1,j);
  1136. break;
  1137. end;
  1138. end;
  1139. if actopcode=A_NONE then
  1140. exit;
  1141. { check for postfix }
  1142. if length(hs)>0 then
  1143. begin
  1144. for j:=low(postfixsorted) to high(postfixsorted) do
  1145. begin
  1146. if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
  1147. begin
  1148. actoppostfix:=postfixsorted[j];
  1149. { strip postfix }
  1150. delete(hs,1,length(postfix2strsorted[j]));
  1151. break;
  1152. end;
  1153. end;
  1154. end;
  1155. { if we stripped all postfixes, it's a valid opcode }
  1156. is_asmopcode:=length(hs)=0;
  1157. end;
  1158. procedure taarch64attreader.ConvertCalljmp(instr: taarch64instruction);
  1159. var
  1160. newopr : toprrec;
  1161. begin
  1162. if instr.Operands[1].opr.typ=OPR_REFERENCE then
  1163. begin
  1164. newopr.typ:=OPR_SYMBOL;
  1165. newopr.symbol:=instr.Operands[1].opr.ref.symbol;
  1166. newopr.symofs:=instr.Operands[1].opr.ref.offset;
  1167. if (instr.Operands[1].opr.ref.base<>NR_NO) or
  1168. (instr.Operands[1].opr.ref.index<>NR_NO) or
  1169. (instr.Operands[1].opr.ref.refaddr<>addr_pic) then
  1170. Message(asmr_e_syn_operand);
  1171. instr.Operands[1].opr:=newopr;
  1172. end;
  1173. end;
  1174. procedure taarch64attreader.handleopcode;
  1175. var
  1176. instr: taarch64instruction;
  1177. begin
  1178. instr:=taarch64instruction.Create(taarch64operand);
  1179. BuildOpcode(instr);
  1180. if is_calljmp(instr.opcode) then
  1181. ConvertCalljmp(instr);
  1182. {
  1183. instr.AddReferenceSizes;
  1184. instr.SetInstructionOpsize;
  1185. instr.CheckOperandSizes;
  1186. }
  1187. instr.ConcatInstruction(curlist);
  1188. instr.Free;
  1189. actoppostfix:=PF_None;
  1190. end;
  1191. procedure taarch64attreader.handletargetdirective;
  1192. function maxoffset(ash:TAsmSehDirective):aint;
  1193. begin
  1194. case ash of
  1195. ash_savefplr,
  1196. ash_saveregp,
  1197. ash_savereg,
  1198. ash_savefregp,
  1199. ash_savefreg:
  1200. result:=504;
  1201. ash_savefplr_x,
  1202. ash_saveregp_x,
  1203. ash_savefregp_x:
  1204. result:=-512;
  1205. ash_savereg_x,
  1206. ash_savefreg_x:
  1207. result:=-256;
  1208. ash_addfp:
  1209. result:=2040;
  1210. else
  1211. internalerror(2020041204);
  1212. end;
  1213. end;
  1214. procedure add_reg_with_offset(ash:TAsmSehDirective;hreg:tregister;hnum:aint;neg:boolean);
  1215. begin
  1216. if (neg and ((hnum>0) or (hnum<maxoffset(ash)) or (((-hnum) and $7)<>0))) or
  1217. (not neg and ((hnum<0) or (hnum>maxoffset(ash)) or ((hnum and $7)<>0))) then
  1218. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[actsehdirective])
  1219. else
  1220. begin
  1221. if neg then
  1222. hnum:=-hnum;
  1223. if hreg=NR_NO then
  1224. curlist.concat(cai_seh_directive.create_offset(actsehdirective,hnum))
  1225. else
  1226. curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
  1227. end;
  1228. end;
  1229. var
  1230. hreg,
  1231. hreg2 : TRegister;
  1232. hnum : aint;
  1233. flags : integer;
  1234. ai : tai_seh_directive;
  1235. hs : string;
  1236. err : boolean;
  1237. begin
  1238. if actasmtoken<>AS_TARGET_DIRECTIVE then
  1239. InternalError(2020033102);
  1240. Consume(AS_TARGET_DIRECTIVE);
  1241. Include(current_procinfo.flags,pi_has_unwind_info);
  1242. case actsehdirective of
  1243. ash_nop,
  1244. ash_setfp,
  1245. ash_endprologue,
  1246. ash_handlerdata:
  1247. curlist.concat(cai_seh_directive.create(actsehdirective));
  1248. ash_handler:
  1249. begin
  1250. hs:=actasmpattern;
  1251. Consume(AS_ID);
  1252. flags:=0;
  1253. err:=false;
  1254. while actasmtoken=AS_COMMA do
  1255. begin
  1256. Consume(AS_COMMA);
  1257. if actasmtoken=AS_AT then
  1258. begin
  1259. Consume(AS_AT);
  1260. if actasmtoken=AS_ID then
  1261. begin
  1262. uppervar(actasmpattern);
  1263. if actasmpattern='EXCEPT' then
  1264. flags:=flags or 1
  1265. else if actasmpattern='UNWIND' then
  1266. flags:=flags or 2
  1267. else
  1268. err:=true;
  1269. Consume(AS_ID);
  1270. end
  1271. else
  1272. err:=true;
  1273. end
  1274. else
  1275. err:=true;
  1276. if err then
  1277. begin
  1278. Message(asmr_e_syntax_error);
  1279. RecoverConsume(false);
  1280. exit;
  1281. end;
  1282. end;
  1283. ai:=cai_seh_directive.create_name(ash_handler,hs);
  1284. ai.data.flags:=flags;
  1285. curlist.concat(ai);
  1286. end;
  1287. ash_savefplr,
  1288. ash_savefplr_x:
  1289. begin
  1290. hnum:=BuildConstExpression(false,false);
  1291. add_reg_with_offset(actsehdirective,NR_NO,hnum,actsehdirective=ash_savefplr_x);
  1292. end;
  1293. ash_savereg,
  1294. ash_savereg_x:
  1295. begin
  1296. hreg:=actasmregister;
  1297. Consume(AS_REGISTER);
  1298. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<19) then
  1299. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1300. Consume(AS_COMMA);
  1301. hnum:=BuildConstExpression(false,false);
  1302. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_savereg_x);
  1303. end;
  1304. ash_saveregp,
  1305. ash_saveregp_x:
  1306. begin
  1307. hreg:=actasmregister;
  1308. consume(AS_REGISTER);
  1309. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<19) then
  1310. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1311. consume(AS_COMMA);
  1312. hreg2:=actasmregister;
  1313. consume(AS_REGISTER);
  1314. if (getregtype(hreg2)<>R_INTREGISTER) or (getsubreg(hreg2)<>R_SUBWHOLE) or (getsupreg(hreg2)<>getsupreg(hreg)+1) then
  1315. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1316. consume(AS_COMMA);
  1317. hnum:=BuildConstExpression(false,false);
  1318. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_saveregp_x);
  1319. end;
  1320. ash_savefreg,
  1321. ash_savefreg_x:
  1322. begin
  1323. hreg:=actasmregister;
  1324. Consume(AS_REGISTER);
  1325. if (getregtype(hreg)<>R_MMREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<8) then
  1326. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1327. Consume(AS_COMMA);
  1328. hnum:=BuildConstExpression(false,false);
  1329. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_savefreg_x);
  1330. end;
  1331. ash_savefregp,
  1332. ash_savefregp_x:
  1333. begin
  1334. hreg:=actasmregister;
  1335. consume(AS_REGISTER);
  1336. if (getregtype(hreg)<>R_MMREGISTER) or (getsubreg(hreg)<>R_SUBWHOLE) or (getsupreg(hreg)<8) then
  1337. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1338. consume(AS_COMMA);
  1339. hreg2:=actasmregister;
  1340. consume(AS_REGISTER);
  1341. if (getregtype(hreg2)<>R_MMREGISTER) or (getsubreg(hreg2)<>R_SUBWHOLE) or (getsupreg(hreg2)<>getsupreg(hreg)+1) then
  1342. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  1343. consume(AS_COMMA);
  1344. hnum:=BuildConstExpression(false,false);
  1345. add_reg_with_offset(actsehdirective,hreg,hnum,actsehdirective=ash_savefregp_x);
  1346. end;
  1347. ash_stackalloc:
  1348. begin
  1349. hnum:=BuildConstExpression(false,false);
  1350. if (hnum<0) or (hnum>$FFFFFF) or ((hnum and 7)<>0) then
  1351. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_stackalloc])
  1352. else
  1353. curlist.concat(cai_seh_directive.create_offset(ash_stackalloc,hnum));
  1354. end;
  1355. else
  1356. InternalError(2020033103);
  1357. end;
  1358. if actasmtoken<>AS_SEPARATOR then
  1359. Consume(AS_SEPARATOR);
  1360. end;
  1361. {*****************************************************************************
  1362. Initialize
  1363. *****************************************************************************}
  1364. const
  1365. asmmode_arm_att_info : tasmmodeinfo =
  1366. (
  1367. id : asmmode_arm_gas;
  1368. idtxt : 'GAS';
  1369. casmreader : taarch64attreader;
  1370. );
  1371. asmmode_arm_standard_info : tasmmodeinfo =
  1372. (
  1373. id : asmmode_standard;
  1374. idtxt : 'STANDARD';
  1375. casmreader : taarch64attreader;
  1376. );
  1377. initialization
  1378. RegisterAsmMode(asmmode_arm_att_info);
  1379. RegisterAsmMode(asmmode_arm_standard_info);
  1380. end.