raarmgas.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  4. Does the parsing for the ARM 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 raarmgas;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses
  22. raatt,raarm,
  23. cpubase;
  24. type
  25. tarmattreader = class(tattreader)
  26. actoppostfix : TOpPostfix;
  27. function is_asmopcode(const s: string):boolean;override;
  28. function is_register(const s:string):boolean;override;
  29. procedure handleopcode;override;
  30. procedure BuildReference(oper : tarmoperand);
  31. procedure BuildOperand(oper : tarmoperand);
  32. function TryBuildShifterOp(oper : tarmoperand) : boolean;
  33. procedure BuildOpCode(instr : tarminstruction);
  34. procedure ReadSym(oper : tarmoperand);
  35. procedure ConvertCalljmp(instr : tarminstruction);
  36. end;
  37. Implementation
  38. uses
  39. { helpers }
  40. cutils,
  41. { global }
  42. globtype,globals,verbose,
  43. systems,
  44. { aasm }
  45. cpuinfo,aasmbase,aasmtai,aasmcpu,
  46. { symtable }
  47. symconst,symbase,symtype,symsym,symtable,
  48. { parser }
  49. scanner,
  50. procinfo,
  51. itcpugas,
  52. rabase,rautils,
  53. cgbase,cgobj
  54. ;
  55. function tarmattreader.is_register(const s:string):boolean;
  56. type
  57. treg2str = record
  58. name : string[2];
  59. reg : tregister;
  60. end;
  61. const
  62. extraregs : array[0..19] of treg2str = (
  63. (name: 'A1'; reg : NR_R0),
  64. (name: 'A2'; reg : NR_R1),
  65. (name: 'A3'; reg : NR_R2),
  66. (name: 'A4'; reg : NR_R3),
  67. (name: 'V1'; reg : NR_R4),
  68. (name: 'V2'; reg : NR_R5),
  69. (name: 'V3'; reg : NR_R6),
  70. (name: 'V4'; reg : NR_R7),
  71. (name: 'V5'; reg : NR_R8),
  72. (name: 'V6'; reg : NR_R9),
  73. (name: 'V7'; reg : NR_R10),
  74. (name: 'V8'; reg : NR_R11),
  75. (name: 'WR'; reg : NR_R7),
  76. (name: 'SB'; reg : NR_R9),
  77. (name: 'SL'; reg : NR_R10),
  78. (name: 'FP'; reg : NR_R11),
  79. (name: 'IP'; reg : NR_R12),
  80. (name: 'SP'; reg : NR_R13),
  81. (name: 'LR'; reg : NR_R14),
  82. (name: 'PC'; reg : NR_R15));
  83. var
  84. i : longint;
  85. begin
  86. result:=inherited is_register(s);
  87. { reg found?
  88. possible aliases are always 2 char
  89. }
  90. if result or (length(s)<>2) then
  91. exit;
  92. for i:=low(extraregs) to high(extraregs) do
  93. begin
  94. if s=extraregs[i].name then
  95. begin
  96. actasmregister:=extraregs[i].reg;
  97. result:=true;
  98. actasmtoken:=AS_REGISTER;
  99. exit;
  100. end;
  101. end;
  102. end;
  103. procedure tarmattreader.ReadSym(oper : tarmoperand);
  104. var
  105. tempstr : string;
  106. typesize,l,k : longint;
  107. begin
  108. tempstr:=actasmpattern;
  109. Consume(AS_ID);
  110. { typecasting? }
  111. if (actasmtoken=AS_LPAREN) and
  112. SearchType(tempstr,typesize) then
  113. begin
  114. oper.hastype:=true;
  115. Consume(AS_LPAREN);
  116. BuildOperand(oper);
  117. Consume(AS_RPAREN);
  118. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  119. oper.SetSize(typesize,true);
  120. end
  121. else
  122. if not oper.SetupVar(tempstr,false) then
  123. Message1(sym_e_unknown_id,tempstr);
  124. { record.field ? }
  125. if actasmtoken=AS_DOT then
  126. begin
  127. BuildRecordOffsetSize(tempstr,l,k);
  128. inc(oper.opr.ref.offset,l);
  129. end;
  130. end;
  131. Procedure tarmattreader.BuildReference(oper : tarmoperand);
  132. procedure Consume_RBracket;
  133. begin
  134. if actasmtoken<>AS_RBRACKET then
  135. Begin
  136. Message(asmr_e_invalid_reference_syntax);
  137. RecoverConsume(true);
  138. end
  139. else
  140. begin
  141. Consume(AS_RBRACKET);
  142. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
  143. Begin
  144. Message(asmr_e_invalid_reference_syntax);
  145. RecoverConsume(true);
  146. end;
  147. end;
  148. end;
  149. procedure read_index;
  150. begin
  151. Consume(AS_COMMA);
  152. if actasmtoken=AS_REGISTER then
  153. Begin
  154. oper.opr.ref.index:=actasmregister;
  155. Consume(AS_REGISTER);
  156. end
  157. else if actasmtoken=AS_HASH then
  158. begin
  159. Consume(AS_HASH);
  160. inc(oper.opr.ref.offset,BuildConstExpression(false,true));
  161. end;
  162. end;
  163. begin
  164. Consume(AS_LBRACKET);
  165. if actasmtoken=AS_REGISTER then
  166. begin
  167. oper.opr.ref.base:=actasmregister;
  168. Consume(AS_REGISTER);
  169. { can either be a register or a right parenthesis }
  170. { (reg) }
  171. if actasmtoken=AS_RBRACKET then
  172. Begin
  173. Consume_RBracket;
  174. oper.opr.ref.addressmode:=AM_POSTINDEXED;
  175. if actasmtoken=AS_COMMA then
  176. read_index;
  177. exit;
  178. end;
  179. if actasmtoken=AS_COMMA then
  180. begin
  181. read_index;
  182. Consume_RBracket;
  183. end;
  184. if actasmtoken=AS_NOT then
  185. begin
  186. consume(AS_NOT);
  187. oper.opr.ref.addressmode:=AM_PREINDEXED;
  188. end;
  189. end {end case }
  190. else
  191. Begin
  192. Message(asmr_e_invalid_reference_syntax);
  193. RecoverConsume(false);
  194. end;
  195. end;
  196. function tarmattreader.TryBuildShifterOp(oper : tarmoperand) : boolean;
  197. procedure handlepara(sm : tshiftmode);
  198. begin
  199. consume(AS_ID);
  200. fillchar(oper.opr,sizeof(oper.opr),0);
  201. oper.opr.typ:=OPR_SHIFTEROP;
  202. oper.opr.shifterop.shiftmode:=sm;
  203. if sm<>SM_RRX then
  204. begin
  205. case actasmtoken of
  206. AS_REGISTER:
  207. begin
  208. oper.opr.shifterop.rs:=actasmregister;
  209. consume(AS_REGISTER);
  210. end;
  211. AS_HASH:
  212. begin
  213. consume(AS_HASH);
  214. oper.opr.shifterop.shiftimm:=BuildConstExpression(false,false);
  215. end;
  216. else
  217. Message(asmr_e_illegal_shifterop_syntax);
  218. end;
  219. end;
  220. end;
  221. begin
  222. result:=true;
  223. if (actasmtoken=AS_ID) then
  224. begin
  225. if (actasmpattern='LSL') then
  226. handlepara(SM_LSL)
  227. else if (actasmpattern='LSR') then
  228. handlepara(SM_LSR)
  229. else if (actasmpattern='ASR') then
  230. handlepara(SM_ASR)
  231. else if (actasmpattern='ROR') then
  232. handlepara(SM_ROR)
  233. else if (actasmpattern='RRX') then
  234. handlepara(SM_ROR)
  235. else
  236. result:=false;
  237. end
  238. else
  239. result:=false;
  240. end;
  241. Procedure tarmattreader.BuildOperand(oper : tarmoperand);
  242. var
  243. expr : string;
  244. typesize,l : longint;
  245. procedure AddLabelOperand(hl:tasmlabel);
  246. begin
  247. if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
  248. is_calljmp(actopcode) then
  249. begin
  250. oper.opr.typ:=OPR_SYMBOL;
  251. oper.opr.symbol:=hl;
  252. end
  253. else
  254. begin
  255. oper.InitRef;
  256. oper.opr.ref.symbol:=hl;
  257. end;
  258. end;
  259. procedure MaybeRecordOffset;
  260. var
  261. hasdot : boolean;
  262. l,
  263. toffset,
  264. tsize : longint;
  265. begin
  266. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  267. exit;
  268. l:=0;
  269. hasdot:=(actasmtoken=AS_DOT);
  270. if hasdot then
  271. begin
  272. if expr<>'' then
  273. begin
  274. BuildRecordOffsetSize(expr,toffset,tsize);
  275. inc(l,toffset);
  276. oper.SetSize(tsize,true);
  277. end;
  278. end;
  279. if actasmtoken in [AS_PLUS,AS_MINUS] then
  280. inc(l,BuildConstExpression(true,false));
  281. case oper.opr.typ of
  282. OPR_LOCAL :
  283. begin
  284. { don't allow direct access to fields of parameters, because that
  285. will generate buggy code. Allow it only for explicit typecasting }
  286. if hasdot and
  287. (not oper.hastype) and
  288. (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
  289. (current_procinfo.procdef.proccalloption<>pocall_register) then
  290. Message(asmr_e_cannot_access_field_directly_for_parameters);
  291. inc(oper.opr.localsymofs,l)
  292. end;
  293. OPR_CONSTANT :
  294. inc(oper.opr.val,l);
  295. OPR_REFERENCE :
  296. inc(oper.opr.ref.offset,l);
  297. else
  298. internalerror(200309221);
  299. end;
  300. end;
  301. function MaybeBuildReference:boolean;
  302. { Try to create a reference, if not a reference is found then false
  303. is returned }
  304. begin
  305. MaybeBuildReference:=true;
  306. case actasmtoken of
  307. AS_INTNUM,
  308. AS_MINUS,
  309. AS_PLUS:
  310. Begin
  311. oper.opr.ref.offset:=BuildConstExpression(True,False);
  312. if actasmtoken<>AS_LPAREN then
  313. Message(asmr_e_invalid_reference_syntax)
  314. else
  315. BuildReference(oper);
  316. end;
  317. AS_LPAREN:
  318. BuildReference(oper);
  319. AS_ID: { only a variable is allowed ... }
  320. Begin
  321. ReadSym(oper);
  322. case actasmtoken of
  323. AS_END,
  324. AS_SEPARATOR,
  325. AS_COMMA: ;
  326. AS_LPAREN:
  327. BuildReference(oper);
  328. else
  329. Begin
  330. Message(asmr_e_invalid_reference_syntax);
  331. Consume(actasmtoken);
  332. end;
  333. end; {end case }
  334. end;
  335. else
  336. MaybeBuildReference:=false;
  337. end; { end case }
  338. end;
  339. var
  340. tempreg : tregister;
  341. ireg : tsuperregister;
  342. hl : tasmlabel;
  343. ofs : longint;
  344. registerset : tcpuregisterset;
  345. Begin
  346. expr:='';
  347. case actasmtoken of
  348. AS_LBRACKET: { Memory reference or constant expression }
  349. Begin
  350. oper.InitRef;
  351. BuildReference(oper);
  352. end;
  353. AS_HASH: { Constant expression }
  354. Begin
  355. Consume(AS_HASH);
  356. BuildConstantOperand(oper);
  357. end;
  358. (*
  359. AS_INTNUM,
  360. AS_MINUS,
  361. AS_PLUS:
  362. Begin
  363. { Constant memory offset }
  364. { This must absolutely be followed by ( }
  365. oper.InitRef;
  366. oper.opr.ref.offset:=BuildConstExpression(True,False);
  367. if actasmtoken<>AS_LPAREN then
  368. begin
  369. ofs:=oper.opr.ref.offset;
  370. BuildConstantOperand(oper);
  371. inc(oper.opr.val,ofs);
  372. end
  373. else
  374. BuildReference(oper);
  375. end;
  376. *)
  377. AS_ID: { A constant expression, or a Variable ref. }
  378. Begin
  379. { Local Label ? }
  380. if is_locallabel(actasmpattern) then
  381. begin
  382. CreateLocalLabel(actasmpattern,hl,false);
  383. Consume(AS_ID);
  384. AddLabelOperand(hl);
  385. end
  386. else
  387. { Check for label }
  388. if SearchLabel(actasmpattern,hl,false) then
  389. begin
  390. Consume(AS_ID);
  391. AddLabelOperand(hl);
  392. end
  393. else
  394. { probably a variable or normal expression }
  395. { or a procedure (such as in CALL ID) }
  396. Begin
  397. { is it a constant ? }
  398. if SearchIConstant(actasmpattern,l) then
  399. Begin
  400. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  401. Message(asmr_e_invalid_operand_type);
  402. BuildConstantOperand(oper);
  403. end
  404. else
  405. begin
  406. expr:=actasmpattern;
  407. Consume(AS_ID);
  408. { typecasting? }
  409. if (actasmtoken=AS_LPAREN) and
  410. SearchType(expr,typesize) then
  411. begin
  412. oper.hastype:=true;
  413. Consume(AS_LPAREN);
  414. BuildOperand(oper);
  415. Consume(AS_RPAREN);
  416. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  417. oper.SetSize(typesize,true);
  418. end
  419. else
  420. begin
  421. if not(oper.SetupVar(expr,false)) then
  422. Begin
  423. { look for special symbols ... }
  424. if expr= '__HIGH' then
  425. begin
  426. consume(AS_LPAREN);
  427. if not oper.setupvar('high'+actasmpattern,false) then
  428. Message1(sym_e_unknown_id,'high'+actasmpattern);
  429. consume(AS_ID);
  430. consume(AS_RPAREN);
  431. end
  432. else
  433. if expr = '__RESULT' then
  434. oper.SetUpResult
  435. else
  436. if expr = '__SELF' then
  437. oper.SetupSelf
  438. else
  439. if expr = '__OLDEBP' then
  440. oper.SetupOldEBP
  441. else
  442. Message1(sym_e_unknown_id,expr);
  443. end;
  444. end;
  445. end;
  446. if actasmtoken=AS_DOT then
  447. MaybeRecordOffset;
  448. { add a constant expression? }
  449. if (actasmtoken=AS_PLUS) then
  450. begin
  451. l:=BuildConstExpression(true,false);
  452. case oper.opr.typ of
  453. OPR_CONSTANT :
  454. inc(oper.opr.val,l);
  455. OPR_LOCAL :
  456. inc(oper.opr.localsymofs,l);
  457. OPR_REFERENCE :
  458. inc(oper.opr.ref.offset,l);
  459. else
  460. internalerror(200309202);
  461. end;
  462. end
  463. end;
  464. { Do we have a indexing reference, then parse it also }
  465. if actasmtoken=AS_LPAREN then
  466. BuildReference(oper);
  467. end;
  468. { Register, a variable reference or a constant reference }
  469. AS_REGISTER:
  470. Begin
  471. { save the type of register used. }
  472. tempreg:=actasmregister;
  473. Consume(AS_REGISTER);
  474. if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  475. Begin
  476. if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
  477. Message(asmr_e_invalid_operand_type);
  478. oper.opr.typ:=OPR_REGISTER;
  479. oper.opr.reg:=tempreg;
  480. end
  481. else if (actasmtoken=AS_NOT) and (actopcode in [A_LDM,A_STM]) then
  482. begin
  483. consume(AS_NOT);
  484. oper.opr.typ:=OPR_REFERENCE;
  485. oper.opr.ref.addressmode:=AM_PREINDEXED;
  486. oper.opr.ref.index:=tempreg;
  487. end
  488. else
  489. Message(asmr_e_syn_operand);
  490. end;
  491. { Registerset }
  492. AS_LSBRACKET:
  493. begin
  494. consume(AS_LSBRACKET);
  495. registerset:=[];
  496. while true do
  497. begin
  498. if actasmtoken=AS_REGISTER then
  499. begin
  500. include(registerset,getsupreg(actasmregister));
  501. tempreg:=actasmregister;
  502. consume(AS_REGISTER);
  503. if actasmtoken=AS_MINUS then
  504. begin
  505. consume(AS_MINUS);
  506. for ireg:=getsupreg(tempreg) to getsupreg(actasmregister) do
  507. include(registerset,ireg);
  508. consume(AS_REGISTER);
  509. end;
  510. end
  511. else
  512. consume(AS_REGISTER);
  513. if actasmtoken=AS_COMMA then
  514. consume(AS_COMMA)
  515. else
  516. break;
  517. end;
  518. consume(AS_RSBRACKET);
  519. oper.opr.typ:=OPR_REGSET;
  520. oper.opr.regset:=registerset;
  521. end;
  522. AS_END,
  523. AS_SEPARATOR,
  524. AS_COMMA: ;
  525. else
  526. Begin
  527. Message(asmr_e_syn_operand);
  528. Consume(actasmtoken);
  529. end;
  530. end; { end case }
  531. end;
  532. {*****************************************************************************
  533. tarmattreader
  534. *****************************************************************************}
  535. procedure tarmattreader.BuildOpCode(instr : tarminstruction);
  536. var
  537. operandnum : longint;
  538. Begin
  539. { opcode }
  540. if (actasmtoken<>AS_OPCODE) then
  541. Begin
  542. Message(asmr_e_invalid_or_missing_opcode);
  543. RecoverConsume(true);
  544. exit;
  545. end;
  546. { Fill the instr object with the current state }
  547. with instr do
  548. begin
  549. Opcode:=ActOpcode;
  550. condition:=ActCondition;
  551. oppostfix:=actoppostfix;
  552. end;
  553. { We are reading operands, so opcode will be an AS_ID }
  554. operandnum:=1;
  555. Consume(AS_OPCODE);
  556. { Zero operand opcode ? }
  557. if actasmtoken in [AS_SEPARATOR,AS_END] then
  558. begin
  559. operandnum:=0;
  560. exit;
  561. end;
  562. { Read the operands }
  563. repeat
  564. case actasmtoken of
  565. AS_COMMA: { Operand delimiter }
  566. Begin
  567. if ((instr.opcode=A_MOV) and (operandnum=2)) or
  568. ((operandnum=3) and not(instr.opcode in [A_UMLAL,A_UMULL,A_SMLAL,A_SMULL])) then
  569. begin
  570. Consume(AS_COMMA);
  571. if not(TryBuildShifterOp(instr.Operands[4] as tarmoperand)) then
  572. Message(asmr_e_illegal_shifterop_syntax);
  573. Inc(operandnum);
  574. end
  575. else
  576. begin
  577. if operandnum>Max_Operands then
  578. Message(asmr_e_too_many_operands)
  579. else
  580. Inc(operandnum);
  581. Consume(AS_COMMA);
  582. end;
  583. end;
  584. AS_SEPARATOR,
  585. AS_END : { End of asm operands for this opcode }
  586. begin
  587. break;
  588. end;
  589. else
  590. BuildOperand(instr.Operands[operandnum] as tarmoperand);
  591. end; { end case }
  592. until false;
  593. instr.Ops:=operandnum;
  594. end;
  595. function tarmattreader.is_asmopcode(const s: string):boolean;
  596. const
  597. { sorted by length so longer postfixes will match first }
  598. postfix2strsorted : array[1..19] of string[2] = (
  599. 'EP','SB','BT','SH',
  600. 'IA','IB','DA','DB','FD','FA','ED','EA',
  601. 'B','D','E','P','T','H','S');
  602. postfixsorted : array[1..19] of TOpPostfix = (
  603. PF_EP,PF_SB,PF_BT,PF_SH,
  604. PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA,
  605. PF_B,PF_D,PF_E,PF_P,PF_T,PF_H,PF_S);
  606. var
  607. str2opentry: tstr2opentry;
  608. len,
  609. j,
  610. sufidx : longint;
  611. hs : string;
  612. maxlen : longint;
  613. icond : tasmcond;
  614. Begin
  615. { making s a value parameter would break other assembler readers }
  616. hs:=s;
  617. is_asmopcode:=false;
  618. { clear op code }
  619. actopcode:=A_None;
  620. actcondition:=C_None;
  621. { first, handle B else BLS is read wrong }
  622. if ((hs[1]='B') and (length(hs)=3)) then
  623. begin
  624. for icond:=low(tasmcond) to high(tasmcond) do
  625. begin
  626. if copy(hs,2,3)=uppercond2str[icond] then
  627. begin
  628. actopcode:=A_B;
  629. actasmtoken:=AS_OPCODE;
  630. actcondition:=icond;
  631. is_asmopcode:=true;
  632. exit;
  633. end;
  634. end;
  635. end;
  636. maxlen:=max(length(hs),5);
  637. for j:=maxlen downto 1 do
  638. begin
  639. str2opentry:=tstr2opentry(iasmops.search(copy(hs,1,j)));
  640. if assigned(str2opentry) then
  641. begin
  642. actopcode:=str2opentry.op;
  643. actasmtoken:=AS_OPCODE;
  644. { strip op code }
  645. delete(hs,1,j);
  646. break;
  647. end;
  648. end;
  649. if not(assigned(str2opentry)) then
  650. exit;
  651. { search for condition, conditions are always 2 chars }
  652. if length(hs)>1 then
  653. begin
  654. for icond:=low(tasmcond) to high(tasmcond) do
  655. begin
  656. if copy(hs,1,2)=uppercond2str[icond] then
  657. begin
  658. actcondition:=icond;
  659. { strip condition }
  660. delete(hs,1,2);
  661. break;
  662. end;
  663. end;
  664. end;
  665. { check for postfix }
  666. if length(hs)>0 then
  667. begin
  668. for j:=low(postfixsorted) to high(postfixsorted) do
  669. begin
  670. if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
  671. begin
  672. actoppostfix:=postfixsorted[j];
  673. { strip postfix }
  674. delete(hs,1,length(postfix2strsorted[j]));
  675. break;
  676. end;
  677. end;
  678. end;
  679. { if we stripped all postfixes, it's a valid opcode }
  680. is_asmopcode:=length(hs)=0;
  681. end;
  682. procedure tarmattreader.ConvertCalljmp(instr : tarminstruction);
  683. var
  684. newopr : toprrec;
  685. begin
  686. if instr.Operands[1].opr.typ=OPR_REFERENCE then
  687. begin
  688. newopr.typ:=OPR_SYMBOL;
  689. newopr.symbol:=instr.Operands[1].opr.ref.symbol;
  690. newopr.symofs:=instr.Operands[1].opr.ref.offset;
  691. if (instr.Operands[1].opr.ref.base<>NR_NO) or
  692. (instr.Operands[1].opr.ref.index<>NR_NO) then
  693. Message(asmr_e_syn_operand);
  694. instr.Operands[1].opr:=newopr;
  695. end;
  696. end;
  697. procedure tarmattreader.handleopcode;
  698. var
  699. instr : tarminstruction;
  700. begin
  701. instr:=TarmInstruction.Create(TarmOperand);
  702. BuildOpcode(instr);
  703. if is_calljmp(instr.opcode) then
  704. ConvertCalljmp(instr);
  705. {
  706. instr.AddReferenceSizes;
  707. instr.SetInstructionOpsize;
  708. instr.CheckOperandSizes;
  709. }
  710. instr.ConcatInstruction(curlist);
  711. instr.Free;
  712. actoppostfix:=PF_None;
  713. end;
  714. {*****************************************************************************
  715. Initialize
  716. *****************************************************************************}
  717. const
  718. asmmode_arm_att_info : tasmmodeinfo =
  719. (
  720. id : asmmode_arm_gas;
  721. idtxt : 'GAS';
  722. casmreader : tarmattreader;
  723. );
  724. asmmode_arm_standard_info : tasmmodeinfo =
  725. (
  726. id : asmmode_standard;
  727. idtxt : 'STANDARD';
  728. casmreader : tarmattreader;
  729. );
  730. initialization
  731. RegisterAsmMode(asmmode_arm_att_info);
  732. RegisterAsmMode(asmmode_arm_standard_info);
  733. end.
  734. {
  735. $Log$
  736. Revision 1.12 2005-01-05 15:22:58 florian
  737. * added support of shifter ops in arm inline assembler
  738. Revision 1.11 2004/11/24 22:03:26 florian
  739. * fixed arm compilation
  740. Revision 1.10 2004/11/11 19:31:33 peter
  741. * fixed compile of powerpc,sparc,arm
  742. Revision 1.9 2004/06/20 08:55:31 florian
  743. * logs truncated
  744. Revision 1.8 2004/03/02 00:36:33 olle
  745. * big transformation of Tai_[const_]Symbol.Create[data]name*
  746. Revision 1.7 2004/01/20 21:02:56 florian
  747. * fixed symbol type writing for arm-linux
  748. * fixed assembler generation for abs
  749. }