racpugas.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. {
  2. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  3. Does the parsing for the Xtensa 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. raatt,raxtensa,
  22. cpubase;
  23. type
  24. txtensaattreader = class(tattreader)
  25. actoppostfix : TOpPostfix;
  26. actIsPrefixed: boolean;
  27. function is_asmopcode(const s: string):boolean;override;
  28. function is_register(const s:string):boolean;override;
  29. procedure handleopcode;override;
  30. procedure BuildReference(oper : TXtensaOperand);
  31. procedure BuildOperand(oper : TXtensaOperand);
  32. procedure BuildSpecialreg(oper : TXtensaOperand);
  33. procedure BuildOpCode(instr : TXtensaInstruction);
  34. procedure ReadSym(oper : TXtensaOperand);
  35. procedure ConvertCalljmp(instr : TXtensaInstruction);
  36. procedure HandleTargetDirective; override;
  37. end;
  38. Implementation
  39. uses
  40. { helpers }
  41. cutils,
  42. { global }
  43. globtype,globals,verbose,
  44. systems,aasmbase,aasmtai,aasmdata,aasmcpu,
  45. { symtable }
  46. symconst,symsym,symdef,
  47. procinfo,
  48. rabase,rautils,
  49. cgbase,cgutils,paramgr;
  50. function txtensaattreader.is_register(const s:string):boolean;
  51. type
  52. treg2str = record
  53. name : string[3];
  54. reg : tregister;
  55. end;
  56. const
  57. extraregs : array[0..0] of treg2str = (
  58. (name: 'A1'; reg : NR_A0)
  59. );
  60. var
  61. i : longint;
  62. begin
  63. result:=inherited is_register(s);
  64. { reg found?
  65. possible aliases are always 2 char
  66. }
  67. if result or (not (length(s) in [2,3])) then
  68. exit;
  69. for i:=low(extraregs) to high(extraregs) do
  70. begin
  71. if s=extraregs[i].name then
  72. begin
  73. actasmregister:=extraregs[i].reg;
  74. result:=true;
  75. actasmtoken:=AS_REGISTER;
  76. exit;
  77. end;
  78. end;
  79. end;
  80. procedure txtensaattreader.ReadSym(oper : TXtensaOperand);
  81. var
  82. tempstr, mangledname : string;
  83. typesize,l,k : tcgint;
  84. begin
  85. tempstr:=actasmpattern;
  86. Consume(AS_ID);
  87. { typecasting? }
  88. if (actasmtoken=AS_LPAREN) and
  89. SearchType(tempstr,typesize) then
  90. begin
  91. oper.hastype:=true;
  92. Consume(AS_LPAREN);
  93. BuildOperand(oper);
  94. Consume(AS_RPAREN);
  95. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  96. oper.SetSize(typesize,true);
  97. end
  98. else
  99. if not oper.SetupVar(tempstr,false) then
  100. Message1(sym_e_unknown_id,tempstr);
  101. { record.field ? }
  102. if actasmtoken=AS_DOT then
  103. begin
  104. BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
  105. if (mangledname<>'') then
  106. Message(asmr_e_invalid_reference_syntax);
  107. inc(oper.opr.ref.offset,l);
  108. end;
  109. end;
  110. Procedure txtensaattreader.BuildReference(oper : TXtensaOperand);
  111. procedure do_error;
  112. begin
  113. Message(asmr_e_invalid_reference_syntax);
  114. RecoverConsume(false);
  115. end;
  116. procedure test_end(require_rbracket : boolean);
  117. begin
  118. if not(actasmtoken in [AS_SEPARATOR,AS_end]) then
  119. do_error
  120. else
  121. begin
  122. {$IFDEF debugasmreader}
  123. writeln('TEST_end_FINAL_OK. Created the following ref:');
  124. writeln('oper.opr.ref.base=',ord(oper.opr.ref.base));
  125. writeln('oper.opr.ref.signindex=',ord(oper.opr.ref.signindex));
  126. writeln('oper.opr.ref.addressmode=',ord(oper.opr.ref.addressmode));
  127. writeln;
  128. {$endIF debugasmreader}
  129. end;
  130. end;
  131. procedure read_index(require_rbracket : boolean);
  132. var
  133. recname : string;
  134. o_int,s_int : tcgint;
  135. begin
  136. case actasmtoken of
  137. AS_ID :
  138. begin
  139. recname := actasmpattern;
  140. Consume(AS_ID);
  141. BuildRecordOffsetSize(recname,o_int,s_int,recname,false);
  142. inc(oper.opr.ref.offset,o_int);
  143. test_end(require_rbracket);
  144. exit;
  145. end;
  146. AS_AT:
  147. begin
  148. do_error;
  149. exit;
  150. end;
  151. AS_DOT : // local label
  152. begin
  153. BuildConstExpression(true,false);
  154. test_end(require_rbracket);
  155. exit;
  156. end;
  157. AS_SEPARATOR,AS_end :
  158. begin
  159. if not require_rbracket then
  160. begin
  161. test_end(false);
  162. exit;
  163. end
  164. else
  165. begin
  166. do_error;
  167. exit;
  168. end;
  169. end;
  170. else
  171. begin
  172. // unexpected token
  173. do_error;
  174. exit;
  175. end;
  176. end; // case
  177. end;
  178. var
  179. lab : TASMLABEL;
  180. begin
  181. Consume(AS_LBRACKET);
  182. if actasmtoken=AS_REGISTER then
  183. begin
  184. oper.opr.ref.base:=actasmregister;
  185. Consume(AS_REGISTER);
  186. case actasmtoken of
  187. AS_COMMA :
  188. begin
  189. Consume(AS_COMMA);
  190. read_index(true);
  191. exit;
  192. end;
  193. else
  194. begin
  195. Message(asmr_e_invalid_reference_syntax);
  196. RecoverConsume(false);
  197. end;
  198. end;
  199. end
  200. else
  201. Begin
  202. case actasmtoken of
  203. AS_ID :
  204. begin
  205. // TODO: Stackpointer implied,
  206. Message(asmr_e_invalid_reference_syntax);
  207. RecoverConsume(false);
  208. exit;
  209. end;
  210. else
  211. begin
  212. Message(asmr_e_invalid_reference_syntax);
  213. RecoverConsume(false);
  214. exit;
  215. end;
  216. end;
  217. end;
  218. end;
  219. Procedure txtensaattreader.BuildOperand(oper : TXtensaOperand);
  220. var
  221. expr : string;
  222. typesize,l : tcgint;
  223. procedure AddLabelOperand(hl:tasmlabel);
  224. begin
  225. oper.opr.typ:=OPR_SYMBOL;
  226. oper.opr.symbol:=hl;
  227. end;
  228. procedure MaybeRecordOffset;
  229. var
  230. mangledname: string;
  231. hasdot : boolean;
  232. l,
  233. toffset,
  234. tsize : tcgint;
  235. begin
  236. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  237. exit;
  238. l:=0;
  239. mangledname:='';
  240. hasdot:=(actasmtoken=AS_DOT);
  241. if hasdot then
  242. begin
  243. if expr<>'' then
  244. begin
  245. BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
  246. if (oper.opr.typ<>OPR_CONSTANT) and
  247. (mangledname<>'') then
  248. Message(asmr_e_wrong_sym_type);
  249. inc(l,toffset);
  250. oper.SetSize(tsize,true);
  251. end;
  252. end;
  253. if actasmtoken in [AS_PLUS,AS_MINUS] then
  254. inc(l,BuildConstExpression(true,false));
  255. case oper.opr.typ of
  256. OPR_LOCAL :
  257. begin
  258. { don't allow direct access to fields of parameters, because that
  259. will generate buggy code. Allow it only for explicit typecasting }
  260. if hasdot and
  261. (not oper.hastype) then
  262. checklocalsubscript(oper.opr.localsym);
  263. oper.opr.localforceref:=true;
  264. inc(oper.opr.localsymofs,l)
  265. end;
  266. OPR_CONSTANT :
  267. inc(oper.opr.val,l);
  268. OPR_REFERENCE :
  269. if (mangledname<>'') then
  270. begin
  271. if (oper.opr.val<>0) then
  272. Message(asmr_e_wrong_sym_type);
  273. oper.opr.typ:=OPR_SYMBOL;
  274. oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname,AT_FUNCTION);
  275. end
  276. else
  277. inc(oper.opr.val,l);
  278. OPR_SYMBOL:
  279. Message(asmr_e_invalid_symbol_ref);
  280. else
  281. internalerror(200309221);
  282. end;
  283. end;
  284. function MaybeBuildReference:boolean;
  285. { Try to create a reference, if not a reference is found then false
  286. is returned }
  287. begin
  288. MaybeBuildReference:=true;
  289. case actasmtoken of
  290. AS_INTNUM,
  291. AS_MINUS,
  292. AS_PLUS:
  293. Begin
  294. oper.opr.ref.offset:=BuildConstExpression(True,False);
  295. if actasmtoken<>AS_LPAREN then
  296. Message(asmr_e_invalid_reference_syntax)
  297. else
  298. BuildReference(oper);
  299. end;
  300. AS_LPAREN:
  301. BuildReference(oper);
  302. AS_ID: { only a variable is allowed ... }
  303. Begin
  304. ReadSym(oper);
  305. case actasmtoken of
  306. AS_end,
  307. AS_SEPARATOR,
  308. AS_COMMA: ;
  309. AS_LPAREN:
  310. BuildReference(oper);
  311. else
  312. Begin
  313. Message(asmr_e_invalid_reference_syntax);
  314. Consume(actasmtoken);
  315. end;
  316. end; {end case }
  317. end;
  318. else
  319. MaybeBuildReference:=false;
  320. end; { end case }
  321. end;
  322. procedure BuildDirectRef;
  323. function GetConstLabel(const symname: string; ofs: aint): TAsmLabel;
  324. var
  325. hp: tai;
  326. newconst: tai_const;
  327. lab: TAsmLabel;
  328. begin
  329. if symname<>'' then
  330. newconst:=tai_const.Createname(symname,ofs)
  331. else
  332. newconst:=tai_const.Create_32bit(ofs);
  333. hp:=tai(current_procinfo.aktlocaldata.First);
  334. while assigned(hp) do
  335. begin
  336. if hp.typ=ait_const then
  337. begin
  338. if (tai_const(hp).sym=newconst.sym) and
  339. (tai_const(hp).value=newconst.value) and
  340. assigned(hp.Previous) and
  341. (tai(hp.previous).typ=ait_label) then
  342. begin
  343. newconst.Free;
  344. result:=tai_label(hp.Previous).labsym;
  345. exit;
  346. end;
  347. end;
  348. hp:=tai(hp.Next);
  349. end;
  350. current_asmdata.getjumplabel(lab);
  351. current_procinfo.aktlocaldata.concat(tai_align.create(4));
  352. current_procinfo.aktlocaldata.concat(tai_label.create(lab));
  353. current_procinfo.aktlocaldata.concat(newconst);
  354. result:=lab;
  355. end;
  356. var
  357. symtype: TAsmsymtype;
  358. sym: string;
  359. val: tcgint;
  360. begin
  361. case actasmtoken of
  362. AS_INTNUM,
  363. AS_ID:
  364. begin
  365. BuildConstSymbolExpression(true,false,false,val,sym,symtype);
  366. if symtype=AT_NONE then
  367. sym:='';
  368. reference_reset(oper.opr.ref,4,[]);
  369. oper.opr.ref.symbol:=GetConstLabel(sym,val);
  370. end;
  371. else
  372. ;
  373. end;
  374. end;
  375. function getregsetindex(reg: tregister): integer;
  376. begin
  377. if getsubreg(reg)=R_SUBFS then
  378. begin
  379. result:=getsupreg(reg)*2;
  380. if result>32 then
  381. result:=result-63;
  382. end
  383. else
  384. result:=getsupreg(reg);
  385. end;
  386. var
  387. tempreg : tregister;
  388. ireg : tsuperregister;
  389. regtype: tregistertype;
  390. subreg: tsubregister;
  391. hl : tasmlabel;
  392. {ofs : longint;}
  393. registerset : tcpuregisterset;
  394. Begin
  395. expr:='';
  396. case actasmtoken of
  397. AS_LBRACKET: { Memory reference or constant expression }
  398. Begin
  399. oper.InitRef;
  400. BuildReference(oper);
  401. end;
  402. AS_MINUS,
  403. AS_PLUS,
  404. AS_INTNUM: { Constant expression }
  405. Begin
  406. BuildConstantOperand(oper);
  407. end;
  408. AS_ID: { A constant expression, or a Variable ref. }
  409. Begin
  410. if is_locallabel(actasmpattern) then
  411. begin
  412. CreateLocalLabel(actasmpattern,hl,false);
  413. Consume(AS_ID);
  414. AddLabelOperand(hl);
  415. end
  416. else
  417. { Check for label }
  418. if SearchLabel(actasmpattern,hl,false) then
  419. begin
  420. Consume(AS_ID);
  421. AddLabelOperand(hl);
  422. end
  423. else
  424. { probably a variable or normal expression }
  425. { or a procedure (such as in CALL ID) }
  426. Begin
  427. { is it a constant ? }
  428. if SearchIConstant(actasmpattern,l) then
  429. Begin
  430. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  431. Message(asmr_e_invalid_operand_type);
  432. BuildConstantOperand(oper);
  433. end
  434. else
  435. begin
  436. expr:=actasmpattern;
  437. Consume(AS_ID);
  438. { typecasting? }
  439. if (actasmtoken=AS_LPAREN) and
  440. SearchType(expr,typesize) then
  441. begin
  442. oper.hastype:=true;
  443. Consume(AS_LPAREN);
  444. BuildOperand(oper);
  445. Consume(AS_RPAREN);
  446. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  447. oper.SetSize(typesize,true);
  448. end
  449. else
  450. begin
  451. if not(oper.SetupVar(expr,false)) then
  452. Begin
  453. { look for special symbols ... }
  454. if expr= '__HIGH' then
  455. begin
  456. consume(AS_LPAREN);
  457. if not oper.setupvar('high'+actasmpattern,false) then
  458. Message1(sym_e_unknown_id,'high'+actasmpattern);
  459. consume(AS_ID);
  460. consume(AS_RPAREN);
  461. end
  462. else
  463. if expr = '__RESULT' then
  464. oper.SetUpResult
  465. else
  466. if expr = '__SELF' then
  467. oper.SetupSelf
  468. else
  469. if expr = '__OLDEBP' then
  470. oper.SetupOldEBP
  471. else
  472. Message1(sym_e_unknown_id,expr);
  473. end;
  474. end;
  475. end;
  476. if actasmtoken=AS_DOT then
  477. MaybeRecordOffset;
  478. { add a constant expression? }
  479. if (actasmtoken=AS_PLUS) then
  480. begin
  481. l:=BuildConstExpression(true,false);
  482. case oper.opr.typ of
  483. OPR_CONSTANT :
  484. inc(oper.opr.val,l);
  485. OPR_LOCAL :
  486. inc(oper.opr.localsymofs,l);
  487. OPR_REFERENCE :
  488. inc(oper.opr.ref.offset,l);
  489. else
  490. internalerror(2003092004);
  491. end;
  492. end
  493. end;
  494. { Do we have a indexing reference, then parse it also }
  495. if actasmtoken=AS_LPAREN then
  496. BuildReference(oper);
  497. end;
  498. { Register, a variable reference or a constant reference }
  499. AS_REGISTER:
  500. Begin
  501. { save the type of register used. }
  502. tempreg:=actasmregister;
  503. Consume(AS_REGISTER);
  504. if (actasmtoken in [AS_end,AS_SEPARATOR,AS_COMMA]) then
  505. Begin
  506. if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
  507. Message(asmr_e_invalid_operand_type);
  508. oper.opr.typ:=OPR_REGISTER;
  509. oper.opr.reg:=tempreg;
  510. end
  511. else
  512. Message(asmr_e_syn_operand);
  513. end;
  514. AS_end,
  515. AS_SEPARATOR,
  516. AS_COMMA: ;
  517. else
  518. Begin
  519. Message(asmr_e_syn_operand);
  520. Consume(actasmtoken);
  521. end;
  522. end; { end case }
  523. end;
  524. procedure txtensaattreader.BuildSpecialreg(oper: TXtensaOperand);
  525. var
  526. hs, reg : String;
  527. ch : char;
  528. i, t : longint;
  529. hreg : tregister;
  530. flags : tspecialregflags;
  531. begin
  532. hreg:=NR_NO;
  533. case actasmtoken of
  534. AS_REGISTER:
  535. begin
  536. oper.opr.typ:=OPR_REGISTER;
  537. oper.opr.reg:=actasmregister;
  538. Consume(AS_REGISTER);
  539. end;
  540. else
  541. Message(asmr_e_invalid_operand_type);
  542. end;
  543. end;
  544. {*****************************************************************************
  545. tarmattreader
  546. *****************************************************************************}
  547. procedure txtensaattreader.BuildOpCode(instr : TXtensaInstruction);
  548. var
  549. operandnum : longint;
  550. Begin
  551. { opcode }
  552. if (actasmtoken<>AS_OPCODE) then
  553. Begin
  554. Message(asmr_e_invalid_or_missing_opcode);
  555. RecoverConsume(true);
  556. exit;
  557. end;
  558. { Fill the instr object with the current state }
  559. with instr do
  560. begin
  561. Opcode:=ActOpcode;
  562. condition:=ActCondition;
  563. oppostfix:=actoppostfix;
  564. opIsPrefixed:=actIsPrefixed;
  565. end;
  566. { We are reading operands, so opcode will be an AS_ID }
  567. operandnum:=1;
  568. Consume(AS_OPCODE);
  569. { Zero operand opcode ? }
  570. if actasmtoken in [AS_SEPARATOR,AS_end] then
  571. begin
  572. operandnum:=0;
  573. exit;
  574. end;
  575. { Read the operands }
  576. repeat
  577. case actasmtoken of
  578. AS_COMMA: { Operand delimiter }
  579. Begin
  580. if operandnum>Max_Operands then
  581. Message(asmr_e_too_many_operands)
  582. else
  583. Inc(operandnum);
  584. Consume(AS_COMMA);
  585. end;
  586. AS_SEPARATOR,
  587. AS_end : { End of asm operands for this opcode }
  588. begin
  589. break;
  590. end;
  591. else
  592. BuildOperand(instr.Operands[operandnum] as TXtensaOperand);
  593. end; { end case }
  594. until false;
  595. instr.Ops:=operandnum;
  596. end;
  597. function txtensaattreader.is_asmopcode(const s: string):boolean;
  598. const
  599. { sorted by length so longer postfixes will match first }
  600. postfix2strsorted : array[1..112] of string[13] = (
  601. 'IBREAKENABLE', 'DA.HH.LDDEC', 'DA.HH.LDINC', 'DA.HL.LDDEC', 'DA.HL.LDINC',
  602. 'DA.LH.LDDEC', 'DA.LH.LDINC', 'DA.LL.LDDEC', 'DA.LL.LDINC', 'DD.HH.LDDEC',
  603. 'DD.HH.LDINC', 'DD.HL.LDDEC', 'DD.HL.LDINC', 'DD.LH.LDDEC', 'DD.LH.LDINC',
  604. 'DD.LL.LDDEC', 'DD.LL.LDINC', 'ICOUNTLEVEL', 'WINDOWSTART', 'DEBUGCAUSE',
  605. 'WINDOWBASE', 'CCOMPARE0', 'CCOMPARE1', 'CCOMPARE2', 'INTENABLE',
  606. 'INTERRUPT', 'SCOMPARE1', 'CPENABLE', 'DBREAKA0', 'DBREAKA1',
  607. 'DBREAKC0', 'DBREAKC1', 'EXCCAUSE', 'EXCSAVE1', 'EXCSAVE2',
  608. 'EXCSAVE3', 'EXCSAVE4', 'EXCSAVE5', 'EXCSAVE6', 'EXCSAVE7',
  609. 'EXCVADDR', 'IBREAKA0', 'IBREAKA1', 'INTCLEAR', 'PTEVADDR',
  610. 'ATOMCTL', 'DTLBCFG', 'ITLBCFG', 'LITBASE', 'MEVADDR',
  611. 'VECBASE', 'CCOUNT', 'ICOUNT', 'INTSET', 'LCOUNT',
  612. 'MESAVE', 'AA.HH', 'AA.HL', 'AA.LH', 'AA.LL',
  613. 'ACCHI', 'ACCLO', 'AD.HH', 'AD.HL', 'AD.LH',
  614. 'AD.LL', 'DA.HH', 'DA.HL', 'DA.LH', 'DA.LL',
  615. 'DD.HH', 'DD.HL', 'DD.LH', 'DD.LL', 'MISC0',
  616. 'MISC1', 'MISC2', 'MISC3', 'RASID', 'DEPC',
  617. 'EPC1', 'EPC2', 'EPC3', 'EPC4', 'EPC5',
  618. 'EPC6', 'EPC7', 'EPS2', 'EPS3', 'EPS4',
  619. 'EPS5', 'EPS6', 'EPS7', 'LBEG', 'LEND',
  620. 'MECR', 'MEPC', 'MEPS', 'MESR', 'MMID',
  621. 'PRID', 'DDR', 'SAR', 'BR', 'M0',
  622. 'M1', 'M2', 'M3', 'PS', 'L',
  623. 'N', 'S');
  624. postfixsorted : array[1..112] of TOpPostfix = (
  625. PF_IBREAKENABLE, PF_DA_HH_LDDEC, PF_DA_HH_LDINC, PF_DA_HL_LDDEC, PF_DA_HL_LDINC,
  626. PF_DA_LH_LDDEC, PF_DA_LH_LDINC, PF_DA_LL_LDDEC, PF_DA_LL_LDINC, PF_DD_HH_LDDEC,
  627. PF_DD_HH_LDINC, PF_DD_HL_LDDEC, PF_DD_HL_LDINC, PF_DD_LH_LDDEC, PF_DD_LH_LDINC,
  628. PF_DD_LL_LDDEC, PF_DD_LL_LDINC, PF_ICOUNTLEVEL, PF_WINDOWSTART, PF_DEBUGCAUSE,
  629. PF_WINDOWBASE, PF_CCOMPARE0, PF_CCOMPARE1, PF_CCOMPARE2, PF_INTENABLE,
  630. PF_INTERRUPT, PF_SCOMPARE1, PF_CPENABLE, PF_DBREAKA0, PF_DBREAKA1,
  631. PF_DBREAKC0, PF_DBREAKC1, PF_EXCCAUSE, PF_EXCSAVE1, PF_EXCSAVE2,
  632. PF_EXCSAVE3, PF_EXCSAVE4, PF_EXCSAVE5, PF_EXCSAVE6, PF_EXCSAVE7,
  633. PF_EXCVADDR, PF_IBREAKA0, PF_IBREAKA1, PF_INTCLEAR, PF_PTEVADDR,
  634. PF_ATOMCTL, PF_DTLBCFG, PF_ITLBCFG, PF_LITBASE, PF_MEVADDR,
  635. PF_VECBASE, PF_CCOUNT, PF_ICOUNT, PF_INTSET, PF_LCOUNT,
  636. PF_MESAVE, PF_AA_HH, PF_AA_HL, PF_AA_LH, PF_AA_LL,
  637. PF_ACCHI, PF_ACCLO, PF_AD_HH, PF_AD_HL, PF_AD_LH,
  638. PF_AD_LL, PF_DA_HH, PF_DA_HL, PF_DA_LH, PF_DA_LL,
  639. PF_DD_HH, PF_DD_HL, PF_DD_LH, PF_DD_LL, PF_MISC0,
  640. PF_MISC1, PF_MISC2, PF_MISC3, PF_RASID, PF_DEPC,
  641. PF_EPC1, PF_EPC2, PF_EPC3, PF_EPC4, PF_EPC5,
  642. PF_EPC6, PF_EPC7, PF_EPS2, PF_EPS3, PF_EPS4,
  643. PF_EPS5, PF_EPS6, PF_EPS7, PF_LBEG, PF_LEND,
  644. PF_MECR, PF_MEPC, PF_MEPS, PF_MESR, PF_MMID,
  645. PF_PRID, PF_DDR, PF_SAR, PF_BR, PF_M0,
  646. PF_M1, PF_M2, PF_M3, PF_PS, PF_L,
  647. PF_N, PF_S);
  648. var
  649. j, j2 : longint;
  650. hs,hs2 : string;
  651. maxlen : longint;
  652. icond : tasmcond;
  653. Begin
  654. { making s a value parameter would break other assembler readers }
  655. hs:=s;
  656. is_asmopcode:=false;
  657. { clear op code }
  658. actopcode:=A_NONE;
  659. actcondition:=C_None;
  660. actoppostfix := PF_None;
  661. actIsPrefixed := false;
  662. if hs[1]='_' then
  663. begin
  664. actIsPrefixed := true;
  665. delete(hs, 1, 1);
  666. end;
  667. if (hs[1]='B') and not(hs='BREAK') then
  668. begin
  669. { Branch condition can be followed by a postfix, e.g. BEQZ.N or BBSI.L }
  670. j:=pos('.', hs);
  671. if j < 2 then
  672. j:=length(hs)
  673. else
  674. dec(j);
  675. hs2:=copy(hs, 2, j-1);
  676. for icond:=low(tasmcond) to high(tasmcond) do
  677. begin
  678. if hs2=uppercond2str[icond] then
  679. begin
  680. actopcode:=A_B;
  681. actasmtoken:=AS_OPCODE;
  682. actcondition:=icond;
  683. is_asmopcode:=true;
  684. delete(hs, 1, j);
  685. break;
  686. end;
  687. end;
  688. end
  689. else
  690. begin
  691. j2:=min(length(hs),7);
  692. hs2:=hs;
  693. while (j2>=1) and (actopcode=A_NONE) do
  694. begin
  695. hs:=hs2;
  696. while j2>=1 do
  697. begin
  698. actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j2))));
  699. if actopcode<>A_NONE then
  700. begin
  701. actasmtoken:=AS_OPCODE;
  702. { strip op code }
  703. delete(hs,1,j2);
  704. dec(j2);
  705. break;
  706. end;
  707. dec(j2);
  708. end;
  709. end;
  710. end;
  711. if actopcode=A_NONE then
  712. exit;
  713. { check for postfix }
  714. if (length(hs)>0) then
  715. begin
  716. for j:=low(postfixsorted) to high(postfixsorted) do
  717. begin
  718. if copy(hs,2,length(postfix2strsorted[j]))=postfix2strsorted[j] then
  719. begin
  720. actoppostfix:=postfixsorted[j];
  721. { strip postfix }
  722. delete(hs,1,length(postfix2strsorted[j])+1);
  723. break;
  724. end;
  725. end;
  726. end;
  727. { if we stripped all postfixes, it's a valid opcode }
  728. is_asmopcode:=length(hs)=0;
  729. end;
  730. procedure txtensaattreader.ConvertCalljmp(instr : TXtensaInstruction);
  731. var
  732. newopr : toprrec;
  733. begin
  734. if instr.Operands[1].opr.typ=OPR_REFERENCE then
  735. begin
  736. newopr.typ:=OPR_SYMBOL;
  737. newopr.symbol:=instr.Operands[1].opr.ref.symbol;
  738. newopr.symofs:=instr.Operands[1].opr.ref.offset;
  739. if (instr.Operands[1].opr.ref.base<>NR_NO) or
  740. (instr.Operands[1].opr.ref.index<>NR_NO) then
  741. Message(asmr_e_syn_operand);
  742. instr.Operands[1].opr:=newopr;
  743. end;
  744. end;
  745. procedure txtensaattreader.HandleTargetDirective;
  746. var
  747. symname,
  748. symval : String;
  749. val : tcgint;
  750. symtyp : TAsmsymtype;
  751. begin
  752. case actasmpattern of
  753. '.code':
  754. begin
  755. consume(AS_TARGET_DIRECTIVE);
  756. val:=BuildConstExpression(false,false);
  757. if not(val in [16,32]) then
  758. Message(asmr_e_invalid_code_value);
  759. curList.concat(tai_directive.create(asd_code,tostr(val)));
  760. end;
  761. else
  762. inherited HandleTargetDirective;
  763. end;
  764. end;
  765. procedure txtensaattreader.handleopcode;
  766. var
  767. instr : TXtensaInstruction;
  768. begin
  769. instr:=TXtensaInstruction.Create(TXtensaOperand);
  770. BuildOpcode(instr);
  771. if is_calljmp(instr.opcode) then
  772. ConvertCalljmp(instr);
  773. instr.ConcatInstruction(curlist);
  774. instr.Free;
  775. end;
  776. {*****************************************************************************
  777. Initialize
  778. *****************************************************************************}
  779. const
  780. asmmode_xtensa_att_info : tasmmodeinfo =
  781. (
  782. id : asmmode_xtensa_gas;
  783. idtxt : 'DIVIDED';
  784. casmreader : txtensaattreader;
  785. );
  786. asmmode_xtensa_standard_info : tasmmodeinfo =
  787. (
  788. id : asmmode_standard;
  789. idtxt : 'STANDARD';
  790. casmreader : txtensaattreader;
  791. );
  792. initialization
  793. RegisterAsmMode(asmmode_xtensa_att_info);
  794. RegisterAsmMode(asmmode_xtensa_standard_info);
  795. end.