rax86att.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  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,globals,verbose,
  40. systems,
  41. { aasm }
  42. cpuinfo,aasmbase,aasmtai,aasmcpu,
  43. { symtable }
  44. symconst,symbase,symtype,symsym,symtable,
  45. { parser }
  46. scanner,
  47. procinfo,
  48. itcpugas,
  49. rabase,rautils,
  50. cgbase,cgobj
  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 : longint;
  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,
  246. l,k : longint;
  247. procedure AddLabelOperand(hl:tasmlabel);
  248. begin
  249. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  250. is_calljmp(actopcode) then
  251. begin
  252. oper.opr.typ:=OPR_SYMBOL;
  253. oper.opr.symbol:=hl;
  254. end
  255. else
  256. begin
  257. oper.InitRef;
  258. oper.opr.ref.symbol:=hl;
  259. end;
  260. end;
  261. procedure MaybeRecordOffset;
  262. var
  263. hasdot : boolean;
  264. l,
  265. toffset,
  266. tsize : longint;
  267. begin
  268. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  269. exit;
  270. l:=0;
  271. hasdot:=(actasmtoken=AS_DOT);
  272. if hasdot then
  273. begin
  274. if expr<>'' then
  275. begin
  276. BuildRecordOffsetSize(expr,toffset,tsize);
  277. inc(l,toffset);
  278. oper.SetSize(tsize,true);
  279. end;
  280. end;
  281. if actasmtoken in [AS_PLUS,AS_MINUS] then
  282. inc(l,BuildConstExpression(true,false));
  283. case oper.opr.typ of
  284. OPR_LOCAL :
  285. begin
  286. { don't allow direct access to fields of parameters, because that
  287. will generate buggy code. Allow it only for explicit typecasting }
  288. if hasdot and
  289. (not oper.hastype) and
  290. (tvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
  291. (current_procinfo.procdef.proccalloption<>pocall_register) then
  292. Message(asmr_e_cannot_access_field_directly_for_parameters);
  293. inc(oper.opr.localsymofs,l)
  294. end;
  295. OPR_CONSTANT :
  296. inc(oper.opr.val,l);
  297. OPR_REFERENCE :
  298. inc(oper.opr.ref.offset,l);
  299. else
  300. internalerror(200309221);
  301. end;
  302. end;
  303. function MaybeBuildReference:boolean;
  304. { Try to create a reference, if not a reference is found then false
  305. is returned }
  306. begin
  307. MaybeBuildReference:=true;
  308. case actasmtoken of
  309. AS_INTNUM,
  310. AS_MINUS,
  311. AS_PLUS:
  312. Begin
  313. oper.opr.ref.offset:=BuildConstExpression(True,False);
  314. if actasmtoken<>AS_LPAREN then
  315. Message(asmr_e_invalid_reference_syntax)
  316. else
  317. BuildReference(oper);
  318. end;
  319. AS_LPAREN:
  320. BuildReference(oper);
  321. AS_ID: { only a variable is allowed ... }
  322. Begin
  323. tempstr:=actasmpattern;
  324. Consume(AS_ID);
  325. { typecasting? }
  326. if (actasmtoken=AS_LPAREN) and
  327. SearchType(tempstr,typesize) then
  328. begin
  329. oper.hastype:=true;
  330. Consume(AS_LPAREN);
  331. BuildOperand(oper);
  332. Consume(AS_RPAREN);
  333. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  334. oper.SetSize(typesize,true);
  335. end
  336. else
  337. if not oper.SetupVar(tempstr,false) then
  338. Message1(sym_e_unknown_id,tempstr);
  339. { record.field ? }
  340. if actasmtoken=AS_DOT then
  341. begin
  342. BuildRecordOffsetSize(tempstr,l,k);
  343. inc(oper.opr.ref.offset,l);
  344. end;
  345. case actasmtoken of
  346. AS_END,
  347. AS_SEPARATOR,
  348. AS_COMMA: ;
  349. AS_LPAREN:
  350. BuildReference(oper);
  351. else
  352. Begin
  353. Message(asmr_e_invalid_reference_syntax);
  354. Consume(actasmtoken);
  355. end;
  356. end; {end case }
  357. end;
  358. else
  359. MaybeBuildReference:=false;
  360. end; { end case }
  361. end;
  362. var
  363. tempreg : tregister;
  364. hl : tasmlabel;
  365. Begin
  366. expr:='';
  367. case actasmtoken of
  368. AS_LPAREN: { Memory reference or constant expression }
  369. Begin
  370. oper.InitRef;
  371. BuildReference(oper);
  372. end;
  373. AS_DOLLAR: { Constant expression }
  374. Begin
  375. Consume(AS_DOLLAR);
  376. BuildConstantOperand(oper);
  377. end;
  378. AS_INTNUM,
  379. AS_MINUS,
  380. AS_PLUS:
  381. Begin
  382. { Constant memory offset }
  383. { This must absolutely be followed by ( }
  384. oper.InitRef;
  385. oper.opr.ref.offset:=BuildConstExpression(True,False);
  386. if actasmtoken<>AS_LPAREN then
  387. Message(asmr_e_invalid_reference_syntax)
  388. else
  389. BuildReference(oper);
  390. end;
  391. AS_STAR: { Call from memory address }
  392. Begin
  393. Consume(AS_STAR);
  394. if actasmtoken=AS_REGISTER then
  395. begin
  396. oper.opr.typ:=OPR_REGISTER;
  397. oper.opr.reg:=actasmregister;
  398. oper.SetSize(tcgsize2size[cg.reg_cgsize(actasmregister)],true);
  399. Consume(AS_REGISTER);
  400. end
  401. else
  402. begin
  403. oper.InitRef;
  404. if not MaybeBuildReference then
  405. Message(asmr_e_syn_operand);
  406. end;
  407. { this is only allowed for call's and jmp's }
  408. if not is_calljmp(actopcode) then
  409. Message(asmr_e_syn_operand);
  410. end;
  411. AS_ID: { A constant expression, or a Variable ref. }
  412. Begin
  413. { Local Label ? }
  414. if is_locallabel(actasmpattern) then
  415. begin
  416. CreateLocalLabel(actasmpattern,hl,false);
  417. Consume(AS_ID);
  418. AddLabelOperand(hl);
  419. end
  420. else
  421. { Check for label }
  422. if SearchLabel(actasmpattern,hl,false) then
  423. begin
  424. Consume(AS_ID);
  425. AddLabelOperand(hl);
  426. end
  427. else
  428. { probably a variable or normal expression }
  429. { or a procedure (such as in CALL ID) }
  430. Begin
  431. { is it a constant ? }
  432. if SearchIConstant(actasmpattern,l) then
  433. Begin
  434. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  435. Message(asmr_e_invalid_operand_type);
  436. BuildConstantOperand(oper);
  437. end
  438. else
  439. begin
  440. expr:=actasmpattern;
  441. Consume(AS_ID);
  442. { typecasting? }
  443. if (actasmtoken=AS_LPAREN) and
  444. SearchType(expr,typesize) then
  445. begin
  446. oper.hastype:=true;
  447. Consume(AS_LPAREN);
  448. BuildOperand(oper);
  449. Consume(AS_RPAREN);
  450. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  451. oper.SetSize(typesize,true);
  452. end
  453. else
  454. begin
  455. if oper.SetupVar(expr,false) then
  456. begin
  457. end
  458. else
  459. Begin
  460. { look for special symbols ... }
  461. if expr= '__HIGH' then
  462. begin
  463. consume(AS_LPAREN);
  464. if not oper.setupvar('high'+actasmpattern,false) then
  465. Message1(sym_e_unknown_id,'high'+actasmpattern);
  466. consume(AS_ID);
  467. consume(AS_RPAREN);
  468. end
  469. else
  470. if expr = '__RESULT' then
  471. oper.SetUpResult
  472. else
  473. if expr = '__SELF' then
  474. oper.SetupSelf
  475. else
  476. if expr = '__OLDEBP' then
  477. oper.SetupOldEBP
  478. else
  479. { check for direct symbolic names }
  480. { only if compiling the system unit }
  481. if (cs_compilesystem in aktmoduleswitches) then
  482. begin
  483. if not oper.SetupDirectVar(expr) then
  484. Begin
  485. { not found, finally ... add it anyways ... }
  486. Message1(asmr_w_id_supposed_external,expr);
  487. oper.InitRef;
  488. oper.opr.ref.symbol:=objectlibrary.newasmsymbol(expr,AB_EXTERNAL,AT_FUNCTION);
  489. end;
  490. end
  491. else
  492. Message1(sym_e_unknown_id,expr);
  493. end;
  494. end;
  495. end;
  496. if actasmtoken=AS_DOT then
  497. MaybeRecordOffset;
  498. { add a constant expression? }
  499. if (actasmtoken=AS_PLUS) then
  500. begin
  501. l:=BuildConstExpression(true,false);
  502. case oper.opr.typ of
  503. OPR_CONSTANT :
  504. inc(oper.opr.val,l);
  505. OPR_LOCAL :
  506. inc(oper.opr.localsymofs,l);
  507. OPR_REFERENCE :
  508. inc(oper.opr.ref.offset,l);
  509. else
  510. internalerror(200309202);
  511. end;
  512. end
  513. end;
  514. { Do we have a indexing reference, then parse it also }
  515. if actasmtoken=AS_LPAREN then
  516. BuildReference(oper);
  517. end;
  518. AS_REGISTER: { Register, a variable reference or a constant reference }
  519. Begin
  520. { save the type of register used. }
  521. tempreg:=actasmregister;
  522. Consume(AS_REGISTER);
  523. if actasmtoken = AS_COLON then
  524. Begin
  525. Consume(AS_COLON);
  526. oper.InitRef;
  527. oper.opr.ref.segment:=tempreg;
  528. { This must absolutely be followed by a reference }
  529. if not MaybeBuildReference then
  530. Begin
  531. Message(asmr_e_invalid_seg_override);
  532. Consume(actasmtoken);
  533. end;
  534. end
  535. { Simple register }
  536. else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  537. Begin
  538. if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
  539. Message(asmr_e_invalid_operand_type);
  540. oper.opr.typ:=OPR_REGISTER;
  541. oper.opr.reg:=tempreg;
  542. oper.SetSize(tcgsize2size[cg.reg_cgsize(oper.opr.reg)],true);
  543. end
  544. else
  545. Message(asmr_e_syn_operand);
  546. end;
  547. AS_END,
  548. AS_SEPARATOR,
  549. AS_COMMA: ;
  550. else
  551. Begin
  552. Message(asmr_e_syn_operand);
  553. Consume(actasmtoken);
  554. end;
  555. end; { end case }
  556. end;
  557. procedure tx86attreader.BuildOpCode(instr : tx86instruction);
  558. var
  559. operandnum : longint;
  560. PrefixOp,OverrideOp: tasmop;
  561. Begin
  562. PrefixOp:=A_None;
  563. OverrideOp:=A_None;
  564. { prefix seg opcode / prefix opcode }
  565. repeat
  566. if is_prefix(actopcode) then
  567. begin
  568. PrefixOp:=ActOpcode;
  569. with instr do
  570. begin
  571. opcode:=ActOpcode;
  572. condition:=ActCondition;
  573. opsize:=ActOpsize;
  574. ConcatInstruction(curlist);
  575. end;
  576. Consume(AS_OPCODE);
  577. end
  578. else
  579. if is_override(actopcode) then
  580. begin
  581. OverrideOp:=ActOpcode;
  582. with instr do
  583. begin
  584. opcode:=ActOpcode;
  585. condition:=ActCondition;
  586. opsize:=ActOpsize;
  587. ConcatInstruction(curlist);
  588. end;
  589. Consume(AS_OPCODE);
  590. end
  591. else
  592. break;
  593. { allow for newline as in gas styled syntax }
  594. while actasmtoken=AS_SEPARATOR do
  595. Consume(AS_SEPARATOR);
  596. until (actasmtoken<>AS_OPCODE);
  597. { opcode }
  598. if (actasmtoken<>AS_OPCODE) then
  599. Begin
  600. Message(asmr_e_invalid_or_missing_opcode);
  601. RecoverConsume(true);
  602. exit;
  603. end;
  604. { Fill the instr object with the current state }
  605. with instr do
  606. begin
  607. Opcode:=ActOpcode;
  608. condition:=ActCondition;
  609. opsize:=ActOpsize;
  610. end;
  611. { Valid combination of prefix/override and instruction ? }
  612. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  613. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  614. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  615. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  616. { We are reading operands, so opcode will be an AS_ID }
  617. operandnum:=1;
  618. Consume(AS_OPCODE);
  619. { Zero operand opcode ? }
  620. if actasmtoken in [AS_SEPARATOR,AS_END] then
  621. begin
  622. operandnum:=0;
  623. exit;
  624. end;
  625. { Read the operands }
  626. repeat
  627. case actasmtoken of
  628. AS_COMMA: { Operand delimiter }
  629. Begin
  630. if operandnum > Max_Operands then
  631. Message(asmr_e_too_many_operands)
  632. else
  633. Inc(operandnum);
  634. Consume(AS_COMMA);
  635. end;
  636. AS_SEPARATOR,
  637. AS_END : { End of asm operands for this opcode }
  638. begin
  639. break;
  640. end;
  641. else
  642. BuildOperand(instr.Operands[operandnum] as tx86operand);
  643. end; { end case }
  644. until false;
  645. instr.Ops:=operandnum;
  646. end;
  647. function tx86attreader.is_asmopcode(const s: string):boolean;
  648. const
  649. { We need first to check the long prefixes, else we get probs
  650. with things like movsbl }
  651. att_sizesuffixstr : array[0..9] of string[2] = (
  652. '','BW','BL','WL','B','W','L','S','Q','T'
  653. );
  654. att_sizesuffix : array[0..9] of topsize = (
  655. S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
  656. );
  657. att_sizefpusuffix : array[0..9] of topsize = (
  658. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
  659. );
  660. att_sizefpuintsuffix : array[0..9] of topsize = (
  661. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
  662. );
  663. var
  664. str2opentry: tstr2opentry;
  665. cond : string[4];
  666. cnd : tasmcond;
  667. len,
  668. j,
  669. sufidx : longint;
  670. Begin
  671. is_asmopcode:=FALSE;
  672. actopcode:=A_None;
  673. actcondition:=C_None;
  674. actopsize:=S_NO;
  675. { search for all possible suffixes }
  676. for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
  677. begin
  678. len:=length(s)-length(att_sizesuffixstr[sufidx]);
  679. if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
  680. begin
  681. { here we search the entire table... }
  682. str2opentry:=nil;
  683. if {(length(s)>0) and} (len>0) then
  684. str2opentry:=tstr2opentry(iasmops.search(copy(s,1,len)));
  685. if assigned(str2opentry) then
  686. begin
  687. actopcode:=str2opentry.op;
  688. if gas_needsuffix[actopcode]=attsufFPU then
  689. actopsize:=att_sizefpusuffix[sufidx]
  690. else if gas_needsuffix[actopcode]=attsufFPUint then
  691. actopsize:=att_sizefpuintsuffix[sufidx]
  692. else
  693. actopsize:=att_sizesuffix[sufidx];
  694. actasmtoken:=AS_OPCODE;
  695. is_asmopcode:=TRUE;
  696. exit;
  697. end;
  698. { not found, check condition opcodes }
  699. j:=0;
  700. while (j<CondAsmOps) do
  701. begin
  702. if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
  703. begin
  704. cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
  705. if cond<>'' then
  706. begin
  707. for cnd:=low(TasmCond) to high(TasmCond) do
  708. if Cond=Upper(cond2str[cnd]) then
  709. begin
  710. actopcode:=CondASmOp[j];
  711. if gas_needsuffix[actopcode]=attsufFPU then
  712. actopsize:=att_sizefpusuffix[sufidx]
  713. else if gas_needsuffix[actopcode]=attsufFPUint then
  714. actopsize:=att_sizefpuintsuffix[sufidx]
  715. else
  716. actopsize:=att_sizesuffix[sufidx];
  717. actcondition:=cnd;
  718. actasmtoken:=AS_OPCODE;
  719. is_asmopcode:=TRUE;
  720. exit;
  721. end;
  722. end;
  723. end;
  724. inc(j);
  725. end;
  726. end;
  727. end;
  728. end;
  729. procedure tx86attreader.handleopcode;
  730. var
  731. instr : Tx86Instruction;
  732. begin
  733. instr:=Tx86Instruction.Create(Tx86Operand);
  734. instr.OpOrder:=op_att;
  735. BuildOpcode(instr);
  736. instr.AddReferenceSizes;
  737. instr.SetInstructionOpsize;
  738. instr.CheckOperandSizes;
  739. instr.ConcatInstruction(curlist);
  740. instr.Free;
  741. end;
  742. end.
  743. {
  744. $Log$
  745. Revision 1.3 2004-03-02 00:36:33 olle
  746. * big transformation of Tai_[const_]Symbol.Create[data]name*
  747. Revision 1.2 2004/02/09 19:23:48 peter
  748. * reg_2_opsize replaced with reg_cgsize
  749. Revision 1.1 2004/01/14 23:39:05 florian
  750. * another bunch of x86-64 fixes mainly calling convention and
  751. assembler reader related
  752. Revision 1.58 2003/11/12 16:05:39 florian
  753. * assembler readers OOPed
  754. + typed currency constants
  755. + typed 128 bit float constants if the CPU supports it
  756. Revision 1.57 2003/11/10 19:08:32 peter
  757. * line numbering is now only done when #10, #10#13 is really parsed
  758. instead of when it is the next character
  759. Revision 1.56 2003/10/29 16:47:18 peter
  760. * fix field offset in reference
  761. Revision 1.55 2003/10/26 13:37:22 florian
  762. * fixed web bug 2128
  763. Revision 1.54 2003/10/24 17:39:03 peter
  764. * more intel parser updates
  765. Revision 1.53 2003/10/23 17:19:44 peter
  766. * typecasting fixes
  767. * reference building more delphi compatible
  768. Revision 1.52 2003/10/20 19:29:35 peter
  769. * fix check for register subscription of reference parameter
  770. Revision 1.51 2003/10/16 21:29:24 peter
  771. + __HIGH() to retrieve high value
  772. Revision 1.50 2003/10/07 18:21:18 peter
  773. * fix crash
  774. * allow parameter subscription for register parameters
  775. Revision 1.49 2003/10/01 20:34:49 peter
  776. * procinfo unit contains tprocinfo
  777. * cginfo renamed to cgbase
  778. * moved cgmessage to verbose
  779. * fixed ppc and sparc compiles
  780. Revision 1.48 2003/09/23 20:37:53 peter
  781. * fix global var+offset
  782. Revision 1.47 2003/09/23 17:56:06 peter
  783. * locals and paras are allocated in the code generation
  784. * tvarsym.localloc contains the location of para/local when
  785. generating code for the current procedure
  786. Revision 1.46 2003/09/03 15:55:01 peter
  787. * NEWRA branch merged
  788. Revision 1.45.2.2 2003/08/31 15:46:26 peter
  789. * more updates for tregister
  790. Revision 1.45.2.1 2003/08/28 18:35:08 peter
  791. * tregister changed to cardinal
  792. Revision 1.45 2003/05/30 23:57:08 peter
  793. * more sparc cleanup
  794. * accumulator removed, splitted in function_return_reg (called) and
  795. function_result_reg (caller)
  796. Revision 1.44 2003/05/22 21:32:29 peter
  797. * removed some unit dependencies
  798. Revision 1.43 2003/04/30 15:45:35 florian
  799. * merged more x86-64/i386 code
  800. Revision 1.42 2003/04/25 12:04:31 florian
  801. * merged agx64att and ag386att to x86/agx86att
  802. Revision 1.41 2003/04/21 20:05:10 peter
  803. * removed some ie checks
  804. Revision 1.40 2003/03/18 18:15:53 peter
  805. * changed reg2opsize to function
  806. Revision 1.39 2003/02/20 15:52:58 pierre
  807. * fix a range check error
  808. Revision 1.38 2003/02/19 22:00:16 daniel
  809. * Code generator converted to new register notation
  810. - Horribily outdated todo.txt removed
  811. Revision 1.37 2003/02/03 22:47:14 daniel
  812. - Removed reg_2_opsize array
  813. Revision 1.36 2003/01/08 18:43:57 daniel
  814. * Tregister changed into a record
  815. Revision 1.35 2002/12/14 15:02:03 carl
  816. * maxoperands -> max_operands (for portability in rautils.pas)
  817. * fix some range-check errors with loadconst
  818. + add ncgadd unit to m68k
  819. * some bugfix of a_param_reg with LOC_CREFERENCE
  820. Revision 1.34 2002/12/01 22:08:34 carl
  821. * some small cleanup (remove some specific operators which are not supported)
  822. Revision 1.33 2002/11/30 23:16:39 carl
  823. - removed unused message
  824. Revision 1.32 2002/11/15 01:58:58 peter
  825. * merged changes from 1.0.7 up to 04-11
  826. - -V option for generating bug report tracing
  827. - more tracing for option parsing
  828. - errors for cdecl and high()
  829. - win32 import stabs
  830. - win32 records<=8 are returned in eax:edx (turned off by default)
  831. - heaptrc update
  832. - more info for temp management in .s file with EXTDEBUG
  833. Revision 1.31 2002/09/03 16:26:28 daniel
  834. * Make Tprocdef.defs protected
  835. Revision 1.30 2002/08/13 18:01:52 carl
  836. * rename swatoperands to swapoperands
  837. + m68k first compilable version (still needs a lot of testing):
  838. assembler generator, system information , inline
  839. assembler reader.
  840. Revision 1.29 2002/08/12 15:08:42 carl
  841. + stab register indexes for powerpc (moved from gdb to cpubase)
  842. + tprocessor enumeration moved to cpuinfo
  843. + linker in target_info is now a class
  844. * many many updates for m68k (will soon start to compile)
  845. - removed some ifdef or correct them for correct cpu
  846. Revision 1.28 2002/08/11 14:32:31 peter
  847. * renamed current_library to objectlibrary
  848. Revision 1.27 2002/08/11 13:24:17 peter
  849. * saving of asmsymbols in ppu supported
  850. * asmsymbollist global is removed and moved into a new class
  851. tasmlibrarydata that will hold the info of a .a file which
  852. corresponds with a single module. Added librarydata to tmodule
  853. to keep the library info stored for the module. In the future the
  854. objectfiles will also be stored to the tasmlibrarydata class
  855. * all getlabel/newasmsymbol and friends are moved to the new class
  856. Revision 1.26 2002/07/26 21:15:44 florian
  857. * rewrote the system handling
  858. Revision 1.25 2002/07/01 18:46:34 peter
  859. * internal linker
  860. * reorganized aasm layer
  861. Revision 1.24 2002/05/18 13:34:25 peter
  862. * readded missing revisions
  863. Revision 1.23 2002/05/16 19:46:52 carl
  864. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  865. + try to fix temp allocation (still in ifdef)
  866. + generic constructor calls
  867. + start of tassembler / tmodulebase class cleanup
  868. Revision 1.21 2002/04/15 19:12:09 carl
  869. + target_info.size_of_pointer -> pointer_size
  870. + some cleanup of unused types/variables
  871. * move several constants from cpubase to their specific units
  872. (where they are used)
  873. + att_Reg2str -> gas_reg2str
  874. + int_reg2str -> std_reg2str
  875. Revision 1.20 2002/04/14 17:01:52 carl
  876. + att_reg2str -> gas_reg2str
  877. Revision 1.19 2002/04/04 19:06:13 peter
  878. * removed unused units
  879. * use tlocation.size in cg.a_*loc*() routines
  880. Revision 1.18 2002/04/02 17:11:39 peter
  881. * tlocation,treference update
  882. * LOC_CONSTANT added for better constant handling
  883. * secondadd splitted in multiple routines
  884. * location_force_reg added for loading a location to a register
  885. of a specified size
  886. * secondassignment parses now first the right and then the left node
  887. (this is compatible with Kylix). This saves a lot of push/pop especially
  888. with string operations
  889. * adapted some routines to use the new cg methods
  890. Revision 1.17 2002/03/28 20:48:25 carl
  891. - remove go32v1 support
  892. Revision 1.16 2002/01/24 18:25:53 peter
  893. * implicit result variable generation for assembler routines
  894. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  895. }