rax86att.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  4. Does the parsing for the x86 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 rax86att;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses
  22. cpubase,
  23. raatt,rax86;
  24. type
  25. tx86attreader = class(tattreader)
  26. ActOpsize : topsize;
  27. function is_asmopcode(const s: string):boolean;override;
  28. procedure handleopcode;override;
  29. procedure BuildReference(oper : tx86operand);
  30. procedure BuildOperand(oper : tx86operand);
  31. procedure BuildOpCode(instr : tx86instruction);
  32. procedure handlepercent;override;
  33. end;
  34. Implementation
  35. uses
  36. { helpers }
  37. cutils,
  38. { global }
  39. globtype,verbose,
  40. systems,
  41. { aasm }
  42. aasmbase,aasmtai,aasmcpu,
  43. { symtable }
  44. symconst,
  45. { parser }
  46. scanner,
  47. procinfo,
  48. itcpugas,
  49. rabase,rautils,
  50. cgbase
  51. ;
  52. procedure tx86attreader.handlepercent;
  53. var
  54. len : longint;
  55. begin
  56. len:=1;
  57. actasmpattern[len]:='%';
  58. c:=current_scanner.asmgetchar;
  59. { to be a register there must be a letter and not a number }
  60. if c in ['0'..'9'] then
  61. begin
  62. actasmtoken:=AS_MOD;
  63. end
  64. else
  65. begin
  66. while c in ['a'..'z','A'..'Z','0'..'9'] do
  67. Begin
  68. inc(len);
  69. actasmpattern[len]:=c;
  70. c:=current_scanner.asmgetchar;
  71. end;
  72. actasmpattern[0]:=chr(len);
  73. uppervar(actasmpattern);
  74. if (actasmpattern = '%ST') and (c='(') then
  75. Begin
  76. actasmpattern:=actasmpattern+c;
  77. c:=current_scanner.asmgetchar;
  78. if c in ['0'..'9'] then
  79. actasmpattern:=actasmpattern + c
  80. else
  81. Message(asmr_e_invalid_fpu_register);
  82. c:=current_scanner.asmgetchar;
  83. if c <> ')' then
  84. Message(asmr_e_invalid_fpu_register)
  85. else
  86. Begin
  87. actasmpattern:=actasmpattern + c;
  88. c:=current_scanner.asmgetchar; { let us point to next character. }
  89. end;
  90. end;
  91. if is_register(actasmpattern) then
  92. exit;
  93. Message(asmr_e_invalid_register);
  94. actasmtoken:=raatt.AS_NONE;
  95. end;
  96. end;
  97. Procedure tx86attreader.BuildReference(oper : tx86operand);
  98. procedure Consume_RParen;
  99. begin
  100. if actasmtoken <> AS_RPAREN then
  101. Begin
  102. Message(asmr_e_invalid_reference_syntax);
  103. RecoverConsume(true);
  104. end
  105. else
  106. begin
  107. Consume(AS_RPAREN);
  108. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
  109. Begin
  110. Message(asmr_e_invalid_reference_syntax);
  111. RecoverConsume(true);
  112. end;
  113. end;
  114. end;
  115. procedure Consume_Scale;
  116. var
  117. l : aint;
  118. begin
  119. { we have to process the scaling }
  120. l:=BuildConstExpression(false,true);
  121. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
  122. oper.opr.ref.scalefactor:=l
  123. else
  124. Begin
  125. Message(asmr_e_wrong_scale_factor);
  126. oper.opr.ref.scalefactor:=0;
  127. end;
  128. end;
  129. begin
  130. oper.InitRef;
  131. Consume(AS_LPAREN);
  132. Case actasmtoken of
  133. AS_INTNUM,
  134. AS_MINUS,
  135. AS_PLUS: { absolute offset, such as fs:(0x046c) }
  136. Begin
  137. { offset(offset) is invalid }
  138. If oper.opr.Ref.Offset <> 0 Then
  139. Begin
  140. Message(asmr_e_invalid_reference_syntax);
  141. RecoverConsume(true);
  142. End
  143. Else
  144. Begin
  145. oper.opr.Ref.Offset:=BuildConstExpression(false,true);
  146. Consume_RParen;
  147. end;
  148. exit;
  149. End;
  150. AS_REGISTER: { (reg ... }
  151. Begin
  152. { Check if there is already a base (mostly ebp,esp) than this is
  153. not allowed, because it will give crashing code }
  154. if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
  155. ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
  156. message(asmr_e_cannot_index_relative_var);
  157. oper.opr.ref.base:=actasmregister;
  158. Consume(AS_REGISTER);
  159. { can either be a register or a right parenthesis }
  160. { (reg) }
  161. if actasmtoken=AS_RPAREN then
  162. Begin
  163. Consume_RParen;
  164. exit;
  165. end;
  166. { (reg,reg .. }
  167. Consume(AS_COMMA);
  168. if actasmtoken=AS_REGISTER then
  169. Begin
  170. oper.opr.ref.index:=actasmregister;
  171. Consume(AS_REGISTER);
  172. { check for scaling ... }
  173. case actasmtoken of
  174. AS_RPAREN:
  175. Begin
  176. Consume_RParen;
  177. exit;
  178. end;
  179. AS_COMMA:
  180. Begin
  181. Consume(AS_COMMA);
  182. Consume_Scale;
  183. Consume_RParen;
  184. end;
  185. else
  186. Begin
  187. Message(asmr_e_invalid_reference_syntax);
  188. RecoverConsume(false);
  189. end;
  190. end; { end case }
  191. end
  192. else
  193. Begin
  194. Message(asmr_e_invalid_reference_syntax);
  195. RecoverConsume(false);
  196. end;
  197. end; {end case }
  198. AS_COMMA: { (, ... can either be scaling, or index }
  199. Begin
  200. Consume(AS_COMMA);
  201. { Index }
  202. if (actasmtoken=AS_REGISTER) then
  203. Begin
  204. oper.opr.ref.index:=actasmregister;
  205. Consume(AS_REGISTER);
  206. { check for scaling ... }
  207. case actasmtoken of
  208. AS_RPAREN:
  209. Begin
  210. Consume_RParen;
  211. exit;
  212. end;
  213. AS_COMMA:
  214. Begin
  215. Consume(AS_COMMA);
  216. Consume_Scale;
  217. Consume_RParen;
  218. end;
  219. else
  220. Begin
  221. Message(asmr_e_invalid_reference_syntax);
  222. RecoverConsume(false);
  223. end;
  224. end; {end case }
  225. end
  226. { Scaling }
  227. else
  228. Begin
  229. Consume_Scale;
  230. Consume_RParen;
  231. exit;
  232. end;
  233. end;
  234. else
  235. Begin
  236. Message(asmr_e_invalid_reference_syntax);
  237. RecoverConsume(false);
  238. end;
  239. end;
  240. end;
  241. Procedure tx86attreader.BuildOperand(oper : tx86operand);
  242. var
  243. tempstr,
  244. expr : string;
  245. typesize,l,k : aint;
  246. procedure AddLabelOperand(hl:tasmlabel);
  247. begin
  248. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  249. is_calljmp(actopcode) then
  250. begin
  251. oper.opr.typ:=OPR_SYMBOL;
  252. oper.opr.symbol:=hl;
  253. end
  254. else
  255. begin
  256. oper.InitRef;
  257. oper.opr.ref.symbol:=hl;
  258. end;
  259. end;
  260. procedure MaybeRecordOffset;
  261. var
  262. hasdot : boolean;
  263. l,
  264. toffset,
  265. tsize : aint;
  266. begin
  267. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  268. exit;
  269. l:=0;
  270. hasdot:=(actasmtoken=AS_DOT);
  271. if hasdot then
  272. begin
  273. if expr<>'' then
  274. begin
  275. BuildRecordOffsetSize(expr,toffset,tsize);
  276. inc(l,toffset);
  277. oper.SetSize(tsize,true);
  278. end;
  279. end;
  280. if actasmtoken in [AS_PLUS,AS_MINUS] then
  281. inc(l,BuildConstExpression(true,false));
  282. case oper.opr.typ of
  283. OPR_LOCAL :
  284. begin
  285. { don't allow direct access to fields of parameters, because that
  286. will generate buggy code. Allow it only for explicit typecasting }
  287. if hasdot and
  288. (not oper.hastype) and
  289. (oper.opr.localsym.owner.symtabletype=parasymtable) and
  290. (current_procinfo.procdef.proccalloption<>pocall_register) then
  291. Message(asmr_e_cannot_access_field_directly_for_parameters);
  292. inc(oper.opr.localsymofs,l)
  293. end;
  294. OPR_CONSTANT :
  295. inc(oper.opr.val,l);
  296. OPR_REFERENCE :
  297. inc(oper.opr.ref.offset,l);
  298. else
  299. internalerror(200309221);
  300. end;
  301. end;
  302. procedure handleat;
  303. begin
  304. end;
  305. function MaybeBuildReference:boolean;
  306. { Try to create a reference, if not a reference is found then false
  307. is returned }
  308. begin
  309. MaybeBuildReference:=true;
  310. case actasmtoken of
  311. AS_INTNUM,
  312. AS_MINUS,
  313. AS_PLUS:
  314. Begin
  315. oper.opr.ref.offset:=BuildConstExpression(True,False);
  316. if actasmtoken<>AS_LPAREN then
  317. Message(asmr_e_invalid_reference_syntax)
  318. else
  319. BuildReference(oper);
  320. end;
  321. AS_LPAREN:
  322. BuildReference(oper);
  323. AS_ID: { only a variable is allowed ... }
  324. Begin
  325. tempstr:=actasmpattern;
  326. Consume(AS_ID);
  327. { typecasting? }
  328. if (actasmtoken=AS_LPAREN) and
  329. SearchType(tempstr,typesize) then
  330. begin
  331. oper.hastype:=true;
  332. Consume(AS_LPAREN);
  333. BuildOperand(oper);
  334. Consume(AS_RPAREN);
  335. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  336. oper.SetSize(typesize,true);
  337. end
  338. else
  339. if not oper.SetupVar(tempstr,false) then
  340. Message1(sym_e_unknown_id,tempstr);
  341. { record.field ? }
  342. if actasmtoken=AS_DOT then
  343. begin
  344. BuildRecordOffsetSize(tempstr,l,k);
  345. inc(oper.opr.ref.offset,l);
  346. end;
  347. if actasmtoken=AS_AT then
  348. begin
  349. consume(AS_AT);
  350. if actasmtoken=AS_ID then
  351. begin
  352. if actasmpattern='GOTPCREL' then
  353. oper.opr.ref.refaddr:=addr_pic
  354. else
  355. Message(asmr_e_invalid_reference_syntax);
  356. end
  357. else
  358. Message(asmr_e_invalid_reference_syntax);
  359. end;
  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. var
  378. tempreg : tregister;
  379. hl : tasmlabel;
  380. Begin
  381. expr:='';
  382. case actasmtoken of
  383. AS_LPAREN: { Memory reference or constant expression }
  384. Begin
  385. oper.InitRef;
  386. BuildReference(oper);
  387. end;
  388. AS_DOLLAR: { Constant expression }
  389. Begin
  390. Consume(AS_DOLLAR);
  391. BuildConstantOperand(oper);
  392. end;
  393. AS_INTNUM,
  394. AS_MINUS,
  395. AS_PLUS:
  396. Begin
  397. { Constant memory offset }
  398. { This must absolutely be followed by ( }
  399. oper.InitRef;
  400. oper.opr.ref.offset:=BuildConstExpression(True,False);
  401. if actasmtoken<>AS_LPAREN then
  402. Message(asmr_e_invalid_reference_syntax)
  403. else
  404. BuildReference(oper);
  405. end;
  406. AS_STAR: { Call from memory address }
  407. Begin
  408. Consume(AS_STAR);
  409. if actasmtoken=AS_REGISTER then
  410. begin
  411. oper.opr.typ:=OPR_REGISTER;
  412. oper.opr.reg:=actasmregister;
  413. oper.SetSize(tcgsize2size[reg_cgsize(actasmregister)],true);
  414. Consume(AS_REGISTER);
  415. end
  416. else
  417. begin
  418. oper.InitRef;
  419. if not MaybeBuildReference then
  420. Message(asmr_e_syn_operand);
  421. end;
  422. { this is only allowed for call's and jmp's }
  423. if not is_calljmp(actopcode) then
  424. Message(asmr_e_syn_operand);
  425. end;
  426. AS_ID: { A constant expression, or a Variable ref. }
  427. Begin
  428. { Local Label ? }
  429. if is_locallabel(actasmpattern) then
  430. begin
  431. CreateLocalLabel(actasmpattern,hl,false);
  432. Consume(AS_ID);
  433. AddLabelOperand(hl);
  434. end
  435. else
  436. { Check for label }
  437. if SearchLabel(actasmpattern,hl,false) then
  438. begin
  439. Consume(AS_ID);
  440. AddLabelOperand(hl);
  441. end
  442. else
  443. { probably a variable or normal expression }
  444. { or a procedure (such as in CALL ID) }
  445. Begin
  446. { is it a constant ? }
  447. if SearchIConstant(actasmpattern,l) then
  448. Begin
  449. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  450. Message(asmr_e_invalid_operand_type);
  451. BuildConstantOperand(oper);
  452. end
  453. else
  454. begin
  455. expr:=actasmpattern;
  456. Consume(AS_ID);
  457. { typecasting? }
  458. if (actasmtoken=AS_LPAREN) and
  459. SearchType(expr,typesize) then
  460. begin
  461. oper.hastype:=true;
  462. Consume(AS_LPAREN);
  463. BuildOperand(oper);
  464. Consume(AS_RPAREN);
  465. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  466. oper.SetSize(typesize,true);
  467. end
  468. else
  469. begin
  470. if oper.SetupVar(expr,false) then
  471. begin
  472. if actasmtoken=AS_AT then
  473. begin
  474. consume(AS_AT);
  475. if actasmtoken=AS_ID then
  476. begin
  477. if actasmpattern='GOTPCREL' then
  478. begin
  479. oper.opr.ref.refaddr:=addr_pic;
  480. consume(AS_ID);
  481. end
  482. else
  483. Message(asmr_e_invalid_reference_syntax);
  484. end
  485. else
  486. Message(asmr_e_invalid_reference_syntax);
  487. end;
  488. end
  489. else
  490. Begin
  491. { look for special symbols ... }
  492. if expr= '__HIGH' then
  493. begin
  494. consume(AS_LPAREN);
  495. if not oper.setupvar('high'+actasmpattern,false) then
  496. Message1(sym_e_unknown_id,'high'+actasmpattern);
  497. consume(AS_ID);
  498. consume(AS_RPAREN);
  499. end
  500. else
  501. if expr = '__RESULT' then
  502. oper.SetUpResult
  503. else
  504. if expr = '__SELF' then
  505. oper.SetupSelf
  506. else
  507. if expr = '__OLDEBP' then
  508. oper.SetupOldEBP
  509. else
  510. Message1(sym_e_unknown_id,expr);
  511. end;
  512. end;
  513. end;
  514. if actasmtoken=AS_DOT then
  515. MaybeRecordOffset;
  516. { add a constant expression? }
  517. if (actasmtoken=AS_PLUS) then
  518. begin
  519. l:=BuildConstExpression(true,false);
  520. case oper.opr.typ of
  521. OPR_CONSTANT :
  522. inc(oper.opr.val,l);
  523. OPR_LOCAL :
  524. inc(oper.opr.localsymofs,l);
  525. OPR_REFERENCE :
  526. inc(oper.opr.ref.offset,l);
  527. else
  528. internalerror(200309202);
  529. end;
  530. end
  531. end;
  532. { Do we have a indexing reference, then parse it also }
  533. if actasmtoken=AS_LPAREN then
  534. BuildReference(oper);
  535. end;
  536. AS_REGISTER: { Register, a variable reference or a constant reference }
  537. Begin
  538. { save the type of register used. }
  539. tempreg:=actasmregister;
  540. Consume(AS_REGISTER);
  541. if actasmtoken = AS_COLON then
  542. Begin
  543. Consume(AS_COLON);
  544. oper.InitRef;
  545. oper.opr.ref.segment:=tempreg;
  546. { This must absolutely be followed by a reference }
  547. if not MaybeBuildReference then
  548. Begin
  549. Message(asmr_e_invalid_seg_override);
  550. Consume(actasmtoken);
  551. end;
  552. end
  553. { Simple register }
  554. else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  555. Begin
  556. if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
  557. Message(asmr_e_invalid_operand_type);
  558. oper.opr.typ:=OPR_REGISTER;
  559. oper.opr.reg:=tempreg;
  560. oper.SetSize(tcgsize2size[reg_cgsize(oper.opr.reg)],true);
  561. end
  562. else
  563. Message(asmr_e_syn_operand);
  564. end;
  565. AS_END,
  566. AS_SEPARATOR,
  567. AS_COMMA: ;
  568. else
  569. Begin
  570. Message(asmr_e_syn_operand);
  571. Consume(actasmtoken);
  572. end;
  573. end; { end case }
  574. end;
  575. procedure tx86attreader.BuildOpCode(instr : tx86instruction);
  576. var
  577. operandnum : longint;
  578. PrefixOp,OverrideOp: tasmop;
  579. Begin
  580. PrefixOp:=A_None;
  581. OverrideOp:=A_None;
  582. { prefix seg opcode / prefix opcode }
  583. repeat
  584. if is_prefix(actopcode) then
  585. begin
  586. PrefixOp:=ActOpcode;
  587. with instr do
  588. begin
  589. opcode:=ActOpcode;
  590. condition:=ActCondition;
  591. opsize:=ActOpsize;
  592. ConcatInstruction(curlist);
  593. end;
  594. Consume(AS_OPCODE);
  595. end
  596. else
  597. if is_override(actopcode) then
  598. begin
  599. OverrideOp:=ActOpcode;
  600. with instr do
  601. begin
  602. opcode:=ActOpcode;
  603. condition:=ActCondition;
  604. opsize:=ActOpsize;
  605. ConcatInstruction(curlist);
  606. end;
  607. Consume(AS_OPCODE);
  608. end
  609. else
  610. break;
  611. { allow for newline as in gas styled syntax }
  612. while actasmtoken=AS_SEPARATOR do
  613. Consume(AS_SEPARATOR);
  614. until (actasmtoken<>AS_OPCODE);
  615. { opcode }
  616. if (actasmtoken<>AS_OPCODE) then
  617. Begin
  618. Message(asmr_e_invalid_or_missing_opcode);
  619. RecoverConsume(true);
  620. exit;
  621. end;
  622. { Fill the instr object with the current state }
  623. with instr do
  624. begin
  625. Opcode:=ActOpcode;
  626. condition:=ActCondition;
  627. opsize:=ActOpsize;
  628. end;
  629. { Valid combination of prefix/override and instruction ? }
  630. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  631. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  632. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  633. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  634. { We are reading operands, so opcode will be an AS_ID }
  635. operandnum:=1;
  636. Consume(AS_OPCODE);
  637. { Zero operand opcode ? }
  638. if actasmtoken in [AS_SEPARATOR,AS_END] then
  639. begin
  640. operandnum:=0;
  641. exit;
  642. end;
  643. { Read the operands }
  644. repeat
  645. case actasmtoken of
  646. AS_COMMA: { Operand delimiter }
  647. Begin
  648. if operandnum > Max_Operands then
  649. Message(asmr_e_too_many_operands)
  650. else
  651. Inc(operandnum);
  652. Consume(AS_COMMA);
  653. end;
  654. AS_SEPARATOR,
  655. AS_END : { End of asm operands for this opcode }
  656. begin
  657. break;
  658. end;
  659. else
  660. BuildOperand(instr.Operands[operandnum] as tx86operand);
  661. end; { end case }
  662. until false;
  663. instr.Ops:=operandnum;
  664. end;
  665. function tx86attreader.is_asmopcode(const s: string):boolean;
  666. const
  667. { We need first to check the long prefixes, else we get probs
  668. with things like movsbl }
  669. att_sizesuffixstr : array[0..9] of string[2] = (
  670. '','BW','BL','WL','B','W','L','S','Q','T'
  671. );
  672. att_sizesuffix : array[0..9] of topsize = (
  673. S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
  674. );
  675. att_sizefpusuffix : array[0..9] of topsize = (
  676. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
  677. );
  678. att_sizefpuintsuffix : array[0..9] of topsize = (
  679. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
  680. );
  681. var
  682. str2opentry: tstr2opentry;
  683. cond : string[4];
  684. cnd : tasmcond;
  685. len,
  686. j,
  687. sufidx : longint;
  688. Begin
  689. is_asmopcode:=FALSE;
  690. actopcode:=A_None;
  691. actcondition:=C_None;
  692. actopsize:=S_NO;
  693. { search for all possible suffixes }
  694. for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
  695. begin
  696. len:=length(s)-length(att_sizesuffixstr[sufidx]);
  697. if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
  698. begin
  699. { here we search the entire table... }
  700. str2opentry:=nil;
  701. if {(length(s)>0) and} (len>0) then
  702. str2opentry:=tstr2opentry(iasmops.search(copy(s,1,len)));
  703. if assigned(str2opentry) then
  704. begin
  705. actopcode:=str2opentry.op;
  706. if gas_needsuffix[actopcode]=attsufFPU then
  707. actopsize:=att_sizefpusuffix[sufidx]
  708. else if gas_needsuffix[actopcode]=attsufFPUint then
  709. actopsize:=att_sizefpuintsuffix[sufidx]
  710. else
  711. actopsize:=att_sizesuffix[sufidx];
  712. actasmtoken:=AS_OPCODE;
  713. is_asmopcode:=TRUE;
  714. exit;
  715. end;
  716. { not found, check condition opcodes }
  717. j:=0;
  718. while (j<CondAsmOps) do
  719. begin
  720. if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
  721. begin
  722. cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
  723. if cond<>'' then
  724. begin
  725. for cnd:=low(TasmCond) to high(TasmCond) do
  726. if Cond=Upper(cond2str[cnd]) then
  727. begin
  728. actopcode:=CondASmOp[j];
  729. if gas_needsuffix[actopcode]=attsufFPU then
  730. actopsize:=att_sizefpusuffix[sufidx]
  731. else if gas_needsuffix[actopcode]=attsufFPUint then
  732. actopsize:=att_sizefpuintsuffix[sufidx]
  733. else
  734. actopsize:=att_sizesuffix[sufidx];
  735. actcondition:=cnd;
  736. actasmtoken:=AS_OPCODE;
  737. is_asmopcode:=TRUE;
  738. exit;
  739. end;
  740. end;
  741. end;
  742. inc(j);
  743. end;
  744. end;
  745. end;
  746. end;
  747. procedure tx86attreader.handleopcode;
  748. var
  749. instr : Tx86Instruction;
  750. begin
  751. instr:=Tx86Instruction.Create(Tx86Operand);
  752. instr.OpOrder:=op_att;
  753. BuildOpcode(instr);
  754. instr.AddReferenceSizes;
  755. instr.SetInstructionOpsize;
  756. instr.CheckOperandSizes;
  757. instr.ConcatInstruction(curlist);
  758. instr.Free;
  759. end;
  760. end.
  761. {
  762. $Log$
  763. Revision 1.11 2005-04-25 09:51:07 florian
  764. + pic code reading for the assembler readers
  765. * loadaddr generates pic code as well now
  766. Revision 1.10 2005/02/14 17:13:10 peter
  767. * truncate log
  768. }