rarvgas.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. {
  2. Copyright (c) 2019 by Jeppe Johansen
  3. Does the parsing for the RISC-V GNU AS styled inline assembler.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit rarvgas;
  18. {$I fpcdefs.inc}
  19. interface
  20. uses
  21. raatt,rarv,
  22. cpubase;
  23. type
  24. trvgasreader = class(tattreader)
  25. actmemoryordering: TMemoryOrdering;
  26. function is_register(const s: string): boolean; override;
  27. function is_asmopcode(const s: string):boolean;override;
  28. procedure handleopcode;override;
  29. procedure BuildReference(oper : trvoperand);
  30. procedure BuildOperand(oper : trvoperand);
  31. procedure BuildOpCode(instr : trvinstruction);
  32. procedure ReadAt(oper : trvoperand);
  33. procedure ReadSym(oper : trvoperand);
  34. function is_targetdirective(const s: string): boolean; override;
  35. procedure HandleTargetDirective; override;
  36. end;
  37. implementation
  38. uses
  39. { helpers }
  40. cutils,
  41. { global }
  42. globtype,globals,verbose,
  43. systems,
  44. { aasm }
  45. aasmbase,aasmtai,aasmdata,aasmcpu,
  46. { symtable }
  47. symconst,symsym,symdef,
  48. { parser }
  49. procinfo,
  50. rabase,rautils,
  51. cgbase,cgobj,cgrv
  52. ;
  53. function trvgasreader.is_targetdirective(const s: string): boolean;
  54. begin
  55. case s of
  56. '.option':
  57. result:=true
  58. else
  59. Result:=inherited is_targetdirective(s);
  60. end;
  61. end;
  62. procedure trvgasreader.HandleTargetDirective;
  63. var
  64. id: string;
  65. begin
  66. case actasmpattern of
  67. '.option':
  68. begin
  69. consume(AS_TARGET_DIRECTIVE);
  70. id:=actasmpattern;
  71. Consume(AS_ID);
  72. curList.concat(tai_directive.create(asd_option, lower(id)));
  73. end
  74. else
  75. inherited HandleTargetDirective;
  76. end;
  77. end;
  78. procedure trvgasreader.ReadSym(oper : trvoperand);
  79. var
  80. tempstr, mangledname : string;
  81. typesize,l,k : TCGInt;
  82. begin
  83. tempstr:=actasmpattern;
  84. Consume(AS_ID);
  85. { typecasting? }
  86. if (actasmtoken=AS_LPAREN) and
  87. SearchType(tempstr,typesize) then
  88. begin
  89. oper.hastype:=true;
  90. Consume(AS_LPAREN);
  91. BuildOperand(oper);
  92. Consume(AS_RPAREN);
  93. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  94. oper.SetSize(typesize,true);
  95. end
  96. else
  97. if not oper.SetupVar(tempstr,false) then
  98. Message1(sym_e_unknown_id,tempstr);
  99. { record.field ? }
  100. if actasmtoken=AS_DOT then
  101. begin
  102. BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
  103. if (mangledname<>'') then
  104. Message(asmr_e_invalid_reference_syntax);
  105. inc(oper.opr.ref.offset,l);
  106. end;
  107. end;
  108. procedure trvgasreader.ReadAt(oper : trvoperand);
  109. begin
  110. { check for ...@ }
  111. if actasmtoken=AS_AT then
  112. begin
  113. if (oper.opr.ref.symbol=nil) and
  114. (oper.opr.ref.offset = 0) then
  115. Message(asmr_e_invalid_reference_syntax);
  116. Consume(AS_AT);
  117. if actasmtoken=AS_ID then
  118. begin
  119. {if upper(actasmpattern)='L' then
  120. oper.opr.ref.refaddr:=addr_low
  121. else if upper(actasmpattern)='HI' then
  122. oper.opr.ref.refaddr:=addr_high
  123. else if upper(actasmpattern)='HA' then
  124. oper.opr.ref.refaddr:=addr_higha
  125. else}
  126. Message(asmr_e_invalid_reference_syntax);
  127. Consume(AS_ID);
  128. end
  129. else
  130. Message(asmr_e_invalid_reference_syntax);
  131. end;
  132. end;
  133. procedure trvgasreader.BuildReference(oper: trvoperand);
  134. procedure Consume_RParen;
  135. begin
  136. if actasmtoken <> AS_RPAREN then
  137. Begin
  138. Message(asmr_e_invalid_reference_syntax);
  139. RecoverConsume(true);
  140. end
  141. else
  142. begin
  143. Consume(AS_RPAREN);
  144. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
  145. Begin
  146. Message(asmr_e_invalid_reference_syntax);
  147. RecoverConsume(true);
  148. end;
  149. end;
  150. end;
  151. var
  152. l : TCGInt;
  153. relsym: string;
  154. asmsymtyp: tasmsymtype;
  155. isflags: tindsymflags;
  156. begin
  157. Consume(AS_LPAREN);
  158. Case actasmtoken of
  159. AS_INTNUM,
  160. AS_MINUS,
  161. AS_PLUS:
  162. Begin
  163. { offset(offset) is invalid }
  164. If oper.opr.Ref.Offset <> 0 Then
  165. Begin
  166. Message(asmr_e_invalid_reference_syntax);
  167. RecoverConsume(true);
  168. End
  169. Else
  170. Begin
  171. oper.opr.Ref.Offset:=BuildConstExpression(false,true);
  172. Consume(AS_RPAREN);
  173. if actasmtoken=AS_AT then
  174. ReadAt(oper);
  175. end;
  176. exit;
  177. End;
  178. AS_REGISTER: { (reg ... }
  179. Begin
  180. if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
  181. ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
  182. message(asmr_e_cannot_index_relative_var);
  183. oper.opr.ref.base:=actasmregister;
  184. Consume(AS_REGISTER);
  185. Consume_RParen;
  186. end; {end case }
  187. AS_ID:
  188. Begin
  189. ReadSym(oper);
  190. case actasmtoken of
  191. AS_PLUS:
  192. begin
  193. { add a constant expression? }
  194. l:=BuildConstExpression(true,true);
  195. case oper.opr.typ of
  196. OPR_CONSTANT :
  197. inc(oper.opr.val,l);
  198. OPR_LOCAL :
  199. inc(oper.opr.localsymofs,l);
  200. OPR_REFERENCE :
  201. inc(oper.opr.ref.offset,l);
  202. else
  203. internalerror(2003092016);
  204. end;
  205. end;
  206. AS_MINUS:
  207. begin
  208. Consume(AS_MINUS);
  209. BuildConstSymbolExpression(false,true,false,l,relsym,asmsymtyp);
  210. if (relsym<>'') then
  211. begin
  212. if (oper.opr.typ = OPR_REFERENCE) then
  213. oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym,AT_DATA)
  214. else
  215. begin
  216. Message(asmr_e_invalid_reference_syntax);
  217. RecoverConsume(false);
  218. end
  219. end
  220. else
  221. begin
  222. case oper.opr.typ of
  223. OPR_CONSTANT :
  224. dec(oper.opr.val,l);
  225. OPR_LOCAL :
  226. dec(oper.opr.localsymofs,l);
  227. OPR_REFERENCE :
  228. dec(oper.opr.ref.offset,l);
  229. else
  230. internalerror(2007092601);
  231. end;
  232. end;
  233. end;
  234. else
  235. ;
  236. end;
  237. Consume(AS_RPAREN);
  238. if actasmtoken=AS_AT then
  239. ReadAt(oper);
  240. End;
  241. AS_COMMA: { (, ... can either be scaling, or index }
  242. Begin
  243. Consume(AS_COMMA);
  244. { Index }
  245. if (actasmtoken=AS_REGISTER) then
  246. Begin
  247. oper.opr.ref.index:=actasmregister;
  248. Consume(AS_REGISTER);
  249. { check for scaling ... }
  250. Consume_RParen;
  251. end
  252. else
  253. begin
  254. Message(asmr_e_invalid_reference_syntax);
  255. RecoverConsume(false);
  256. end;
  257. end;
  258. else
  259. Begin
  260. Message(asmr_e_invalid_reference_syntax);
  261. RecoverConsume(false);
  262. end;
  263. end;
  264. end;
  265. procedure trvgasreader.BuildOperand(oper: trvoperand);
  266. var
  267. expr : string;
  268. typesize,l : TCGInt;
  269. procedure AddLabelOperand(hl:tasmlabel);
  270. begin
  271. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  272. is_calljmp(actopcode) then
  273. begin
  274. oper.opr.typ:=OPR_SYMBOL;
  275. oper.opr.symbol:=hl;
  276. end
  277. else
  278. begin
  279. oper.InitRef;
  280. oper.opr.ref.symbol:=hl;
  281. end;
  282. end;
  283. procedure MaybeRecordOffset;
  284. var
  285. mangledname: string;
  286. hasdot : boolean;
  287. l,
  288. toffset,
  289. tsize : TCGInt;
  290. begin
  291. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  292. exit;
  293. l:=0;
  294. hasdot:=(actasmtoken=AS_DOT);
  295. if hasdot then
  296. begin
  297. if expr<>'' then
  298. begin
  299. BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
  300. if (oper.opr.typ<>OPR_CONSTANT) and
  301. (mangledname<>'') then
  302. Message(asmr_e_wrong_sym_type);
  303. inc(l,toffset);
  304. oper.SetSize(tsize,true);
  305. end;
  306. end;
  307. if actasmtoken in [AS_PLUS,AS_MINUS] then
  308. inc(l,BuildConstExpression(true,false));
  309. case oper.opr.typ of
  310. OPR_LOCAL :
  311. begin
  312. { don't allow direct access to fields of parameters, because that
  313. will generate buggy code. Allow it only for explicit typecasting }
  314. if hasdot and
  315. (not oper.hastype) and
  316. (tabstractvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
  317. (current_procinfo.procdef.proccalloption<>pocall_register) then
  318. Message(asmr_e_cannot_access_field_directly_for_parameters);
  319. inc(oper.opr.localsymofs,l)
  320. end;
  321. OPR_CONSTANT :
  322. if (mangledname<>'') then
  323. begin
  324. if (oper.opr.val<>0) then
  325. Message(asmr_e_wrong_sym_type);
  326. oper.opr.typ:=OPR_SYMBOL;
  327. oper.opr.symbol:=current_asmdata.DefineAsmSymbol(mangledname,AB_EXTERNAL,AT_FUNCTION,voidcodepointertype);
  328. end
  329. else
  330. inc(oper.opr.val,l);
  331. OPR_REFERENCE :
  332. inc(oper.opr.ref.offset,l);
  333. OPR_SYMBOL:
  334. Message(asmr_e_invalid_symbol_ref);
  335. else
  336. internalerror(200309221);
  337. end;
  338. end;
  339. function MaybeBuildReference:boolean;
  340. { Try to create a reference, if not a reference is found then false
  341. is returned }
  342. begin
  343. MaybeBuildReference:=true;
  344. case actasmtoken of
  345. AS_INTNUM,
  346. AS_MINUS,
  347. AS_PLUS:
  348. Begin
  349. oper.opr.ref.offset:=BuildConstExpression(True,False);
  350. if actasmtoken<>AS_LPAREN then
  351. Message(asmr_e_invalid_reference_syntax)
  352. else
  353. BuildReference(oper);
  354. end;
  355. AS_LPAREN:
  356. BuildReference(oper);
  357. AS_ID: { only a variable is allowed ... }
  358. Begin
  359. ReadSym(oper);
  360. case actasmtoken of
  361. AS_END,
  362. AS_SEPARATOR,
  363. AS_COMMA: ;
  364. AS_LPAREN:
  365. BuildReference(oper);
  366. else
  367. Begin
  368. Message(asmr_e_invalid_reference_syntax);
  369. Consume(actasmtoken);
  370. end;
  371. end; {end case }
  372. end;
  373. else
  374. MaybeBuildReference:=false;
  375. end; { end case }
  376. end;
  377. function is_fenceflag(hs : string): boolean;
  378. var
  379. i: longint;
  380. flags: TFenceFlags;
  381. begin
  382. is_fenceflag := false;
  383. flags:=[];
  384. hs:=lower(hs);
  385. if (actopcode in [A_FENCE]) and (length(hs) >= 1) then
  386. begin
  387. for i:=1 to length(hs) do
  388. begin
  389. case hs[i] of
  390. 'i':
  391. Include(flags,ffi);
  392. 'o':
  393. Include(flags,ffo);
  394. 'r':
  395. Include(flags,ffr);
  396. 'w':
  397. Include(flags,ffw);
  398. else
  399. exit;
  400. end;
  401. end;
  402. oper.opr.typ := OPR_FENCEFLAGS;
  403. oper.opr.fenceflags := flags;
  404. exit(true);
  405. end;
  406. end;
  407. var
  408. tempreg : tregister;
  409. hl : tasmlabel;
  410. ofs : aint;
  411. refaddr: trefaddr;
  412. entered_paren: Boolean;
  413. Begin
  414. expr:='';
  415. entered_paren:=false;
  416. refaddr:=addr_full;
  417. if actasmtoken=AS_MOD then
  418. begin
  419. consume(AS_MOD);
  420. if actasmtoken<>AS_ID then
  421. begin
  422. Message(asmr_e_invalid_reference_syntax);
  423. RecoverConsume(false);
  424. end
  425. else
  426. begin
  427. if lower(actasmpattern)='pcrel_hi' then
  428. refaddr:=addr_pcrel_hi20
  429. else if lower(actasmpattern)='pcrel_lo' then
  430. refaddr:=addr_pcrel_lo12
  431. else if lower(actasmpattern)='hi' then
  432. refaddr:=addr_hi20
  433. else if lower(actasmpattern)='lo' then
  434. refaddr:=addr_lo12
  435. else
  436. begin
  437. Message(asmr_e_invalid_reference_syntax);
  438. RecoverConsume(false);
  439. end;
  440. consume(AS_ID);
  441. consume(AS_LPAREN);
  442. entered_paren:=true;
  443. end;
  444. end;
  445. case actasmtoken of
  446. AS_LPAREN: { Memory reference or constant expression }
  447. Begin
  448. oper.InitRef;
  449. BuildReference(oper);
  450. end;
  451. AS_INTNUM,
  452. AS_MINUS,
  453. AS_PLUS:
  454. Begin
  455. { Constant memory offset }
  456. { This must absolutely be followed by ( }
  457. oper.InitRef;
  458. oper.opr.ref.offset:=BuildConstExpression(True,False);
  459. if actasmtoken<>AS_LPAREN then
  460. begin
  461. ofs:=oper.opr.ref.offset;
  462. BuildConstantOperand(oper);
  463. inc(oper.opr.val,ofs);
  464. end
  465. else
  466. BuildReference(oper);
  467. end;
  468. AS_DOT,
  469. AS_ID: { A constant expression, or a Variable ref. }
  470. Begin
  471. if is_fenceflag(actasmpattern) then
  472. begin
  473. consume(AS_ID);
  474. end
  475. else
  476. { Local Label ? }
  477. if is_locallabel(actasmpattern) then
  478. begin
  479. CreateLocalLabel(actasmpattern,hl,false);
  480. Consume(AS_ID);
  481. AddLabelOperand(hl);
  482. end
  483. else
  484. { Check for label }
  485. if SearchLabel(actasmpattern,hl,false) then
  486. begin
  487. Consume(AS_ID);
  488. AddLabelOperand(hl);
  489. end
  490. else
  491. { probably a variable or normal expression }
  492. { or a procedure (such as in CALL ID) }
  493. Begin
  494. { is it a constant ? }
  495. if SearchIConstant(actasmpattern,l) then
  496. Begin
  497. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  498. Message(asmr_e_invalid_operand_type);
  499. BuildConstantOperand(oper);
  500. end
  501. else
  502. begin
  503. expr:=actasmpattern;
  504. Consume(AS_ID);
  505. { typecasting? }
  506. if (actasmtoken=AS_LPAREN) and
  507. SearchType(expr,typesize) then
  508. begin
  509. oper.hastype:=true;
  510. Consume(AS_LPAREN);
  511. BuildOperand(oper);
  512. Consume(AS_RPAREN);
  513. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  514. oper.SetSize(typesize,true);
  515. end
  516. else
  517. begin
  518. if oper.SetupVar(expr,false) then
  519. ReadAt(oper)
  520. else
  521. Begin
  522. { look for special symbols ... }
  523. if expr= '__HIGH' then
  524. begin
  525. consume(AS_LPAREN);
  526. if not oper.setupvar('high'+actasmpattern,false) then
  527. Message1(sym_e_unknown_id,'high'+actasmpattern);
  528. consume(AS_ID);
  529. consume(AS_RPAREN);
  530. end
  531. else
  532. if expr = '__RESULT' then
  533. oper.SetUpResult
  534. else
  535. if expr = '__SELF' then
  536. oper.SetupSelf
  537. else
  538. if expr = '__OLDEBP' then
  539. oper.SetupOldEBP
  540. else
  541. Message1(sym_e_unknown_id,expr);
  542. end;
  543. end;
  544. end;
  545. if actasmtoken=AS_DOT then
  546. MaybeRecordOffset;
  547. { add a constant expression? }
  548. if (actasmtoken=AS_PLUS) then
  549. begin
  550. l:=BuildConstExpression(true,entered_paren);
  551. case oper.opr.typ of
  552. OPR_CONSTANT :
  553. inc(oper.opr.val,l);
  554. OPR_LOCAL :
  555. inc(oper.opr.localsymofs,l);
  556. OPR_REFERENCE :
  557. inc(oper.opr.ref.offset,l);
  558. else
  559. internalerror(2003092017);
  560. end;
  561. end
  562. end;
  563. { Do we have a indexing reference, then parse it also }
  564. if actasmtoken=AS_LPAREN then
  565. begin
  566. oper.InitRef;
  567. BuildReference(oper);
  568. end;
  569. end;
  570. AS_REGISTER: { Register, a variable reference or a constant reference }
  571. Begin
  572. { save the type of register used. }
  573. tempreg:=actasmregister;
  574. Consume(AS_REGISTER);
  575. if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  576. begin
  577. if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
  578. Message(asmr_e_invalid_operand_type);
  579. oper.opr.typ:=OPR_REGISTER;
  580. oper.opr.reg:=tempreg;
  581. end
  582. else
  583. Message(asmr_e_syn_operand);
  584. end;
  585. AS_END,
  586. AS_SEPARATOR,
  587. AS_COMMA: ;
  588. else
  589. Begin
  590. Message(asmr_e_syn_operand);
  591. Consume(actasmtoken);
  592. end;
  593. end; { end case }
  594. if refaddr<>addr_full then
  595. begin
  596. if oper.opr.typ<>OPR_REFERENCE then
  597. oper.InitRef;
  598. oper.opr.ref.refaddr:=refaddr;
  599. Consume(AS_RPAREN);
  600. end
  601. else if (oper.opr.typ=OPR_REFERENCE) and
  602. (oper.opr.ref.refaddr=addr_no) and
  603. assigned(oper.opr.ref.symbol) then
  604. oper.opr.ref.refaddr:=addr_full;
  605. end;
  606. {*****************************************************************************
  607. trvgasreader
  608. *****************************************************************************}
  609. procedure trvgasreader.BuildOpCode(instr : trvinstruction);
  610. var
  611. operandnum : longint;
  612. Begin
  613. { opcode }
  614. if (actasmtoken<>AS_OPCODE) then
  615. Begin
  616. Message(asmr_e_invalid_or_missing_opcode);
  617. RecoverConsume(true);
  618. exit;
  619. end;
  620. { Fill the instr object with the current state }
  621. with instr do
  622. begin
  623. Opcode:=ActOpcode;
  624. condition:=ActCondition;
  625. ordering:=actmemoryordering;
  626. end;
  627. { We are reading operands, so opcode will be an AS_ID }
  628. operandnum:=1;
  629. Consume(AS_OPCODE);
  630. { Zero operand opcode ? }
  631. if actasmtoken in [AS_SEPARATOR,AS_END] then
  632. begin
  633. operandnum:=0;
  634. exit;
  635. end;
  636. { Read the operands }
  637. repeat
  638. case actasmtoken of
  639. AS_COMMA: { Operand delimiter }
  640. Begin
  641. if operandnum>Max_Operands then
  642. Message(asmr_e_too_many_operands)
  643. else
  644. begin
  645. { condition operands doesn't set the operand but write to the
  646. condition field of the instruction
  647. }
  648. if instr.Operands[operandnum].opr.typ<>OPR_NONE then
  649. Inc(operandnum);
  650. end;
  651. Consume(AS_COMMA);
  652. end;
  653. AS_SEPARATOR,
  654. AS_END : { End of asm operands for this opcode }
  655. begin
  656. break;
  657. end;
  658. else
  659. BuildOperand(instr.Operands[operandnum] as trvoperand);
  660. end; { end case }
  661. until false;
  662. if (operandnum=1) and (instr.Operands[operandnum].opr.typ=OPR_NONE) then
  663. dec(operandnum);
  664. instr.Ops:=operandnum;
  665. end;
  666. function trvgasreader.is_register(const s: string): boolean;
  667. var
  668. reg: TRegister;
  669. begin
  670. result:=inherited is_register(s);
  671. { reg found?
  672. possible aliases are always 2 to 4 chars
  673. }
  674. if not(result) then
  675. begin
  676. reg:=is_extra_reg(s);
  677. if reg<>NR_NO then
  678. begin
  679. actasmregister:=reg;
  680. result:=true;
  681. actasmtoken:=AS_REGISTER;
  682. end;
  683. end;
  684. end;
  685. function trvgasreader.is_asmopcode(const s: string):boolean;
  686. var
  687. cond : tasmcond;
  688. hs, postfix : string;
  689. l: longint;
  690. Begin
  691. { making s a value parameter would break other assembler readers }
  692. hs:=s;
  693. is_asmopcode:=false;
  694. { clear op code }
  695. actopcode:=A_None;
  696. { clear condition }
  697. fillchar(actcondition,sizeof(actcondition),0);
  698. { check for direction hint }
  699. actopcode := tasmop(ptruint(iasmops.find(hs)));
  700. if actopcode <> A_NONE then
  701. begin
  702. actasmtoken:=AS_OPCODE;
  703. is_asmopcode:=true;
  704. exit;
  705. end;
  706. { not found, check branch instructions }
  707. if hs[1]='B' then
  708. begin
  709. { we can search here without an extra table which is sorted by string length
  710. because we take the whole remaining string without the leading B }
  711. actopcode := A_Bxx;
  712. for cond:=low(TAsmCond) to high(TAsmCond) do
  713. if copy(hs,2,length(s)-1)=uppercond2str[cond] then
  714. begin
  715. actcondition:=cond;
  716. actasmtoken:=AS_OPCODE;
  717. is_asmopcode:=true;
  718. exit;
  719. end;
  720. end;
  721. { check atomic instructions }
  722. if (pos('AMO',hs)=1) or
  723. (pos('LR', hs)=1) or
  724. (pos('SC', hs)=1) then
  725. begin
  726. l := length(hs)-1;
  727. while l>1 do
  728. begin
  729. actopcode := tasmop(ptruint(iasmops.find(copy(hs,1,l))));
  730. if actopcode <> A_None then
  731. begin
  732. postfix := copy(hs,l+1,length(hs)-l);
  733. if postfix='.AQRL' then actmemoryordering:=[moAq,moRl]
  734. else if postfix='.RL' then actmemoryordering:=[moRl]
  735. else if postfix='.AQ' then actmemoryordering:=[moAq]
  736. else
  737. exit;
  738. actasmtoken:=AS_OPCODE;
  739. is_asmopcode:=true;
  740. exit;
  741. end;
  742. dec(l);
  743. end;
  744. end;
  745. end;
  746. procedure trvgasreader.handleopcode;
  747. var
  748. instr : trvinstruction;
  749. begin
  750. instr:=trvinstruction.Create(trvoperand);
  751. BuildOpcode(instr);
  752. instr.condition := actcondition;
  753. {
  754. instr.AddReferenceSizes;
  755. instr.SetInstructionOpsize;
  756. instr.CheckOperandSizes;
  757. }
  758. instr.ConcatInstruction(curlist);
  759. instr.Free;
  760. actmemoryordering:=[];
  761. end;
  762. {*****************************************************************************
  763. Initialize
  764. *****************************************************************************}
  765. const
  766. asmmode_rv64_standard_info : tasmmodeinfo =
  767. (
  768. id : asmmode_standard;
  769. idtxt : 'STANDARD';
  770. casmreader : trvgasreader;
  771. );
  772. asmmode_rv32_standard_info : tasmmodeinfo =
  773. (
  774. id : asmmode_standard;
  775. idtxt : 'STANDARD';
  776. casmreader : trvgasreader;
  777. );
  778. initialization
  779. {$ifdef RISCV32}
  780. RegisterAsmMode(asmmode_rv32_standard_info);
  781. {$endif RISCV32}
  782. {$ifdef RISCV64}
  783. RegisterAsmMode(asmmode_rv64_standard_info);
  784. {$endif RISCV32}
  785. end.