rax86att.pas 33 KB

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