racpugas.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. {
  2. Copyright (c) 2019 by Jeppe Johansen
  3. Does the parsing for the LoongArch64 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 racpugas;
  18. {$I fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. raatt,racpu,
  23. cpubase;
  24. const
  25. NRCalMax=64;
  26. type
  27. TArithOpers = (LLOR,LLAND,LINOR,LEXOR,LAND,LEQU,LUNE,LSLT,
  28. LBGT,LSLE,LBGE,LSL,LSR,LADD,LSUB,LMUL,LMOD,LDIV);
  29. TArithTreeType = (ATT_NUM,ATT_OP);
  30. TArithTree = record
  31. left : integer;
  32. right : integer;
  33. case typ:TArithTreeType of
  34. ATT_NUM : (num : tcgint);
  35. ATT_OP : (op : TArithOpers);
  36. end;
  37. TArrCals = array[1..NRCalMax] of TArithTree;
  38. TArrNums = array[1..(NRCalMax shr 1)] of tcgint;
  39. TArrAOps = array[1..(NRCalMax shr 1)] of TArithOpers;
  40. tloongarch64gasreader = class(tattreader)
  41. function is_register(const s: string):boolean;override;
  42. function is_asmopcode(const s: string):boolean;override;
  43. procedure handledollar;override;
  44. procedure handleopcode;override;
  45. procedure BuildOperand(oper : tloongarch64operand);
  46. procedure BuildOpCode(instr : tloongarch64instruction);
  47. function CalculateExprs(nr,first : tcgint; var nums : TArrNums; var ops : TArrAOps): tcgint;
  48. function BuildConstLA(from_question,cond : boolean): tcgint;
  49. function BuildSymLA(oper : tloongarch64operand; maybeconst: boolean): boolean;
  50. end;
  51. implementation
  52. uses
  53. { helpers }
  54. cutils,
  55. { global }
  56. globals,verbose,
  57. systems,
  58. { aasm }
  59. aasmbase,aasmtai,aasmdata,aasmcpu,
  60. { symtable }
  61. symconst,symsym,symdef,
  62. { parser }
  63. scanner,
  64. procinfo,
  65. rabase,rautils,
  66. cgbase,cgobj
  67. ;
  68. procedure tloongarch64gasreader.BuildOperand(oper: tloongarch64operand);
  69. var
  70. expr : string;
  71. typesize,l : TCGInt;
  72. tempreg : tregister;
  73. hl : tasmlabel;
  74. ofs : aint;
  75. refaddr: trefaddr;
  76. entered_paren: Boolean;
  77. Begin
  78. expr:='';
  79. entered_paren:=false;
  80. refaddr:=addr_no;
  81. { Although assembler has diverse ways to decode parameters,
  82. there are four normal ways to describe them.
  83. 1. Registers.
  84. 2. %addrtype(Symbol'addend'), addend means expression.
  85. 3. Symbol'addend'.
  86. 4. Else, expression. }
  87. case actasmtoken of
  88. AS_REGISTER:
  89. begin
  90. { save the type of register used. }
  91. tempreg:=actasmregister;
  92. Consume(AS_REGISTER);
  93. if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  94. begin
  95. oper.opr.typ:=OPR_REGISTER;
  96. oper.opr.reg:=tempreg;
  97. end
  98. else
  99. Message(asmr_e_syn_operand);
  100. end;
  101. AS_MOD:
  102. begin
  103. Consume(AS_MOD);
  104. if actasmtoken<>AS_ID then
  105. Message(asmr_e_syntax_error);
  106. if lower(actasmpattern)='b16' then
  107. refaddr:=addr_b16
  108. else if lower(actasmpattern)='b21' then
  109. refaddr:=addr_b21
  110. else if lower(actasmpattern)='b26' then
  111. refaddr:=addr_b26
  112. else if lower(actasmpattern)='plt' then
  113. refaddr:=addr_plt
  114. else if lower(actasmpattern)='abs_hi20' then
  115. refaddr:=addr_abs_hi20
  116. else if lower(actasmpattern)='abs_lo12' then
  117. refaddr:=addr_abs_lo12
  118. else if lower(actasmpattern)='abs64_lo20' then
  119. refaddr:=addr_abs64_lo20
  120. else if lower(actasmpattern)='abs64_hi12' then
  121. refaddr:=addr_abs64_hi12
  122. else if lower(actasmpattern)='pc_hi20' then
  123. refaddr:=addr_pc_hi20
  124. else if lower(actasmpattern)='pc_lo12' then
  125. refaddr:=addr_pc_lo12
  126. else if lower(actasmpattern)='got_pc_hi20' then
  127. refaddr:=addr_got_pc_hi20
  128. else if lower(actasmpattern)='got_pc_lo12' then
  129. refaddr:=addr_got_pc_lo12
  130. else
  131. Message(asmr_e_syntax_error);
  132. Consume(AS_ID);
  133. if actasmtoken<>AS_LPAREN then
  134. Message(asmr_e_syntax_error);
  135. Consume(AS_LPAREN);
  136. BuildSymLA(oper,false);
  137. if actasmtoken<>AS_RPAREN then
  138. Message(asmr_e_syntax_error);
  139. Consume(AS_RPAREN);
  140. end;
  141. AS_DOT, AS_ID:
  142. begin
  143. if actopcode=A_LA_GOT then
  144. refaddr:=addr_pcrel
  145. else if actopcode=A_LA_ABS then
  146. refaddr:=addr_abs
  147. else
  148. refaddr:=addr_pcrel;
  149. if not BuildSymLA(oper,actasmtoken=AS_ID) then
  150. refaddr:=addr_no;
  151. end;
  152. AS_END,
  153. AS_SEPARATOR,
  154. AS_COMMA: ;
  155. else
  156. begin
  157. oper.opr.typ:=OPR_CONSTANT;
  158. oper.opr.val:=BuildConstLA(false,false);
  159. end;
  160. end; { end case }
  161. if refaddr<>addr_no then
  162. begin
  163. { Indirectly use parameter can be local and sym is paravarsym. }
  164. if oper.opr.typ=OPR_LOCAL then
  165. exit;
  166. if oper.opr.typ<>OPR_REFERENCE then
  167. oper.InitRef;
  168. oper.opr.ref.refaddr:=refaddr;
  169. end
  170. else if (oper.opr.typ=OPR_REFERENCE) and
  171. (oper.opr.ref.refaddr=addr_no) and
  172. assigned(oper.opr.ref.symbol) then
  173. oper.opr.ref.refaddr:=addr_pcrel;
  174. end;
  175. {*****************************************************************************
  176. tloongarch64gasreader
  177. *****************************************************************************}
  178. procedure tloongarch64gasreader.BuildOpCode(instr : tloongarch64instruction);
  179. var
  180. operandnum : longint;
  181. begin
  182. { opcode }
  183. if (actasmtoken<>AS_OPCODE) then
  184. begin
  185. Message(asmr_e_invalid_or_missing_opcode);
  186. RecoverConsume(true);
  187. exit;
  188. end;
  189. { Fill the instr object with the current state }
  190. with instr do
  191. begin
  192. Opcode:=ActOpcode;
  193. condition:=ActCondition;
  194. end;
  195. { We are reading operands, so opcode will be an AS_ID }
  196. operandnum:=1;
  197. Consume(AS_OPCODE);
  198. { Zero operand opcode ? }
  199. if actasmtoken in [AS_SEPARATOR,AS_END] then
  200. begin
  201. operandnum:=0;
  202. exit;
  203. end;
  204. { Read the operands }
  205. repeat
  206. case actasmtoken of
  207. AS_COMMA: { Operand delimiter }
  208. begin
  209. if operandnum>Max_Operands then
  210. Message(asmr_e_too_many_operands)
  211. else
  212. begin
  213. { condition operands doesn't set the operand but write to the
  214. condition field of the instruction
  215. }
  216. if instr.Operands[operandnum].opr.typ<>OPR_NONE then
  217. Inc(operandnum);
  218. end;
  219. Consume(AS_COMMA);
  220. end;
  221. AS_SEPARATOR,
  222. AS_END : { End of asm operands for this opcode }
  223. begin
  224. break;
  225. end;
  226. else
  227. BuildOperand(instr.Operands[operandnum] as tloongarch64operand);
  228. end; { end case }
  229. until false;
  230. if (operandnum=1) and (instr.Operands[operandnum].opr.typ=OPR_NONE) then
  231. dec(operandnum);
  232. instr.Ops:=operandnum;
  233. end;
  234. function tloongarch64gasreader.is_register(const s: string): boolean;
  235. var
  236. reg: TRegister;
  237. begin
  238. result:=inherited is_register(s);
  239. { reg found? search it in abinames? }
  240. if not(result) then
  241. begin
  242. reg:=is_extra_reg(s);
  243. if reg<>NR_NO then
  244. begin
  245. actasmregister:=reg;
  246. result:=true;
  247. actasmtoken:=AS_REGISTER;
  248. end;
  249. end;
  250. end;
  251. function tloongarch64gasreader.is_asmopcode(const s: string):boolean;
  252. var
  253. cond : tasmcond;
  254. hs, postfix : string;
  255. l: longint;
  256. begin
  257. { making s a value parameter would break other assembler readers }
  258. hs:=s;
  259. is_asmopcode:=false;
  260. { clear op code }
  261. actopcode:=A_None;
  262. { clear condition }
  263. fillchar(actcondition,sizeof(actcondition),0);
  264. { check for direction hint }
  265. actopcode := tasmop(ptruint(iasmops.find(hs)));
  266. if actopcode <> A_NONE then
  267. begin
  268. actasmtoken:=AS_OPCODE;
  269. is_asmopcode:=true;
  270. exit;
  271. end;
  272. end;
  273. procedure tloongarch64gasreader.handledollar;
  274. var
  275. len: longint;
  276. begin
  277. len:=1;
  278. actasmpattern[len]:='$';
  279. c:=current_scanner.asmgetchar;
  280. while c in ['A'..'Z','a'..'z','0'..'9'] do
  281. begin
  282. inc(len);
  283. actasmpattern[len]:=c;
  284. c:=current_scanner.asmgetchar;
  285. end;
  286. actasmpattern[0]:=chr(len);
  287. actasmpattern:=lower(actasmpattern);
  288. { TODO Something else. }
  289. if not is_register(actasmpattern) then
  290. internalerror(2022062915);
  291. end;
  292. procedure tloongarch64gasreader.handleopcode;
  293. var
  294. instr : tloongarch64instruction;
  295. begin
  296. instr:=tloongarch64instruction.create(tloongarch64operand);
  297. BuildOpCode(instr);
  298. { TODO insruction field }
  299. instr.ConcatInstruction(curlist);
  300. instr.Free;
  301. end;
  302. { In LoongArch binutils gas, the expression calculation is complex.
  303. The priority is ternary is the lowest and the unary is the highest.
  304. Ternary '?:', binary ordered by form low to high is '||', '&&',
  305. '|', '^', '&', '==,!=', '<,<=,>,>=', '<<,>>', '+,-' and '*,/,%',
  306. Unary is '+,-,~,!'. It is different form CalculateExpression, so
  307. we should implement ourselves. Collect integers and binary,
  308. calculate parentheses by recursing call, mark ternay and calculate
  309. unary in time. }
  310. function tloongarch64gasreader.CalculateExprs(nr,first : tcgint; var nums : TArrNums; var ops : TArrAOps): tcgint;
  311. procedure alloc_num(var idx : integer; var arr : TArrCals; num : int64);
  312. begin
  313. idx:=idx+1;
  314. if idx>NRCalMax then
  315. internalerror(2022081601);
  316. arr[idx].typ:=ATT_NUM;
  317. arr[idx].num:=num;
  318. end;
  319. procedure alloc_op(var idx : integer; var arr : TArrCals; op : TArithOpers);
  320. begin
  321. idx:=idx+1;
  322. if idx>NRCalMax then
  323. internalerror(2022081602);
  324. arr[idx].typ:=ATT_OP;
  325. arr[idx].op:=op;
  326. end;
  327. function priority_less(op1, op2 : TArithOpers): boolean;
  328. begin
  329. case op1 of
  330. LMUL,LMOD,LDIV:
  331. priority_less:=false;
  332. LADD,LSUB:
  333. priority_less:=op2 in [LMUL..LDIV];
  334. LSL,LSR:
  335. priority_less:=op2 in [LADD..LDIV];
  336. LSLT,LBGT,LSLE,LBGE:
  337. priority_less:=op2 in [LSL..LDIV];
  338. LEQU,LUNE:
  339. priority_less:=op2 in [LSLT..LDIV];
  340. LAND:
  341. priority_less:=op2 in [LEQU..LDIV];
  342. LEXOR:
  343. priority_less:=op2 in [LAND..LDIV];
  344. LINOR:
  345. priority_less:=op2 in [LEXOR..LDIV];
  346. LLAND:
  347. priority_less:=op2 in [LINOR..LDIV];
  348. LLOR:
  349. priority_less:=op2<>LLOR;
  350. end;
  351. end;
  352. function get_where_insert(head,item : integer; var arr : TArrCals) : integer;
  353. var
  354. last,t : integer;
  355. begin
  356. last:=0;
  357. t:=head;
  358. while arr[t].typ=ATT_OP do
  359. begin
  360. if priority_less(arr[item].op,arr[t].op) then
  361. break;
  362. last:=t;
  363. t:=arr[t].right;
  364. end;
  365. get_where_insert:=last;
  366. end;
  367. function arith_treecal(var arr : TArrCals; idx : integer): tcgint;
  368. var
  369. lv,rv : tcgint;
  370. begin
  371. if arr[idx].typ=ATT_NUM then
  372. begin
  373. result:=arr[idx].num;
  374. exit;
  375. end;
  376. if (arr[idx].left=0) and (arr[idx].right=0) then
  377. internalerror(2022081705);
  378. lv:=arith_treecal(arr,arr[idx].left);
  379. rv:=arith_treecal(arr,arr[idx].right);
  380. case arr[idx].op of
  381. LLOR: result:=tcgint((lv<>0) or (rv<>0));
  382. LLAND: result:=tcgint((lv<>0) and (rv<>0));
  383. LINOR: result:=lv or rv;
  384. LEXOR: result:=lv xor rv;
  385. LAND: result:=lv and rv;
  386. LEQU: result:=tcgint(lv=rv);
  387. LUNE: result:=tcgint(lv<>rv);
  388. LSLT: result:=tcgint(lv<rv);
  389. LBGT: result:=tcgint(lv>rv);
  390. LSLE: result:=tcgint(lv<=rv);
  391. LBGE: result:=tcgint(lv>=rv);
  392. LSL: result:=lv<<rv;
  393. LSR: result:=lv>>rv;
  394. LADD: result:=lv+rv;
  395. LSUB: result:=lv-rv;
  396. LMUL: result:=lv*rv;
  397. LMOD: result:=lv mod rv;
  398. LDIV: result:=lv div rv;
  399. end;
  400. end;
  401. procedure debug_treecal(var arr : TArrCals; idx : integer; first : boolean);
  402. const
  403. strops: Array[LLOR..LDIV] of string[3] =
  404. ('||','&&','|','^','&','==','!=','<','>',
  405. '<=','>=','<<','>>','+','-','*','%','/');
  406. begin
  407. if first then
  408. writeln('[Debug] ');
  409. if arr[idx].typ=ATT_NUM then
  410. begin
  411. write(arr[idx].num);
  412. exit;
  413. end;
  414. if (arr[idx].left=0) and (arr[idx].right=0) then
  415. writeln(#10,'[Debug Error]');
  416. debug_treecal(arr,arr[idx].left,false);
  417. if arr[idx].typ=ATT_OP then
  418. write(strops[arr[idx].op]);
  419. debug_treecal(arr,arr[idx].right,false);
  420. if first then
  421. writeln('=',arith_treecal(arr,idx));
  422. end;
  423. var
  424. i,curidx,curhead,curright,cursym,insidx : integer;
  425. exprs : TArrCals;
  426. begin
  427. if nr=0 then
  428. internalerror(2022081704);
  429. curidx:=0;
  430. alloc_num(curidx,exprs,first);
  431. curhead:=curidx;
  432. cursym:=0;
  433. for i := 1 to nr do
  434. begin
  435. alloc_op(curidx,exprs,ops[i]);
  436. cursym:=curidx;
  437. alloc_num(curidx,exprs,nums[i]);
  438. curright:=curidx;
  439. exprs[cursym].right:=curright;
  440. insidx:=get_where_insert(curhead,cursym,exprs);
  441. if insidx=0 then
  442. begin
  443. exprs[cursym].left:=curhead;
  444. curhead:=cursym;
  445. end
  446. else
  447. begin
  448. exprs[cursym].left:=exprs[insidx].right;
  449. exprs[insidx].right:=cursym;
  450. end;
  451. end;
  452. { debug_treecal(exprs,curhead,true); }
  453. result:=arith_treecal(exprs,curhead);
  454. end;
  455. function tloongarch64gasreader.BuildConstLA(from_question,cond : boolean): tcgint;
  456. function get_a_int: tcgint;
  457. var
  458. l : tcgint;
  459. begin
  460. result:=0;
  461. case actasmtoken of
  462. AS_PLUS:
  463. begin
  464. Consume(AS_PLUS);
  465. result:=get_a_int();
  466. end;
  467. AS_MINUS:
  468. begin
  469. Consume(AS_MINUS);
  470. result:=-get_a_int();
  471. end;
  472. AS_NOT:
  473. begin
  474. Consume(AS_NOT);
  475. result:=tcgint(get_a_int()=0);
  476. end;
  477. AS_NOR:
  478. begin
  479. Consume(AS_NOR);
  480. result:=not get_a_int();
  481. end;
  482. AS_ID:
  483. begin
  484. if SearchIConstant(actasmpattern,l) then
  485. result:=l
  486. else
  487. internalerror(2022081101);
  488. Consume(AS_ID);
  489. end;
  490. AS_INTNUM:
  491. begin
  492. result:=CalculateExpression(actasmpattern);
  493. Consume(AS_INTNUM);
  494. end;
  495. AS_LPAREN:
  496. begin
  497. Consume(AS_LPAREN);
  498. l:=BuildConstLA(false,false);
  499. if actasmtoken<>AS_RPAREN then
  500. Message(asmr_e_syntax_error);
  501. Consume(AS_RPAREN);
  502. result:=l;
  503. end;
  504. else
  505. Message(asmr_e_syntax_error);
  506. end;
  507. end;
  508. function get_a_op: TArithOpers;
  509. begin
  510. result:=LADD; { As initialized }
  511. case actasmtoken of
  512. AS_SHL:
  513. begin
  514. Consume(AS_SHL);
  515. result:=LSL;
  516. end;
  517. AS_SHR:
  518. begin
  519. Consume(AS_SHR);
  520. result:=LSR;
  521. end;
  522. AS_LT:
  523. begin
  524. Consume(AS_LT);
  525. if actasmtoken=AS_EQUAL then
  526. begin
  527. Consume(AS_EQUAL);
  528. result:=LSLE;
  529. end
  530. else
  531. result:=LSLT;
  532. end;
  533. AS_GT:
  534. begin
  535. Consume(AS_GT);
  536. if actasmtoken=AS_EQUAL then
  537. begin
  538. Consume(AS_EQUAL);
  539. result:=LBGE;
  540. end
  541. else
  542. result:=LBGT;
  543. end;
  544. AS_OR:
  545. begin
  546. Consume(AS_OR);
  547. if actasmtoken=AS_OR then
  548. begin
  549. Consume(AS_OR);
  550. result:=LLOR;
  551. end
  552. else
  553. result:=LINOR;
  554. end;
  555. AS_AND:
  556. begin
  557. Consume(AS_AND);
  558. if actasmtoken=AS_AND then
  559. begin
  560. Consume(AS_AND);
  561. result:=LLAND;
  562. end
  563. else
  564. result:=LAND;
  565. end;
  566. AS_EQUAL:
  567. begin
  568. Consume(AS_EQUAL);
  569. if actasmtoken<>AS_EQUAL then
  570. internalerror(2022081701);
  571. Consume(AS_EQUAL);
  572. result:=LEQU;
  573. end;
  574. AS_NOT:
  575. begin
  576. Consume(AS_NOT);
  577. if actasmtoken<>AS_EQUAL then
  578. internalerror(2022081702);
  579. Consume(AS_EQUAL);
  580. result:=LUNE;
  581. end;
  582. AS_XOR:
  583. begin
  584. Consume(AS_XOR);
  585. result:=LEXOR;
  586. end;
  587. AS_PLUS:
  588. begin
  589. Consume(AS_PLUS);
  590. result:=LADD;
  591. end;
  592. AS_MINUS:
  593. begin
  594. Consume(AS_MINUS);
  595. result:=LSUB;
  596. end;
  597. AS_STAR:
  598. begin
  599. Consume(AS_STAR);
  600. result:=LMUL;
  601. end;
  602. AS_MOD:
  603. begin
  604. Consume(AS_MOD);
  605. result:=LMOD;
  606. end;
  607. AS_SLASH:
  608. begin
  609. Consume(AS_SLASH);
  610. result:=LDIV;
  611. end;
  612. else
  613. Message(asmr_e_syntax_error);
  614. end;
  615. end;
  616. var
  617. firstnum,nr,l,l2 : tcgint;
  618. IntStack : TArrNums;
  619. OpsStack : TArrAOps;
  620. op_or_int: boolean;
  621. begin
  622. result:=0;
  623. nr:=0;
  624. firstnum:=get_a_int;
  625. { Most of case will return as they only have an integer. }
  626. repeat
  627. case actasmtoken of
  628. AS_END,AS_SEPARATOR,AS_COMMA,AS_RPAREN: break;
  629. AS_LPAREN:
  630. begin
  631. Consume(AS_LPAREN);
  632. l:=BuildConstLA(false,false);
  633. if actasmtoken<>AS_RPAREN then
  634. Message(asmr_e_syntax_error);
  635. Consume(AS_RPAREN);
  636. end;
  637. AS_QUESTION:
  638. begin
  639. Consume(AS_QUESTION);
  640. if nr=0 then
  641. l:=firstnum
  642. else
  643. l:=CalculateExprs(nr,firstnum,IntStack,OpsStack);
  644. result:=BuildConstLA(true,l<>0);
  645. exit;
  646. end;
  647. AS_COLON:
  648. begin
  649. if not from_question then
  650. Message(asmr_e_syntax_error);
  651. Consume(AS_COLON);
  652. if nr=0 then
  653. l:=firstnum
  654. else
  655. l:=CalculateExprs(nr,firstnum,IntStack,OpsStack);
  656. l2:=BuildConstLA(false,false);
  657. if cond then
  658. result:=l
  659. else
  660. result:=l2;
  661. exit;
  662. end;
  663. else
  664. begin
  665. nr:=nr+1;
  666. if nr>(NRCalMax shr 1) then
  667. internalerror(2022081703);
  668. OpsStack[nr]:=get_a_op;
  669. IntStack[nr]:=get_a_int;
  670. end;
  671. end; { case actasmtoken }
  672. until false;
  673. if nr=0 then
  674. result:=firstnum
  675. else
  676. result:=CalculateExprs(nr,firstnum,IntStack,OpsStack);
  677. end;
  678. function tloongarch64gasreader.BuildSymLA(oper : tloongarch64operand; maybeconst : boolean): boolean;
  679. var
  680. hl : tasmlabel;
  681. value : tcgint;
  682. toffset, tsize: tcgint;
  683. expr,mangledname: string;
  684. begin
  685. result:=True;
  686. if (is_locallabel(actasmpattern)) then
  687. begin
  688. CreateLocalLabel(actasmpattern,hl,false);
  689. Consume(AS_ID);
  690. oper.InitRef;
  691. oper.opr.ref.symbol:=hl;
  692. end
  693. else if SearchLabel(actasmpattern,hl,false) then
  694. begin
  695. Consume(AS_ID);
  696. oper.InitRef;
  697. oper.opr.ref.symbol:=hl;
  698. end
  699. else if maybeconst then
  700. begin
  701. if not SearchIConstant(actasmpattern,value) then
  702. begin
  703. expr:=actasmpattern;
  704. Consume(AS_ID);
  705. if actasmtoken = AS_DOT then
  706. begin
  707. mangledname:='';
  708. BuildRecordOffsetSize(expr, toffset, tsize, mangledname, false);
  709. if mangledname <> '' then
  710. Message(asmr_e_wrong_sym_type);
  711. oper.opr.typ:=OPR_CONSTANT;
  712. oper.opr.val:=toffset;
  713. Result:=False;
  714. end
  715. else
  716. begin
  717. oper.InitRef;
  718. oper.SetupVar(expr,false);
  719. end;
  720. end;
  721. end
  722. else if actasmtoken=AS_ID then
  723. begin
  724. oper.InitRef;
  725. oper.SetupVar(actasmpattern,false);
  726. Consume(AS_ID);
  727. end
  728. else
  729. begin
  730. Message(asmr_e_syntax_error);
  731. internalerror(2022082501);
  732. end;
  733. if actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA,AS_RPAREN] then
  734. exit;
  735. value:=BuildConstLA(false,false);
  736. if assigned(oper.opr.ref.symbol) then
  737. oper.opr.ref.offset:=value
  738. else
  739. begin
  740. oper.opr.typ:=OPR_CONSTANT;
  741. oper.opr.val:=value;
  742. Result:=False;
  743. end;
  744. end;
  745. {*****************************************************************************
  746. Initialize
  747. *****************************************************************************}
  748. const
  749. asmmode_loongarch64_standard_info : tasmmodeinfo =
  750. (
  751. id : asmmode_standard;
  752. idtxt : 'STANDARD';
  753. casmreader : tloongarch64gasreader;
  754. );
  755. initialization
  756. RegisterAsmMode(asmmode_loongarch64_standard_info);
  757. end.