raarmgas.pas 25 KB

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