rax86att.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. {
  2. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  3. Does the parsing for the x86 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 rax86att;
  18. {$i fpcdefs.inc}
  19. Interface
  20. uses
  21. cpubase,
  22. raatt,rax86, rautils;
  23. type
  24. { tx86attreader }
  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. protected
  34. procedure MaybeGetPICModifier(var oper: tx86operand);
  35. end;
  36. { Tx86attInstruction }
  37. Tx86attInstruction = class(Tx86Instruction)
  38. procedure AddReferenceSizes; override;
  39. procedure FixupOpcode;override;
  40. end;
  41. Implementation
  42. uses
  43. { helpers }
  44. cutils,
  45. { global }
  46. globtype,verbose,
  47. systems,
  48. { aasm }
  49. aasmbase,aasmtai,aasmdata,aasmcpu,
  50. { symtable }
  51. symconst,
  52. { parser }
  53. scanner,
  54. procinfo,
  55. itcpugas,
  56. rabase,
  57. cgbase
  58. ;
  59. { Tx86attInstruction }
  60. procedure Tx86attInstruction.AddReferenceSizes;
  61. var
  62. i: integer;
  63. begin
  64. if (Opsize <> S_NO) and
  65. (MemRefInfo(opcode).ExistsSSEAVX) and
  66. (MemRefInfo(opcode).MemRefSize in MemRefMultiples) then
  67. begin
  68. for i := 1 to ops do
  69. begin
  70. if operands[i].Opr.Typ in [OPR_REFERENCE, OPR_LOCAL] then
  71. begin
  72. if (tx86operand(operands[i]).opsize = S_NO) then
  73. tx86operand(operands[i]).opsize := Opsize;
  74. end;
  75. end;
  76. end;
  77. inherited AddReferenceSizes;
  78. end;
  79. procedure Tx86attInstruction.FixupOpcode;
  80. begin
  81. if (OpOrder=op_intel) then
  82. SwapOperands;
  83. case opcode of
  84. A_MOVQ:
  85. begin
  86. { May be either real 'movq' or a generic 'mov' with 'q' suffix. Convert to mov
  87. if source is a constant, or if neither operand is an mmx/xmm register }
  88. {$ifdef x86_64}
  89. if (ops=2) and
  90. (
  91. (operands[1].opr.typ=OPR_CONSTANT) or not
  92. (
  93. ((operands[1].opr.typ=OPR_REGISTER) and
  94. (getregtype(operands[1].opr.reg) in [R_MMXREGISTER,R_MMREGISTER])) or
  95. ((operands[2].opr.typ=OPR_REGISTER) and
  96. (getregtype(operands[2].opr.reg) in [R_MMXREGISTER,R_MMREGISTER]))
  97. )
  98. ) then
  99. opcode:=A_MOV;
  100. {$endif x86_64}
  101. end;
  102. end;
  103. end;
  104. { Tx86attReader }
  105. procedure tx86attreader.handlepercent;
  106. var
  107. len : longint;
  108. begin
  109. len:=1;
  110. actasmpattern[len]:='%';
  111. c:=current_scanner.asmgetchar;
  112. { to be a register there must be a letter and not a number }
  113. if c in ['0'..'9'] then
  114. begin
  115. actasmtoken:=AS_MOD;
  116. end
  117. else
  118. begin
  119. while c in ['a'..'z','A'..'Z','0'..'9'] do
  120. Begin
  121. inc(len);
  122. actasmpattern[len]:=c;
  123. c:=current_scanner.asmgetchar;
  124. end;
  125. actasmpattern[0]:=chr(len);
  126. uppervar(actasmpattern);
  127. if (actasmpattern = '%ST') and (c='(') then
  128. Begin
  129. actasmpattern:=actasmpattern+c;
  130. c:=current_scanner.asmgetchar;
  131. if c in ['0'..'9'] then
  132. actasmpattern:=actasmpattern + c
  133. else
  134. Message(asmr_e_invalid_fpu_register);
  135. c:=current_scanner.asmgetchar;
  136. if c <> ')' then
  137. Message(asmr_e_invalid_fpu_register)
  138. else
  139. Begin
  140. actasmpattern:=actasmpattern + c;
  141. c:=current_scanner.asmgetchar; { let us point to next character. }
  142. end;
  143. end;
  144. if is_register(actasmpattern) then
  145. exit;
  146. Message(asmr_e_invalid_register);
  147. actasmtoken:=raatt.AS_NONE;
  148. end;
  149. end;
  150. Procedure tx86attreader.BuildReference(oper : tx86operand);
  151. procedure Consume_RParen;
  152. begin
  153. if actasmtoken <> AS_RPAREN then
  154. Begin
  155. Message(asmr_e_invalid_reference_syntax);
  156. RecoverConsume(true);
  157. end
  158. else
  159. begin
  160. Consume(AS_RPAREN);
  161. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
  162. Begin
  163. Message(asmr_e_invalid_reference_syntax);
  164. RecoverConsume(true);
  165. end;
  166. end;
  167. end;
  168. procedure Consume_Scale;
  169. var
  170. l : aint;
  171. begin
  172. { we have to process the scaling }
  173. l:=BuildConstExpression(false,true);
  174. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
  175. oper.opr.ref.scalefactor:=l
  176. else
  177. Begin
  178. Message(asmr_e_wrong_scale_factor);
  179. oper.opr.ref.scalefactor:=0;
  180. end;
  181. end;
  182. begin
  183. oper.InitRef;
  184. Consume(AS_LPAREN);
  185. Case actasmtoken of
  186. AS_INTNUM,
  187. AS_MINUS,
  188. AS_PLUS: { absolute offset, such as fs:(0x046c) }
  189. Begin
  190. { offset(offset) is invalid }
  191. If oper.opr.Ref.Offset <> 0 Then
  192. Begin
  193. Message(asmr_e_invalid_reference_syntax);
  194. RecoverConsume(true);
  195. End
  196. Else
  197. Begin
  198. oper.opr.Ref.Offset:=BuildConstExpression(false,true);
  199. Consume_RParen;
  200. end;
  201. exit;
  202. End;
  203. AS_REGISTER: { (reg ... }
  204. Begin
  205. { Check if there is already a base (mostly ebp,esp) than this is
  206. not allowed, because it will give crashing code }
  207. if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
  208. ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
  209. message(asmr_e_cannot_index_relative_var);
  210. oper.opr.ref.base:=actasmregister;
  211. {$ifdef x86_64}
  212. { non-GOT based RIP-relative accesses are also position-independent }
  213. if (oper.opr.ref.base=NR_RIP) and
  214. (oper.opr.ref.refaddr<>addr_pic) then
  215. oper.opr.ref.refaddr:=addr_pic_no_got;
  216. {$endif x86_64}
  217. Consume(AS_REGISTER);
  218. { can either be a register or a right parenthesis }
  219. { (reg) }
  220. if actasmtoken=AS_RPAREN then
  221. Begin
  222. Consume_RParen;
  223. exit;
  224. end;
  225. { (reg,reg .. }
  226. Consume(AS_COMMA);
  227. if actasmtoken=AS_REGISTER then
  228. Begin
  229. oper.opr.ref.index:=actasmregister;
  230. Consume(AS_REGISTER);
  231. { check for scaling ... }
  232. case actasmtoken of
  233. AS_RPAREN:
  234. Begin
  235. Consume_RParen;
  236. exit;
  237. end;
  238. AS_COMMA:
  239. Begin
  240. Consume(AS_COMMA);
  241. Consume_Scale;
  242. Consume_RParen;
  243. end;
  244. else
  245. Begin
  246. Message(asmr_e_invalid_reference_syntax);
  247. RecoverConsume(false);
  248. end;
  249. end; { end case }
  250. end
  251. else
  252. Begin
  253. Message(asmr_e_invalid_reference_syntax);
  254. RecoverConsume(false);
  255. end;
  256. end; {end case }
  257. AS_COMMA: { (, ... can either be scaling, or index }
  258. Begin
  259. Consume(AS_COMMA);
  260. { Index }
  261. if (actasmtoken=AS_REGISTER) then
  262. Begin
  263. oper.opr.ref.index:=actasmregister;
  264. Consume(AS_REGISTER);
  265. { check for scaling ... }
  266. case actasmtoken of
  267. AS_RPAREN:
  268. Begin
  269. Consume_RParen;
  270. exit;
  271. end;
  272. AS_COMMA:
  273. Begin
  274. Consume(AS_COMMA);
  275. Consume_Scale;
  276. Consume_RParen;
  277. end;
  278. else
  279. Begin
  280. Message(asmr_e_invalid_reference_syntax);
  281. RecoverConsume(false);
  282. end;
  283. end; {end case }
  284. end
  285. { Scaling }
  286. else
  287. Begin
  288. Consume_Scale;
  289. Consume_RParen;
  290. exit;
  291. end;
  292. end;
  293. else
  294. Begin
  295. Message(asmr_e_invalid_reference_syntax);
  296. RecoverConsume(false);
  297. end;
  298. end;
  299. end;
  300. Procedure tx86attreader.MaybeGetPICModifier(var oper: tx86operand);
  301. var
  302. relsym: string;
  303. asmsymtyp: tasmsymtype;
  304. l: aint;
  305. sym: tasmsymbol;
  306. begin
  307. case actasmtoken of
  308. AS_AT:
  309. begin
  310. { darwin/i386 needs a relsym instead, and we can't }
  311. { generate this automatically }
  312. if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
  313. Message(asmr_e_invalid_reference_syntax);
  314. consume(AS_AT);
  315. if actasmtoken=AS_ID then
  316. begin
  317. {$ifdef x86_64}
  318. if (actasmpattern='GOTPCREL') or
  319. (actasmpattern='PLT') then
  320. {$endif x86_64}
  321. {$ifdef i386}
  322. if actasmpattern='GOT' then
  323. {$endif i386}
  324. {$ifdef i8086}
  325. if actasmpattern='GOT' then
  326. {$endif i8086}
  327. begin
  328. case oper.opr.typ of
  329. OPR_SYMBOL:
  330. begin
  331. sym:=oper.opr.symbol;
  332. if oper.opr.symofs<>0 then
  333. Message(asmr_e_invalid_reference_syntax);
  334. oper.opr.typ:=OPR_REFERENCE;
  335. fillchar(oper.opr.ref,sizeof(oper.opr.ref),0);
  336. oper.opr.ref.symbol:=sym;
  337. end;
  338. OPR_REFERENCE:
  339. begin
  340. { ok }
  341. end;
  342. else
  343. Message(asmr_e_invalid_reference_syntax)
  344. end;
  345. oper.opr.ref.refaddr:=addr_pic;
  346. consume(AS_ID);
  347. end
  348. else
  349. Message(asmr_e_invalid_reference_syntax);
  350. end
  351. else
  352. Message(asmr_e_invalid_reference_syntax);
  353. end;
  354. AS_MINUS:
  355. begin
  356. { relsym? }
  357. Consume(AS_MINUS);
  358. BuildConstSymbolExpression(true,true,false,l,relsym,asmsymtyp);
  359. if (relsym<>'') then
  360. if not assigned(oper.opr.ref.relsymbol) then
  361. oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym)
  362. else
  363. Message(asmr_e_invalid_reference_syntax)
  364. else
  365. dec(oper.opr.ref.offset,l);
  366. end;
  367. end;
  368. end;
  369. Procedure tx86attreader.BuildOperand(oper : tx86operand);
  370. var
  371. tempstr,
  372. expr : string;
  373. typesize,l,k : aint;
  374. procedure AddLabelOperand(hl:tasmlabel);
  375. begin
  376. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  377. is_calljmp(actopcode) then
  378. begin
  379. oper.opr.typ:=OPR_SYMBOL;
  380. oper.opr.symbol:=hl;
  381. end
  382. else
  383. begin
  384. oper.InitRef;
  385. oper.opr.ref.symbol:=hl;
  386. end;
  387. end;
  388. procedure MaybeRecordOffset;
  389. var
  390. mangledname: string;
  391. hasdot : boolean;
  392. l,
  393. toffset,
  394. tsize : aint;
  395. begin
  396. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  397. exit;
  398. l:=0;
  399. hasdot:=(actasmtoken=AS_DOT);
  400. if hasdot then
  401. begin
  402. if expr<>'' then
  403. begin
  404. BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
  405. if (oper.opr.typ<>OPR_CONSTANT) and
  406. (mangledname<>'') then
  407. Message(asmr_e_wrong_sym_type);
  408. inc(l,toffset);
  409. oper.SetSize(tsize,true);
  410. case oper.opr.typ of
  411. OPR_REFERENCE: oper.opr.varsize := tsize;
  412. OPR_LOCAL: oper.opr.localvarsize := tsize;
  413. end;
  414. end;
  415. end;
  416. if actasmtoken in [AS_PLUS,AS_MINUS] then
  417. inc(l,BuildConstExpression(true,false));
  418. case oper.opr.typ of
  419. OPR_LOCAL :
  420. begin
  421. { don't allow direct access to fields of parameters, because that
  422. will generate buggy code. Allow it only for explicit typecasting }
  423. if hasdot and
  424. (not oper.hastype) and
  425. (oper.opr.localsym.owner.symtabletype=parasymtable) and
  426. (current_procinfo.procdef.proccalloption<>pocall_register) then
  427. Message(asmr_e_cannot_access_field_directly_for_parameters);
  428. inc(oper.opr.localsymofs,l);
  429. inc(oper.opr.localconstoffset,l);
  430. end;
  431. OPR_CONSTANT :
  432. if (mangledname<>'') then
  433. begin
  434. if (oper.opr.val<>0) then
  435. Message(asmr_e_wrong_sym_type);
  436. oper.opr.typ:=OPR_SYMBOL;
  437. oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
  438. end
  439. else
  440. inc(oper.opr.val,l);
  441. OPR_REFERENCE :
  442. begin
  443. inc(oper.opr.ref.offset,l);
  444. inc(oper.opr.constoffset,l);
  445. end;
  446. OPR_SYMBOL:
  447. Message(asmr_e_invalid_symbol_ref);
  448. else
  449. internalerror(200309221);
  450. end;
  451. end;
  452. function MaybeBuildReference:boolean;
  453. { Try to create a reference, if not a reference is found then false
  454. is returned }
  455. var
  456. mangledname: string;
  457. begin
  458. MaybeBuildReference:=true;
  459. case actasmtoken of
  460. AS_INTNUM:
  461. Begin
  462. { allow %segmentregister:number }
  463. if oper.opr.ref.segment<>NR_NO then
  464. begin
  465. // already done before calling oper.InitRef;
  466. if oper.opr.Ref.Offset <> 0 Then
  467. Message(asmr_e_invalid_reference_syntax)
  468. else
  469. begin
  470. oper.opr.Ref.Offset:=BuildConstExpression(true,false);
  471. if actasmtoken=AS_LPAREN then
  472. BuildReference(oper)
  473. else if (oper.opr.ref.segment <> NR_FS) and
  474. (oper.opr.ref.segment <> NR_GS) then
  475. Message(asmr_w_general_segment_with_constant);
  476. end;
  477. end
  478. else
  479. begin
  480. oper.opr.ref.offset:=BuildConstExpression(True,False);
  481. BuildReference(oper);
  482. end;
  483. end;
  484. AS_MINUS,
  485. AS_PLUS:
  486. Begin
  487. oper.opr.ref.offset:=BuildConstExpression(True,False);
  488. if actasmtoken<>AS_LPAREN then
  489. Message(asmr_e_invalid_reference_syntax)
  490. else
  491. BuildReference(oper);
  492. end;
  493. AS_LPAREN:
  494. BuildReference(oper);
  495. AS_ID: { only a variable is allowed ... }
  496. Begin
  497. tempstr:=actasmpattern;
  498. Consume(AS_ID);
  499. { typecasting? }
  500. if (actasmtoken=AS_LPAREN) and
  501. SearchType(tempstr,typesize) then
  502. begin
  503. oper.hastype:=true;
  504. Consume(AS_LPAREN);
  505. BuildOperand(oper);
  506. Consume(AS_RPAREN);
  507. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  508. oper.SetSize(typesize,true);
  509. end
  510. else
  511. if not oper.SetupVar(tempstr,false) then
  512. Message1(sym_e_unknown_id,tempstr);
  513. { record.field ? }
  514. if actasmtoken=AS_DOT then
  515. begin
  516. BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
  517. if (mangledname<>'') then
  518. Message(asmr_e_invalid_reference_syntax);
  519. inc(oper.opr.ref.offset,l);
  520. case oper.opr.typ of
  521. OPR_REFERENCE: oper.opr.varsize := k;
  522. OPR_LOCAL: oper.opr.localvarsize := k;
  523. end;
  524. end;
  525. MaybeGetPICModifier(oper);
  526. case actasmtoken of
  527. AS_END,
  528. AS_SEPARATOR,
  529. AS_COMMA: ;
  530. AS_LPAREN:
  531. BuildReference(oper);
  532. else
  533. Begin
  534. Message(asmr_e_invalid_reference_syntax);
  535. Consume(actasmtoken);
  536. end;
  537. end; {end case }
  538. end;
  539. else
  540. MaybeBuildReference:=false;
  541. end; { end case }
  542. end;
  543. var
  544. tempreg : tregister;
  545. hl : tasmlabel;
  546. Begin
  547. expr:='';
  548. case actasmtoken of
  549. AS_LPAREN: { Memory reference or constant expression }
  550. Begin
  551. oper.InitRef;
  552. BuildReference(oper);
  553. end;
  554. AS_DOLLAR: { Constant expression }
  555. Begin
  556. Consume(AS_DOLLAR);
  557. BuildConstantOperand(oper);
  558. end;
  559. AS_INTNUM,
  560. AS_MINUS,
  561. AS_PLUS:
  562. Begin
  563. { Constant memory offset }
  564. { This must absolutely be followed by ( }
  565. oper.InitRef;
  566. oper.opr.ref.offset:=BuildConstExpression(True,False);
  567. if actasmtoken<>AS_LPAREN then
  568. Message(asmr_e_invalid_reference_syntax)
  569. else
  570. BuildReference(oper);
  571. end;
  572. AS_STAR: { Call from memory address }
  573. Begin
  574. Consume(AS_STAR);
  575. if actasmtoken=AS_REGISTER then
  576. begin
  577. oper.opr.typ:=OPR_REGISTER;
  578. oper.opr.reg:=actasmregister;
  579. oper.SetSize(tcgsize2size[reg_cgsize(actasmregister)],true);
  580. Consume(AS_REGISTER);
  581. end
  582. else
  583. begin
  584. oper.InitRef;
  585. if not MaybeBuildReference then
  586. Message(asmr_e_syn_operand);
  587. end;
  588. { this is only allowed for call's and jmp's }
  589. if not is_calljmp(actopcode) then
  590. Message(asmr_e_syn_operand);
  591. end;
  592. AS_ID: { A constant expression, or a Variable ref. }
  593. Begin
  594. { Local Label ? }
  595. if is_locallabel(actasmpattern) then
  596. begin
  597. CreateLocalLabel(actasmpattern,hl,false);
  598. Consume(AS_ID);
  599. AddLabelOperand(hl);
  600. end
  601. else
  602. { Check for label }
  603. if SearchLabel(actasmpattern,hl,false) then
  604. begin
  605. Consume(AS_ID);
  606. AddLabelOperand(hl);
  607. end
  608. else
  609. { probably a variable or normal expression }
  610. { or a procedure (such as in CALL ID) }
  611. Begin
  612. { is it a constant ? }
  613. if SearchIConstant(actasmpattern,l) then
  614. Begin
  615. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  616. Message(asmr_e_invalid_operand_type);
  617. BuildConstantOperand(oper);
  618. end
  619. else
  620. begin
  621. expr:=actasmpattern;
  622. Consume(AS_ID);
  623. { typecasting? }
  624. if (actasmtoken=AS_LPAREN) and
  625. SearchType(expr,typesize) then
  626. begin
  627. oper.hastype:=true;
  628. Consume(AS_LPAREN);
  629. BuildOperand(oper);
  630. Consume(AS_RPAREN);
  631. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  632. oper.SetSize(typesize,true);
  633. end
  634. else
  635. begin
  636. if oper.SetupVar(expr,false) then
  637. MaybeGetPICModifier(oper)
  638. else
  639. Begin
  640. { look for special symbols ... }
  641. if expr= '__HIGH' then
  642. begin
  643. consume(AS_LPAREN);
  644. if not oper.setupvar('high'+actasmpattern,false) then
  645. Message1(sym_e_unknown_id,'high'+actasmpattern);
  646. consume(AS_ID);
  647. consume(AS_RPAREN);
  648. end
  649. else
  650. if expr = '__RESULT' then
  651. oper.SetUpResult
  652. else
  653. if expr = '__SELF' then
  654. oper.SetupSelf
  655. else
  656. if expr = '__OLDEBP' then
  657. oper.SetupOldEBP
  658. else
  659. Message1(sym_e_unknown_id,expr);
  660. end;
  661. end;
  662. end;
  663. if oper.opr.typ<>OPR_NONE Then
  664. begin
  665. if (actasmtoken=AS_DOT) then
  666. MaybeRecordOffset;
  667. { add a constant expression? }
  668. if (actasmtoken=AS_PLUS) then
  669. begin
  670. l:=BuildConstExpression(true,false);
  671. case oper.opr.typ of
  672. OPR_CONSTANT :
  673. inc(oper.opr.val,l);
  674. OPR_LOCAL :
  675. begin
  676. inc(oper.opr.localsymofs,l);
  677. inc(oper.opr.localconstoffset, l);
  678. end;
  679. OPR_REFERENCE :
  680. begin
  681. inc(oper.opr.ref.offset,l);
  682. inc(oper.opr.constoffset, l);
  683. end;
  684. else
  685. internalerror(200309202);
  686. end;
  687. end;
  688. end;
  689. end;
  690. { Do we have a indexing reference, then parse it also }
  691. if actasmtoken=AS_LPAREN then
  692. BuildReference(oper);
  693. end;
  694. AS_REGISTER: { Register, a variable reference or a constant reference }
  695. Begin
  696. { save the type of register used. }
  697. tempreg:=actasmregister;
  698. Consume(AS_REGISTER);
  699. if actasmtoken = AS_COLON then
  700. Begin
  701. Consume(AS_COLON);
  702. oper.InitRef;
  703. oper.opr.ref.segment:=tempreg;
  704. { This must absolutely be followed by a reference }
  705. if not MaybeBuildReference then
  706. Begin
  707. Message(asmr_e_invalid_seg_override);
  708. Consume(actasmtoken);
  709. end;
  710. end
  711. { Simple register }
  712. else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  713. Begin
  714. if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
  715. Message(asmr_e_invalid_operand_type);
  716. oper.opr.typ:=OPR_REGISTER;
  717. oper.opr.reg:=tempreg;
  718. oper.SetSize(tcgsize2size[reg_cgsize(oper.opr.reg)],true);
  719. end
  720. else
  721. Message(asmr_e_syn_operand);
  722. end;
  723. AS_END,
  724. AS_SEPARATOR,
  725. AS_COMMA: ;
  726. else
  727. Begin
  728. Message(asmr_e_syn_operand);
  729. Consume(actasmtoken);
  730. end;
  731. end; { end case }
  732. end;
  733. procedure tx86attreader.BuildOpCode(instr : tx86instruction);
  734. var
  735. operandnum : longint;
  736. PrefixOp,OverrideOp: tasmop;
  737. Begin
  738. PrefixOp:=A_None;
  739. OverrideOp:=A_None;
  740. { prefix seg opcode / prefix opcode }
  741. repeat
  742. if is_prefix(actopcode) then
  743. begin
  744. PrefixOp:=ActOpcode;
  745. with instr do
  746. begin
  747. opcode:=ActOpcode;
  748. condition:=ActCondition;
  749. opsize:=ActOpsize;
  750. ConcatInstruction(curlist);
  751. end;
  752. Consume(AS_OPCODE);
  753. end
  754. else
  755. if is_override(actopcode) then
  756. begin
  757. OverrideOp:=ActOpcode;
  758. with instr do
  759. begin
  760. opcode:=ActOpcode;
  761. condition:=ActCondition;
  762. opsize:=ActOpsize;
  763. ConcatInstruction(curlist);
  764. end;
  765. Consume(AS_OPCODE);
  766. end
  767. else
  768. break;
  769. { allow for newline as in gas styled syntax }
  770. while actasmtoken=AS_SEPARATOR do
  771. Consume(AS_SEPARATOR);
  772. until (actasmtoken<>AS_OPCODE);
  773. { opcode }
  774. if (actasmtoken<>AS_OPCODE) then
  775. Begin
  776. Message(asmr_e_invalid_or_missing_opcode);
  777. RecoverConsume(true);
  778. exit;
  779. end;
  780. { Fill the instr object with the current state }
  781. with instr do
  782. begin
  783. Opcode:=ActOpcode;
  784. condition:=ActCondition;
  785. opsize:=ActOpsize;
  786. end;
  787. { Valid combination of prefix/override and instruction ? }
  788. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  789. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  790. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  791. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  792. { We are reading operands, so opcode will be an AS_ID }
  793. operandnum:=1;
  794. Consume(AS_OPCODE);
  795. { Zero operand opcode ? }
  796. if actasmtoken in [AS_SEPARATOR,AS_END] then
  797. begin
  798. operandnum:=0;
  799. exit;
  800. end;
  801. { Read the operands }
  802. repeat
  803. case actasmtoken of
  804. AS_COMMA: { Operand delimiter }
  805. Begin
  806. if operandnum > Max_Operands then
  807. Message(asmr_e_too_many_operands)
  808. else
  809. Inc(operandnum);
  810. Consume(AS_COMMA);
  811. end;
  812. AS_SEPARATOR,
  813. AS_END : { End of asm operands for this opcode }
  814. begin
  815. break;
  816. end;
  817. else
  818. BuildOperand(instr.Operands[operandnum] as tx86operand);
  819. end; { end case }
  820. until false;
  821. instr.Ops:=operandnum;
  822. end;
  823. function tx86attreader.is_asmopcode(const s: string):boolean;
  824. var
  825. cond : string[4];
  826. cnd : tasmcond;
  827. len,
  828. j,
  829. sufidx,
  830. suflen : longint;
  831. Begin
  832. is_asmopcode:=FALSE;
  833. actopcode:=A_None;
  834. actcondition:=C_None;
  835. actopsize:=S_NO;
  836. { search for all possible suffixes }
  837. for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
  838. begin
  839. suflen:=length(att_sizesuffixstr[sufidx]);
  840. len:=length(s)-suflen;
  841. if copy(s,len+1,suflen)=att_sizesuffixstr[sufidx] then
  842. begin
  843. { Search opcodes }
  844. if len>0 then
  845. begin
  846. actopcode:=tasmop(PtrUInt(iasmops.Find(copy(s,1,len))));
  847. { movsd needs special handling because it has two namings in at&t syntax (movsl for string handling and
  848. movsd for the sse instruction) while only one in intel syntax (movsd, both string and sse)
  849. this cannot be expressed by the instruction table format so we have to hack around this here }
  850. if (actopcode = A_NONE) and (upper(s) = 'MOVSD') then
  851. actopcode := A_MOVSD;
  852. { two-letter suffix is allowed by just a few instructions (movsx,movzx),
  853. and it is always required whenever allowed }
  854. if (gas_needsuffix[actopcode]=attsufINTdual) xor (suflen=2) then
  855. continue;
  856. if actopcode<>A_NONE then
  857. begin
  858. if gas_needsuffix[actopcode]=attsufFPU then
  859. actopsize:=att_sizefpusuffix[sufidx]
  860. else if gas_needsuffix[actopcode]=attsufFPUint then
  861. actopsize:=att_sizefpuintsuffix[sufidx]
  862. else
  863. actopsize:=att_sizesuffix[sufidx];
  864. { only accept suffix from the same category that the opcode belongs to }
  865. if (actopsize<>S_NO) or (suflen=0) then
  866. begin
  867. actasmtoken:=AS_OPCODE;
  868. is_asmopcode:=TRUE;
  869. exit;
  870. end;
  871. end;
  872. end;
  873. { not found, check condition opcodes }
  874. j:=0;
  875. while (j<CondAsmOps) do
  876. begin
  877. if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
  878. begin
  879. cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
  880. if cond<>'' then
  881. begin
  882. for cnd:=low(TasmCond) to high(TasmCond) do
  883. if Cond=Upper(cond2str[cnd]) then
  884. begin
  885. actopcode:=CondASmOp[j];
  886. if gas_needsuffix[actopcode]=attsufFPU then
  887. actopsize:=att_sizefpusuffix[sufidx]
  888. else if gas_needsuffix[actopcode]=attsufFPUint then
  889. actopsize:=att_sizefpuintsuffix[sufidx]
  890. else
  891. actopsize:=att_sizesuffix[sufidx];
  892. { only accept suffix from the same category that the opcode belongs to }
  893. if (actopsize<>S_NO) or (suflen=0) then
  894. begin
  895. actcondition:=cnd;
  896. actasmtoken:=AS_OPCODE;
  897. is_asmopcode:=TRUE;
  898. exit;
  899. end;
  900. end;
  901. end;
  902. end;
  903. inc(j);
  904. end;
  905. end;
  906. end;
  907. end;
  908. procedure tx86attreader.handleopcode;
  909. var
  910. instr : Tx86Instruction;
  911. begin
  912. instr:=Tx86attInstruction.Create(Tx86Operand);
  913. instr.OpOrder:=op_att;
  914. BuildOpcode(instr);
  915. instr.AddReferenceSizes;
  916. instr.SetInstructionOpsize;
  917. instr.CheckOperandSizes;
  918. instr.FixupOpcode;
  919. instr.ConcatInstruction(curlist);
  920. instr.Free;
  921. end;
  922. end.